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