<http://webkit.org/b/91015> Remove BUILDING_ON / TARGETING macros in favor of system...
[WebKit-https.git] / Source / WebCore / platform / mac / CursorMac.mm
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
39 namespace WebCore {
40
41 // Simple NSCursor calls shouldn't need protection,
42 // but creating a cursor with a bad image might throw.
43
44 static 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 RetainPtr<NSCursor>(AdoptNS, [[NSCursor alloc] initWithImage:nsImage hotSpot:hotSpot]);
52     END_BLOCK_OBJC_EXCEPTIONS;
53     return 0;
54 }
55
56 static 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         NSPoint hotSpotPoint = {x, y}; // workaround for 4213314
66         cursor.adoptNS([[NSCursor alloc] initWithImage:cursorImage.get() hotSpot:hotSpotPoint]);
67     }
68     return cursor;
69     END_BLOCK_OBJC_EXCEPTIONS;
70     return nil;
71 }
72
73 void Cursor::ensurePlatformCursor() const
74 {
75     if (m_platformCursor)
76         return;
77
78     switch (m_type) {
79     case Cursor::Pointer:
80         m_platformCursor = [NSCursor arrowCursor];
81         break;
82
83     case Cursor::Cross:
84         m_platformCursor = [NSCursor crosshairCursor];
85         break;
86
87     case Cursor::Hand:
88 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
89         m_platformCursor = [NSCursor pointingHandCursor];
90 #else
91         // The pointingHandCursor from NSCursor does not have a shadow on
92         // older versions of OS X, so use our own custom cursor.
93         m_platformCursor = createNamedCursor("linkCursor", 6, 1);
94 #endif
95         break;
96
97     case Cursor::IBeam:
98         m_platformCursor = [NSCursor IBeamCursor];
99         break;
100
101     case Cursor::Wait:
102 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
103         m_platformCursor = wkCursor("BusyButClickable");
104 #else
105         m_platformCursor = createNamedCursor("waitCursor", 7, 7);
106 #endif
107         break;
108
109     case Cursor::Help:
110 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
111         m_platformCursor = wkCursor("Help");
112         if (m_platformCursor)
113             break;
114 #endif
115         m_platformCursor = createNamedCursor("helpCursor", 8, 8);
116         break;
117
118     case Cursor::Move:
119     case Cursor::MiddlePanning:
120 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
121         m_platformCursor = wkCursor("Move");
122 #else
123         m_platformCursor = createNamedCursor("moveCursor", 7, 7);
124 #endif
125         break;
126
127     case Cursor::EastResize:
128     case Cursor::EastPanning:
129 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
130         m_platformCursor = wkCursor("ResizeEast");
131 #else
132         m_platformCursor = createNamedCursor("eastResizeCursor", 14, 7);
133 #endif
134         break;
135
136     case Cursor::NorthResize:
137     case Cursor::NorthPanning:
138 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
139         m_platformCursor = wkCursor("ResizeNorth");
140 #else
141         m_platformCursor = createNamedCursor("northResizeCursor", 7, 1);
142 #endif
143         break;
144
145     case Cursor::NorthEastResize:
146     case Cursor::NorthEastPanning:
147 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
148         m_platformCursor = wkCursor("ResizeNortheast");
149 #else
150         m_platformCursor = createNamedCursor("northEastResizeCursor", 14, 1);
151 #endif
152         break;
153
154     case Cursor::NorthWestResize:
155     case Cursor::NorthWestPanning:
156 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
157         m_platformCursor = wkCursor("ResizeNorthwest");
158 #else
159         m_platformCursor = createNamedCursor("northWestResizeCursor", 0, 0);
160 #endif
161         break;
162
163     case Cursor::SouthResize:
164     case Cursor::SouthPanning:
165 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
166         m_platformCursor = wkCursor("ResizeSouth");
167 #else
168         m_platformCursor = createNamedCursor("southResizeCursor", 7, 14);
169 #endif
170         break;
171
172     case Cursor::SouthEastResize:
173     case Cursor::SouthEastPanning:
174 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
175         m_platformCursor = wkCursor("ResizeSoutheast");
176 #else
177         m_platformCursor = createNamedCursor("southEastResizeCursor", 14, 14);
178 #endif
179         break;
180
181     case Cursor::SouthWestResize:
182     case Cursor::SouthWestPanning:
183 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
184         m_platformCursor = wkCursor("ResizeSouthwest");
185 #else
186         m_platformCursor = createNamedCursor("southWestResizeCursor", 1, 14);
187 #endif
188         break;
189
190     case Cursor::WestResize:
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     case Cursor::WestPanning:
208 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
209         m_platformCursor = wkCursor("ResizeEastWest");
210 #else
211         m_platformCursor = createNamedCursor("eastWestResizeCursor", 7, 7);
212 #endif
213         break;
214
215     case Cursor::NorthEastSouthWestResize:
216 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
217         m_platformCursor = wkCursor("ResizeNortheastSouthwest");
218 #else
219         m_platformCursor = createNamedCursor("northEastSouthWestResizeCursor", 7, 7);
220 #endif
221         break;
222
223     case Cursor::NorthWestSouthEastResize:
224 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
225         m_platformCursor = wkCursor("ResizeNorthwestSoutheast");
226 #else
227         m_platformCursor = createNamedCursor("northWestSouthEastResizeCursor", 7, 7);
228 #endif
229         break;
230
231     case Cursor::ColumnResize:
232         m_platformCursor = [NSCursor resizeLeftRightCursor];
233         break;
234
235     case Cursor::RowResize:
236         m_platformCursor = [NSCursor resizeUpDownCursor];
237         break;
238
239     case Cursor::VerticalText:
240 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
241         m_platformCursor = [NSCursor IBeamCursorForVerticalLayout];
242 #else
243         m_platformCursor = createNamedCursor("verticalTextCursor", 7, 7);
244 #endif
245         break;
246
247     case Cursor::Cell:
248 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
249         m_platformCursor = wkCursor("Cell");
250         if (m_platformCursor)
251             break;
252 #endif
253         m_platformCursor = createNamedCursor("cellCursor", 7, 7);
254         break;
255
256     case Cursor::ContextMenu:
257 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
258         m_platformCursor = [NSCursor contextualMenuCursor];
259 #else
260         m_platformCursor = createNamedCursor("contextMenuCursor", 3, 2);
261 #endif
262         break;
263
264     case Cursor::Alias:
265 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
266         m_platformCursor = wkCursor("MakeAlias");
267 #else
268         m_platformCursor = createNamedCursor("aliasCursor", 11, 3);
269 #endif
270         break;
271
272     case Cursor::Progress:
273 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
274         m_platformCursor = wkCursor("BusyButClickable");
275 #else
276         m_platformCursor = createNamedCursor("progressCursor", 3, 2);
277 #endif
278         break;
279
280     case Cursor::NoDrop:
281 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
282         m_platformCursor = [NSCursor operationNotAllowedCursor];
283 #else
284         m_platformCursor = createNamedCursor("noDropCursor", 3, 1);
285 #endif
286         break;
287
288     case Cursor::Copy:
289 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
290         m_platformCursor = [NSCursor dragCopyCursor];
291 #else
292         m_platformCursor = createNamedCursor("copyCursor", 3, 2);
293 #endif
294         break;
295
296     case Cursor::None:
297         m_platformCursor = createNamedCursor("noneCursor", 7, 7);
298         break;
299
300     case Cursor::NotAllowed:
301 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
302         m_platformCursor = [NSCursor operationNotAllowedCursor];
303 #else
304         m_platformCursor = createNamedCursor("notAllowedCursor", 11, 11);
305 #endif
306         break;
307
308     case Cursor::ZoomIn:
309 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
310         m_platformCursor = wkCursor("ZoomIn");
311         if (m_platformCursor)
312             break;
313 #endif
314         m_platformCursor = createNamedCursor("zoomInCursor", 7, 7);
315         break;
316
317     case Cursor::ZoomOut:
318 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
319         m_platformCursor = wkCursor("ZoomOut");
320         if (m_platformCursor)
321             break;
322 #endif
323         m_platformCursor = createNamedCursor("zoomOutCursor", 7, 7);
324         break;
325
326     case Cursor::Grab:
327         m_platformCursor = [NSCursor openHandCursor];
328         break;
329
330     case Cursor::Grabbing:
331         m_platformCursor = [NSCursor closedHandCursor];
332         break;
333
334     case Cursor::Custom:
335         m_platformCursor = createCustomCursor(m_image.get(), m_hotSpot);
336         break;
337     }
338 }
339
340 Cursor::Cursor(const Cursor& other)
341     : m_type(other.m_type)
342     , m_image(other.m_image)
343     , m_hotSpot(other.m_hotSpot)
344     , m_platformCursor(other.m_platformCursor)
345 {
346 }
347
348 Cursor& Cursor::operator=(const Cursor& other)
349 {
350     m_type = other.m_type;
351     m_image = other.m_image;
352     m_hotSpot = other.m_hotSpot;
353     m_platformCursor = other.m_platformCursor;
354     return *this;
355 }
356
357 Cursor::~Cursor()
358 {
359 }
360
361 NSCursor *Cursor::platformCursor() const
362 {
363     ensurePlatformCursor();
364     return m_platformCursor.get();
365 }
366
367 } // namespace WebCore