1 /* 2 * Copyright (C) 2006 Samuel Weinig (sam.weinig (at) gmail.com) 3 * Copyright (C) 2006, 2007, 2008 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 "BitmapInfo.h" 31 #include "Image.h" 32 #include "IntPoint.h" 33 34 #include <wtf/OwnPtr.h> 35 36 #include <windows.h> 37 38 #define ALPHA_CURSORS 39 40 namespace WebCore { 41 42 Cursor::Cursor(const Cursor& other) 43 : m_impl(other.m_impl) 44 { 45 } 46 47 static inline bool supportsAlphaCursors() 48 { 49 OSVERSIONINFO osinfo = {0}; 50 osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 51 GetVersionEx(&osinfo); 52 return osinfo.dwMajorVersion > 5 || (osinfo.dwMajorVersion == 5 && osinfo.dwMinorVersion > 0); 53 } 54 55 Cursor::Cursor(Image* img, const IntPoint& hotspot) 56 { 57 static bool doAlpha = supportsAlphaCursors(); 58 BitmapInfo cursorImage = BitmapInfo::create(IntSize(img->width(), img->height())); 59 60 HDC dc = GetDC(0); 61 HDC workingDC = CreateCompatibleDC(dc); 62 if (doAlpha) { 63 OwnPtr<HBITMAP> hCursor(CreateDIBSection(dc, (BITMAPINFO *)&cursorImage, DIB_RGB_COLORS, 0, 0, 0)); 64 ASSERT(hCursor); 65 66 img->getHBITMAP(hCursor.get()); 67 HBITMAP hOldBitmap = (HBITMAP)SelectObject(workingDC, hCursor.get()); 68 SetBkMode(workingDC, TRANSPARENT); 69 SelectObject(workingDC, hOldBitmap); 70 71 Vector<unsigned char, 128> maskBits; 72 maskBits.fill(0xff, (img->width() + 7) / 8 * img->height()); 73 OwnPtr<HBITMAP> hMask(CreateBitmap(img->width(), img->height(), 1, 1, maskBits.data())); 74 75 ICONINFO ii; 76 ii.fIcon = FALSE; 77 ii.xHotspot = hotspot.x(); 78 ii.yHotspot = hotspot.y(); 79 ii.hbmMask = hMask.get(); 80 ii.hbmColor = hCursor.get(); 81 82 m_impl = SharedCursor::create(CreateIconIndirect(&ii)); 83 } else { 84 // Platform doesn't support alpha blended cursors, so we need 85 // to create the mask manually 86 HDC andMaskDC = CreateCompatibleDC(dc); 87 HDC xorMaskDC = CreateCompatibleDC(dc); 88 OwnPtr<HBITMAP> hCursor(CreateDIBSection(dc, &cursorImage, DIB_RGB_COLORS, 0, 0, 0)); 89 ASSERT(hCursor); 90 img->getHBITMAP(hCursor.get()); 91 BITMAP cursor; 92 GetObject(hCursor.get(), sizeof(BITMAP), &cursor); 93 OwnPtr<HBITMAP> andMask(CreateBitmap(cursor.bmWidth, cursor.bmHeight, 1, 1, NULL)); 94 OwnPtr<HBITMAP> xorMask(CreateCompatibleBitmap(dc, cursor.bmWidth, cursor.bmHeight)); 95 HBITMAP oldCursor = (HBITMAP)SelectObject(workingDC, hCursor.get()); 96 HBITMAP oldAndMask = (HBITMAP)SelectObject(andMaskDC, andMask.get()); 97 HBITMAP oldXorMask = (HBITMAP)SelectObject(xorMaskDC, xorMask.get()); 98 99 SetBkColor(workingDC, RGB(0,0,0)); 100 BitBlt(andMaskDC, 0, 0, cursor.bmWidth, cursor.bmHeight, workingDC, 0, 0, SRCCOPY); 101 102 SetBkColor(xorMaskDC, RGB(255, 255, 255)); 103 SetTextColor(xorMaskDC, RGB(255, 255, 255)); 104 BitBlt(xorMaskDC, 0, 0, cursor.bmWidth, cursor.bmHeight, andMaskDC, 0, 0, SRCCOPY); 105 BitBlt(xorMaskDC, 0, 0, cursor.bmWidth, cursor.bmHeight, workingDC, 0,0, SRCAND); 106 107 SelectObject(workingDC, oldCursor); 108 SelectObject(andMaskDC, oldAndMask); 109 SelectObject(xorMaskDC, oldXorMask); 110 111 ICONINFO icon = {0}; 112 icon.fIcon = FALSE; 113 icon.xHotspot = hotspot.x(); 114 icon.yHotspot = hotspot.y(); 115 icon.hbmMask = andMask.get(); 116 icon.hbmColor = xorMask.get(); 117 m_impl = SharedCursor::create(CreateIconIndirect(&icon)); 118 119 DeleteDC(xorMaskDC); 120 DeleteDC(andMaskDC); 121 } 122 DeleteDC(workingDC); 123 ReleaseDC(0, dc); 124 } 125 126 Cursor::~Cursor() 127 { 128 } 129 130 Cursor& Cursor::operator=(const Cursor& other) 131 { 132 m_impl = other.m_impl; 133 return *this; 134 } 135 136 Cursor::Cursor(PlatformCursor c) 137 : m_impl(c) 138 { 139 } 140 141 static Cursor loadCursorByName(char* name, int x, int y) 142 { 143 IntPoint hotSpot(x, y); 144 Cursor c; 145 RefPtr<Image> cursorImage(Image::loadPlatformResource(name)); 146 if (cursorImage && !cursorImage->isNull()) 147 c = Cursor(cursorImage.get(), hotSpot); 148 else 149 c = pointerCursor(); 150 return c; 151 } 152 153 static PassRefPtr<SharedCursor> loadSharedCursor(HINSTANCE hInstance, LPCTSTR lpCursorName) 154 { 155 return SharedCursor::create(LoadCursor(hInstance, lpCursorName)); 156 } 157 158 const Cursor& pointerCursor() 159 { 160 static Cursor c = loadSharedCursor(0, IDC_ARROW); 161 return c; 162 } 163 164 const Cursor& crossCursor() 165 { 166 static Cursor c = loadSharedCursor(0, IDC_CROSS); 167 return c; 168 } 169 170 const Cursor& handCursor() 171 { 172 static Cursor c = loadSharedCursor(0, IDC_HAND); 173 return c; 174 } 175 176 const Cursor& iBeamCursor() 177 { 178 static Cursor c = loadSharedCursor(0, IDC_IBEAM); 179 return c; 180 } 181 182 const Cursor& waitCursor() 183 { 184 static Cursor c = loadSharedCursor(0, IDC_WAIT); 185 return c; 186 } 187 188 const Cursor& helpCursor() 189 { 190 static Cursor c = loadSharedCursor(0, IDC_HELP); 191 return c; 192 } 193 194 const Cursor& eastResizeCursor() 195 { 196 static Cursor c = loadSharedCursor(0, IDC_SIZEWE); 197 return c; 198 } 199 200 const Cursor& northResizeCursor() 201 { 202 static Cursor c = loadSharedCursor(0, IDC_SIZENS); 203 return c; 204 } 205 206 const Cursor& northEastResizeCursor() 207 { 208 static Cursor c = loadSharedCursor(0, IDC_SIZENESW); 209 return c; 210 } 211 212 const Cursor& northWestResizeCursor() 213 { 214 static Cursor c = loadSharedCursor(0, IDC_SIZENWSE); 215 return c; 216 } 217 218 const Cursor& southResizeCursor() 219 { 220 static Cursor c = loadSharedCursor(0, IDC_SIZENS); 221 return c; 222 } 223 224 const Cursor& southEastResizeCursor() 225 { 226 static Cursor c = loadSharedCursor(0, IDC_SIZENWSE); 227 return c; 228 } 229 230 const Cursor& southWestResizeCursor() 231 { 232 static Cursor c = loadSharedCursor(0, IDC_SIZENESW); 233 return c; 234 } 235 236 const Cursor& westResizeCursor() 237 { 238 static Cursor c = loadSharedCursor(0, IDC_SIZEWE); 239 return c; 240 } 241 242 const Cursor& northSouthResizeCursor() 243 { 244 static Cursor c = loadSharedCursor(0, IDC_SIZENS); 245 return c; 246 } 247 248 const Cursor& eastWestResizeCursor() 249 { 250 static Cursor c = loadSharedCursor(0, IDC_SIZEWE); 251 return c; 252 } 253 254 const Cursor& northEastSouthWestResizeCursor() 255 { 256 static Cursor c = loadSharedCursor(0, IDC_SIZENESW); 257 return c; 258 } 259 260 const Cursor& northWestSouthEastResizeCursor() 261 { 262 static Cursor c = loadSharedCursor(0, IDC_SIZENWSE); 263 return c; 264 } 265 266 const Cursor& columnResizeCursor() 267 { 268 // FIXME: Windows does not have a standard column resize cursor <rdar://problem/5018591> 269 static Cursor c = loadSharedCursor(0, IDC_SIZEWE); 270 return c; 271 } 272 273 const Cursor& rowResizeCursor() 274 { 275 // FIXME: Windows does not have a standard row resize cursor <rdar://problem/5018591> 276 static Cursor c = loadSharedCursor(0, IDC_SIZENS); 277 return c; 278 } 279 280 const Cursor& middlePanningCursor() 281 { 282 static const Cursor c = loadCursorByName("panIcon", 8, 8); 283 return c; 284 } 285 286 const Cursor& eastPanningCursor() 287 { 288 static const Cursor c = loadCursorByName("panEastCursor", 7, 7); 289 return c; 290 } 291 292 const Cursor& northPanningCursor() 293 { 294 static const Cursor c = loadCursorByName("panNorthCursor", 7, 7); 295 return c; 296 } 297 298 const Cursor& northEastPanningCursor() 299 { 300 static const Cursor c = loadCursorByName("panNorthEastCursor", 7, 7); 301 return c; 302 } 303 304 const Cursor& northWestPanningCursor() 305 { 306 static const Cursor c = loadCursorByName("panNorthWestCursor", 7, 7); 307 return c; 308 } 309 310 const Cursor& southPanningCursor() 311 { 312 static const Cursor c = loadCursorByName("panSouthCursor", 7, 7); 313 return c; 314 } 315 316 const Cursor& southEastPanningCursor() 317 { 318 static const Cursor c = loadCursorByName("panSouthEastCursor", 7, 7); 319 return c; 320 } 321 322 const Cursor& southWestPanningCursor() 323 { 324 static const Cursor c = loadCursorByName("panSouthWestCursor", 7, 7); 325 return c; 326 } 327 328 const Cursor& westPanningCursor() 329 { 330 static const Cursor c = loadCursorByName("panWestCursor", 7, 7); 331 return c; 332 } 333 334 const Cursor& moveCursor() 335 { 336 static Cursor c = loadSharedCursor(0, IDC_SIZEALL); 337 return c; 338 } 339 340 const Cursor& verticalTextCursor() 341 { 342 static const Cursor c = loadCursorByName("verticalTextCursor", 7, 7); 343 return c; 344 } 345 346 const Cursor& cellCursor() 347 { 348 return pointerCursor(); 349 } 350 351 const Cursor& contextMenuCursor() 352 { 353 return pointerCursor(); 354 } 355 356 const Cursor& aliasCursor() 357 { 358 return pointerCursor(); 359 } 360 361 const Cursor& progressCursor() 362 { 363 static Cursor c = loadSharedCursor(0, IDC_APPSTARTING); 364 return c; 365 } 366 367 const Cursor& noDropCursor() 368 { 369 static Cursor c = loadSharedCursor(0, IDC_NO); 370 return c; 371 } 372 373 const Cursor& copyCursor() 374 { 375 return pointerCursor(); 376 } 377 378 const Cursor& noneCursor() 379 { 380 return pointerCursor(); 381 } 382 383 const Cursor& notAllowedCursor() 384 { 385 static Cursor c = loadSharedCursor(0, IDC_NO); 386 return c; 387 } 388 389 const Cursor& zoomInCursor() 390 { 391 static const Cursor c = loadCursorByName("zoomInCursor", 7, 7); 392 return c; 393 } 394 395 const Cursor& zoomOutCursor() 396 { 397 static const Cursor c = loadCursorByName("zoomOutCursor", 7, 7); 398 return c; 399 } 400 401 const Cursor& grabCursor() 402 { 403 return pointerCursor(); 404 } 405 406 const Cursor& grabbingCursor() 407 { 408 return pointerCursor(); 409 } 410 411 SharedCursor::~SharedCursor() 412 { 413 DestroyIcon(m_nativeCursor); 414 } 415 416 } 417