Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: webkit/glue/webcursor_mac.mm

Issue 15971005: Move the WebCursor sources from webkit/glue to webkit/common/cursors. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/glue/webcursor_gtk_data.h ('k') | webkit/glue/webcursor_null.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 "webkit/glue/webcursor.h"
6
7 #import <AppKit/AppKit.h>
8
9 #include "base/logging.h"
10 #include "base/mac/mac_util.h"
11 #include "base/mac/scoped_cftyperef.h"
12 #include "base/memory/scoped_nsobject.h"
13 #include "grit/webkit_chromium_resources.h"
14 #include "skia/ext/skia_utils_mac.h"
15 #include "third_party/WebKit/public/platform/WebImage.h"
16 #include "third_party/WebKit/public/platform/WebSize.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
18 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/gfx/point_conversions.h"
20 #include "ui/gfx/size_conversions.h"
21
22
23 using WebKit::WebCursorInfo;
24 using WebKit::WebImage;
25 using WebKit::WebSize;
26
27 // Declare symbols that are part of the 10.7 SDK.
28 #if !defined(MAC_OS_X_VERSION_10_7) || \
29 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
30
31 @interface NSCursor (LionSDKDeclarations)
32 + (NSCursor*)IBeamCursorForVerticalLayout;
33 @end
34
35 #endif // MAC_OS_X_VERSION_10_7
36
37 // Private interface to CoreCursor, as of Mac OS X 10.7. This is essentially the
38 // implementation of WKCursor in WebKitSystemInterface.
39
40 enum {
41 kArrowCursor = 0,
42 kIBeamCursor = 1,
43 kMakeAliasCursor = 2,
44 kOperationNotAllowedCursor = 3,
45 kBusyButClickableCursor = 4,
46 kCopyCursor = 5,
47 kClosedHandCursor = 11,
48 kOpenHandCursor = 12,
49 kPointingHandCursor = 13,
50 kCountingUpHandCursor = 14,
51 kCountingDownHandCursor = 15,
52 kCountingUpAndDownHandCursor = 16,
53 kResizeLeftCursor = 17,
54 kResizeRightCursor = 18,
55 kResizeLeftRightCursor = 19,
56 kCrosshairCursor = 20,
57 kResizeUpCursor = 21,
58 kResizeDownCursor = 22,
59 kResizeUpDownCursor = 23,
60 kContextualMenuCursor = 24,
61 kDisappearingItemCursor = 25,
62 kVerticalIBeamCursor = 26,
63 kResizeEastCursor = 27,
64 kResizeEastWestCursor = 28,
65 kResizeNortheastCursor = 29,
66 kResizeNortheastSouthwestCursor = 30,
67 kResizeNorthCursor = 31,
68 kResizeNorthSouthCursor = 32,
69 kResizeNorthwestCursor = 33,
70 kResizeNorthwestSoutheastCursor = 34,
71 kResizeSoutheastCursor = 35,
72 kResizeSouthCursor = 36,
73 kResizeSouthwestCursor = 37,
74 kResizeWestCursor = 38,
75 kMoveCursor = 39,
76 kHelpCursor = 40, // Present on >= 10.7.3.
77 kCellCursor = 41, // Present on >= 10.7.3.
78 kZoomInCursor = 42, // Present on >= 10.7.3.
79 kZoomOutCursor = 43 // Present on >= 10.7.3.
80 };
81 typedef long long CrCoreCursorType;
82
83 @interface CrCoreCursor : NSCursor {
84 @private
85 CrCoreCursorType type_;
86 }
87
88 + (id)cursorWithType:(CrCoreCursorType)type;
89 - (id)initWithType:(CrCoreCursorType)type;
90 - (CrCoreCursorType)_coreCursorType;
91
92 @end
93
94 @implementation CrCoreCursor
95
96 + (id)cursorWithType:(CrCoreCursorType)type {
97 NSCursor* cursor = [[CrCoreCursor alloc] initWithType:type];
98 if ([cursor image])
99 return [cursor autorelease];
100
101 [cursor release];
102 return nil;
103 }
104
105 - (id)initWithType:(CrCoreCursorType)type {
106 if ((self = [super init])) {
107 type_ = type;
108 }
109 return self;
110 }
111
112 - (CrCoreCursorType)_coreCursorType {
113 return type_;
114 }
115
116 @end
117
118 namespace {
119
120 NSCursor* LoadCursor(int resource_id, int hotspot_x, int hotspot_y) {
121 const gfx::Image& cursor_image =
122 ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id);
123 DCHECK(!cursor_image.IsEmpty());
124 return [[[NSCursor alloc] initWithImage:cursor_image.ToNSImage()
125 hotSpot:NSMakePoint(hotspot_x,
126 hotspot_y)] autorelease];
127 }
128
129 // Gets a specified cursor from CoreCursor, falling back to loading it from the
130 // image cache if CoreCursor cannot provide it.
131 NSCursor* GetCoreCursorWithFallback(CrCoreCursorType type,
132 int resource_id,
133 int hotspot_x,
134 int hotspot_y) {
135 if (base::mac::IsOSLionOrLater()) {
136 NSCursor* cursor = [CrCoreCursor cursorWithType:type];
137 if (cursor)
138 return cursor;
139 }
140
141 return LoadCursor(resource_id, hotspot_x, hotspot_y);
142 }
143
144 // TODO(avi): When Skia becomes default, fold this function into the remaining
145 // caller, InitFromCursor().
146 CGImageRef CreateCGImageFromCustomData(const std::vector<char>& custom_data,
147 const gfx::Size& custom_size) {
148 // If the data is missing, leave the backing transparent.
149 void* data = NULL;
150 if (!custom_data.empty()) {
151 // This is safe since we're not going to draw into the context we're
152 // creating.
153 data = const_cast<char*>(&custom_data[0]);
154 }
155
156 // If the size is empty, use a 1x1 transparent image.
157 gfx::Size size = custom_size;
158 if (size.IsEmpty()) {
159 size.SetSize(1, 1);
160 data = NULL;
161 }
162
163 base::mac::ScopedCFTypeRef<CGColorSpaceRef> cg_color(
164 CGColorSpaceCreateDeviceRGB());
165 // The settings here match SetCustomData() below; keep in sync.
166 base::mac::ScopedCFTypeRef<CGContextRef> context(
167 CGBitmapContextCreate(data,
168 size.width(),
169 size.height(),
170 8,
171 size.width()*4,
172 cg_color.get(),
173 kCGImageAlphaPremultipliedLast |
174 kCGBitmapByteOrder32Big));
175 return CGBitmapContextCreateImage(context.get());
176 }
177
178 NSCursor* CreateCustomCursor(const std::vector<char>& custom_data,
179 const gfx::Size& custom_size,
180 float custom_scale,
181 const gfx::Point& hotspot) {
182 // If the data is missing, leave the backing transparent.
183 void* data = NULL;
184 size_t data_size = 0;
185 if (!custom_data.empty()) {
186 // This is safe since we're not going to draw into the context we're
187 // creating.
188 data = const_cast<char*>(&custom_data[0]);
189 data_size = custom_data.size();
190 }
191
192 // If the size is empty, use a 1x1 transparent image.
193 gfx::Size size = custom_size;
194 if (size.IsEmpty()) {
195 size.SetSize(1, 1);
196 data = NULL;
197 }
198
199 SkBitmap bitmap;
200 bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
201 bitmap.allocPixels();
202 if (data)
203 memcpy(bitmap.getAddr32(0, 0), data, data_size);
204 else
205 bitmap.eraseARGB(0, 0, 0, 0);
206
207 // Convert from pixels to view units.
208 if (custom_scale == 0)
209 custom_scale = 1;
210 NSSize dip_size = NSSizeFromCGSize(gfx::ToFlooredSize(
211 gfx::ScaleSize(custom_size, 1 / custom_scale)).ToCGSize());
212 NSPoint dip_hotspot = NSPointFromCGPoint(gfx::ToFlooredPoint(
213 gfx::ScalePoint(hotspot, 1 / custom_scale)).ToCGPoint());
214
215 NSImage* cursor_image = gfx::SkBitmapToNSImage(bitmap);
216 [cursor_image setSize:dip_size];
217
218 NSCursor* cursor = [[NSCursor alloc] initWithImage:cursor_image
219 hotSpot:dip_hotspot];
220
221 return [cursor autorelease];
222 }
223
224 } // namespace
225
226 // Match Safari's cursor choices; see platform/mac/CursorMac.mm .
227 gfx::NativeCursor WebCursor::GetNativeCursor() {
228 switch (type_) {
229 case WebCursorInfo::TypePointer:
230 return [NSCursor arrowCursor];
231 case WebCursorInfo::TypeCross:
232 return [NSCursor crosshairCursor];
233 case WebCursorInfo::TypeHand:
234 // If >= 10.7, the pointingHandCursor has a shadow so use it. Otherwise
235 // use the custom one.
236 if (base::mac::IsOSLionOrLater())
237 return [NSCursor pointingHandCursor];
238 else
239 return LoadCursor(IDR_LINK_CURSOR, 6, 1);
240 case WebCursorInfo::TypeIBeam:
241 return [NSCursor IBeamCursor];
242 case WebCursorInfo::TypeWait:
243 return GetCoreCursorWithFallback(kBusyButClickableCursor,
244 IDR_WAIT_CURSOR, 7, 7);
245 case WebCursorInfo::TypeHelp:
246 return GetCoreCursorWithFallback(kHelpCursor,
247 IDR_HELP_CURSOR, 8, 8);
248 case WebCursorInfo::TypeEastResize:
249 case WebCursorInfo::TypeEastPanning:
250 return GetCoreCursorWithFallback(kResizeEastCursor,
251 IDR_EAST_RESIZE_CURSOR, 14, 7);
252 case WebCursorInfo::TypeNorthResize:
253 case WebCursorInfo::TypeNorthPanning:
254 return GetCoreCursorWithFallback(kResizeNorthCursor,
255 IDR_NORTH_RESIZE_CURSOR, 7, 1);
256 case WebCursorInfo::TypeNorthEastResize:
257 case WebCursorInfo::TypeNorthEastPanning:
258 return GetCoreCursorWithFallback(kResizeNortheastCursor,
259 IDR_NORTHEAST_RESIZE_CURSOR, 14, 1);
260 case WebCursorInfo::TypeNorthWestResize:
261 case WebCursorInfo::TypeNorthWestPanning:
262 return GetCoreCursorWithFallback(kResizeNorthwestCursor,
263 IDR_NORTHWEST_RESIZE_CURSOR, 0, 0);
264 case WebCursorInfo::TypeSouthResize:
265 case WebCursorInfo::TypeSouthPanning:
266 return GetCoreCursorWithFallback(kResizeSouthCursor,
267 IDR_SOUTH_RESIZE_CURSOR, 7, 14);
268 case WebCursorInfo::TypeSouthEastResize:
269 case WebCursorInfo::TypeSouthEastPanning:
270 return GetCoreCursorWithFallback(kResizeSoutheastCursor,
271 IDR_SOUTHEAST_RESIZE_CURSOR, 14, 14);
272 case WebCursorInfo::TypeSouthWestResize:
273 case WebCursorInfo::TypeSouthWestPanning:
274 return GetCoreCursorWithFallback(kResizeSouthwestCursor,
275 IDR_SOUTHWEST_RESIZE_CURSOR, 1, 14);
276 case WebCursorInfo::TypeWestResize:
277 case WebCursorInfo::TypeWestPanning:
278 return GetCoreCursorWithFallback(kResizeWestCursor,
279 IDR_WEST_RESIZE_CURSOR, 1, 7);
280 case WebCursorInfo::TypeNorthSouthResize:
281 return GetCoreCursorWithFallback(kResizeNorthSouthCursor,
282 IDR_NORTHSOUTH_RESIZE_CURSOR, 7, 7);
283 case WebCursorInfo::TypeEastWestResize:
284 return GetCoreCursorWithFallback(kResizeEastWestCursor,
285 IDR_EASTWEST_RESIZE_CURSOR, 7, 7);
286 case WebCursorInfo::TypeNorthEastSouthWestResize:
287 return GetCoreCursorWithFallback(kResizeNortheastSouthwestCursor,
288 IDR_NORTHEASTSOUTHWEST_RESIZE_CURSOR,
289 7, 7);
290 case WebCursorInfo::TypeNorthWestSouthEastResize:
291 return GetCoreCursorWithFallback(kResizeNorthwestSoutheastCursor,
292 IDR_NORTHWESTSOUTHEAST_RESIZE_CURSOR,
293 7, 7);
294 case WebCursorInfo::TypeColumnResize:
295 return [NSCursor resizeLeftRightCursor];
296 case WebCursorInfo::TypeRowResize:
297 return [NSCursor resizeUpDownCursor];
298 case WebCursorInfo::TypeMiddlePanning:
299 case WebCursorInfo::TypeMove:
300 return GetCoreCursorWithFallback(kMoveCursor,
301 IDR_MOVE_CURSOR, 7, 7);
302 case WebCursorInfo::TypeVerticalText:
303 // IBeamCursorForVerticalLayout is >= 10.7.
304 if ([NSCursor respondsToSelector:@selector(IBeamCursorForVerticalLayout)])
305 return [NSCursor IBeamCursorForVerticalLayout];
306 else
307 return LoadCursor(IDR_VERTICALTEXT_CURSOR, 7, 7);
308 case WebCursorInfo::TypeCell:
309 return GetCoreCursorWithFallback(kCellCursor,
310 IDR_CELL_CURSOR, 7, 7);
311 case WebCursorInfo::TypeContextMenu:
312 return [NSCursor contextualMenuCursor];
313 case WebCursorInfo::TypeAlias:
314 return GetCoreCursorWithFallback(kMakeAliasCursor,
315 IDR_ALIAS_CURSOR, 11, 3);
316 case WebCursorInfo::TypeProgress:
317 return GetCoreCursorWithFallback(kBusyButClickableCursor,
318 IDR_PROGRESS_CURSOR, 3, 2);
319 case WebCursorInfo::TypeNoDrop:
320 case WebCursorInfo::TypeNotAllowed:
321 return [NSCursor operationNotAllowedCursor];
322 case WebCursorInfo::TypeCopy:
323 return [NSCursor dragCopyCursor];
324 case WebCursorInfo::TypeNone:
325 return LoadCursor(IDR_NONE_CURSOR, 7, 7);
326 case WebCursorInfo::TypeZoomIn:
327 return GetCoreCursorWithFallback(kZoomInCursor,
328 IDR_ZOOMIN_CURSOR, 7, 7);
329 case WebCursorInfo::TypeZoomOut:
330 return GetCoreCursorWithFallback(kZoomOutCursor,
331 IDR_ZOOMOUT_CURSOR, 7, 7);
332 case WebCursorInfo::TypeGrab:
333 return [NSCursor openHandCursor];
334 case WebCursorInfo::TypeGrabbing:
335 return [NSCursor closedHandCursor];
336 case WebCursorInfo::TypeCustom:
337 return CreateCustomCursor(
338 custom_data_, custom_size_, custom_scale_, hotspot_);
339 }
340 NOTREACHED();
341 return nil;
342 }
343
344 void WebCursor::InitFromNSCursor(NSCursor* cursor) {
345 CursorInfo cursor_info;
346
347 if ([cursor isEqual:[NSCursor arrowCursor]]) {
348 cursor_info.type = WebCursorInfo::TypePointer;
349 } else if ([cursor isEqual:[NSCursor IBeamCursor]]) {
350 cursor_info.type = WebCursorInfo::TypeIBeam;
351 } else if ([cursor isEqual:[NSCursor crosshairCursor]]) {
352 cursor_info.type = WebCursorInfo::TypeCross;
353 } else if ([cursor isEqual:[NSCursor pointingHandCursor]]) {
354 cursor_info.type = WebCursorInfo::TypeHand;
355 } else if ([cursor isEqual:[NSCursor resizeLeftCursor]]) {
356 cursor_info.type = WebCursorInfo::TypeWestResize;
357 } else if ([cursor isEqual:[NSCursor resizeRightCursor]]) {
358 cursor_info.type = WebCursorInfo::TypeEastResize;
359 } else if ([cursor isEqual:[NSCursor resizeLeftRightCursor]]) {
360 cursor_info.type = WebCursorInfo::TypeEastWestResize;
361 } else if ([cursor isEqual:[NSCursor resizeUpCursor]]) {
362 cursor_info.type = WebCursorInfo::TypeNorthResize;
363 } else if ([cursor isEqual:[NSCursor resizeDownCursor]]) {
364 cursor_info.type = WebCursorInfo::TypeSouthResize;
365 } else if ([cursor isEqual:[NSCursor resizeUpDownCursor]]) {
366 cursor_info.type = WebCursorInfo::TypeNorthSouthResize;
367 } else if ([cursor isEqual:[NSCursor openHandCursor]]) {
368 cursor_info.type = WebCursorInfo::TypeGrab;
369 } else if ([cursor isEqual:[NSCursor closedHandCursor]]) {
370 cursor_info.type = WebCursorInfo::TypeGrabbing;
371 } else if ([cursor isEqual:[NSCursor operationNotAllowedCursor]]) {
372 cursor_info.type = WebCursorInfo::TypeNotAllowed;
373 } else if ([cursor isEqual:[NSCursor dragCopyCursor]]) {
374 cursor_info.type = WebCursorInfo::TypeCopy;
375 } else if ([cursor isEqual:[NSCursor contextualMenuCursor]]) {
376 cursor_info.type = WebCursorInfo::TypeContextMenu;
377 } else if (
378 [NSCursor respondsToSelector:@selector(IBeamCursorForVerticalLayout)] &&
379 [cursor isEqual:[NSCursor IBeamCursorForVerticalLayout]]) {
380 cursor_info.type = WebCursorInfo::TypeVerticalText;
381 } else {
382 // Also handles the [NSCursor disappearingItemCursor] case. Quick-and-dirty
383 // image conversion; TODO(avi): do better.
384 CGImageRef cg_image = nil;
385 NSImage* image = [cursor image];
386 for (id rep in [image representations]) {
387 if ([rep isKindOfClass:[NSBitmapImageRep class]]) {
388 cg_image = [rep CGImage];
389 break;
390 }
391 }
392
393 if (cg_image) {
394 cursor_info.type = WebCursorInfo::TypeCustom;
395 NSPoint hot_spot = [cursor hotSpot];
396 cursor_info.hotspot = gfx::Point(hot_spot.x, hot_spot.y);
397 cursor_info.custom_image = gfx::CGImageToSkBitmap(cg_image);
398 } else {
399 cursor_info.type = WebCursorInfo::TypePointer;
400 }
401 }
402
403 InitFromCursorInfo(cursor_info);
404 }
405
406 void WebCursor::InitPlatformData() {
407 return;
408 }
409
410 bool WebCursor::SerializePlatformData(Pickle* pickle) const {
411 return true;
412 }
413
414 bool WebCursor::DeserializePlatformData(PickleIterator* iter) {
415 return true;
416 }
417
418 bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const {
419 return true;
420 }
421
422 void WebCursor::CleanupPlatformData() {
423 return;
424 }
425
426 void WebCursor::CopyPlatformData(const WebCursor& other) {
427 return;
428 }
OLDNEW
« no previous file with comments | « webkit/glue/webcursor_gtk_data.h ('k') | webkit/glue/webcursor_null.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698