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 |