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 <wtf/StdLibExtras.h> 31 32@interface WebCoreCursorBundle : NSObject { } 33@end 34 35@implementation WebCoreCursorBundle 36@end 37 38namespace WebCore { 39 40// Simple NSCursor calls shouldn't need protection, 41// but creating a cursor with a bad image might throw. 42 43static RetainPtr<NSCursor> createCustomCursor(Image* image, const IntPoint& hotSpot) 44{ 45 // FIXME: The cursor won't animate. Not sure if that's a big deal. 46 NSImage* nsImage = image->getNSImage(); 47 if (!nsImage) 48 return 0; 49 BEGIN_BLOCK_OBJC_EXCEPTIONS; 50 return RetainPtr<NSCursor>(AdoptNS, [[NSCursor alloc] initWithImage:nsImage hotSpot:hotSpot]); 51 END_BLOCK_OBJC_EXCEPTIONS; 52 return 0; 53} 54 55// Leak these cursors intentionally, that way we won't waste time trying to clean them 56// up at process exit time. 57static NSCursor* leakNamedCursor(const char* name, int x, int y) 58{ 59 BEGIN_BLOCK_OBJC_EXCEPTIONS; 60 NSString* resourceName = [[NSString alloc] initWithUTF8String:name]; 61 NSImage* cursorImage = [[NSImage alloc] initWithContentsOfFile: 62 [[NSBundle bundleForClass:[WebCoreCursorBundle class]] 63 pathForResource:resourceName ofType:@"png"]]; 64 [resourceName release]; 65 NSCursor* cursor = 0; 66 if (cursorImage) { 67 NSPoint hotSpotPoint = {x, y}; // workaround for 4213314 68 cursor = [[NSCursor alloc] initWithImage:cursorImage hotSpot:hotSpotPoint]; 69 [cursorImage release]; 70 } 71 return cursor; 72 END_BLOCK_OBJC_EXCEPTIONS; 73 return nil; 74} 75 76void Cursor::ensurePlatformCursor() const 77{ 78 if (m_platformCursor) 79 return; 80 81 switch (m_type) { 82 case Cursor::Pointer: 83 m_platformCursor = [NSCursor arrowCursor]; 84 break; 85 case Cursor::Cross: 86 m_platformCursor = leakNamedCursor("crossHairCursor", 11, 11); 87 break; 88 case Cursor::Hand: 89 m_platformCursor = leakNamedCursor("linkCursor", 6, 1); 90 break; 91 case Cursor::IBeam: 92 m_platformCursor = [NSCursor IBeamCursor]; 93 break; 94 case Cursor::Wait: 95 m_platformCursor = leakNamedCursor("waitCursor", 7, 7); 96 break; 97 case Cursor::Help: 98 m_platformCursor = leakNamedCursor("helpCursor", 8, 8); 99 break; 100 case Cursor::Move: 101 case Cursor::MiddlePanning: 102 m_platformCursor = leakNamedCursor("moveCursor", 7, 7); 103 break; 104 case Cursor::EastResize: 105 case Cursor::EastPanning: 106 m_platformCursor = leakNamedCursor("eastResizeCursor", 14, 7); 107 break; 108 case Cursor::NorthResize: 109 case Cursor::NorthPanning: 110 m_platformCursor = leakNamedCursor("northResizeCursor", 7, 1); 111 break; 112 case Cursor::NorthEastResize: 113 case Cursor::NorthEastPanning: 114 m_platformCursor = leakNamedCursor("northEastResizeCursor", 14, 1); 115 break; 116 case Cursor::NorthWestResize: 117 case Cursor::NorthWestPanning: 118 m_platformCursor = leakNamedCursor("northWestResizeCursor", 0, 0); 119 break; 120 case Cursor::SouthResize: 121 case Cursor::SouthPanning: 122 m_platformCursor = leakNamedCursor("southResizeCursor", 7, 14); 123 break; 124 case Cursor::SouthEastResize: 125 case Cursor::SouthEastPanning: 126 m_platformCursor = leakNamedCursor("southEastResizeCursor", 14, 14); 127 break; 128 case Cursor::SouthWestResize: 129 case Cursor::SouthWestPanning: 130 m_platformCursor = leakNamedCursor("southWestResizeCursor", 1, 14); 131 break; 132 case Cursor::WestResize: 133 m_platformCursor = leakNamedCursor("westResizeCursor", 1, 7); 134 break; 135 case Cursor::NorthSouthResize: 136 m_platformCursor = leakNamedCursor("northSouthResizeCursor", 7, 7); 137 break; 138 case Cursor::EastWestResize: 139 case Cursor::WestPanning: 140 m_platformCursor = leakNamedCursor("eastWestResizeCursor", 7, 7); 141 break; 142 case Cursor::NorthEastSouthWestResize: 143 m_platformCursor = leakNamedCursor("northEastSouthWestResizeCursor", 7, 7); 144 break; 145 case Cursor::NorthWestSouthEastResize: 146 m_platformCursor = leakNamedCursor("northWestSouthEastResizeCursor", 7, 7); 147 break; 148 case Cursor::ColumnResize: 149 m_platformCursor = [NSCursor resizeLeftRightCursor]; 150 break; 151 case Cursor::RowResize: 152 m_platformCursor = [NSCursor resizeUpDownCursor]; 153 break; 154 case Cursor::VerticalText: 155 m_platformCursor = leakNamedCursor("verticalTextCursor", 7, 7); 156 break; 157 case Cursor::Cell: 158 m_platformCursor = leakNamedCursor("cellCursor", 7, 7); 159 break; 160 case Cursor::ContextMenu: 161 m_platformCursor = leakNamedCursor("contextMenuCursor", 3, 2); 162 break; 163 case Cursor::Alias: 164 m_platformCursor = leakNamedCursor("aliasCursor", 11, 3); 165 break; 166 case Cursor::Progress: 167 m_platformCursor = leakNamedCursor("progressCursor", 3, 2); 168 break; 169 case Cursor::NoDrop: 170 m_platformCursor = leakNamedCursor("noDropCursor", 3, 1); 171 break; 172 case Cursor::Copy: 173 m_platformCursor = leakNamedCursor("copyCursor", 3, 2); 174 break; 175 case Cursor::None: 176 m_platformCursor = leakNamedCursor("noneCursor", 7, 7); 177 break; 178 case Cursor::NotAllowed: 179 m_platformCursor = leakNamedCursor("notAllowedCursor", 11, 11); 180 break; 181 case Cursor::ZoomIn: 182 m_platformCursor = leakNamedCursor("zoomInCursor", 7, 7); 183 break; 184 case Cursor::ZoomOut: 185 m_platformCursor = leakNamedCursor("zoomOutCursor", 7, 7); 186 break; 187 case Cursor::Grab: 188 m_platformCursor = [NSCursor openHandCursor]; 189 break; 190 case Cursor::Grabbing: 191 m_platformCursor = [NSCursor closedHandCursor]; 192 break; 193 case Cursor::Custom: 194 m_platformCursor = createCustomCursor(m_image.get(), m_hotSpot); 195 break; 196 } 197} 198 199Cursor::Cursor(const Cursor& other) 200 : m_type(other.m_type) 201 , m_image(other.m_image) 202 , m_hotSpot(other.m_hotSpot) 203 , m_platformCursor(other.m_platformCursor) 204{ 205} 206 207Cursor& Cursor::operator=(const Cursor& other) 208{ 209 m_type = other.m_type; 210 m_image = other.m_image; 211 m_hotSpot = other.m_hotSpot; 212 m_platformCursor = other.m_platformCursor; 213 return *this; 214} 215 216Cursor::~Cursor() 217{ 218} 219 220NSCursor *Cursor::platformCursor() const 221{ 222 ensurePlatformCursor(); 223 return m_platformCursor.get(); 224} 225 226} // namespace WebCore 227