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

Side by Side Diff: webkit/common/cursors/webcursor_mac.mm

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

Powered by Google App Engine
This is Rietveld 408576698