1/* 2 * Copyright (C) 2004, 2006, 2010 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#import "config.h" 27#import "Cursor.h" 28 29#import "BlockExceptions.h" 30#import "WebCoreSystemInterface.h" 31#import <wtf/StdLibExtras.h> 32 33@interface WebCoreCursorBundle : NSObject { } 34@end 35 36@implementation WebCoreCursorBundle 37@end 38 39namespace WebCore { 40 41// Simple NSCursor calls shouldn't need protection, 42// but creating a cursor with a bad image might throw. 43 44static RetainPtr<NSCursor> createCustomCursor(Image* image, const IntPoint& hotSpot) 45{ 46 // FIXME: The cursor won't animate. Not sure if that's a big deal. 47 NSImage* nsImage = image->getNSImage(); 48 if (!nsImage) 49 return 0; 50 BEGIN_BLOCK_OBJC_EXCEPTIONS; 51 return adoptNS([[NSCursor alloc] initWithImage:nsImage hotSpot:hotSpot]); 52 END_BLOCK_OBJC_EXCEPTIONS; 53 return 0; 54} 55 56static RetainPtr<NSCursor> createNamedCursor(const char* name, int x, int y) 57{ 58 BEGIN_BLOCK_OBJC_EXCEPTIONS; 59 RetainPtr<NSString> resourceName = adoptNS([[NSString alloc] initWithUTF8String:name]); 60 RetainPtr<NSImage> cursorImage = adoptNS([[NSImage alloc] initWithContentsOfFile:[[NSBundle bundleForClass:[WebCoreCursorBundle class]] pathForResource:resourceName.get() ofType:@"png"]]); 61 62 RetainPtr<NSCursor> cursor; 63 64 if (cursorImage) 65 cursor = adoptNS([[NSCursor alloc] initWithImage:cursorImage.get() hotSpot:NSMakePoint(x, y)]); 66 67 return cursor; 68 END_BLOCK_OBJC_EXCEPTIONS; 69 return nil; 70} 71 72void Cursor::ensurePlatformCursor() const 73{ 74 if (m_platformCursor) 75 return; 76 77 switch (m_type) { 78 case Cursor::Pointer: 79 m_platformCursor = [NSCursor arrowCursor]; 80 break; 81 82 case Cursor::Cross: 83 m_platformCursor = [NSCursor crosshairCursor]; 84 break; 85 86 case Cursor::Hand: 87#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 88 m_platformCursor = [NSCursor pointingHandCursor]; 89#else 90 // The pointingHandCursor from NSCursor does not have a shadow on 91 // older versions of OS X, so use our own custom cursor. 92 m_platformCursor = createNamedCursor("linkCursor", 6, 1); 93#endif 94 break; 95 96 case Cursor::IBeam: 97 m_platformCursor = [NSCursor IBeamCursor]; 98 break; 99 100 case Cursor::Wait: 101#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 102 m_platformCursor = wkCursor("BusyButClickable"); 103#else 104 m_platformCursor = createNamedCursor("waitCursor", 7, 7); 105#endif 106 break; 107 108 case Cursor::Help: 109#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 110 m_platformCursor = wkCursor("Help"); 111 if (m_platformCursor) 112 break; 113#endif 114 m_platformCursor = createNamedCursor("helpCursor", 8, 8); 115 break; 116 117 case Cursor::Move: 118 case Cursor::MiddlePanning: 119#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 120 m_platformCursor = wkCursor("Move"); 121#else 122 m_platformCursor = createNamedCursor("moveCursor", 7, 7); 123#endif 124 break; 125 126 case Cursor::EastResize: 127 case Cursor::EastPanning: 128#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 129 m_platformCursor = wkCursor("ResizeEast"); 130#else 131 m_platformCursor = createNamedCursor("eastResizeCursor", 14, 7); 132#endif 133 break; 134 135 case Cursor::NorthResize: 136 case Cursor::NorthPanning: 137#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 138 m_platformCursor = wkCursor("ResizeNorth"); 139#else 140 m_platformCursor = createNamedCursor("northResizeCursor", 7, 1); 141#endif 142 break; 143 144 case Cursor::NorthEastResize: 145 case Cursor::NorthEastPanning: 146#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 147 m_platformCursor = wkCursor("ResizeNortheast"); 148#else 149 m_platformCursor = createNamedCursor("northEastResizeCursor", 14, 1); 150#endif 151 break; 152 153 case Cursor::NorthWestResize: 154 case Cursor::NorthWestPanning: 155#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 156 m_platformCursor = wkCursor("ResizeNorthwest"); 157#else 158 m_platformCursor = createNamedCursor("northWestResizeCursor", 0, 0); 159#endif 160 break; 161 162 case Cursor::SouthResize: 163 case Cursor::SouthPanning: 164#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 165 m_platformCursor = wkCursor("ResizeSouth"); 166#else 167 m_platformCursor = createNamedCursor("southResizeCursor", 7, 14); 168#endif 169 break; 170 171 case Cursor::SouthEastResize: 172 case Cursor::SouthEastPanning: 173#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 174 m_platformCursor = wkCursor("ResizeSoutheast"); 175#else 176 m_platformCursor = createNamedCursor("southEastResizeCursor", 14, 14); 177#endif 178 break; 179 180 case Cursor::SouthWestResize: 181 case Cursor::SouthWestPanning: 182#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 183 m_platformCursor = wkCursor("ResizeSouthwest"); 184#else 185 m_platformCursor = createNamedCursor("southWestResizeCursor", 1, 14); 186#endif 187 break; 188 189 case Cursor::WestResize: 190 case Cursor::WestPanning: 191#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 192 m_platformCursor = wkCursor("ResizeWest"); 193#else 194 m_platformCursor = createNamedCursor("westResizeCursor", 1, 7); 195#endif 196 break; 197 198 case Cursor::NorthSouthResize: 199#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 200 m_platformCursor = wkCursor("ResizeNorthSouth"); 201#else 202 m_platformCursor = createNamedCursor("northSouthResizeCursor", 7, 7); 203#endif 204 break; 205 206 case Cursor::EastWestResize: 207#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 208 m_platformCursor = wkCursor("ResizeEastWest"); 209#else 210 m_platformCursor = createNamedCursor("eastWestResizeCursor", 7, 7); 211#endif 212 break; 213 214 case Cursor::NorthEastSouthWestResize: 215#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 216 m_platformCursor = wkCursor("ResizeNortheastSouthwest"); 217#else 218 m_platformCursor = createNamedCursor("northEastSouthWestResizeCursor", 7, 7); 219#endif 220 break; 221 222 case Cursor::NorthWestSouthEastResize: 223#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 224 m_platformCursor = wkCursor("ResizeNorthwestSoutheast"); 225#else 226 m_platformCursor = createNamedCursor("northWestSouthEastResizeCursor", 7, 7); 227#endif 228 break; 229 230 case Cursor::ColumnResize: 231 m_platformCursor = [NSCursor resizeLeftRightCursor]; 232 break; 233 234 case Cursor::RowResize: 235 m_platformCursor = [NSCursor resizeUpDownCursor]; 236 break; 237 238 case Cursor::VerticalText: 239#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 240 m_platformCursor = [NSCursor IBeamCursorForVerticalLayout]; 241#else 242 m_platformCursor = createNamedCursor("verticalTextCursor", 7, 7); 243#endif 244 break; 245 246 case Cursor::Cell: 247#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 248 m_platformCursor = wkCursor("Cell"); 249 if (m_platformCursor) 250 break; 251#endif 252 m_platformCursor = createNamedCursor("cellCursor", 7, 7); 253 break; 254 255 case Cursor::ContextMenu: 256 m_platformCursor = [NSCursor contextualMenuCursor]; 257 break; 258 259 case Cursor::Alias: 260#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 261 m_platformCursor = wkCursor("MakeAlias"); 262#else 263 m_platformCursor = createNamedCursor("aliasCursor", 11, 3); 264#endif 265 break; 266 267 case Cursor::Progress: 268#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 269 m_platformCursor = wkCursor("BusyButClickable"); 270#else 271 m_platformCursor = createNamedCursor("progressCursor", 3, 2); 272#endif 273 break; 274 275 case Cursor::NoDrop: 276 m_platformCursor = [NSCursor operationNotAllowedCursor]; 277 break; 278 279 case Cursor::Copy: 280 m_platformCursor = [NSCursor dragCopyCursor]; 281 break; 282 283 case Cursor::None: 284 m_platformCursor = createNamedCursor("noneCursor", 7, 7); 285 break; 286 287 case Cursor::NotAllowed: 288 m_platformCursor = [NSCursor operationNotAllowedCursor]; 289 break; 290 291 case Cursor::ZoomIn: 292#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 293 m_platformCursor = wkCursor("ZoomIn"); 294 if (m_platformCursor) 295 break; 296#endif 297 m_platformCursor = createNamedCursor("zoomInCursor", 7, 7); 298 break; 299 300 case Cursor::ZoomOut: 301#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 302 m_platformCursor = wkCursor("ZoomOut"); 303 if (m_platformCursor) 304 break; 305#endif 306 m_platformCursor = createNamedCursor("zoomOutCursor", 7, 7); 307 break; 308 309 case Cursor::Grab: 310 m_platformCursor = [NSCursor openHandCursor]; 311 break; 312 313 case Cursor::Grabbing: 314 m_platformCursor = [NSCursor closedHandCursor]; 315 break; 316 317 case Cursor::Custom: 318 m_platformCursor = createCustomCursor(m_image.get(), m_hotSpot); 319 break; 320 } 321} 322 323Cursor::Cursor(const Cursor& other) 324 : m_type(other.m_type) 325 , m_image(other.m_image) 326 , m_hotSpot(other.m_hotSpot) 327 , m_imageScaleFactor(other.m_imageScaleFactor) 328 , m_platformCursor(other.m_platformCursor) 329{ 330} 331 332Cursor& Cursor::operator=(const Cursor& other) 333{ 334 m_type = other.m_type; 335 m_image = other.m_image; 336 m_hotSpot = other.m_hotSpot; 337 m_imageScaleFactor = other.m_imageScaleFactor; 338 m_platformCursor = other.m_platformCursor; 339 return *this; 340} 341 342Cursor::~Cursor() 343{ 344} 345 346NSCursor *Cursor::platformCursor() const 347{ 348 ensurePlatformCursor(); 349 return m_platformCursor.get(); 350} 351 352} // namespace WebCore 353