Reviewed by eseidel.
[WebKit-https.git] / WebCore / platform / mac / CursorMac.mm
1 /*
2  * Copyright (C) 2004, 2006 Apple Computer, 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
34 @interface WebCoreCursorBundle : NSObject { }
35 @end
36
37 @implementation WebCoreCursorBundle
38 @end
39
40 namespace WebCore {
41
42 // Simple NSCursor calls shouldn't need protection,
43 // but creating a cursor with a bad image might throw.
44
45 static NSCursor* createCustomCursor(Image* image, const IntPoint& hotspot)
46 {
47     // FIXME: The cursor won't animate.  Not sure if that's a big deal.
48     NSImage* img = image->getNSImage();
49     if (!img)
50         return 0;
51     BEGIN_BLOCK_OBJC_EXCEPTIONS;
52     return [[NSCursor alloc] initWithImage:img hotSpot:hotspot];
53     END_BLOCK_OBJC_EXCEPTIONS;
54     return 0;
55 }
56
57 // Leak these cursors intentionally, that way we won't waste time trying to clean them
58 // up at process exit time.
59 static NSCursor* leakNamedCursor(const char* name, int x, int y)
60 {
61     BEGIN_BLOCK_OBJC_EXCEPTIONS;
62     NSString* resourceName = [[NSString alloc] initWithUTF8String:name];
63     NSImage* cursorImage = [[NSImage alloc] initWithContentsOfFile:
64         [[NSBundle bundleForClass:[WebCoreCursorBundle class]]
65         pathForResource:resourceName ofType:@"tiff"]];
66     [resourceName release];
67     NSCursor* cursor = 0;
68     if (cursorImage) {
69         NSPoint hotSpotPoint = {x, y}; // workaround for 4213314
70         cursor = [[NSCursor alloc] initWithImage:cursorImage hotSpot:hotSpotPoint];
71         [cursorImage release];
72     }
73     return cursor;
74     END_BLOCK_OBJC_EXCEPTIONS;
75     return 0;
76 }
77
78 Cursor::Cursor(Image* image, const IntPoint& hotspot)
79     : m_impl(HardRetainWithNSRelease(createCustomCursor(image, hotspot)))
80 {
81 }
82
83 Cursor::Cursor(const Cursor& other)
84     : m_impl(HardRetain(other.m_impl))
85 {
86 }
87
88 Cursor::~Cursor()
89 {
90     HardRelease(m_impl);
91 }
92
93 Cursor& Cursor::operator=(const Cursor& other)
94 {
95     HardRetain(other.m_impl);
96     HardRelease(m_impl);
97     m_impl = other.m_impl;
98     return *this;
99 }
100
101 Cursor::Cursor(NSCursor* c)
102     : m_impl(HardRetain(c))
103 {
104 }
105
106 const Cursor& crossCursor()
107 {
108     static Cursor c = [NSCursor crosshairCursor];
109     return c;
110 }
111
112 const Cursor& handCursor()
113 {
114     // FIXME: Use [NSCursor pointingHandCursor]?
115     static Cursor c = leakNamedCursor("linkCursor", 6, 1);
116     return c;
117 }
118
119 const Cursor& moveCursor()
120 {
121     static Cursor c = leakNamedCursor("moveCursor", 7, 7);
122     return c;
123 }
124
125 const Cursor& iBeamCursor()
126 {
127     static Cursor c = [NSCursor IBeamCursor];
128     return c;
129 }
130
131 const Cursor& waitCursor()
132 {
133     static Cursor c = leakNamedCursor("waitCursor", 7, 7);
134     return c;
135 }
136
137 const Cursor& helpCursor()
138 {
139     static Cursor c = leakNamedCursor("helpCursor", 8, 8);
140     return c;
141 }
142
143 const Cursor& eastResizeCursor()
144 {
145     static Cursor c = leakNamedCursor("eastResizeCursor", 14, 7);
146     return c;
147 }
148
149 const Cursor& northResizeCursor()
150 {
151     static Cursor c = leakNamedCursor("northResizeCursor", 7, 1);
152     return c;
153 }
154
155 const Cursor& northEastResizeCursor()
156 {
157     static Cursor c = leakNamedCursor("northEastResizeCursor", 14, 1);
158     return c;
159 }
160
161 const Cursor& northWestResizeCursor()
162 {
163     static Cursor c = leakNamedCursor("northWestResizeCursor", 0, 0);
164     return c;
165 }
166
167 const Cursor& southResizeCursor()
168 {
169     static Cursor c = leakNamedCursor("southResizeCursor", 7, 14);
170     return c;
171 }
172
173 const Cursor& southEastResizeCursor()
174 {
175     static Cursor c = leakNamedCursor("southEastResizeCursor", 14, 14);
176     return c;
177 }
178
179 const Cursor& southWestResizeCursor()
180 {
181     static Cursor c = leakNamedCursor("southWestResizeCursor", 1, 14);
182     return c;
183 }
184
185 const Cursor& westResizeCursor()
186 {
187     static Cursor c = leakNamedCursor("westResizeCursor", 1, 7);
188     return c;
189 }
190
191 const Cursor& northSouthResizeCursor()
192 {
193     static Cursor c = leakNamedCursor("northSouthResizeCursor", 7, 7);
194     return c;
195 }
196
197 const Cursor& eastWestResizeCursor()
198 {
199     static Cursor c = leakNamedCursor("eastWestResizeCursor", 7, 7);
200     return c;
201 }
202
203 const Cursor& northEastSouthWestResizeCursor()
204 {
205     static Cursor c = leakNamedCursor("northEastSouthWestResizeCursor", 7, 7);
206     return c;
207 }
208
209 const Cursor& northWestSouthEastResizeCursor()
210 {
211     static Cursor c = leakNamedCursor("northWestSouthEastResizeCursor", 7, 7);
212     return c;
213 }
214
215 const Cursor& columnResizeCursor()
216 {
217     static Cursor c = [NSCursor resizeLeftRightCursor];
218     return c;
219 }
220
221 const Cursor& rowResizeCursor()
222 {
223     static Cursor c = [NSCursor resizeUpDownCursor];
224     return c;
225 }
226
227 }