1 // Copyright (c) 2011 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 "base/logging.h"
6 #include "base/pickle.h"
7 #include "grit/webkit_resources.h"
8 #include "third_party/skia/include/core/SkBitmap.h"
9 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
10 #include "ui/gfx/gdi_util.h"
11 #include "webkit/glue/webcursor.h"
12
13 using WebKit::WebCursorInfo;
14
ToCursorID(WebCursorInfo::Type type)15 static LPCWSTR ToCursorID(WebCursorInfo::Type type) {
16 switch (type) {
17 case WebCursorInfo::TypePointer:
18 return IDC_ARROW;
19 case WebCursorInfo::TypeCross:
20 return IDC_CROSS;
21 case WebCursorInfo::TypeHand:
22 return IDC_HAND;
23 case WebCursorInfo::TypeIBeam:
24 return IDC_IBEAM;
25 case WebCursorInfo::TypeWait:
26 return IDC_WAIT;
27 case WebCursorInfo::TypeHelp:
28 return IDC_HELP;
29 case WebCursorInfo::TypeEastResize:
30 return IDC_SIZEWE;
31 case WebCursorInfo::TypeNorthResize:
32 return IDC_SIZENS;
33 case WebCursorInfo::TypeNorthEastResize:
34 return IDC_SIZENESW;
35 case WebCursorInfo::TypeNorthWestResize:
36 return IDC_SIZENWSE;
37 case WebCursorInfo::TypeSouthResize:
38 return IDC_SIZENS;
39 case WebCursorInfo::TypeSouthEastResize:
40 return IDC_SIZENWSE;
41 case WebCursorInfo::TypeSouthWestResize:
42 return IDC_SIZENESW;
43 case WebCursorInfo::TypeWestResize:
44 return IDC_SIZEWE;
45 case WebCursorInfo::TypeNorthSouthResize:
46 return IDC_SIZENS;
47 case WebCursorInfo::TypeEastWestResize:
48 return IDC_SIZEWE;
49 case WebCursorInfo::TypeNorthEastSouthWestResize:
50 return IDC_SIZENESW;
51 case WebCursorInfo::TypeNorthWestSouthEastResize:
52 return IDC_SIZENWSE;
53 case WebCursorInfo::TypeColumnResize:
54 return MAKEINTRESOURCE(IDC_COLRESIZE);
55 case WebCursorInfo::TypeRowResize:
56 return MAKEINTRESOURCE(IDC_ROWRESIZE);
57 case WebCursorInfo::TypeMiddlePanning:
58 return MAKEINTRESOURCE(IDC_PAN_MIDDLE);
59 case WebCursorInfo::TypeEastPanning:
60 return MAKEINTRESOURCE(IDC_PAN_EAST);
61 case WebCursorInfo::TypeNorthPanning:
62 return MAKEINTRESOURCE(IDC_PAN_NORTH);
63 case WebCursorInfo::TypeNorthEastPanning:
64 return MAKEINTRESOURCE(IDC_PAN_NORTH_EAST);
65 case WebCursorInfo::TypeNorthWestPanning:
66 return MAKEINTRESOURCE(IDC_PAN_NORTH_WEST);
67 case WebCursorInfo::TypeSouthPanning:
68 return MAKEINTRESOURCE(IDC_PAN_SOUTH);
69 case WebCursorInfo::TypeSouthEastPanning:
70 return MAKEINTRESOURCE(IDC_PAN_SOUTH_EAST);
71 case WebCursorInfo::TypeSouthWestPanning:
72 return MAKEINTRESOURCE(IDC_PAN_SOUTH_WEST);
73 case WebCursorInfo::TypeWestPanning:
74 return MAKEINTRESOURCE(IDC_PAN_WEST);
75 case WebCursorInfo::TypeMove:
76 return IDC_SIZEALL;
77 case WebCursorInfo::TypeVerticalText:
78 return MAKEINTRESOURCE(IDC_VERTICALTEXT);
79 case WebCursorInfo::TypeCell:
80 return MAKEINTRESOURCE(IDC_CELL);
81 case WebCursorInfo::TypeContextMenu:
82 return MAKEINTRESOURCE(IDC_ARROW);
83 case WebCursorInfo::TypeAlias:
84 return MAKEINTRESOURCE(IDC_ALIAS);
85 case WebCursorInfo::TypeProgress:
86 return IDC_APPSTARTING;
87 case WebCursorInfo::TypeNoDrop:
88 return IDC_NO;
89 case WebCursorInfo::TypeCopy:
90 return MAKEINTRESOURCE(IDC_COPYCUR);
91 case WebCursorInfo::TypeNone:
92 return IDC_ARROW;
93 case WebCursorInfo::TypeNotAllowed:
94 return IDC_NO;
95 case WebCursorInfo::TypeZoomIn:
96 return MAKEINTRESOURCE(IDC_ZOOMIN);
97 case WebCursorInfo::TypeZoomOut:
98 return MAKEINTRESOURCE(IDC_ZOOMOUT);
99 // TODO(avi): get cursor images for grab/grabbing
100 // http://crbug.com/74699
101 case WebCursorInfo::TypeGrab:
102 case WebCursorInfo::TypeGrabbing:
103 return IDC_ARROW;
104 }
105 NOTREACHED();
106 return NULL;
107 }
108
IsSystemCursorID(LPCWSTR cursor_id)109 static bool IsSystemCursorID(LPCWSTR cursor_id) {
110 return cursor_id >= IDC_ARROW; // See WinUser.h
111 }
112
ToCursorType(HCURSOR cursor)113 static WebCursorInfo::Type ToCursorType(HCURSOR cursor) {
114 static struct {
115 HCURSOR cursor;
116 WebCursorInfo::Type type;
117 } kStandardCursors[] = {
118 { LoadCursor(NULL, IDC_ARROW), WebCursorInfo::TypePointer },
119 { LoadCursor(NULL, IDC_CROSS), WebCursorInfo::TypeCross },
120 { LoadCursor(NULL, IDC_HAND), WebCursorInfo::TypeHand },
121 { LoadCursor(NULL, IDC_IBEAM), WebCursorInfo::TypeIBeam },
122 { LoadCursor(NULL, IDC_WAIT), WebCursorInfo::TypeWait },
123 { LoadCursor(NULL, IDC_HELP), WebCursorInfo::TypeHelp },
124 { LoadCursor(NULL, IDC_SIZENESW), WebCursorInfo::TypeNorthEastResize },
125 { LoadCursor(NULL, IDC_SIZENWSE), WebCursorInfo::TypeNorthWestResize },
126 { LoadCursor(NULL, IDC_SIZENS), WebCursorInfo::TypeNorthSouthResize },
127 { LoadCursor(NULL, IDC_SIZEWE), WebCursorInfo::TypeEastWestResize },
128 { LoadCursor(NULL, IDC_SIZEALL), WebCursorInfo::TypeMove },
129 { LoadCursor(NULL, IDC_APPSTARTING), WebCursorInfo::TypeProgress },
130 { LoadCursor(NULL, IDC_NO), WebCursorInfo::TypeNotAllowed },
131 };
132 for (int i = 0; i < arraysize(kStandardCursors); i++) {
133 if (cursor == kStandardCursors[i].cursor)
134 return kStandardCursors[i].type;
135 }
136 return WebCursorInfo::TypeCustom;
137 }
138
GetCursor(HINSTANCE module_handle)139 HCURSOR WebCursor::GetCursor(HINSTANCE module_handle){
140 if (!IsCustom()) {
141 const wchar_t* cursor_id =
142 ToCursorID(static_cast<WebCursorInfo::Type>(type_));
143
144 if (IsSystemCursorID(cursor_id))
145 module_handle = NULL;
146
147 return LoadCursor(module_handle, cursor_id);
148 }
149
150 if (custom_cursor_) {
151 DCHECK(external_cursor_ == NULL);
152 return custom_cursor_;
153 }
154
155 if (external_cursor_)
156 return external_cursor_;
157
158 BITMAPINFO cursor_bitmap_info = {0};
159 gfx::CreateBitmapHeader(
160 custom_size_.width(), custom_size_.height(),
161 reinterpret_cast<BITMAPINFOHEADER*>(&cursor_bitmap_info));
162 HDC dc = GetDC(0);
163 HDC workingDC = CreateCompatibleDC(dc);
164 HBITMAP bitmap_handle = CreateDIBSection(
165 dc, &cursor_bitmap_info, DIB_RGB_COLORS, 0, 0, 0);
166 if (!custom_data_.empty())
167 SetDIBits(
168 0, bitmap_handle, 0, custom_size_.height(), &custom_data_[0],
169 &cursor_bitmap_info, DIB_RGB_COLORS);
170
171 HBITMAP old_bitmap = reinterpret_cast<HBITMAP>(
172 SelectObject(workingDC, bitmap_handle));
173 SetBkMode(workingDC, TRANSPARENT);
174 SelectObject(workingDC, old_bitmap);
175
176 HBITMAP mask = CreateBitmap(
177 custom_size_.width(), custom_size_.height(), 1, 1, NULL);
178 ICONINFO ii = {0};
179 ii.fIcon = FALSE;
180 ii.xHotspot = hotspot_.x();
181 ii.yHotspot = hotspot_.y();
182 ii.hbmMask = mask;
183 ii.hbmColor = bitmap_handle;
184
185 custom_cursor_ = CreateIconIndirect(&ii);
186
187 DeleteObject(mask);
188 DeleteObject(bitmap_handle);
189 DeleteDC(workingDC);
190 ReleaseDC(0, dc);
191 return custom_cursor_;
192 }
193
GetNativeCursor()194 gfx::NativeCursor WebCursor::GetNativeCursor() {
195 return GetCursor(NULL);
196 }
197
InitFromExternalCursor(HCURSOR cursor)198 void WebCursor::InitFromExternalCursor(HCURSOR cursor) {
199 WebCursorInfo::Type cursor_type = ToCursorType(cursor);
200
201 InitFromCursorInfo(WebCursorInfo(cursor_type));
202
203 if (cursor_type == WebCursorInfo::TypeCustom)
204 external_cursor_ = cursor;
205 }
206
InitPlatformData()207 void WebCursor::InitPlatformData() {
208 external_cursor_ = NULL;
209 custom_cursor_ = NULL;
210 }
211
SerializePlatformData(Pickle * pickle) const212 bool WebCursor::SerializePlatformData(Pickle* pickle) const {
213 // There are some issues with converting certain HCURSORS to bitmaps. The
214 // HCURSOR being a user object can be marshaled as is.
215 // HCURSORs are always 32 bits on Windows, even on 64 bit systems.
216 return pickle->WriteUInt32(reinterpret_cast<uint32>(external_cursor_));
217 }
218
DeserializePlatformData(const Pickle * pickle,void ** iter)219 bool WebCursor::DeserializePlatformData(const Pickle* pickle, void** iter) {
220 return pickle->ReadUInt32(iter, reinterpret_cast<uint32*>(&external_cursor_));
221 }
222
IsPlatformDataEqual(const WebCursor & other) const223 bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const {
224 if (!IsCustom())
225 return true;
226
227 return (external_cursor_ == other.external_cursor_);
228 }
229
CopyPlatformData(const WebCursor & other)230 void WebCursor::CopyPlatformData(const WebCursor& other) {
231 external_cursor_ = other.external_cursor_;
232 // The custom_cursor_ member will be initialized to a HCURSOR the next time
233 // the GetCursor member function is invoked on this WebCursor instance. The
234 // cursor is created using the data in the custom_data_ vector.
235 custom_cursor_ = NULL;
236 }
237
CleanupPlatformData()238 void WebCursor::CleanupPlatformData() {
239 external_cursor_ = NULL;
240
241 if (custom_cursor_) {
242 DestroyIcon(custom_cursor_);
243 custom_cursor_ = NULL;
244 }
245 }
246