1/* 2 * Copyright (C) 2004, 2006 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 "FoundationExtras.h" 31#import "Image.h" 32#import "IntPoint.h" 33#import <wtf/StdLibExtras.h> 34 35@interface WebCoreCursorBundle : NSObject { } 36@end 37 38@implementation WebCoreCursorBundle 39@end 40 41namespace WebCore { 42 43// Simple NSCursor calls shouldn't need protection, 44// but creating a cursor with a bad image might throw. 45 46static NSCursor* createCustomCursor(Image* image, const IntPoint& hotspot) 47{ 48 // FIXME: The cursor won't animate. Not sure if that's a big deal. 49 NSImage* img = image->getNSImage(); 50 if (!img) 51 return 0; 52 BEGIN_BLOCK_OBJC_EXCEPTIONS; 53 return [[NSCursor alloc] initWithImage:img hotSpot:hotspot]; 54 END_BLOCK_OBJC_EXCEPTIONS; 55 return 0; 56} 57 58// Leak these cursors intentionally, that way we won't waste time trying to clean them 59// up at process exit time. 60static NSCursor* leakNamedCursor(const char* name, int x, int y) 61{ 62 BEGIN_BLOCK_OBJC_EXCEPTIONS; 63 NSString* resourceName = [[NSString alloc] initWithUTF8String:name]; 64 NSImage* cursorImage = [[NSImage alloc] initWithContentsOfFile: 65 [[NSBundle bundleForClass:[WebCoreCursorBundle class]] 66 pathForResource:resourceName ofType:@"png"]]; 67 [resourceName release]; 68 NSCursor* cursor = 0; 69 if (cursorImage) { 70 NSPoint hotSpotPoint = {x, y}; // workaround for 4213314 71 cursor = [[NSCursor alloc] initWithImage:cursorImage hotSpot:hotSpotPoint]; 72 [cursorImage release]; 73 } 74 return cursor; 75 END_BLOCK_OBJC_EXCEPTIONS; 76 return nil; 77} 78 79Cursor::Cursor(Image* image, const IntPoint& hotspot) 80 : m_impl(HardRetainWithNSRelease(createCustomCursor(image, hotspot))) 81{ 82} 83 84Cursor::Cursor(const Cursor& other) 85 : m_impl(HardRetain(other.m_impl)) 86{ 87} 88 89Cursor::~Cursor() 90{ 91 HardRelease(m_impl); 92} 93 94Cursor& Cursor::operator=(const Cursor& other) 95{ 96 HardRetain(other.m_impl); 97 HardRelease(m_impl); 98 m_impl = other.m_impl; 99 return *this; 100} 101 102Cursor::Cursor(NSCursor* c) 103 : m_impl(HardRetain(c)) 104{ 105} 106 107const Cursor& pointerCursor() 108{ 109 DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor arrowCursor])); 110 return c; 111} 112 113const Cursor& crossCursor() 114{ 115 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("crossHairCursor", 11, 11))); 116 return c; 117} 118 119const Cursor& handCursor() 120{ 121 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("linkCursor", 6, 1))); 122 return c; 123} 124 125const Cursor& moveCursor() 126{ 127 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("moveCursor", 7, 7))); 128 return c; 129} 130 131const Cursor& verticalTextCursor() 132{ 133 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("verticalTextCursor", 7, 7))); 134 return c; 135} 136 137const Cursor& cellCursor() 138{ 139 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("cellCursor", 7, 7))); 140 return c; 141} 142 143const Cursor& contextMenuCursor() 144{ 145 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("contextMenuCursor", 3, 2))); 146 return c; 147} 148 149const Cursor& aliasCursor() 150{ 151 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("aliasCursor", 11, 3))); 152 return c; 153} 154 155const Cursor& zoomInCursor() 156{ 157 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("zoomInCursor", 7, 7))); 158 return c; 159} 160 161const Cursor& zoomOutCursor() 162{ 163 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("zoomOutCursor", 7, 7))); 164 return c; 165} 166 167const Cursor& copyCursor() 168{ 169 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("copyCursor", 3, 2))); 170 return c; 171} 172 173const Cursor& noneCursor() 174{ 175 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("noneCursor", 7, 7))); 176 return c; 177} 178 179const Cursor& progressCursor() 180{ 181 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("progressCursor", 3, 2))); 182 return c; 183} 184 185const Cursor& noDropCursor() 186{ 187 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("noDropCursor", 3, 1))); 188 return c; 189} 190 191const Cursor& notAllowedCursor() 192{ 193 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("notAllowedCursor", 11, 11))); 194 return c; 195} 196 197const Cursor& iBeamCursor() 198{ 199 DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor IBeamCursor])); 200 return c; 201} 202 203const Cursor& waitCursor() 204{ 205 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("waitCursor", 7, 7))); 206 return c; 207} 208 209const Cursor& helpCursor() 210{ 211 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("helpCursor", 8, 8))); 212 return c; 213} 214 215const Cursor& eastResizeCursor() 216{ 217 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("eastResizeCursor", 14, 7))); 218 return c; 219} 220 221const Cursor& northResizeCursor() 222{ 223 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northResizeCursor", 7, 1))); 224 return c; 225} 226 227const Cursor& northEastResizeCursor() 228{ 229 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northEastResizeCursor", 14, 1))); 230 return c; 231} 232 233const Cursor& northWestResizeCursor() 234{ 235 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northWestResizeCursor", 0, 0))); 236 return c; 237} 238 239const Cursor& southResizeCursor() 240{ 241 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("southResizeCursor", 7, 14))); 242 return c; 243} 244 245const Cursor& southEastResizeCursor() 246{ 247 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("southEastResizeCursor", 14, 14))); 248 return c; 249} 250 251const Cursor& southWestResizeCursor() 252{ 253 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("southWestResizeCursor", 1, 14))); 254 return c; 255} 256 257const Cursor& westResizeCursor() 258{ 259 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("westResizeCursor", 1, 7))); 260 return c; 261} 262 263const Cursor& northSouthResizeCursor() 264{ 265 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northSouthResizeCursor", 7, 7))); 266 return c; 267} 268 269const Cursor& eastWestResizeCursor() 270{ 271 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("eastWestResizeCursor", 7, 7))); 272 return c; 273} 274 275const Cursor& northEastSouthWestResizeCursor() 276{ 277 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northEastSouthWestResizeCursor", 7, 7))); 278 return c; 279} 280 281const Cursor& northWestSouthEastResizeCursor() 282{ 283 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northWestSouthEastResizeCursor", 7, 7))); 284 return c; 285} 286 287const Cursor& columnResizeCursor() 288{ 289 DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor resizeLeftRightCursor])); 290 return c; 291} 292 293const Cursor& rowResizeCursor() 294{ 295 DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor resizeUpDownCursor])); 296 return c; 297} 298 299const Cursor& middlePanningCursor() 300{ 301 return moveCursor(); 302} 303 304const Cursor& eastPanningCursor() 305{ 306 return eastResizeCursor(); 307} 308 309const Cursor& northPanningCursor() 310{ 311 return northResizeCursor(); 312} 313 314const Cursor& northEastPanningCursor() 315{ 316 return northEastResizeCursor(); 317} 318 319const Cursor& northWestPanningCursor() 320{ 321 return northWestResizeCursor(); 322} 323 324const Cursor& southPanningCursor() 325{ 326 return southResizeCursor(); 327} 328 329const Cursor& southEastPanningCursor() 330{ 331 return southEastResizeCursor(); 332} 333 334const Cursor& southWestPanningCursor() 335{ 336 return southWestResizeCursor(); 337} 338 339const Cursor& westPanningCursor() 340{ 341 return westResizeCursor(); 342} 343 344const Cursor& grabCursor() 345{ 346 DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor openHandCursor])); 347 return c; 348} 349 350const Cursor& grabbingCursor() 351{ 352 DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor closedHandCursor])); 353 return c; 354} 355 356} 357