From 679147eead574d186ebf3069647b4c23e8ccace6 Mon Sep 17 00:00:00 2001 From: Zeno Albisser Date: Thu, 15 Aug 2013 21:46:11 +0200 Subject: Initial import. --- chromium/ui/gfx/gtk_util.cc | 190 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 chromium/ui/gfx/gtk_util.cc (limited to 'chromium/ui/gfx/gtk_util.cc') diff --git a/chromium/ui/gfx/gtk_util.cc b/chromium/ui/gfx/gtk_util.cc new file mode 100644 index 00000000000..0c111687572 --- /dev/null +++ b/chromium/ui/gfx/gtk_util.cc @@ -0,0 +1,190 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gfx/gtk_util.h" + +#include +#include +#include + +#include "base/basictypes.h" +#include "base/command_line.h" +#include "base/memory/scoped_ptr.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkUnPreMultiply.h" +#include "ui/gfx/rect.h" + +namespace { + +// A process wide singleton that manages our usage of gdk cursors. +// gdk_cursor_new() hits the disk in several places and GdkCursor instances can +// be reused throughout the process. +class GdkCursorCache { + public: + GdkCursorCache() {} + ~GdkCursorCache() { + for (GdkCursorMap::iterator i(cursors_.begin()); i != cursors_.end(); ++i) { + gdk_cursor_unref(i->second); + } + cursors_.clear(); + } + + GdkCursor* GetCursorImpl(GdkCursorType type) { + GdkCursorMap::iterator it = cursors_.find(type); + GdkCursor* cursor = NULL; + if (it == cursors_.end()) { + cursor = gdk_cursor_new(type); + cursors_.insert(std::make_pair(type, cursor)); + } else { + cursor = it->second; + } + + // It is not necessary to add a reference here. The callers can ref the + // cursor if they need it for something. + return cursor; + } + + private: + typedef std::map GdkCursorMap; + GdkCursorMap cursors_; + + DISALLOW_COPY_AND_ASSIGN(GdkCursorCache); +}; + +} // namespace + +namespace gfx { + +static void CommonInitFromCommandLine(const CommandLine& command_line, + void (*init_func)(gint*, gchar***)) { + const std::vector& args = command_line.argv(); + int argc = args.size(); + scoped_ptr argv(new char *[argc + 1]); + for (size_t i = 0; i < args.size(); ++i) { + // TODO(piman@google.com): can gtk_init modify argv? Just being safe + // here. + argv[i] = strdup(args[i].c_str()); + } + argv[argc] = NULL; + char **argv_pointer = argv.get(); + + init_func(&argc, &argv_pointer); + for (size_t i = 0; i < args.size(); ++i) { + free(argv[i]); + } +} + +void GtkInitFromCommandLine(const CommandLine& command_line) { + CommonInitFromCommandLine(command_line, gtk_init); +} + +void GdkInitFromCommandLine(const CommandLine& command_line) { + CommonInitFromCommandLine(command_line, gdk_init); +} + +GdkPixbuf* GdkPixbufFromSkBitmap(const SkBitmap& bitmap) { + if (bitmap.isNull()) + return NULL; + + SkAutoLockPixels lock_pixels(bitmap); + + int width = bitmap.width(); + int height = bitmap.height(); + + GdkPixbuf* pixbuf = gdk_pixbuf_new( + GDK_COLORSPACE_RGB, // The only colorspace gtk supports. + TRUE, // There is an alpha channel. + 8, + width, height); + + // SkBitmaps are premultiplied, we need to unpremultiply them. + const int kBytesPerPixel = 4; + uint8* divided = gdk_pixbuf_get_pixels(pixbuf); + + for (int y = 0, i = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + uint32 pixel = bitmap.getAddr32(0, y)[x]; + + int alpha = SkColorGetA(pixel); + if (alpha != 0 && alpha != 255) { + SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(pixel); + divided[i + 0] = SkColorGetR(unmultiplied); + divided[i + 1] = SkColorGetG(unmultiplied); + divided[i + 2] = SkColorGetB(unmultiplied); + divided[i + 3] = alpha; + } else { + divided[i + 0] = SkColorGetR(pixel); + divided[i + 1] = SkColorGetG(pixel); + divided[i + 2] = SkColorGetB(pixel); + divided[i + 3] = alpha; + } + i += kBytesPerPixel; + } + } + + return pixbuf; +} + +void SubtractRectanglesFromRegion(GdkRegion* region, + const std::vector& cutouts) { + for (size_t i = 0; i < cutouts.size(); ++i) { + GdkRectangle rect = cutouts[i].ToGdkRectangle(); + GdkRegion* rect_region = gdk_region_rectangle(&rect); + gdk_region_subtract(region, rect_region); + // TODO(deanm): It would be nice to be able to reuse the GdkRegion here. + gdk_region_destroy(rect_region); + } +} + +GdkCursor* GetCursor(int type) { + CR_DEFINE_STATIC_LOCAL(GdkCursorCache, impl, ()); + return impl.GetCursorImpl(static_cast(type)); +} + +void InitRCStyles() { + static const char kRCText[] = + // Make our dialogs styled like the GNOME HIG. + // + // TODO(evanm): content-area-spacing was introduced in a later + // version of GTK, so we need to set that manually on all dialogs. + // Perhaps it would make sense to have a shared FixupDialog() function. + "style \"gnome-dialog\" {\n" + " xthickness = 12\n" + " GtkDialog::action-area-border = 0\n" + " GtkDialog::button-spacing = 6\n" + " GtkDialog::content-area-spacing = 18\n" + " GtkDialog::content-area-border = 12\n" + "}\n" + // Note we set it at the "application" priority, so users can override. + "widget \"GtkDialog\" style : application \"gnome-dialog\"\n" + + // Make our about dialog special, so the image is flush with the edge. + "style \"about-dialog\" {\n" + " GtkDialog::action-area-border = 12\n" + " GtkDialog::button-spacing = 6\n" + " GtkDialog::content-area-spacing = 18\n" + " GtkDialog::content-area-border = 0\n" + "}\n" + "widget \"about-dialog\" style : application \"about-dialog\"\n"; + + gtk_rc_parse_string(kRCText); +} + +base::TimeDelta GetCursorBlinkCycle() { + // From http://library.gnome.org/devel/gtk/unstable/GtkSettings.html, this is + // the default value for gtk-cursor-blink-time. + static const gint kGtkDefaultCursorBlinkTime = 1200; + + gint cursor_blink_time = kGtkDefaultCursorBlinkTime; + gboolean cursor_blink = TRUE; + g_object_get(gtk_settings_get_default(), + "gtk-cursor-blink-time", &cursor_blink_time, + "gtk-cursor-blink", &cursor_blink, + NULL); + return cursor_blink ? + base::TimeDelta::FromMilliseconds(cursor_blink_time) : + base::TimeDelta(); +} + +} // namespace gfx -- cgit v1.2.1