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

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

Issue 9355017: Merge 122386 - Fix Mac custom cursor color. (Closed) Base URL: svn://svn.chromium.org/chrome/branches/1025/src/
Patch Set: Created 8 years, 10 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.h ('k') | webkit/tools/test_shell/mac/test_webview_delegate.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "webkit/glue/webcursor.h" 5 #include "webkit/glue/webcursor.h"
6 6
7 #import <AppKit/AppKit.h> 7 #import <AppKit/AppKit.h>
8 #include <Carbon/Carbon.h> 8 #include <Carbon/Carbon.h>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/mac/mac_util.h" 11 #include "base/mac/mac_util.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 // resource bundle instead of going through the image cache. 52 // resource bundle instead of going through the image cache.
53 NSCursor* LoadCursor(const char* name, int x, int y) { 53 NSCursor* LoadCursor(const char* name, int x, int y) {
54 NSString* file_name = [NSString stringWithUTF8String:name]; 54 NSString* file_name = [NSString stringWithUTF8String:name];
55 DCHECK(file_name); 55 DCHECK(file_name);
56 NSImage* cursor_image = gfx::GetCachedImageWithName(file_name); 56 NSImage* cursor_image = gfx::GetCachedImageWithName(file_name);
57 DCHECK(cursor_image); 57 DCHECK(cursor_image);
58 return [[[NSCursor alloc] initWithImage:cursor_image 58 return [[[NSCursor alloc] initWithImage:cursor_image
59 hotSpot:NSMakePoint(x, y)] autorelease]; 59 hotSpot:NSMakePoint(x, y)] autorelease];
60 } 60 }
61 61
62 // TODO(avi): When Skia becomes default, fold this function into the remaining
63 // caller, InitFromCursor().
62 CGImageRef CreateCGImageFromCustomData(const std::vector<char>& custom_data, 64 CGImageRef CreateCGImageFromCustomData(const std::vector<char>& custom_data,
63 const gfx::Size& custom_size) { 65 const gfx::Size& custom_size) {
64 // This is safe since we're not going to draw into the context we're creating.
65 // The settings here match SetCustomData() below; keep in sync.
66 // If the data is missing, leave the backing transparent. 66 // If the data is missing, leave the backing transparent.
67 void* data = NULL; 67 void* data = NULL;
68 if (!custom_data.empty()) 68 if (!custom_data.empty()) {
69 // This is safe since we're not going to draw into the context we're
70 // creating.
69 data = const_cast<char*>(&custom_data[0]); 71 data = const_cast<char*>(&custom_data[0]);
72 }
70 73
71 // If the size is empty, use a 1x1 transparent image. 74 // If the size is empty, use a 1x1 transparent image.
72 gfx::Size size = custom_size; 75 gfx::Size size = custom_size;
73 if (size.IsEmpty()) { 76 if (size.IsEmpty()) {
74 size.SetSize(1, 1); 77 size.SetSize(1, 1);
75 data = NULL; 78 data = NULL;
76 } 79 }
77 80
78 base::mac::ScopedCFTypeRef<CGColorSpaceRef> cg_color( 81 base::mac::ScopedCFTypeRef<CGColorSpaceRef> cg_color(
79 CGColorSpaceCreateDeviceRGB()); 82 CGColorSpaceCreateDeviceRGB());
83 // The settings here match SetCustomData() below; keep in sync.
80 base::mac::ScopedCFTypeRef<CGContextRef> context( 84 base::mac::ScopedCFTypeRef<CGContextRef> context(
81 CGBitmapContextCreate(data, 85 CGBitmapContextCreate(data,
82 size.width(), 86 size.width(),
83 size.height(), 87 size.height(),
84 8, 88 8,
85 size.width()*4, 89 size.width()*4,
86 cg_color.get(), 90 cg_color.get(),
87 kCGImageAlphaPremultipliedLast | 91 kCGImageAlphaPremultipliedLast |
88 kCGBitmapByteOrder32Big)); 92 kCGBitmapByteOrder32Big));
89 return CGBitmapContextCreateImage(context.get()); 93 return CGBitmapContextCreateImage(context.get());
90 } 94 }
91 95
92 NSCursor* CreateCustomCursor(const std::vector<char>& custom_data, 96 NSCursor* CreateCustomCursor(const std::vector<char>& custom_data,
93 const gfx::Size& custom_size, 97 const gfx::Size& custom_size,
94 const gfx::Point& hotspot) { 98 const gfx::Point& hotspot) {
99 #if WEBKIT_USING_SKIA
100 // If the data is missing, leave the backing transparent.
101 void* data = NULL;
102 size_t data_size = 0;
103 if (!custom_data.empty()) {
104 // This is safe since we're not going to draw into the context we're
105 // creating.
106 data = const_cast<char*>(&custom_data[0]);
107 data_size = custom_data.size();
108 }
109
110 // If the size is empty, use a 1x1 transparent image.
111 gfx::Size size = custom_size;
112 if (size.IsEmpty()) {
113 size.SetSize(1, 1);
114 data = NULL;
115 }
116
117 SkBitmap bitmap;
118 bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
119 bitmap.allocPixels();
120 if (data)
121 memcpy(bitmap.getAddr32(0, 0), data, data_size);
122 else
123 bitmap.eraseARGB(0, 0, 0, 0);
124 NSImage* cursor_image = gfx::SkBitmapToNSImage(bitmap);
125 #else
95 base::mac::ScopedCFTypeRef<CGImageRef> cg_image( 126 base::mac::ScopedCFTypeRef<CGImageRef> cg_image(
96 CreateCGImageFromCustomData(custom_data, custom_size)); 127 CreateCGImageFromCustomData(custom_data, custom_size));
97 128
98 scoped_nsobject<NSBitmapImageRep> ns_bitmap( 129 scoped_nsobject<NSBitmapImageRep> ns_bitmap(
99 [[NSBitmapImageRep alloc] initWithCGImage:cg_image.get()]); 130 [[NSBitmapImageRep alloc] initWithCGImage:cg_image.get()]);
100 NSImage* cursor_image = [[NSImage alloc] init]; 131 scoped_nsobject<NSImage> cursor_image([[NSImage alloc] init]);
101 DCHECK(cursor_image); 132 DCHECK(cursor_image);
102 [cursor_image addRepresentation:ns_bitmap]; 133 [cursor_image addRepresentation:ns_bitmap];
134 #endif // WEBKIT_USING_SKIA
103 135
104 NSCursor* cursor = [[NSCursor alloc] initWithImage:cursor_image 136 NSCursor* cursor = [[NSCursor alloc] initWithImage:cursor_image
105 hotSpot:NSMakePoint(hotspot.x(), 137 hotSpot:NSMakePoint(hotspot.x(),
106 hotspot.y())]; 138 hotspot.y())];
107 [cursor_image release];
108 139
109 return [cursor autorelease]; 140 return [cursor autorelease];
110 } 141 }
111 142
112 } // namespace 143 } // namespace
113 144
114 // We're (mostly) matching Safari's cursor choices; see 145 // We're (mostly) matching Safari's cursor choices; see
115 // platform/mac/CursorMac.mm . Note that Safari uses some magic in wkCursor to 146 // platform/mac/CursorMac.mm . Note that Safari uses some magic in wkCursor to
116 // access private system cursors. A sample implementation using the same 147 // access private system cursors. A sample implementation using the same
117 // technique can be found attached to http://crbug.com/92892 . However, it's not 148 // technique can be found attached to http://crbug.com/92892 . However, it's not
118 // clear that accessing system cursors this way is enough of a gain to risk 149 // clear that accessing system cursors this way is enough of a gain to risk
119 // using SPIs. Until the benefits more clearly outweigh the risks, API is all 150 // using SPIs. Until the benefits more clearly outweigh the risks, API is all
120 // that will be used. 151 // that will be used.
121 NSCursor* WebCursor::GetCursor() const { 152 gfx::NativeCursor WebCursor::GetNativeCursor() {
122 switch (type_) { 153 switch (type_) {
123 case WebCursorInfo::TypePointer: 154 case WebCursorInfo::TypePointer:
124 return [NSCursor arrowCursor]; 155 return [NSCursor arrowCursor];
125 case WebCursorInfo::TypeCross: 156 case WebCursorInfo::TypeCross:
126 return [NSCursor crosshairCursor]; 157 return [NSCursor crosshairCursor];
127 case WebCursorInfo::TypeHand: 158 case WebCursorInfo::TypeHand:
128 // If >= 10.7, the pointingHandCursor has a shadow so use it. Otherwise 159 // If >= 10.7, the pointingHandCursor has a shadow so use it. Otherwise
129 // use the custom one. 160 // use the custom one.
130 if (base::mac::IsOSLionOrLater()) 161 if (base::mac::IsOSLionOrLater())
131 return [NSCursor pointingHandCursor]; 162 return [NSCursor pointingHandCursor];
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 return [NSCursor openHandCursor]; 247 return [NSCursor openHandCursor];
217 case WebCursorInfo::TypeGrabbing: 248 case WebCursorInfo::TypeGrabbing:
218 return [NSCursor closedHandCursor]; 249 return [NSCursor closedHandCursor];
219 case WebCursorInfo::TypeCustom: 250 case WebCursorInfo::TypeCustom:
220 return CreateCustomCursor(custom_data_, custom_size_, hotspot_); 251 return CreateCustomCursor(custom_data_, custom_size_, hotspot_);
221 } 252 }
222 NOTREACHED(); 253 NOTREACHED();
223 return nil; 254 return nil;
224 } 255 }
225 256
226 gfx::NativeCursor WebCursor::GetNativeCursor() {
227 return GetCursor();
228 }
229
230 void WebCursor::InitFromThemeCursor(ThemeCursor cursor) { 257 void WebCursor::InitFromThemeCursor(ThemeCursor cursor) {
231 WebKit::WebCursorInfo cursor_info; 258 WebKit::WebCursorInfo cursor_info;
232 259
233 switch (cursor) { 260 switch (cursor) {
234 case kThemeArrowCursor: 261 case kThemeArrowCursor:
235 cursor_info.type = WebCursorInfo::TypePointer; 262 cursor_info.type = WebCursorInfo::TypePointer;
236 break; 263 break;
237 case kThemeCopyArrowCursor: 264 case kThemeCopyArrowCursor:
238 cursor_info.type = WebCursorInfo::TypeCopy; 265 cursor_info.type = WebCursorInfo::TypeCopy;
239 break; 266 break;
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 } 357 }
331 } 358 }
332 359
333 base::mac::ScopedCFTypeRef<CGImageRef> cg_image( 360 base::mac::ScopedCFTypeRef<CGImageRef> cg_image(
334 CreateCGImageFromCustomData(raw_data, custom_size)); 361 CreateCGImageFromCustomData(raw_data, custom_size));
335 362
336 WebKit::WebCursorInfo cursor_info; 363 WebKit::WebCursorInfo cursor_info;
337 cursor_info.type = WebCursorInfo::TypeCustom; 364 cursor_info.type = WebCursorInfo::TypeCustom;
338 cursor_info.hotSpot = WebKit::WebPoint(cursor->hotSpot.h, cursor->hotSpot.v); 365 cursor_info.hotSpot = WebKit::WebPoint(cursor->hotSpot.h, cursor->hotSpot.v);
339 #if WEBKIT_USING_SKIA 366 #if WEBKIT_USING_SKIA
367 // TODO(avi): build the cursor image in Skia directly rather than going via
368 // this roundabout path.
340 cursor_info.customImage = gfx::CGImageToSkBitmap(cg_image.get()); 369 cursor_info.customImage = gfx::CGImageToSkBitmap(cg_image.get());
341 #else 370 #else
342 cursor_info.customImage = cg_image.get(); 371 cursor_info.customImage = cg_image.get();
343 #endif 372 #endif
344 373
345 InitFromCursorInfo(cursor_info); 374 InitFromCursorInfo(cursor_info);
346 } 375 }
347 376
348 void WebCursor::InitFromNSCursor(NSCursor* cursor) { 377 void WebCursor::InitFromNSCursor(NSCursor* cursor) {
349 WebKit::WebCursorInfo cursor_info; 378 WebKit::WebCursorInfo cursor_info;
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 } 476 }
448 477
449 void WebCursor::ImageFromCustomData(WebImage* image) const { 478 void WebCursor::ImageFromCustomData(WebImage* image) const {
450 if (custom_data_.empty()) 479 if (custom_data_.empty())
451 return; 480 return;
452 481
453 base::mac::ScopedCFTypeRef<CGImageRef> cg_image( 482 base::mac::ScopedCFTypeRef<CGImageRef> cg_image(
454 CreateCGImageFromCustomData(custom_data_, custom_size_)); 483 CreateCGImageFromCustomData(custom_data_, custom_size_));
455 *image = cg_image.get(); 484 *image = cg_image.get();
456 } 485 }
457 #endif 486 #endif // !WEBKIT_USING_SKIA
458 487
459 void WebCursor::InitPlatformData() { 488 void WebCursor::InitPlatformData() {
460 return; 489 return;
461 } 490 }
462 491
463 bool WebCursor::SerializePlatformData(Pickle* pickle) const { 492 bool WebCursor::SerializePlatformData(Pickle* pickle) const {
464 return true; 493 return true;
465 } 494 }
466 495
467 bool WebCursor::DeserializePlatformData(const Pickle* pickle, void** iter) { 496 bool WebCursor::DeserializePlatformData(const Pickle* pickle, void** iter) {
468 return true; 497 return true;
469 } 498 }
470 499
471 bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const { 500 bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const {
472 return true; 501 return true;
473 } 502 }
474 503
475 void WebCursor::CleanupPlatformData() { 504 void WebCursor::CleanupPlatformData() {
476 return; 505 return;
477 } 506 }
478 507
479 void WebCursor::CopyPlatformData(const WebCursor& other) { 508 void WebCursor::CopyPlatformData(const WebCursor& other) {
480 return; 509 return;
481 } 510 }
OLDNEW
« no previous file with comments | « webkit/glue/webcursor.h ('k') | webkit/tools/test_shell/mac/test_webview_delegate.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698