• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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