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.
5 #include "webkit/common/cursors/webcursor.h"
10 #include "base/logging.h"
11 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
12 #include "ui/gfx/gtk_util.h"
14 using blink::WebCursorInfo
;
18 // webcursor_gtk_data.h is taken directly from WebKit's CursorGtk.h.
19 #include "webkit/common/cursors/webcursor_gtk_data.h"
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
];
29 const CustomCursor
& custom
= CustomCursors
[type
];
30 cursor
= gdk_cursor_new_from_name(gdk_display_get_default(), custom
.name
);
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
);
43 CustomCursorsGdk
[type
] = cursor
;
47 } // end anonymous namespace
49 int WebCursor::GetCursorType() const {
50 // http://library.gnome.org/devel/gdk/2.12/gdk-Cursors.html has images
51 // of the default X theme, but beware that the user's cursor theme can
54 case WebCursorInfo::TypePointer
:
55 return GDK_LAST_CURSOR
;
56 case WebCursorInfo::TypeCross
:
58 case WebCursorInfo::TypeHand
:
60 case WebCursorInfo::TypeIBeam
:
62 case WebCursorInfo::TypeWait
:
64 case WebCursorInfo::TypeHelp
:
65 return GDK_QUESTION_ARROW
;
66 case WebCursorInfo::TypeEastResize
:
67 return GDK_RIGHT_SIDE
;
68 case WebCursorInfo::TypeNorthResize
:
70 case WebCursorInfo::TypeNorthEastResize
:
71 return GDK_TOP_RIGHT_CORNER
;
72 case WebCursorInfo::TypeNorthWestResize
:
73 return GDK_TOP_LEFT_CORNER
;
74 case WebCursorInfo::TypeSouthResize
:
75 return GDK_BOTTOM_SIDE
;
76 case WebCursorInfo::TypeSouthEastResize
:
77 return GDK_BOTTOM_RIGHT_CORNER
;
78 case WebCursorInfo::TypeSouthWestResize
:
79 return GDK_BOTTOM_LEFT_CORNER
;
80 case WebCursorInfo::TypeWestResize
:
82 case WebCursorInfo::TypeNorthSouthResize
:
83 return GDK_SB_V_DOUBLE_ARROW
;
84 case WebCursorInfo::TypeEastWestResize
:
85 return GDK_SB_H_DOUBLE_ARROW
;
86 case WebCursorInfo::TypeNorthEastSouthWestResize
:
87 case WebCursorInfo::TypeNorthWestSouthEastResize
:
88 // There isn't really a useful cursor available for these.
89 return GDK_LAST_CURSOR
;
90 case WebCursorInfo::TypeColumnResize
:
91 return GDK_SB_H_DOUBLE_ARROW
; // TODO(evanm): is this correct?
92 case WebCursorInfo::TypeRowResize
:
93 return GDK_SB_V_DOUBLE_ARROW
; // TODO(evanm): is this correct?
94 case WebCursorInfo::TypeMiddlePanning
:
96 case WebCursorInfo::TypeEastPanning
:
97 return GDK_SB_RIGHT_ARROW
;
98 case WebCursorInfo::TypeNorthPanning
:
99 return GDK_SB_UP_ARROW
;
100 case WebCursorInfo::TypeNorthEastPanning
:
101 return GDK_TOP_RIGHT_CORNER
;
102 case WebCursorInfo::TypeNorthWestPanning
:
103 return GDK_TOP_LEFT_CORNER
;
104 case WebCursorInfo::TypeSouthPanning
:
105 return GDK_SB_DOWN_ARROW
;
106 case WebCursorInfo::TypeSouthEastPanning
:
107 return GDK_BOTTOM_RIGHT_CORNER
;
108 case WebCursorInfo::TypeSouthWestPanning
:
109 return GDK_BOTTOM_LEFT_CORNER
;
110 case WebCursorInfo::TypeWestPanning
:
111 return GDK_SB_LEFT_ARROW
;
112 case WebCursorInfo::TypeMove
:
114 case WebCursorInfo::TypeVerticalText
:
115 return GDK_LAST_CURSOR
;
116 case WebCursorInfo::TypeCell
:
117 return GDK_LAST_CURSOR
;
118 case WebCursorInfo::TypeContextMenu
:
119 return GDK_LAST_CURSOR
;
120 case WebCursorInfo::TypeAlias
:
121 return GDK_LAST_CURSOR
;
122 case WebCursorInfo::TypeProgress
:
124 case WebCursorInfo::TypeNoDrop
:
125 return GDK_LAST_CURSOR
;
126 case WebCursorInfo::TypeCopy
:
127 return GDK_LAST_CURSOR
;
128 case WebCursorInfo::TypeNone
:
129 return GDK_BLANK_CURSOR
;
130 case WebCursorInfo::TypeNotAllowed
:
131 return GDK_LAST_CURSOR
;
132 case WebCursorInfo::TypeZoomIn
:
133 case WebCursorInfo::TypeZoomOut
:
134 case WebCursorInfo::TypeGrab
:
135 case WebCursorInfo::TypeGrabbing
:
136 case WebCursorInfo::TypeCustom
:
137 return GDK_CURSOR_IS_PIXMAP
;
140 return GDK_LAST_CURSOR
;
143 gfx::NativeCursor
WebCursor::GetNativeCursor() {
144 int type
= GetCursorType();
145 if (type
== GDK_CURSOR_IS_PIXMAP
)
146 return GetCustomCursor();
147 return gfx::GetCursor(type
);
150 GdkCursor
* WebCursor::GetCustomCursor() {
152 case WebCursorInfo::TypeZoomIn
:
153 return GetInlineCustomCursor(CustomCursorZoomIn
);
154 case WebCursorInfo::TypeZoomOut
:
155 return GetInlineCustomCursor(CustomCursorZoomOut
);
156 case WebCursorInfo::TypeGrab
:
157 return GetInlineCustomCursor(CustomCursorGrab
);
158 case WebCursorInfo::TypeGrabbing
:
159 return GetInlineCustomCursor(CustomCursorGrabbing
);
162 if (type_
!= WebCursorInfo::TypeCustom
) {
167 if (custom_size_
.width() == 0 || custom_size_
.height() == 0) {
168 // Some websites specify cursor images that are 0 sized, such as Bing Maps.
169 // Don't crash on this; just use the default cursor.
174 bitmap
.setConfig(SkBitmap::kARGB_8888_Config
,
175 custom_size_
.width(), custom_size_
.height());
176 bitmap
.allocPixels();
177 memcpy(bitmap
.getAddr32(0, 0), custom_data_
.data(), custom_data_
.size());
179 GdkPixbuf
* pixbuf
= gfx::GdkPixbufFromSkBitmap(bitmap
);
180 GdkCursor
* cursor
= gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
185 g_object_unref(pixbuf
);
188 gdk_cursor_unref(unref_
);
193 void WebCursor::InitPlatformData() {
198 bool WebCursor::SerializePlatformData(Pickle
* pickle
) const {
202 bool WebCursor::DeserializePlatformData(PickleIterator
* iter
) {
206 bool WebCursor::IsPlatformDataEqual(const WebCursor
& other
) const {
210 void WebCursor::CleanupPlatformData() {
212 gdk_cursor_unref(unref_
);
218 void WebCursor::CopyPlatformData(const WebCursor
& other
) {
220 unref_
= gdk_cursor_ref(other
.unref_
);