CursorWin.cpp revision 2bde8e466a4451c7319e3a072d118917957d6554
1/* 2 * Copyright (C) 2006 Samuel Weinig (sam.weinig@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#include "SystemInfo.h" 34 35#include <wtf/OwnPtr.h> 36 37#include <windows.h> 38 39#define ALPHA_CURSORS 40 41namespace WebCore { 42 43static PassRefPtr<SharedCursor> createSharedCursor(Image* img, const IntPoint& hotSpot) 44{ 45 RefPtr<SharedCursor> impl; 46 47 IntPoint effectiveHotSpot = determineHotSpot(img, hotSpot); 48 static bool doAlpha = windowsVersion() >= WindowsXP; 49 BitmapInfo cursorImage = BitmapInfo::create(IntSize(img->width(), img->height())); 50 51 HDC dc = GetDC(0); 52 HDC workingDC = CreateCompatibleDC(dc); 53 if (doAlpha) { 54 OwnPtr<HBITMAP> hCursor(CreateDIBSection(dc, (BITMAPINFO *)&cursorImage, DIB_RGB_COLORS, 0, 0, 0)); 55 ASSERT(hCursor); 56 57 img->getHBITMAP(hCursor.get()); 58 HBITMAP hOldBitmap = (HBITMAP)SelectObject(workingDC, hCursor.get()); 59 SetBkMode(workingDC, TRANSPARENT); 60 SelectObject(workingDC, hOldBitmap); 61 62 Vector<unsigned char, 128> maskBits; 63 maskBits.fill(0xff, (img->width() + 7) / 8 * img->height()); 64 OwnPtr<HBITMAP> hMask(CreateBitmap(img->width(), img->height(), 1, 1, maskBits.data())); 65 66 ICONINFO ii; 67 ii.fIcon = FALSE; 68 ii.xHotspot = effectiveHotSpot.x(); 69 ii.yHotspot = effectiveHotSpot.y(); 70 ii.hbmMask = hMask.get(); 71 ii.hbmColor = hCursor.get(); 72 73 impl = SharedCursor::create(CreateIconIndirect(&ii)); 74 } else { 75 // Platform doesn't support alpha blended cursors, so we need 76 // to create the mask manually 77 HDC andMaskDC = CreateCompatibleDC(dc); 78 HDC xorMaskDC = CreateCompatibleDC(dc); 79 OwnPtr<HBITMAP> hCursor(CreateDIBSection(dc, &cursorImage, DIB_RGB_COLORS, 0, 0, 0)); 80 ASSERT(hCursor); 81 img->getHBITMAP(hCursor.get()); 82 BITMAP cursor; 83 GetObject(hCursor.get(), sizeof(BITMAP), &cursor); 84 OwnPtr<HBITMAP> andMask(CreateBitmap(cursor.bmWidth, cursor.bmHeight, 1, 1, NULL)); 85 OwnPtr<HBITMAP> xorMask(CreateCompatibleBitmap(dc, cursor.bmWidth, cursor.bmHeight)); 86 HBITMAP oldCursor = (HBITMAP)SelectObject(workingDC, hCursor.get()); 87 HBITMAP oldAndMask = (HBITMAP)SelectObject(andMaskDC, andMask.get()); 88 HBITMAP oldXorMask = (HBITMAP)SelectObject(xorMaskDC, xorMask.get()); 89 90 SetBkColor(workingDC, RGB(0,0,0)); 91 BitBlt(andMaskDC, 0, 0, cursor.bmWidth, cursor.bmHeight, workingDC, 0, 0, SRCCOPY); 92 93 SetBkColor(xorMaskDC, RGB(255, 255, 255)); 94 SetTextColor(xorMaskDC, RGB(255, 255, 255)); 95 BitBlt(xorMaskDC, 0, 0, cursor.bmWidth, cursor.bmHeight, andMaskDC, 0, 0, SRCCOPY); 96 BitBlt(xorMaskDC, 0, 0, cursor.bmWidth, cursor.bmHeight, workingDC, 0,0, SRCAND); 97 98 SelectObject(workingDC, oldCursor); 99 SelectObject(andMaskDC, oldAndMask); 100 SelectObject(xorMaskDC, oldXorMask); 101 102 ICONINFO icon = {0}; 103 icon.fIcon = FALSE; 104 icon.xHotspot = effectiveHotSpot.x(); 105 icon.yHotspot = effectiveHotSpot.y(); 106 icon.hbmMask = andMask.get(); 107 icon.hbmColor = xorMask.get(); 108 impl = SharedCursor::create(CreateIconIndirect(&icon)); 109 110 DeleteDC(xorMaskDC); 111 DeleteDC(andMaskDC); 112 } 113 DeleteDC(workingDC); 114 ReleaseDC(0, dc); 115 116 return impl.release(); 117} 118 119static PassRefPtr<SharedCursor> loadSharedCursor(HINSTANCE hInstance, LPCWSTR lpCursorName) 120{ 121 return SharedCursor::create(::LoadCursorW(hInstance, lpCursorName)); 122} 123 124static PassRefPtr<SharedCursor> loadCursorByName(char* name, int x, int y) 125{ 126 IntPoint hotSpot(x, y); 127 RefPtr<Image> cursorImage(Image::loadPlatformResource(name)); 128 if (cursorImage && !cursorImage->isNull()) 129 return createSharedCursor(cursorImage.get(), hotSpot); 130 return loadSharedCursor(0, IDC_ARROW); 131} 132 133void Cursor::ensurePlatformCursor() const 134{ 135 if (m_platformCursor) 136 return; 137 138 switch (m_type) { 139 case Cursor::Pointer: 140 case Cursor::Cell: 141 case Cursor::ContextMenu: 142 case Cursor::Alias: 143 case Cursor::Copy: 144 case Cursor::None: 145 case Cursor::Grab: 146 case Cursor::Grabbing: 147 m_platformCursor = loadSharedCursor(0, IDC_ARROW); 148 break; 149 case Cursor::Cross: 150 m_platformCursor = loadSharedCursor(0, IDC_CROSS); 151 break; 152 case Cursor::Hand: 153 m_platformCursor = loadSharedCursor(0, IDC_HAND); 154 break; 155 case Cursor::IBeam: 156 m_platformCursor = loadSharedCursor(0, IDC_IBEAM); 157 break; 158 case Cursor::Wait: 159 m_platformCursor = loadSharedCursor(0, IDC_WAIT); 160 break; 161 case Cursor::Help: 162 m_platformCursor = loadSharedCursor(0, IDC_HELP); 163 break; 164 case Cursor::Move: 165 m_platformCursor = loadSharedCursor(0, IDC_SIZEALL); 166 break; 167 case Cursor::MiddlePanning: 168 m_platformCursor = loadCursorByName("panIcon", 8, 8); 169 break; 170 case Cursor::EastResize: 171 m_platformCursor = loadSharedCursor(0, IDC_SIZEWE); 172 break; 173 case Cursor::EastPanning: 174 m_platformCursor = loadCursorByName("panEastCursor", 7, 7); 175 break; 176 case Cursor::NorthResize: 177 m_platformCursor = loadSharedCursor(0, IDC_SIZENS); 178 break; 179 case Cursor::NorthPanning: 180 m_platformCursor = loadCursorByName("panNorthCursor", 7, 7); 181 break; 182 case Cursor::NorthEastResize: 183 m_platformCursor = loadSharedCursor(0, IDC_SIZENESW); 184 break; 185 case Cursor::NorthEastPanning: 186 m_platformCursor = loadCursorByName("panNorthEastCursor", 7, 7); 187 break; 188 case Cursor::NorthWestResize: 189 m_platformCursor = loadSharedCursor(0, IDC_SIZENWSE); 190 break; 191 case Cursor::NorthWestPanning: 192 m_platformCursor = loadCursorByName("panNorthWestCursor", 7, 7); 193 break; 194 case Cursor::SouthResize: 195 m_platformCursor = loadSharedCursor(0, IDC_SIZENS); 196 break; 197 case Cursor::SouthPanning: 198 m_platformCursor = loadCursorByName("panSouthCursor", 7, 7); 199 break; 200 case Cursor::SouthEastResize: 201 m_platformCursor = loadSharedCursor(0, IDC_SIZENWSE); 202 break; 203 case Cursor::SouthEastPanning: 204 m_platformCursor = loadCursorByName("panSouthEastCursor", 7, 7); 205 break; 206 case Cursor::SouthWestResize: 207 m_platformCursor = loadSharedCursor(0, IDC_SIZENESW); 208 break; 209 case Cursor::SouthWestPanning: 210 m_platformCursor = loadCursorByName("panSouthWestCursor", 7, 7); 211 break; 212 case Cursor::WestResize: 213 m_platformCursor = loadSharedCursor(0, IDC_SIZEWE); 214 break; 215 case Cursor::NorthSouthResize: 216 m_platformCursor = loadSharedCursor(0, IDC_SIZENS); 217 break; 218 case Cursor::EastWestResize: 219 m_platformCursor = loadSharedCursor(0, IDC_SIZEWE); 220 break; 221 case Cursor::WestPanning: 222 m_platformCursor = loadCursorByName("panWestCursor", 7, 7); 223 break; 224 case Cursor::NorthEastSouthWestResize: 225 m_platformCursor = loadSharedCursor(0, IDC_SIZENESW); 226 break; 227 case Cursor::NorthWestSouthEastResize: 228 m_platformCursor = loadSharedCursor(0, IDC_SIZENWSE); 229 break; 230 case Cursor::ColumnResize: 231 // FIXME: Windows does not have a standard column resize cursor <rdar://problem/5018591> 232 m_platformCursor = loadSharedCursor(0, IDC_SIZEWE); 233 break; 234 case Cursor::RowResize: 235 // FIXME: Windows does not have a standard row resize cursor <rdar://problem/5018591> 236 m_platformCursor = loadSharedCursor(0, IDC_SIZENS); 237 break; 238 case Cursor::VerticalText: 239 m_platformCursor = loadCursorByName("verticalTextCursor", 7, 7); 240 break; 241 case Cursor::Progress: 242 m_platformCursor = loadSharedCursor(0, IDC_APPSTARTING); 243 break; 244 case Cursor::NoDrop: 245 break; 246 case Cursor::NotAllowed: 247 m_platformCursor = loadSharedCursor(0, IDC_NO); 248 break; 249 case Cursor::ZoomIn: 250 m_platformCursor = loadCursorByName("zoomInCursor", 7, 7); 251 break; 252 case Cursor::ZoomOut: 253 m_platformCursor = loadCursorByName("zoomOutCursor", 7, 7); 254 break; 255 case Cursor::Custom: 256 m_platformCursor = createSharedCursor(m_image.get(), m_hotSpot); 257 break; 258 } 259} 260 261SharedCursor::~SharedCursor() 262{ 263 DestroyIcon(m_nativeCursor); 264} 265 266Cursor::Cursor(const Cursor& other) 267 : m_type(other.m_type) 268 , m_image(other.m_image) 269 , m_hotSpot(other.m_hotSpot) 270 , m_platformCursor(other.m_platformCursor) 271{ 272} 273 274Cursor& Cursor::operator=(const Cursor& other) 275{ 276 m_type = other.m_type; 277 m_image = other.m_image; 278 m_hotSpot = other.m_hotSpot; 279 m_platformCursor = other.m_platformCursor; 280 return *this; 281} 282 283Cursor::~Cursor() 284{ 285} 286 287} // namespace WebCore 288