1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/plugins/ipc/PluginInterposeOSX.mm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1159 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +// vim:set ts=2 sts=2 sw=2 et cin: 1.6 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.7 +// 1.8 +// Redistribution and use in source and binary forms, with or without 1.9 +// modification, are permitted provided that the following conditions are 1.10 +// met: 1.11 +// 1.12 +// * Redistributions of source code must retain the above copyright 1.13 +// notice, this list of conditions and the following disclaimer. 1.14 +// * Redistributions in binary form must reproduce the above 1.15 +// copyright notice, this list of conditions and the following disclaimer 1.16 +// in the documentation and/or other materials provided with the 1.17 +// distribution. 1.18 +// * Neither the name of Google Inc. nor the names of its 1.19 +// contributors may be used to endorse or promote products derived from 1.20 +// this software without specific prior written permission. 1.21 +// 1.22 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.23 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.24 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.25 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.26 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.27 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.28 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.29 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.30 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.31 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.32 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.33 + 1.34 +#include "base/basictypes.h" 1.35 +#include "nsCocoaUtils.h" 1.36 +#include "PluginModuleChild.h" 1.37 +#include "nsDebug.h" 1.38 +#include "PluginInterposeOSX.h" 1.39 +#include <set> 1.40 +#import <AppKit/AppKit.h> 1.41 +#import <objc/runtime.h> 1.42 +#import <Carbon/Carbon.h> 1.43 + 1.44 +using mozilla::plugins::PluginModuleChild; 1.45 +using mozilla::plugins::AssertPluginThread; 1.46 + 1.47 +namespace mac_plugin_interposing { 1.48 + 1.49 +int32_t NSCursorInfo::mNativeCursorsSupported = -1; 1.50 + 1.51 +// This constructor may be called from the browser process or the plugin 1.52 +// process. 1.53 +NSCursorInfo::NSCursorInfo() 1.54 + : mType(TypeArrow) 1.55 + , mHotSpot(nsPoint(0, 0)) 1.56 + , mCustomImageData(NULL) 1.57 + , mCustomImageDataLength(0) 1.58 +{ 1.59 +} 1.60 + 1.61 +NSCursorInfo::NSCursorInfo(NSCursor* aCursor) 1.62 + : mType(TypeArrow) 1.63 + , mHotSpot(nsPoint(0, 0)) 1.64 + , mCustomImageData(NULL) 1.65 + , mCustomImageDataLength(0) 1.66 +{ 1.67 + // This constructor is only ever called from the plugin process, so the 1.68 + // following is safe. 1.69 + if (!GetNativeCursorsSupported()) { 1.70 + return; 1.71 + } 1.72 + 1.73 + NSPoint hotSpotCocoa = [aCursor hotSpot]; 1.74 + mHotSpot = nsPoint(hotSpotCocoa.x, hotSpotCocoa.y); 1.75 + 1.76 + Class nsCursorClass = [NSCursor class]; 1.77 + if ([aCursor isEqual:[NSCursor arrowCursor]]) { 1.78 + mType = TypeArrow; 1.79 + } else if ([aCursor isEqual:[NSCursor closedHandCursor]]) { 1.80 + mType = TypeClosedHand; 1.81 + } else if ([aCursor isEqual:[NSCursor crosshairCursor]]) { 1.82 + mType = TypeCrosshair; 1.83 + } else if ([aCursor isEqual:[NSCursor disappearingItemCursor]]) { 1.84 + mType = TypeDisappearingItem; 1.85 + } else if ([aCursor isEqual:[NSCursor IBeamCursor]]) { 1.86 + mType = TypeIBeam; 1.87 + } else if ([aCursor isEqual:[NSCursor openHandCursor]]) { 1.88 + mType = TypeOpenHand; 1.89 + } else if ([aCursor isEqual:[NSCursor pointingHandCursor]]) { 1.90 + mType = TypePointingHand; 1.91 + } else if ([aCursor isEqual:[NSCursor resizeDownCursor]]) { 1.92 + mType = TypeResizeDown; 1.93 + } else if ([aCursor isEqual:[NSCursor resizeLeftCursor]]) { 1.94 + mType = TypeResizeLeft; 1.95 + } else if ([aCursor isEqual:[NSCursor resizeLeftRightCursor]]) { 1.96 + mType = TypeResizeLeftRight; 1.97 + } else if ([aCursor isEqual:[NSCursor resizeRightCursor]]) { 1.98 + mType = TypeResizeRight; 1.99 + } else if ([aCursor isEqual:[NSCursor resizeUpCursor]]) { 1.100 + mType = TypeResizeUp; 1.101 + } else if ([aCursor isEqual:[NSCursor resizeUpDownCursor]]) { 1.102 + mType = TypeResizeUpDown; 1.103 + // The following cursor types are only supported on OS X 10.6 and up. 1.104 + } else if ([nsCursorClass respondsToSelector:@selector(contextualMenuCursor)] && 1.105 + [aCursor isEqual:[nsCursorClass performSelector:@selector(contextualMenuCursor)]]) { 1.106 + mType = TypeContextualMenu; 1.107 + } else if ([nsCursorClass respondsToSelector:@selector(dragCopyCursor)] && 1.108 + [aCursor isEqual:[nsCursorClass performSelector:@selector(dragCopyCursor)]]) { 1.109 + mType = TypeDragCopy; 1.110 + } else if ([nsCursorClass respondsToSelector:@selector(dragLinkCursor)] && 1.111 + [aCursor isEqual:[nsCursorClass performSelector:@selector(dragLinkCursor)]]) { 1.112 + mType = TypeDragLink; 1.113 + } else if ([nsCursorClass respondsToSelector:@selector(operationNotAllowedCursor)] && 1.114 + [aCursor isEqual:[nsCursorClass performSelector:@selector(operationNotAllowedCursor)]]) { 1.115 + mType = TypeNotAllowed; 1.116 + } else { 1.117 + NSImage* image = [aCursor image]; 1.118 + NSArray* reps = image ? [image representations] : nil; 1.119 + NSUInteger repsCount = reps ? [reps count] : 0; 1.120 + if (!repsCount) { 1.121 + // If we have a custom cursor with no image representations, assume we 1.122 + // need a transparent cursor. 1.123 + mType = TypeTransparent; 1.124 + } else { 1.125 + CGImageRef cgImage = nil; 1.126 + // XXX We don't know how to deal with a cursor that doesn't have a 1.127 + // bitmap image representation. For now we fall back to an arrow 1.128 + // cursor. 1.129 + for (NSUInteger i = 0; i < repsCount; ++i) { 1.130 + id rep = [reps objectAtIndex:i]; 1.131 + if ([rep isKindOfClass:[NSBitmapImageRep class]]) { 1.132 + cgImage = [(NSBitmapImageRep*)rep CGImage]; 1.133 + break; 1.134 + } 1.135 + } 1.136 + if (cgImage) { 1.137 + CFMutableDataRef data = ::CFDataCreateMutable(kCFAllocatorDefault, 0); 1.138 + if (data) { 1.139 + CGImageDestinationRef dest = ::CGImageDestinationCreateWithData(data, 1.140 + kUTTypePNG, 1.141 + 1, 1.142 + NULL); 1.143 + if (dest) { 1.144 + ::CGImageDestinationAddImage(dest, cgImage, NULL); 1.145 + if (::CGImageDestinationFinalize(dest)) { 1.146 + uint32_t dataLength = (uint32_t) ::CFDataGetLength(data); 1.147 + mCustomImageData = (uint8_t*) moz_xmalloc(dataLength); 1.148 + ::CFDataGetBytes(data, ::CFRangeMake(0, dataLength), mCustomImageData); 1.149 + mCustomImageDataLength = dataLength; 1.150 + mType = TypeCustom; 1.151 + } 1.152 + ::CFRelease(dest); 1.153 + } 1.154 + ::CFRelease(data); 1.155 + } 1.156 + } 1.157 + if (!mCustomImageData) { 1.158 + mType = TypeArrow; 1.159 + } 1.160 + } 1.161 + } 1.162 +} 1.163 + 1.164 +NSCursorInfo::NSCursorInfo(const Cursor* aCursor) 1.165 + : mType(TypeArrow) 1.166 + , mHotSpot(nsPoint(0, 0)) 1.167 + , mCustomImageData(NULL) 1.168 + , mCustomImageDataLength(0) 1.169 +{ 1.170 + // This constructor is only ever called from the plugin process, so the 1.171 + // following is safe. 1.172 + if (!GetNativeCursorsSupported()) { 1.173 + return; 1.174 + } 1.175 + 1.176 + mHotSpot = nsPoint(aCursor->hotSpot.h, aCursor->hotSpot.v); 1.177 + 1.178 + int width = 16, height = 16; 1.179 + int bytesPerPixel = 4; 1.180 + int rowBytes = width * bytesPerPixel; 1.181 + int bitmapSize = height * rowBytes; 1.182 + 1.183 + bool isTransparent = true; 1.184 + 1.185 + uint8_t* bitmap = (uint8_t*) moz_xmalloc(bitmapSize); 1.186 + // The way we create 'bitmap' is largely "borrowed" from Chrome's 1.187 + // WebCursor::InitFromCursor(). 1.188 + for (int y = 0; y < height; ++y) { 1.189 + unsigned short data = aCursor->data[y]; 1.190 + unsigned short mask = aCursor->mask[y]; 1.191 + // Change 'data' and 'mask' from big-endian to little-endian, but output 1.192 + // big-endian data below. 1.193 + data = ((data << 8) & 0xFF00) | ((data >> 8) & 0x00FF); 1.194 + mask = ((mask << 8) & 0xFF00) | ((mask >> 8) & 0x00FF); 1.195 + // It'd be nice to use a gray-scale bitmap. But 1.196 + // CGBitmapContextCreateImage() (used below) won't work with one that also 1.197 + // has alpha values. 1.198 + for (int x = 0; x < width; ++x) { 1.199 + int offset = (y * rowBytes) + (x * bytesPerPixel); 1.200 + // Color value 1.201 + if (data & 0x8000) { 1.202 + bitmap[offset] = 0x0; 1.203 + bitmap[offset + 1] = 0x0; 1.204 + bitmap[offset + 2] = 0x0; 1.205 + } else { 1.206 + bitmap[offset] = 0xFF; 1.207 + bitmap[offset + 1] = 0xFF; 1.208 + bitmap[offset + 2] = 0xFF; 1.209 + } 1.210 + // Mask value 1.211 + if (mask & 0x8000) { 1.212 + bitmap[offset + 3] = 0xFF; 1.213 + isTransparent = false; 1.214 + } else { 1.215 + bitmap[offset + 3] = 0x0; 1.216 + } 1.217 + data <<= 1; 1.218 + mask <<= 1; 1.219 + } 1.220 + } 1.221 + 1.222 + if (isTransparent) { 1.223 + // If aCursor is transparent, we don't need to serialize custom cursor 1.224 + // data over IPC. 1.225 + mType = TypeTransparent; 1.226 + } else { 1.227 + CGColorSpaceRef color = ::CGColorSpaceCreateDeviceRGB(); 1.228 + if (color) { 1.229 + CGContextRef context = 1.230 + ::CGBitmapContextCreate(bitmap, 1.231 + width, 1.232 + height, 1.233 + 8, 1.234 + rowBytes, 1.235 + color, 1.236 + kCGImageAlphaPremultipliedLast | 1.237 + kCGBitmapByteOrder32Big); 1.238 + if (context) { 1.239 + CGImageRef image = ::CGBitmapContextCreateImage(context); 1.240 + if (image) { 1.241 + ::CFMutableDataRef data = ::CFDataCreateMutable(kCFAllocatorDefault, 0); 1.242 + if (data) { 1.243 + CGImageDestinationRef dest = 1.244 + ::CGImageDestinationCreateWithData(data, 1.245 + kUTTypePNG, 1.246 + 1, 1.247 + NULL); 1.248 + if (dest) { 1.249 + ::CGImageDestinationAddImage(dest, image, NULL); 1.250 + if (::CGImageDestinationFinalize(dest)) { 1.251 + uint32_t dataLength = (uint32_t) ::CFDataGetLength(data); 1.252 + mCustomImageData = (uint8_t*) moz_xmalloc(dataLength); 1.253 + ::CFDataGetBytes(data, 1.254 + ::CFRangeMake(0, dataLength), 1.255 + mCustomImageData); 1.256 + mCustomImageDataLength = dataLength; 1.257 + mType = TypeCustom; 1.258 + } 1.259 + ::CFRelease(dest); 1.260 + } 1.261 + ::CFRelease(data); 1.262 + } 1.263 + ::CGImageRelease(image); 1.264 + } 1.265 + ::CGContextRelease(context); 1.266 + } 1.267 + ::CGColorSpaceRelease(color); 1.268 + } 1.269 + } 1.270 + 1.271 + moz_free(bitmap); 1.272 +} 1.273 + 1.274 +NSCursorInfo::~NSCursorInfo() 1.275 +{ 1.276 + if (mCustomImageData) { 1.277 + moz_free(mCustomImageData); 1.278 + } 1.279 +} 1.280 + 1.281 +NSCursor* NSCursorInfo::GetNSCursor() const 1.282 +{ 1.283 + NSCursor* retval = nil; 1.284 + 1.285 + Class nsCursorClass = [NSCursor class]; 1.286 + switch(mType) { 1.287 + case TypeArrow: 1.288 + retval = [NSCursor arrowCursor]; 1.289 + break; 1.290 + case TypeClosedHand: 1.291 + retval = [NSCursor closedHandCursor]; 1.292 + break; 1.293 + case TypeCrosshair: 1.294 + retval = [NSCursor crosshairCursor]; 1.295 + break; 1.296 + case TypeDisappearingItem: 1.297 + retval = [NSCursor disappearingItemCursor]; 1.298 + break; 1.299 + case TypeIBeam: 1.300 + retval = [NSCursor IBeamCursor]; 1.301 + break; 1.302 + case TypeOpenHand: 1.303 + retval = [NSCursor openHandCursor]; 1.304 + break; 1.305 + case TypePointingHand: 1.306 + retval = [NSCursor pointingHandCursor]; 1.307 + break; 1.308 + case TypeResizeDown: 1.309 + retval = [NSCursor resizeDownCursor]; 1.310 + break; 1.311 + case TypeResizeLeft: 1.312 + retval = [NSCursor resizeLeftCursor]; 1.313 + break; 1.314 + case TypeResizeLeftRight: 1.315 + retval = [NSCursor resizeLeftRightCursor]; 1.316 + break; 1.317 + case TypeResizeRight: 1.318 + retval = [NSCursor resizeRightCursor]; 1.319 + break; 1.320 + case TypeResizeUp: 1.321 + retval = [NSCursor resizeUpCursor]; 1.322 + break; 1.323 + case TypeResizeUpDown: 1.324 + retval = [NSCursor resizeUpDownCursor]; 1.325 + break; 1.326 + // The following four cursor types are only supported on OS X 10.6 and up. 1.327 + case TypeContextualMenu: { 1.328 + if ([nsCursorClass respondsToSelector:@selector(contextualMenuCursor)]) { 1.329 + retval = [nsCursorClass performSelector:@selector(contextualMenuCursor)]; 1.330 + } 1.331 + break; 1.332 + } 1.333 + case TypeDragCopy: { 1.334 + if ([nsCursorClass respondsToSelector:@selector(dragCopyCursor)]) { 1.335 + retval = [nsCursorClass performSelector:@selector(dragCopyCursor)]; 1.336 + } 1.337 + break; 1.338 + } 1.339 + case TypeDragLink: { 1.340 + if ([nsCursorClass respondsToSelector:@selector(dragLinkCursor)]) { 1.341 + retval = [nsCursorClass performSelector:@selector(dragLinkCursor)]; 1.342 + } 1.343 + break; 1.344 + } 1.345 + case TypeNotAllowed: { 1.346 + if ([nsCursorClass respondsToSelector:@selector(operationNotAllowedCursor)]) { 1.347 + retval = [nsCursorClass performSelector:@selector(operationNotAllowedCursor)]; 1.348 + } 1.349 + break; 1.350 + } 1.351 + case TypeTransparent: 1.352 + retval = GetTransparentCursor(); 1.353 + break; 1.354 + default: 1.355 + break; 1.356 + } 1.357 + 1.358 + if (!retval && mCustomImageData && mCustomImageDataLength) { 1.359 + CGDataProviderRef provider = ::CGDataProviderCreateWithData(NULL, 1.360 + (const void*)mCustomImageData, 1.361 + mCustomImageDataLength, 1.362 + NULL); 1.363 + if (provider) { 1.364 + CGImageRef cgImage = ::CGImageCreateWithPNGDataProvider(provider, 1.365 + NULL, 1.366 + false, 1.367 + kCGRenderingIntentDefault); 1.368 + if (cgImage) { 1.369 + NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage]; 1.370 + if (rep) { 1.371 + NSImage* image = [[NSImage alloc] init]; 1.372 + if (image) { 1.373 + [image addRepresentation:rep]; 1.374 + retval = [[[NSCursor alloc] initWithImage:image 1.375 + hotSpot:NSMakePoint(mHotSpot.x, mHotSpot.y)] 1.376 + autorelease]; 1.377 + [image release]; 1.378 + } 1.379 + [rep release]; 1.380 + } 1.381 + ::CGImageRelease(cgImage); 1.382 + } 1.383 + ::CFRelease(provider); 1.384 + } 1.385 + } 1.386 + 1.387 + // Fall back to an arrow cursor if need be. 1.388 + if (!retval) { 1.389 + retval = [NSCursor arrowCursor]; 1.390 + } 1.391 + 1.392 + return retval; 1.393 +} 1.394 + 1.395 +// Get a transparent cursor with the appropriate hot spot. We need one if 1.396 +// (for example) we have a custom cursor with no image data. 1.397 +NSCursor* NSCursorInfo::GetTransparentCursor() const 1.398 +{ 1.399 + NSCursor* retval = nil; 1.400 + 1.401 + int width = 16, height = 16; 1.402 + int bytesPerPixel = 2; 1.403 + int rowBytes = width * bytesPerPixel; 1.404 + int dataSize = height * rowBytes; 1.405 + 1.406 + uint8_t* data = (uint8_t*) moz_xmalloc(dataSize); 1.407 + for (int y = 0; y < height; ++y) { 1.408 + for (int x = 0; x < width; ++x) { 1.409 + int offset = (y * rowBytes) + (x * bytesPerPixel); 1.410 + data[offset] = 0x7E; // Arbitrary gray-scale value 1.411 + data[offset + 1] = 0; // Alpha value to make us transparent 1.412 + } 1.413 + } 1.414 + 1.415 + NSBitmapImageRep* imageRep = 1.416 + [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil 1.417 + pixelsWide:width 1.418 + pixelsHigh:height 1.419 + bitsPerSample:8 1.420 + samplesPerPixel:2 1.421 + hasAlpha:YES 1.422 + isPlanar:NO 1.423 + colorSpaceName:NSCalibratedWhiteColorSpace 1.424 + bytesPerRow:rowBytes 1.425 + bitsPerPixel:16] 1.426 + autorelease]; 1.427 + if (imageRep) { 1.428 + uint8_t* repDataPtr = [imageRep bitmapData]; 1.429 + if (repDataPtr) { 1.430 + memcpy(repDataPtr, data, dataSize); 1.431 + NSImage *image = 1.432 + [[[NSImage alloc] initWithSize:NSMakeSize(width, height)] 1.433 + autorelease]; 1.434 + if (image) { 1.435 + [image addRepresentation:imageRep]; 1.436 + retval = 1.437 + [[[NSCursor alloc] initWithImage:image 1.438 + hotSpot:NSMakePoint(mHotSpot.x, mHotSpot.y)] 1.439 + autorelease]; 1.440 + } 1.441 + } 1.442 + } 1.443 + 1.444 + moz_free(data); 1.445 + 1.446 + // Fall back to an arrow cursor if (for some reason) the above code failed. 1.447 + if (!retval) { 1.448 + retval = [NSCursor arrowCursor]; 1.449 + } 1.450 + 1.451 + return retval; 1.452 +} 1.453 + 1.454 +NSCursorInfo::Type NSCursorInfo::GetType() const 1.455 +{ 1.456 + return mType; 1.457 +} 1.458 + 1.459 +const char* NSCursorInfo::GetTypeName() const 1.460 +{ 1.461 + switch(mType) { 1.462 + case TypeCustom: 1.463 + return "TypeCustom"; 1.464 + case TypeArrow: 1.465 + return "TypeArrow"; 1.466 + case TypeClosedHand: 1.467 + return "TypeClosedHand"; 1.468 + case TypeContextualMenu: 1.469 + return "TypeContextualMenu"; 1.470 + case TypeCrosshair: 1.471 + return "TypeCrosshair"; 1.472 + case TypeDisappearingItem: 1.473 + return "TypeDisappearingItem"; 1.474 + case TypeDragCopy: 1.475 + return "TypeDragCopy"; 1.476 + case TypeDragLink: 1.477 + return "TypeDragLink"; 1.478 + case TypeIBeam: 1.479 + return "TypeIBeam"; 1.480 + case TypeNotAllowed: 1.481 + return "TypeNotAllowed"; 1.482 + case TypeOpenHand: 1.483 + return "TypeOpenHand"; 1.484 + case TypePointingHand: 1.485 + return "TypePointingHand"; 1.486 + case TypeResizeDown: 1.487 + return "TypeResizeDown"; 1.488 + case TypeResizeLeft: 1.489 + return "TypeResizeLeft"; 1.490 + case TypeResizeLeftRight: 1.491 + return "TypeResizeLeftRight"; 1.492 + case TypeResizeRight: 1.493 + return "TypeResizeRight"; 1.494 + case TypeResizeUp: 1.495 + return "TypeResizeUp"; 1.496 + case TypeResizeUpDown: 1.497 + return "TypeResizeUpDown"; 1.498 + case TypeTransparent: 1.499 + return "TypeTransparent"; 1.500 + default: 1.501 + break; 1.502 + } 1.503 + return "TypeUnknown"; 1.504 +} 1.505 + 1.506 +nsPoint NSCursorInfo::GetHotSpot() const 1.507 +{ 1.508 + return mHotSpot; 1.509 +} 1.510 + 1.511 +uint8_t* NSCursorInfo::GetCustomImageData() const 1.512 +{ 1.513 + return mCustomImageData; 1.514 +} 1.515 + 1.516 +uint32_t NSCursorInfo::GetCustomImageDataLength() const 1.517 +{ 1.518 + return mCustomImageDataLength; 1.519 +} 1.520 + 1.521 +void NSCursorInfo::SetType(Type aType) 1.522 +{ 1.523 + mType = aType; 1.524 +} 1.525 + 1.526 +void NSCursorInfo::SetHotSpot(nsPoint aHotSpot) 1.527 +{ 1.528 + mHotSpot = aHotSpot; 1.529 +} 1.530 + 1.531 +void NSCursorInfo::SetCustomImageData(uint8_t* aData, uint32_t aDataLength) 1.532 +{ 1.533 + if (mCustomImageData) { 1.534 + moz_free(mCustomImageData); 1.535 + } 1.536 + if (aDataLength) { 1.537 + mCustomImageData = (uint8_t*) moz_xmalloc(aDataLength); 1.538 + memcpy(mCustomImageData, aData, aDataLength); 1.539 + } else { 1.540 + mCustomImageData = NULL; 1.541 + } 1.542 + mCustomImageDataLength = aDataLength; 1.543 +} 1.544 + 1.545 +// This should never be called from the browser process -- only from the 1.546 +// plugin process. 1.547 +bool NSCursorInfo::GetNativeCursorsSupported() 1.548 +{ 1.549 + if (mNativeCursorsSupported == -1) { 1.550 + AssertPluginThread(); 1.551 + PluginModuleChild *pmc = PluginModuleChild::current(); 1.552 + if (pmc) { 1.553 + bool result = pmc->GetNativeCursorsSupported(); 1.554 + if (result) { 1.555 + mNativeCursorsSupported = 1; 1.556 + } else { 1.557 + mNativeCursorsSupported = 0; 1.558 + } 1.559 + } 1.560 + } 1.561 + return (mNativeCursorsSupported == 1); 1.562 +} 1.563 + 1.564 +} // namespace mac_plugin_interposing 1.565 + 1.566 +namespace mac_plugin_interposing { 1.567 +namespace parent { 1.568 + 1.569 +// Tracks plugin windows currently visible. 1.570 +std::set<uint32_t> plugin_visible_windows_set_; 1.571 +// Tracks full screen windows currently visible. 1.572 +std::set<uint32_t> plugin_fullscreen_windows_set_; 1.573 +// Tracks modal windows currently visible. 1.574 +std::set<uint32_t> plugin_modal_windows_set_; 1.575 + 1.576 +void OnPluginShowWindow(uint32_t window_id, 1.577 + CGRect window_bounds, 1.578 + bool modal) { 1.579 + plugin_visible_windows_set_.insert(window_id); 1.580 + 1.581 + if (modal) 1.582 + plugin_modal_windows_set_.insert(window_id); 1.583 + 1.584 + CGRect main_display_bounds = ::CGDisplayBounds(CGMainDisplayID()); 1.585 + 1.586 + if (CGRectEqualToRect(window_bounds, main_display_bounds) && 1.587 + (plugin_fullscreen_windows_set_.find(window_id) == 1.588 + plugin_fullscreen_windows_set_.end())) { 1.589 + plugin_fullscreen_windows_set_.insert(window_id); 1.590 + 1.591 + nsCocoaUtils::HideOSChromeOnScreen(TRUE, [[NSScreen screens] objectAtIndex:0]); 1.592 + } 1.593 +} 1.594 + 1.595 +static void ActivateProcess(pid_t pid) { 1.596 + ProcessSerialNumber process; 1.597 + OSStatus status = ::GetProcessForPID(pid, &process); 1.598 + 1.599 + if (status == noErr) { 1.600 + SetFrontProcess(&process); 1.601 + } else { 1.602 + NS_WARNING("Unable to get process for pid."); 1.603 + } 1.604 +} 1.605 + 1.606 +// Must be called on the UI thread. 1.607 +// If plugin_pid is -1, the browser will be the active process on return, 1.608 +// otherwise that process will be given focus back before this function returns. 1.609 +static void ReleasePluginFullScreen(pid_t plugin_pid) { 1.610 + // Releasing full screen only works if we are the frontmost process; grab 1.611 + // focus, but give it back to the plugin process if requested. 1.612 + ActivateProcess(base::GetCurrentProcId()); 1.613 + 1.614 + nsCocoaUtils::HideOSChromeOnScreen(FALSE, [[NSScreen screens] objectAtIndex:0]); 1.615 + 1.616 + if (plugin_pid != -1) { 1.617 + ActivateProcess(plugin_pid); 1.618 + } 1.619 +} 1.620 + 1.621 +void OnPluginHideWindow(uint32_t window_id, pid_t aPluginPid) { 1.622 + bool had_windows = !plugin_visible_windows_set_.empty(); 1.623 + plugin_visible_windows_set_.erase(window_id); 1.624 + bool browser_needs_activation = had_windows && 1.625 + plugin_visible_windows_set_.empty(); 1.626 + 1.627 + plugin_modal_windows_set_.erase(window_id); 1.628 + if (plugin_fullscreen_windows_set_.find(window_id) != 1.629 + plugin_fullscreen_windows_set_.end()) { 1.630 + plugin_fullscreen_windows_set_.erase(window_id); 1.631 + pid_t plugin_pid = browser_needs_activation ? -1 : aPluginPid; 1.632 + browser_needs_activation = false; 1.633 + ReleasePluginFullScreen(plugin_pid); 1.634 + } 1.635 + 1.636 + if (browser_needs_activation) { 1.637 + ActivateProcess(getpid()); 1.638 + } 1.639 +} 1.640 + 1.641 +void OnSetCursor(const NSCursorInfo& cursorInfo) 1.642 +{ 1.643 + NSCursor* aCursor = cursorInfo.GetNSCursor(); 1.644 + if (aCursor) { 1.645 + [aCursor set]; 1.646 + } 1.647 +} 1.648 + 1.649 +void OnShowCursor(bool show) 1.650 +{ 1.651 + if (show) { 1.652 + [NSCursor unhide]; 1.653 + } else { 1.654 + [NSCursor hide]; 1.655 + } 1.656 +} 1.657 + 1.658 +void OnPushCursor(const NSCursorInfo& cursorInfo) 1.659 +{ 1.660 + NSCursor* aCursor = cursorInfo.GetNSCursor(); 1.661 + if (aCursor) { 1.662 + [aCursor push]; 1.663 + } 1.664 +} 1.665 + 1.666 +void OnPopCursor() 1.667 +{ 1.668 + [NSCursor pop]; 1.669 +} 1.670 + 1.671 +} // parent 1.672 +} // namespace mac_plugin_interposing 1.673 + 1.674 +namespace mac_plugin_interposing { 1.675 +namespace child { 1.676 + 1.677 +// TODO(stuartmorgan): Make this an IPC to order the plugin process above the 1.678 +// browser process only if the browser is current frontmost. 1.679 +void FocusPluginProcess() { 1.680 + ProcessSerialNumber this_process, front_process; 1.681 + if ((GetCurrentProcess(&this_process) != noErr) || 1.682 + (GetFrontProcess(&front_process) != noErr)) { 1.683 + return; 1.684 + } 1.685 + 1.686 + Boolean matched = false; 1.687 + if ((SameProcess(&this_process, &front_process, &matched) == noErr) && 1.688 + !matched) { 1.689 + SetFrontProcess(&this_process); 1.690 + } 1.691 +} 1.692 + 1.693 +void NotifyBrowserOfPluginShowWindow(uint32_t window_id, CGRect bounds, 1.694 + bool modal) { 1.695 + AssertPluginThread(); 1.696 + 1.697 + PluginModuleChild *pmc = PluginModuleChild::current(); 1.698 + if (pmc) 1.699 + pmc->PluginShowWindow(window_id, modal, bounds); 1.700 +} 1.701 + 1.702 +void NotifyBrowserOfPluginHideWindow(uint32_t window_id, CGRect bounds) { 1.703 + AssertPluginThread(); 1.704 + 1.705 + PluginModuleChild *pmc = PluginModuleChild::current(); 1.706 + if (pmc) 1.707 + pmc->PluginHideWindow(window_id); 1.708 +} 1.709 + 1.710 +void NotifyBrowserOfSetCursor(NSCursorInfo& aCursorInfo) 1.711 +{ 1.712 + AssertPluginThread(); 1.713 + PluginModuleChild *pmc = PluginModuleChild::current(); 1.714 + if (pmc) { 1.715 + pmc->SetCursor(aCursorInfo); 1.716 + } 1.717 +} 1.718 + 1.719 +void NotifyBrowserOfShowCursor(bool show) 1.720 +{ 1.721 + AssertPluginThread(); 1.722 + PluginModuleChild *pmc = PluginModuleChild::current(); 1.723 + if (pmc) { 1.724 + pmc->ShowCursor(show); 1.725 + } 1.726 +} 1.727 + 1.728 +void NotifyBrowserOfPushCursor(NSCursorInfo& aCursorInfo) 1.729 +{ 1.730 + AssertPluginThread(); 1.731 + PluginModuleChild *pmc = PluginModuleChild::current(); 1.732 + if (pmc) { 1.733 + pmc->PushCursor(aCursorInfo); 1.734 + } 1.735 +} 1.736 + 1.737 +void NotifyBrowserOfPopCursor() 1.738 +{ 1.739 + AssertPluginThread(); 1.740 + PluginModuleChild *pmc = PluginModuleChild::current(); 1.741 + if (pmc) { 1.742 + pmc->PopCursor(); 1.743 + } 1.744 +} 1.745 + 1.746 +struct WindowInfo { 1.747 + uint32_t window_id; 1.748 + CGRect bounds; 1.749 + WindowInfo(NSWindow* window) { 1.750 + NSInteger window_num = [window windowNumber]; 1.751 + window_id = window_num > 0 ? window_num : 0; 1.752 + bounds = NSRectToCGRect([window frame]); 1.753 + } 1.754 +}; 1.755 + 1.756 +static void OnPluginWindowClosed(const WindowInfo& window_info) { 1.757 + if (window_info.window_id == 0) 1.758 + return; 1.759 + mac_plugin_interposing::child::NotifyBrowserOfPluginHideWindow(window_info.window_id, 1.760 + window_info.bounds); 1.761 +} 1.762 + 1.763 +static void OnPluginWindowShown(const WindowInfo& window_info, BOOL is_modal) { 1.764 + // The window id is 0 if it has never been shown (including while it is the 1.765 + // process of being shown for the first time); when that happens, we'll catch 1.766 + // it in _setWindowNumber instead. 1.767 + static BOOL s_pending_display_is_modal = NO; 1.768 + if (window_info.window_id == 0) { 1.769 + if (is_modal) 1.770 + s_pending_display_is_modal = YES; 1.771 + return; 1.772 + } 1.773 + if (s_pending_display_is_modal) { 1.774 + is_modal = YES; 1.775 + s_pending_display_is_modal = NO; 1.776 + } 1.777 + mac_plugin_interposing::child::NotifyBrowserOfPluginShowWindow( 1.778 + window_info.window_id, window_info.bounds, is_modal); 1.779 +} 1.780 + 1.781 +static BOOL OnSetCursor(NSCursorInfo &aInfo) 1.782 +{ 1.783 + if (NSCursorInfo::GetNativeCursorsSupported()) { 1.784 + NotifyBrowserOfSetCursor(aInfo); 1.785 + return YES; 1.786 + } 1.787 + return NO; 1.788 +} 1.789 + 1.790 +static BOOL OnHideCursor() 1.791 +{ 1.792 + if (NSCursorInfo::GetNativeCursorsSupported()) { 1.793 + NotifyBrowserOfShowCursor(NO); 1.794 + return YES; 1.795 + } 1.796 + return NO; 1.797 +} 1.798 + 1.799 +static BOOL OnUnhideCursor() 1.800 +{ 1.801 + if (NSCursorInfo::GetNativeCursorsSupported()) { 1.802 + NotifyBrowserOfShowCursor(YES); 1.803 + return YES; 1.804 + } 1.805 + return NO; 1.806 +} 1.807 + 1.808 +static BOOL OnPushCursor(NSCursorInfo &aInfo) 1.809 +{ 1.810 + if (NSCursorInfo::GetNativeCursorsSupported()) { 1.811 + NotifyBrowserOfPushCursor(aInfo); 1.812 + return YES; 1.813 + } 1.814 + return NO; 1.815 +} 1.816 + 1.817 +static BOOL OnPopCursor() 1.818 +{ 1.819 + if (NSCursorInfo::GetNativeCursorsSupported()) { 1.820 + NotifyBrowserOfPopCursor(); 1.821 + return YES; 1.822 + } 1.823 + return NO; 1.824 +} 1.825 + 1.826 +} // child 1.827 +} // namespace mac_plugin_interposing 1.828 + 1.829 +using namespace mac_plugin_interposing::child; 1.830 + 1.831 +@interface NSWindow (PluginInterposing) 1.832 +- (void)pluginInterpose_orderOut:(id)sender; 1.833 +- (void)pluginInterpose_orderFront:(id)sender; 1.834 +- (void)pluginInterpose_makeKeyAndOrderFront:(id)sender; 1.835 +- (void)pluginInterpose_setWindowNumber:(NSInteger)num; 1.836 +@end 1.837 + 1.838 +@implementation NSWindow (PluginInterposing) 1.839 + 1.840 +- (void)pluginInterpose_orderOut:(id)sender { 1.841 + WindowInfo window_info(self); 1.842 + [self pluginInterpose_orderOut:sender]; 1.843 + OnPluginWindowClosed(window_info); 1.844 +} 1.845 + 1.846 +- (void)pluginInterpose_orderFront:(id)sender { 1.847 + mac_plugin_interposing::child::FocusPluginProcess(); 1.848 + [self pluginInterpose_orderFront:sender]; 1.849 + OnPluginWindowShown(WindowInfo(self), NO); 1.850 +} 1.851 + 1.852 +- (void)pluginInterpose_makeKeyAndOrderFront:(id)sender { 1.853 + mac_plugin_interposing::child::FocusPluginProcess(); 1.854 + [self pluginInterpose_makeKeyAndOrderFront:sender]; 1.855 + OnPluginWindowShown(WindowInfo(self), NO); 1.856 +} 1.857 + 1.858 +- (void)pluginInterpose_setWindowNumber:(NSInteger)num { 1.859 + if (num > 0) 1.860 + mac_plugin_interposing::child::FocusPluginProcess(); 1.861 + [self pluginInterpose_setWindowNumber:num]; 1.862 + if (num > 0) 1.863 + OnPluginWindowShown(WindowInfo(self), NO); 1.864 +} 1.865 + 1.866 +@end 1.867 + 1.868 +@interface NSApplication (PluginInterposing) 1.869 +- (NSInteger)pluginInterpose_runModalForWindow:(NSWindow*)window; 1.870 +@end 1.871 + 1.872 +@implementation NSApplication (PluginInterposing) 1.873 + 1.874 +- (NSInteger)pluginInterpose_runModalForWindow:(NSWindow*)window { 1.875 + mac_plugin_interposing::child::FocusPluginProcess(); 1.876 + // This is out-of-order relative to the other calls, but runModalForWindow: 1.877 + // won't return until the window closes, and the order only matters for 1.878 + // full-screen windows. 1.879 + OnPluginWindowShown(WindowInfo(window), YES); 1.880 + return [self pluginInterpose_runModalForWindow:window]; 1.881 +} 1.882 + 1.883 +@end 1.884 + 1.885 +// Hook commands to manipulate the current cursor, so that they can be passed 1.886 +// from the child process to the parent process. These commands have no 1.887 +// effect unless they're performed in the parent process. 1.888 +@interface NSCursor (PluginInterposing) 1.889 +- (void)pluginInterpose_set; 1.890 +- (void)pluginInterpose_push; 1.891 +- (void)pluginInterpose_pop; 1.892 ++ (NSCursor*)pluginInterpose_currentCursor; 1.893 ++ (void)pluginInterpose_hide; 1.894 ++ (void)pluginInterpose_unhide; 1.895 ++ (void)pluginInterpose_pop; 1.896 +@end 1.897 + 1.898 +// Cache the results of [NSCursor set], [NSCursor push] and [NSCursor pop]. 1.899 +// The last element is always the current cursor. 1.900 +static NSMutableArray* gCursorStack = nil; 1.901 + 1.902 +static BOOL initCursorStack() 1.903 +{ 1.904 + if (!gCursorStack) { 1.905 + gCursorStack = [[NSMutableArray arrayWithCapacity:5] retain]; 1.906 + } 1.907 + return (gCursorStack != NULL); 1.908 +} 1.909 + 1.910 +static NSCursor* currentCursorFromCache() 1.911 +{ 1.912 + if (!initCursorStack()) 1.913 + return nil; 1.914 + return (NSCursor*) [gCursorStack lastObject]; 1.915 +} 1.916 + 1.917 +static void setCursorInCache(NSCursor* aCursor) 1.918 +{ 1.919 + if (!initCursorStack() || !aCursor) 1.920 + return; 1.921 + NSUInteger count = [gCursorStack count]; 1.922 + if (count) { 1.923 + [gCursorStack replaceObjectAtIndex:count - 1 withObject:aCursor]; 1.924 + } else { 1.925 + [gCursorStack addObject:aCursor]; 1.926 + } 1.927 +} 1.928 + 1.929 +static void pushCursorInCache(NSCursor* aCursor) 1.930 +{ 1.931 + if (!initCursorStack() || !aCursor) 1.932 + return; 1.933 + [gCursorStack addObject:aCursor]; 1.934 +} 1.935 + 1.936 +static void popCursorInCache() 1.937 +{ 1.938 + if (!initCursorStack()) 1.939 + return; 1.940 + // Apple's doc on the +[NSCursor pop] method says: "If the current cursor 1.941 + // is the only cursor on the stack, this method does nothing." 1.942 + if ([gCursorStack count] > 1) { 1.943 + [gCursorStack removeLastObject]; 1.944 + } 1.945 +} 1.946 + 1.947 +@implementation NSCursor (PluginInterposing) 1.948 + 1.949 +- (void)pluginInterpose_set 1.950 +{ 1.951 + NSCursorInfo info(self); 1.952 + OnSetCursor(info); 1.953 + setCursorInCache(self); 1.954 + [self pluginInterpose_set]; 1.955 +} 1.956 + 1.957 +- (void)pluginInterpose_push 1.958 +{ 1.959 + NSCursorInfo info(self); 1.960 + OnPushCursor(info); 1.961 + pushCursorInCache(self); 1.962 + [self pluginInterpose_push]; 1.963 +} 1.964 + 1.965 +- (void)pluginInterpose_pop 1.966 +{ 1.967 + OnPopCursor(); 1.968 + popCursorInCache(); 1.969 + [self pluginInterpose_pop]; 1.970 +} 1.971 + 1.972 +// The currentCursor method always returns nil when running in a background 1.973 +// process. But this may confuse plugins (notably Flash, see bug 621117). So 1.974 +// if we get a nil return from the "call to super", we return a cursor that's 1.975 +// been cached by previous calls to set or push. According to Apple's docs, 1.976 +// currentCursor "only returns the cursor set by your application using 1.977 +// NSCursor methods". So we don't need to worry about changes to the cursor 1.978 +// made by other methods like SetThemeCursor(). 1.979 ++ (NSCursor*)pluginInterpose_currentCursor 1.980 +{ 1.981 + NSCursor* retval = [self pluginInterpose_currentCursor]; 1.982 + if (!retval) { 1.983 + retval = currentCursorFromCache(); 1.984 + } 1.985 + return retval; 1.986 +} 1.987 + 1.988 ++ (void)pluginInterpose_hide 1.989 +{ 1.990 + OnHideCursor(); 1.991 + [self pluginInterpose_hide]; 1.992 +} 1.993 + 1.994 ++ (void)pluginInterpose_unhide 1.995 +{ 1.996 + OnUnhideCursor(); 1.997 + [self pluginInterpose_unhide]; 1.998 +} 1.999 + 1.1000 ++ (void)pluginInterpose_pop 1.1001 +{ 1.1002 + OnPopCursor(); 1.1003 + popCursorInCache(); 1.1004 + [self pluginInterpose_pop]; 1.1005 +} 1.1006 + 1.1007 +@end 1.1008 + 1.1009 +static void ExchangeMethods(Class target_class, 1.1010 + BOOL class_method, 1.1011 + SEL original, 1.1012 + SEL replacement) { 1.1013 + Method m1; 1.1014 + Method m2; 1.1015 + if (class_method) { 1.1016 + m1 = class_getClassMethod(target_class, original); 1.1017 + m2 = class_getClassMethod(target_class, replacement); 1.1018 + } else { 1.1019 + m1 = class_getInstanceMethod(target_class, original); 1.1020 + m2 = class_getInstanceMethod(target_class, replacement); 1.1021 + } 1.1022 + 1.1023 + if (m1 == m2) 1.1024 + return; 1.1025 + 1.1026 + if (m1 && m2) 1.1027 + method_exchangeImplementations(m1, m2); 1.1028 + else 1.1029 + NS_NOTREACHED("Cocoa swizzling failed"); 1.1030 +} 1.1031 + 1.1032 +namespace mac_plugin_interposing { 1.1033 +namespace child { 1.1034 + 1.1035 +void SetUpCocoaInterposing() { 1.1036 + Class nswindow_class = [NSWindow class]; 1.1037 + ExchangeMethods(nswindow_class, NO, @selector(orderOut:), 1.1038 + @selector(pluginInterpose_orderOut:)); 1.1039 + ExchangeMethods(nswindow_class, NO, @selector(orderFront:), 1.1040 + @selector(pluginInterpose_orderFront:)); 1.1041 + ExchangeMethods(nswindow_class, NO, @selector(makeKeyAndOrderFront:), 1.1042 + @selector(pluginInterpose_makeKeyAndOrderFront:)); 1.1043 + ExchangeMethods(nswindow_class, NO, @selector(_setWindowNumber:), 1.1044 + @selector(pluginInterpose_setWindowNumber:)); 1.1045 + 1.1046 + ExchangeMethods([NSApplication class], NO, @selector(runModalForWindow:), 1.1047 + @selector(pluginInterpose_runModalForWindow:)); 1.1048 + 1.1049 + Class nscursor_class = [NSCursor class]; 1.1050 + ExchangeMethods(nscursor_class, NO, @selector(set), 1.1051 + @selector(pluginInterpose_set)); 1.1052 + ExchangeMethods(nscursor_class, NO, @selector(push), 1.1053 + @selector(pluginInterpose_push)); 1.1054 + ExchangeMethods(nscursor_class, NO, @selector(pop), 1.1055 + @selector(pluginInterpose_pop)); 1.1056 + ExchangeMethods(nscursor_class, YES, @selector(currentCursor), 1.1057 + @selector(pluginInterpose_currentCursor)); 1.1058 + ExchangeMethods(nscursor_class, YES, @selector(hide), 1.1059 + @selector(pluginInterpose_hide)); 1.1060 + ExchangeMethods(nscursor_class, YES, @selector(unhide), 1.1061 + @selector(pluginInterpose_unhide)); 1.1062 + ExchangeMethods(nscursor_class, YES, @selector(pop), 1.1063 + @selector(pluginInterpose_pop)); 1.1064 +} 1.1065 + 1.1066 +} // namespace child 1.1067 +} // namespace mac_plugin_interposing 1.1068 + 1.1069 +// Called from plugin_child_interpose.mm, which hooks calls to 1.1070 +// SetCursor() (the QuickDraw call) from the plugin child process. 1.1071 +extern "C" NS_VISIBILITY_DEFAULT BOOL 1.1072 +mac_plugin_interposing_child_OnSetCursor(const Cursor* cursor) 1.1073 +{ 1.1074 + NSCursorInfo info(cursor); 1.1075 + return OnSetCursor(info); 1.1076 +} 1.1077 + 1.1078 +// Called from plugin_child_interpose.mm, which hooks calls to 1.1079 +// SetThemeCursor() (the Appearance Manager call) from the plugin child 1.1080 +// process. 1.1081 +extern "C" NS_VISIBILITY_DEFAULT BOOL 1.1082 +mac_plugin_interposing_child_OnSetThemeCursor(ThemeCursor cursor) 1.1083 +{ 1.1084 + NSCursorInfo info; 1.1085 + switch (cursor) { 1.1086 + case kThemeArrowCursor: 1.1087 + info.SetType(NSCursorInfo::TypeArrow); 1.1088 + break; 1.1089 + case kThemeCopyArrowCursor: 1.1090 + info.SetType(NSCursorInfo::TypeDragCopy); 1.1091 + break; 1.1092 + case kThemeAliasArrowCursor: 1.1093 + info.SetType(NSCursorInfo::TypeDragLink); 1.1094 + break; 1.1095 + case kThemeContextualMenuArrowCursor: 1.1096 + info.SetType(NSCursorInfo::TypeContextualMenu); 1.1097 + break; 1.1098 + case kThemeIBeamCursor: 1.1099 + info.SetType(NSCursorInfo::TypeIBeam); 1.1100 + break; 1.1101 + case kThemeCrossCursor: 1.1102 + case kThemePlusCursor: 1.1103 + info.SetType(NSCursorInfo::TypeCrosshair); 1.1104 + break; 1.1105 + case kThemeWatchCursor: 1.1106 + case kThemeSpinningCursor: 1.1107 + info.SetType(NSCursorInfo::TypeArrow); 1.1108 + break; 1.1109 + case kThemeClosedHandCursor: 1.1110 + info.SetType(NSCursorInfo::TypeClosedHand); 1.1111 + break; 1.1112 + case kThemeOpenHandCursor: 1.1113 + info.SetType(NSCursorInfo::TypeOpenHand); 1.1114 + break; 1.1115 + case kThemePointingHandCursor: 1.1116 + case kThemeCountingUpHandCursor: 1.1117 + case kThemeCountingDownHandCursor: 1.1118 + case kThemeCountingUpAndDownHandCursor: 1.1119 + info.SetType(NSCursorInfo::TypePointingHand); 1.1120 + break; 1.1121 + case kThemeResizeLeftCursor: 1.1122 + info.SetType(NSCursorInfo::TypeResizeLeft); 1.1123 + break; 1.1124 + case kThemeResizeRightCursor: 1.1125 + info.SetType(NSCursorInfo::TypeResizeRight); 1.1126 + break; 1.1127 + case kThemeResizeLeftRightCursor: 1.1128 + info.SetType(NSCursorInfo::TypeResizeLeftRight); 1.1129 + break; 1.1130 + case kThemeNotAllowedCursor: 1.1131 + info.SetType(NSCursorInfo::TypeNotAllowed); 1.1132 + break; 1.1133 + case kThemeResizeUpCursor: 1.1134 + info.SetType(NSCursorInfo::TypeResizeUp); 1.1135 + break; 1.1136 + case kThemeResizeDownCursor: 1.1137 + info.SetType(NSCursorInfo::TypeResizeDown); 1.1138 + break; 1.1139 + case kThemeResizeUpDownCursor: 1.1140 + info.SetType(NSCursorInfo::TypeResizeUpDown); 1.1141 + break; 1.1142 + case kThemePoofCursor: 1.1143 + info.SetType(NSCursorInfo::TypeDisappearingItem); 1.1144 + break; 1.1145 + default: 1.1146 + info.SetType(NSCursorInfo::TypeArrow); 1.1147 + break; 1.1148 + } 1.1149 + return OnSetCursor(info); 1.1150 +} 1.1151 + 1.1152 +extern "C" NS_VISIBILITY_DEFAULT BOOL 1.1153 +mac_plugin_interposing_child_OnHideCursor() 1.1154 +{ 1.1155 + return OnHideCursor(); 1.1156 +} 1.1157 + 1.1158 +extern "C" NS_VISIBILITY_DEFAULT BOOL 1.1159 +mac_plugin_interposing_child_OnShowCursor() 1.1160 +{ 1.1161 + return OnUnhideCursor(); 1.1162 +}