| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "content/common/cursors/webcursor.h" | |
| 6 | |
| 7 #include <gdk/gdk.h> | |
| 8 #include <gtk/gtk.h> | |
| 9 | |
| 10 #include "base/logging.h" | |
| 11 #include "third_party/WebKit/public/platform/WebCursorInfo.h" | |
| 12 #include "ui/gfx/gtk_util.h" | |
| 13 | |
| 14 using blink::WebCursorInfo; | |
| 15 | |
| 16 namespace { | |
| 17 | |
| 18 // webcursor_gtk_data.h is taken directly from WebKit's CursorGtk.h. | |
| 19 #include "content/common/cursors/webcursor_gtk_data.h" | |
| 20 | |
| 21 // This helper function is taken directly from WebKit's CursorGtk.cpp. | |
| 22 // It attempts to create a custom cursor from the data inlined in | |
| 23 // webcursor_gtk_data.h. | |
| 24 GdkCursor* GetInlineCustomCursor(CustomCursorType type) { | |
| 25 static GdkCursor* CustomCursorsGdk[G_N_ELEMENTS(CustomCursors)]; | |
| 26 GdkCursor* cursor = CustomCursorsGdk[type]; | |
| 27 if (cursor) | |
| 28 return cursor; | |
| 29 const CustomCursor& custom = CustomCursors[type]; | |
| 30 cursor = gdk_cursor_new_from_name(gdk_display_get_default(), custom.name); | |
| 31 if (!cursor) { | |
| 32 const GdkColor fg = { 0, 0, 0, 0 }; | |
| 33 const GdkColor bg = { 65535, 65535, 65535, 65535 }; | |
| 34 GdkPixmap* source = gdk_bitmap_create_from_data( | |
| 35 NULL, reinterpret_cast<const gchar*>(custom.bits), 32, 32); | |
| 36 GdkPixmap* mask = gdk_bitmap_create_from_data( | |
| 37 NULL, reinterpret_cast<const gchar*>(custom.mask_bits), 32, 32); | |
| 38 cursor = gdk_cursor_new_from_pixmap(source, mask, &fg, &bg, | |
| 39 custom.hot_x, custom.hot_y); | |
| 40 g_object_unref(source); | |
| 41 g_object_unref(mask); | |
| 42 } | |
| 43 CustomCursorsGdk[type] = cursor; | |
| 44 return cursor; | |
| 45 } | |
| 46 | |
| 47 } // namespace | |
| 48 | |
| 49 namespace content { | |
| 50 | |
| 51 int WebCursor::GetCursorType() const { | |
| 52 // http://library.gnome.org/devel/gdk/2.12/gdk-Cursors.html has images | |
| 53 // of the default X theme, but beware that the user's cursor theme can | |
| 54 // change everything. | |
| 55 switch (type_) { | |
| 56 case WebCursorInfo::TypePointer: | |
| 57 return GDK_LAST_CURSOR; | |
| 58 case WebCursorInfo::TypeCross: | |
| 59 return GDK_CROSS; | |
| 60 case WebCursorInfo::TypeHand: | |
| 61 return GDK_HAND2; | |
| 62 case WebCursorInfo::TypeIBeam: | |
| 63 return GDK_XTERM; | |
| 64 case WebCursorInfo::TypeWait: | |
| 65 return GDK_WATCH; | |
| 66 case WebCursorInfo::TypeHelp: | |
| 67 return GDK_QUESTION_ARROW; | |
| 68 case WebCursorInfo::TypeEastResize: | |
| 69 return GDK_RIGHT_SIDE; | |
| 70 case WebCursorInfo::TypeNorthResize: | |
| 71 return GDK_TOP_SIDE; | |
| 72 case WebCursorInfo::TypeNorthEastResize: | |
| 73 return GDK_TOP_RIGHT_CORNER; | |
| 74 case WebCursorInfo::TypeNorthWestResize: | |
| 75 return GDK_TOP_LEFT_CORNER; | |
| 76 case WebCursorInfo::TypeSouthResize: | |
| 77 return GDK_BOTTOM_SIDE; | |
| 78 case WebCursorInfo::TypeSouthEastResize: | |
| 79 return GDK_BOTTOM_RIGHT_CORNER; | |
| 80 case WebCursorInfo::TypeSouthWestResize: | |
| 81 return GDK_BOTTOM_LEFT_CORNER; | |
| 82 case WebCursorInfo::TypeWestResize: | |
| 83 return GDK_LEFT_SIDE; | |
| 84 case WebCursorInfo::TypeNorthSouthResize: | |
| 85 return GDK_SB_V_DOUBLE_ARROW; | |
| 86 case WebCursorInfo::TypeEastWestResize: | |
| 87 return GDK_SB_H_DOUBLE_ARROW; | |
| 88 case WebCursorInfo::TypeNorthEastSouthWestResize: | |
| 89 case WebCursorInfo::TypeNorthWestSouthEastResize: | |
| 90 // There isn't really a useful cursor available for these. | |
| 91 return GDK_LAST_CURSOR; | |
| 92 case WebCursorInfo::TypeColumnResize: | |
| 93 return GDK_SB_H_DOUBLE_ARROW; // TODO(evanm): is this correct? | |
| 94 case WebCursorInfo::TypeRowResize: | |
| 95 return GDK_SB_V_DOUBLE_ARROW; // TODO(evanm): is this correct? | |
| 96 case WebCursorInfo::TypeMiddlePanning: | |
| 97 return GDK_FLEUR; | |
| 98 case WebCursorInfo::TypeEastPanning: | |
| 99 return GDK_SB_RIGHT_ARROW; | |
| 100 case WebCursorInfo::TypeNorthPanning: | |
| 101 return GDK_SB_UP_ARROW; | |
| 102 case WebCursorInfo::TypeNorthEastPanning: | |
| 103 return GDK_TOP_RIGHT_CORNER; | |
| 104 case WebCursorInfo::TypeNorthWestPanning: | |
| 105 return GDK_TOP_LEFT_CORNER; | |
| 106 case WebCursorInfo::TypeSouthPanning: | |
| 107 return GDK_SB_DOWN_ARROW; | |
| 108 case WebCursorInfo::TypeSouthEastPanning: | |
| 109 return GDK_BOTTOM_RIGHT_CORNER; | |
| 110 case WebCursorInfo::TypeSouthWestPanning: | |
| 111 return GDK_BOTTOM_LEFT_CORNER; | |
| 112 case WebCursorInfo::TypeWestPanning: | |
| 113 return GDK_SB_LEFT_ARROW; | |
| 114 case WebCursorInfo::TypeMove: | |
| 115 return GDK_FLEUR; | |
| 116 case WebCursorInfo::TypeVerticalText: | |
| 117 return GDK_LAST_CURSOR; | |
| 118 case WebCursorInfo::TypeCell: | |
| 119 return GDK_LAST_CURSOR; | |
| 120 case WebCursorInfo::TypeContextMenu: | |
| 121 return GDK_LAST_CURSOR; | |
| 122 case WebCursorInfo::TypeAlias: | |
| 123 return GDK_LAST_CURSOR; | |
| 124 case WebCursorInfo::TypeProgress: | |
| 125 return GDK_WATCH; | |
| 126 case WebCursorInfo::TypeNoDrop: | |
| 127 return GDK_LAST_CURSOR; | |
| 128 case WebCursorInfo::TypeCopy: | |
| 129 return GDK_LAST_CURSOR; | |
| 130 case WebCursorInfo::TypeNone: | |
| 131 return GDK_BLANK_CURSOR; | |
| 132 case WebCursorInfo::TypeNotAllowed: | |
| 133 return GDK_LAST_CURSOR; | |
| 134 case WebCursorInfo::TypeZoomIn: | |
| 135 case WebCursorInfo::TypeZoomOut: | |
| 136 case WebCursorInfo::TypeGrab: | |
| 137 case WebCursorInfo::TypeGrabbing: | |
| 138 case WebCursorInfo::TypeCustom: | |
| 139 return GDK_CURSOR_IS_PIXMAP; | |
| 140 } | |
| 141 NOTREACHED(); | |
| 142 return GDK_LAST_CURSOR; | |
| 143 } | |
| 144 | |
| 145 gfx::NativeCursor WebCursor::GetNativeCursor() { | |
| 146 int type = GetCursorType(); | |
| 147 if (type == GDK_CURSOR_IS_PIXMAP) | |
| 148 return GetCustomCursor(); | |
| 149 return gfx::GetCursor(type); | |
| 150 } | |
| 151 | |
| 152 GdkCursor* WebCursor::GetCustomCursor() { | |
| 153 switch (type_) { | |
| 154 case WebCursorInfo::TypeZoomIn: | |
| 155 return GetInlineCustomCursor(CustomCursorZoomIn); | |
| 156 case WebCursorInfo::TypeZoomOut: | |
| 157 return GetInlineCustomCursor(CustomCursorZoomOut); | |
| 158 case WebCursorInfo::TypeGrab: | |
| 159 return GetInlineCustomCursor(CustomCursorGrab); | |
| 160 case WebCursorInfo::TypeGrabbing: | |
| 161 return GetInlineCustomCursor(CustomCursorGrabbing); | |
| 162 } | |
| 163 | |
| 164 if (type_ != WebCursorInfo::TypeCustom) { | |
| 165 NOTREACHED(); | |
| 166 return NULL; | |
| 167 } | |
| 168 | |
| 169 if (custom_size_.width() == 0 || custom_size_.height() == 0) { | |
| 170 // Some websites specify cursor images that are 0 sized, such as Bing Maps. | |
| 171 // Don't crash on this; just use the default cursor. | |
| 172 return NULL; | |
| 173 } | |
| 174 | |
| 175 SkBitmap bitmap; | |
| 176 bitmap.setConfig(SkBitmap::kARGB_8888_Config, | |
| 177 custom_size_.width(), custom_size_.height()); | |
| 178 bitmap.allocPixels(); | |
| 179 memcpy(bitmap.getAddr32(0, 0), custom_data_.data(), custom_data_.size()); | |
| 180 | |
| 181 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(bitmap); | |
| 182 GdkCursor* cursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), | |
| 183 pixbuf, | |
| 184 hotspot_.x(), | |
| 185 hotspot_.y()); | |
| 186 | |
| 187 g_object_unref(pixbuf); | |
| 188 | |
| 189 if (unref_) | |
| 190 gdk_cursor_unref(unref_); | |
| 191 unref_ = cursor; | |
| 192 return cursor; | |
| 193 } | |
| 194 | |
| 195 void WebCursor::InitPlatformData() { | |
| 196 unref_ = NULL; | |
| 197 return; | |
| 198 } | |
| 199 | |
| 200 bool WebCursor::SerializePlatformData(Pickle* pickle) const { | |
| 201 return true; | |
| 202 } | |
| 203 | |
| 204 bool WebCursor::DeserializePlatformData(PickleIterator* iter) { | |
| 205 return true; | |
| 206 } | |
| 207 | |
| 208 bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const { | |
| 209 return true; | |
| 210 } | |
| 211 | |
| 212 void WebCursor::CleanupPlatformData() { | |
| 213 if (unref_) { | |
| 214 gdk_cursor_unref(unref_); | |
| 215 unref_ = NULL; | |
| 216 } | |
| 217 return; | |
| 218 } | |
| 219 | |
| 220 void WebCursor::CopyPlatformData(const WebCursor& other) { | |
| 221 if (other.unref_) | |
| 222 unref_ = gdk_cursor_ref(other.unref_); | |
| 223 return; | |
| 224 } | |
| 225 | |
| 226 } // namespace content | |
| OLD | NEW |