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 41 namespace WebCore { 42 43 // Simple NSCursor calls shouldn't need protection, 44 // but creating a cursor with a bad image might throw. 45 46 static 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. 60 static 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 79 Cursor::Cursor(Image* image, const IntPoint& hotspot) 80 : m_impl(HardRetainWithNSRelease(createCustomCursor(image, hotspot))) 81 { 82 } 83 84 Cursor::Cursor(const Cursor& other) 85 : m_impl(HardRetain(other.m_impl)) 86 { 87 } 88 89 Cursor::~Cursor() 90 { 91 HardRelease(m_impl); 92 } 93 94 Cursor& 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 102 Cursor::Cursor(NSCursor* c) 103 : m_impl(HardRetain(c)) 104 { 105 } 106 107 const Cursor& pointerCursor() 108 { 109 DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor arrowCursor])); 110 return c; 111 } 112 113 const Cursor& crossCursor() 114 { 115 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("crossHairCursor", 11, 11))); 116 return c; 117 } 118 119 const Cursor& handCursor() 120 { 121 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("linkCursor", 6, 1))); 122 return c; 123 } 124 125 const Cursor& moveCursor() 126 { 127 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("moveCursor", 7, 7))); 128 return c; 129 } 130 131 const Cursor& verticalTextCursor() 132 { 133 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("verticalTextCursor", 7, 7))); 134 return c; 135 } 136 137 const Cursor& cellCursor() 138 { 139 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("cellCursor", 7, 7))); 140 return c; 141 } 142 143 const Cursor& contextMenuCursor() 144 { 145 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("contextMenuCursor", 3, 2))); 146 return c; 147 } 148 149 const Cursor& aliasCursor() 150 { 151 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("aliasCursor", 11, 3))); 152 return c; 153 } 154 155 const Cursor& zoomInCursor() 156 { 157 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("zoomInCursor", 7, 7))); 158 return c; 159 } 160 161 const Cursor& zoomOutCursor() 162 { 163 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("zoomOutCursor", 7, 7))); 164 return c; 165 } 166 167 const Cursor& copyCursor() 168 { 169 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("copyCursor", 3, 2))); 170 return c; 171 } 172 173 const Cursor& noneCursor() 174 { 175 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("noneCursor", 7, 7))); 176 return c; 177 } 178 179 const Cursor& progressCursor() 180 { 181 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("progressCursor", 3, 2))); 182 return c; 183 } 184 185 const Cursor& noDropCursor() 186 { 187 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("noDropCursor", 3, 1))); 188 return c; 189 } 190 191 const Cursor& notAllowedCursor() 192 { 193 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("notAllowedCursor", 11, 11))); 194 return c; 195 } 196 197 const Cursor& iBeamCursor() 198 { 199 DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor IBeamCursor])); 200 return c; 201 } 202 203 const Cursor& waitCursor() 204 { 205 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("waitCursor", 7, 7))); 206 return c; 207 } 208 209 const Cursor& helpCursor() 210 { 211 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("helpCursor", 8, 8))); 212 return c; 213 } 214 215 const Cursor& eastResizeCursor() 216 { 217 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("eastResizeCursor", 14, 7))); 218 return c; 219 } 220 221 const Cursor& northResizeCursor() 222 { 223 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northResizeCursor", 7, 1))); 224 return c; 225 } 226 227 const Cursor& northEastResizeCursor() 228 { 229 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northEastResizeCursor", 14, 1))); 230 return c; 231 } 232 233 const Cursor& northWestResizeCursor() 234 { 235 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northWestResizeCursor", 0, 0))); 236 return c; 237 } 238 239 const Cursor& southResizeCursor() 240 { 241 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("southResizeCursor", 7, 14))); 242 return c; 243 } 244 245 const Cursor& southEastResizeCursor() 246 { 247 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("southEastResizeCursor", 14, 14))); 248 return c; 249 } 250 251 const Cursor& southWestResizeCursor() 252 { 253 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("southWestResizeCursor", 1, 14))); 254 return c; 255 } 256 257 const Cursor& westResizeCursor() 258 { 259 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("westResizeCursor", 1, 7))); 260 return c; 261 } 262 263 const Cursor& northSouthResizeCursor() 264 { 265 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northSouthResizeCursor", 7, 7))); 266 return c; 267 } 268 269 const Cursor& eastWestResizeCursor() 270 { 271 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("eastWestResizeCursor", 7, 7))); 272 return c; 273 } 274 275 const Cursor& northEastSouthWestResizeCursor() 276 { 277 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northEastSouthWestResizeCursor", 7, 7))); 278 return c; 279 } 280 281 const Cursor& northWestSouthEastResizeCursor() 282 { 283 DEFINE_STATIC_LOCAL(Cursor, c, (leakNamedCursor("northWestSouthEastResizeCursor", 7, 7))); 284 return c; 285 } 286 287 const Cursor& columnResizeCursor() 288 { 289 DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor resizeLeftRightCursor])); 290 return c; 291 } 292 293 const Cursor& rowResizeCursor() 294 { 295 DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor resizeUpDownCursor])); 296 return c; 297 } 298 299 const Cursor& middlePanningCursor() 300 { 301 return moveCursor(); 302 } 303 304 const Cursor& eastPanningCursor() 305 { 306 return eastResizeCursor(); 307 } 308 309 const Cursor& northPanningCursor() 310 { 311 return northResizeCursor(); 312 } 313 314 const Cursor& northEastPanningCursor() 315 { 316 return northEastResizeCursor(); 317 } 318 319 const Cursor& northWestPanningCursor() 320 { 321 return northWestResizeCursor(); 322 } 323 324 const Cursor& southPanningCursor() 325 { 326 return southResizeCursor(); 327 } 328 329 const Cursor& southEastPanningCursor() 330 { 331 return southEastResizeCursor(); 332 } 333 334 const Cursor& southWestPanningCursor() 335 { 336 return southWestResizeCursor(); 337 } 338 339 const Cursor& westPanningCursor() 340 { 341 return westResizeCursor(); 342 } 343 344 const Cursor& grabCursor() 345 { 346 DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor openHandCursor])); 347 return c; 348 } 349 350 const Cursor& grabbingCursor() 351 { 352 DEFINE_STATIC_LOCAL(Cursor, c, ([NSCursor closedHandCursor])); 353 return c; 354 } 355 356 } 357