JavaScriptCore:
[WebKit-https.git] / WebCore / platform / win / CursorWin.cpp
1 /*
2  * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
3  * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "Cursor.h"
29
30 #include "Image.h"
31 #include "IntPoint.h"
32
33 #include <wtf/OwnPtr.h>
34
35 #include <windows.h>
36
37 #define ALPHA_CURSORS
38
39 namespace WebCore {
40
41 Cursor::Cursor(const Cursor& other)
42     : m_impl(other.m_impl)
43 {
44 }
45
46 static inline bool supportsAlphaCursors() 
47 {
48     OSVERSIONINFO osinfo = {0};
49     osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
50     GetVersionEx(&osinfo);
51     return osinfo.dwMajorVersion > 5 || (osinfo.dwMajorVersion == 5 && osinfo.dwMinorVersion > 0);
52 }
53
54 Cursor::Cursor(Image* img, const IntPoint& hotspot) 
55
56     static bool doAlpha = supportsAlphaCursors();
57     BITMAPINFO cursorImage = {0};
58     cursorImage.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
59     cursorImage.bmiHeader.biWidth = img->width();
60     cursorImage.bmiHeader.biHeight = img->height();
61     cursorImage.bmiHeader.biPlanes = 1;
62     cursorImage.bmiHeader.biBitCount = 32;
63     cursorImage.bmiHeader.biCompression = BI_RGB;
64     HDC dc = GetDC(0);
65     HDC workingDC = CreateCompatibleDC(dc);
66     if (doAlpha) {
67         OwnPtr<HBITMAP> hCursor(CreateDIBSection(dc, (BITMAPINFO *)&cursorImage, DIB_RGB_COLORS, 0, 0, 0));
68         ASSERT(hCursor);
69
70         img->getHBITMAP(hCursor.get()); 
71         HBITMAP hOldBitmap = (HBITMAP)SelectObject(workingDC, hCursor.get());
72         SetBkMode(workingDC, TRANSPARENT);
73         SelectObject(workingDC, hOldBitmap);
74
75         OwnPtr<HBITMAP> hMask(CreateBitmap(img->width(), img->height(), 1, 1, NULL));
76
77         ICONINFO ii;
78         ii.fIcon = FALSE;
79         ii.xHotspot = hotspot.x();
80         ii.yHotspot = hotspot.y();
81         ii.hbmMask = hMask.get();
82         ii.hbmColor = hCursor.get();
83
84         m_impl = new SharedCursor(CreateIconIndirect(&ii));
85     } else {
86         // Platform doesn't support alpha blended cursors, so we need
87         // to create the mask manually
88         HDC andMaskDC = CreateCompatibleDC(dc);
89         HDC xorMaskDC = CreateCompatibleDC(dc);
90         OwnPtr<HBITMAP> hCursor(CreateDIBSection(dc, &cursorImage, DIB_RGB_COLORS, 0, 0, 0));
91         ASSERT(hCursor);
92         img->getHBITMAP(hCursor.get()); 
93         BITMAP cursor;
94         GetObject(hCursor.get(), sizeof(BITMAP), &cursor);
95         OwnPtr<HBITMAP> andMask(CreateBitmap(cursor.bmWidth, cursor.bmHeight, 1, 1, NULL));
96         OwnPtr<HBITMAP> xorMask(CreateCompatibleBitmap(dc, cursor.bmWidth, cursor.bmHeight));
97         HBITMAP oldCursor = (HBITMAP)SelectObject(workingDC, hCursor.get());
98         HBITMAP oldAndMask = (HBITMAP)SelectObject(andMaskDC, andMask.get());
99         HBITMAP oldXorMask = (HBITMAP)SelectObject(xorMaskDC, xorMask.get());
100
101         SetBkColor(workingDC, RGB(0,0,0));  
102         BitBlt(andMaskDC, 0, 0, cursor.bmWidth, cursor.bmHeight, workingDC, 0, 0, SRCCOPY);
103     
104         SetBkColor(xorMaskDC, RGB(255, 255, 255));
105         SetTextColor(xorMaskDC, RGB(255, 255, 255));
106         BitBlt(xorMaskDC, 0, 0, cursor.bmWidth, cursor.bmHeight, andMaskDC, 0, 0, SRCCOPY);
107         BitBlt(xorMaskDC, 0, 0, cursor.bmWidth, cursor.bmHeight, workingDC, 0,0, SRCAND);
108
109         SelectObject(workingDC, oldCursor);
110         SelectObject(andMaskDC, oldAndMask);
111         SelectObject(xorMaskDC, oldXorMask);
112
113         ICONINFO icon = {0};
114         icon.fIcon = FALSE;
115         icon.xHotspot = hotspot.x();
116         icon.yHotspot = hotspot.y();
117         icon.hbmMask = andMask.get();
118         icon.hbmColor = xorMask.get();
119         m_impl = new SharedCursor(CreateIconIndirect(&icon));
120
121         DeleteDC(xorMaskDC);
122         DeleteDC(andMaskDC);
123     }
124     DeleteDC(workingDC);
125     ReleaseDC(0, dc);
126 }
127
128 Cursor::~Cursor()
129 {
130 }
131
132 Cursor& Cursor::operator=(const Cursor& other)
133 {
134     m_impl = other.m_impl;
135     return *this;
136 }
137
138 Cursor::Cursor(PlatformCursor c)
139     : m_impl(c)
140 {
141 }
142
143 static Cursor loadCursorByName(char* name, int x, int y) 
144 {
145     IntPoint hotSpot(x, y);
146     Cursor c;
147     OwnPtr<Image> cursorImage(Image::loadPlatformResource(name));
148     if (cursorImage && !cursorImage->isNull()) 
149         c = Cursor(cursorImage.get(), hotSpot);
150     else
151         c = pointerCursor();
152     return c;
153 }
154
155 static PassRefPtr<SharedCursor> loadSharedCursor(HINSTANCE hInstance, LPCTSTR lpCursorName)
156 {
157     return new SharedCursor(LoadCursor(hInstance, lpCursorName));
158 }
159
160 const Cursor& pointerCursor()
161 {
162     static Cursor c = loadSharedCursor(0, IDC_ARROW);
163     return c;
164 }
165
166 const Cursor& crossCursor()
167 {
168     static Cursor c = loadSharedCursor(0, IDC_CROSS);
169     return c;
170 }
171
172 const Cursor& handCursor()
173 {
174     static Cursor c = loadSharedCursor(0, IDC_HAND);
175     return c;
176 }
177
178 const Cursor& iBeamCursor()
179 {
180     static Cursor c = loadSharedCursor(0, IDC_IBEAM);
181     return c;
182 }
183
184 const Cursor& waitCursor()
185 {
186     static Cursor c = loadSharedCursor(0, IDC_WAIT);
187     return c;
188 }
189
190 const Cursor& helpCursor()
191 {
192     static Cursor c = loadSharedCursor(0, IDC_HELP);
193     return c;
194 }
195
196 const Cursor& eastResizeCursor()
197 {
198     static Cursor c = loadSharedCursor(0, IDC_SIZEWE);
199     return c;
200 }
201
202 const Cursor& northResizeCursor()
203 {
204     static Cursor c = loadSharedCursor(0, IDC_SIZENS);
205     return c;
206 }
207
208 const Cursor& northEastResizeCursor()
209 {
210     static Cursor c = loadSharedCursor(0, IDC_SIZENESW);
211     return c;
212 }
213
214 const Cursor& northWestResizeCursor()
215 {
216     static Cursor c = loadSharedCursor(0, IDC_SIZENWSE);
217     return c;
218 }
219
220 const Cursor& southResizeCursor()
221 {
222     static Cursor c = loadSharedCursor(0, IDC_SIZENS);
223     return c;
224 }
225
226 const Cursor& southEastResizeCursor()
227 {
228     static Cursor c = loadSharedCursor(0, IDC_SIZENWSE);
229     return c;
230 }
231
232 const Cursor& southWestResizeCursor()
233 {
234     static Cursor c = loadSharedCursor(0, IDC_SIZENESW);
235     return c;
236 }
237
238 const Cursor& westResizeCursor()
239 {
240     static Cursor c = loadSharedCursor(0, IDC_SIZEWE);
241     return c;
242 }
243
244 const Cursor& northSouthResizeCursor()
245 {
246     static Cursor c = loadSharedCursor(0, IDC_SIZENS);
247     return c;
248 }
249
250 const Cursor& eastWestResizeCursor()
251 {
252     static Cursor c = loadSharedCursor(0, IDC_SIZEWE);
253     return c;
254 }
255
256 const Cursor& northEastSouthWestResizeCursor()
257 {
258     static Cursor c = loadSharedCursor(0, IDC_SIZENESW);
259     return c;
260 }
261
262 const Cursor& northWestSouthEastResizeCursor()
263 {
264     static Cursor c = loadSharedCursor(0, IDC_SIZENWSE);
265     return c;
266 }
267
268 const Cursor& columnResizeCursor()
269 {
270     // FIXME: Windows does not have a standard column resize cursor <rdar://problem/5018591>
271     static Cursor c = loadSharedCursor(0, IDC_SIZEWE);
272     return c;
273 }
274
275 const Cursor& rowResizeCursor()
276 {
277     // FIXME: Windows does not have a standard row resize cursor <rdar://problem/5018591>
278     static Cursor c = loadSharedCursor(0, IDC_SIZENS);
279     return c;
280 }
281
282 const Cursor& moveCursor() 
283 {
284     static Cursor c = loadSharedCursor(0, IDC_SIZEALL);
285     return c;
286 }
287
288 const Cursor& verticalTextCursor()
289 {
290     static const Cursor c = loadCursorByName("verticalTextCursor", 7, 7);
291     return c;
292 }
293
294 const Cursor& cellCursor()
295 {
296     return pointerCursor();
297 }
298
299 const Cursor& contextMenuCursor()
300 {
301     return pointerCursor();
302 }
303
304 const Cursor& aliasCursor()
305 {
306     return pointerCursor();
307 }
308
309 const Cursor& progressCursor()
310 {
311     static Cursor c = loadSharedCursor(0, IDC_APPSTARTING);
312     return c;
313 }
314
315 const Cursor& noDropCursor()
316 {
317     static Cursor c = loadSharedCursor(0, IDC_NO);
318     return c;
319 }
320
321 const Cursor& copyCursor()
322 {
323     return pointerCursor();
324 }
325
326 const Cursor& noneCursor()
327 {
328     return pointerCursor();
329 }
330
331 const Cursor& notAllowedCursor()
332 {
333     static Cursor c = loadSharedCursor(0, IDC_NO);
334     return c;
335 }
336
337 const Cursor& zoomInCursor()
338 {
339     static const Cursor c = loadCursorByName("zoomInCursor", 7, 7);
340     return c;
341 }
342
343 const Cursor& zoomOutCursor()
344 {
345     static const Cursor c = loadCursorByName("zoomOutCursor", 7, 7);
346     return c;
347 }
348
349 }