Home | History | Annotate | Download | only in win
      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