summaryrefslogtreecommitdiff
path: root/chromium/ui/gfx/gtk_util.cc
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
committerZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
commit679147eead574d186ebf3069647b4c23e8ccace6 (patch)
treefc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /chromium/ui/gfx/gtk_util.cc
downloadqtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz
Initial import.
Diffstat (limited to 'chromium/ui/gfx/gtk_util.cc')
-rw-r--r--chromium/ui/gfx/gtk_util.cc190
1 files changed, 190 insertions, 0 deletions
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 <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <stdlib.h>
+
+#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<GdkCursorType, GdkCursor*> 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<std::string>& args = command_line.argv();
+ int argc = args.size();
+ scoped_ptr<char *[]> 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<Rect>& 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<GdkCursorType>(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