Ken Thomases : winemac: Use system cursors when possible.
Alexandre Julliard
julliard at winehq.org
Mon Feb 25 14:33:46 CST 2013
Module: wine
Branch: master
Commit: b79d955342754df7aee8143e530d2054c092bece
URL: http://source.winehq.org/git/wine.git/?a=commit;h=b79d955342754df7aee8143e530d2054c092bece
Author: Ken Thomases <ken at codeweavers.com>
Date: Sun Feb 24 22:53:25 2013 -0600
winemac: Use system cursors when possible.
---
dlls/winemac.drv/mouse.c | 215 ++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 196 insertions(+), 19 deletions(-)
diff --git a/dlls/winemac.drv/mouse.c b/dlls/winemac.drv/mouse.c
index 4d87324..8e16388 100644
--- a/dlls/winemac.drv/mouse.c
+++ b/dlls/winemac.drv/mouse.c
@@ -44,6 +44,90 @@ static CRITICAL_SECTION cursor_cache_section = { &critsect_debug, -1, 0, 0, 0, 0
static CFMutableDictionaryRef cursor_cache;
+struct system_cursors
+{
+ WORD id;
+ CFStringRef name;
+};
+
+static const struct system_cursors user32_cursors[] =
+{
+ { OCR_NORMAL, CFSTR("arrowCursor") },
+ { OCR_IBEAM, CFSTR("IBeamCursor") },
+ { OCR_CROSS, CFSTR("crosshairCursor") },
+ { OCR_SIZEWE, CFSTR("resizeLeftRightCursor") },
+ { OCR_SIZENS, CFSTR("resizeUpDownCursor") },
+ { OCR_NO, CFSTR("operationNotAllowedCursor") },
+ { OCR_HAND, CFSTR("pointingHandCursor") },
+ { 0 }
+};
+
+static const struct system_cursors comctl32_cursors[] =
+{
+ { 102, CFSTR("closedHandCursor") },
+ { 104, CFSTR("dragCopyCursor") },
+ { 105, CFSTR("arrowCursor") },
+ { 106, CFSTR("resizeLeftRightCursor") },
+ { 107, CFSTR("resizeLeftRightCursor") },
+ { 108, CFSTR("pointingHandCursor") },
+ { 135, CFSTR("resizeUpDownCursor") },
+ { 0 }
+};
+
+static const struct system_cursors ole32_cursors[] =
+{
+ { 1, CFSTR("operationNotAllowedCursor") },
+ { 2, CFSTR("closedHandCursor") },
+ { 3, CFSTR("dragCopyCursor") },
+ { 4, CFSTR("dragLinkCursor") },
+ { 0 }
+};
+
+static const struct system_cursors riched20_cursors[] =
+{
+ { 105, CFSTR("pointingHandCursor") },
+ { 109, CFSTR("dragCopyCursor") },
+ { 110, CFSTR("closedHandCursor") },
+ { 111, CFSTR("operationNotAllowedCursor") },
+ { 0 }
+};
+
+static const struct
+{
+ const struct system_cursors *cursors;
+ WCHAR name[16];
+} module_cursors[] =
+{
+ { user32_cursors, {'u','s','e','r','3','2','.','d','l','l',0} },
+ { comctl32_cursors, {'c','o','m','c','t','l','3','2','.','d','l','l',0} },
+ { ole32_cursors, {'o','l','e','3','2','.','d','l','l',0} },
+ { riched20_cursors, {'r','i','c','h','e','d','2','0','.','d','l','l',0} }
+};
+
+/* The names of NSCursor class methods which return cursor objects. */
+static const CFStringRef cocoa_cursor_names[] =
+{
+ CFSTR("arrowCursor"),
+ CFSTR("closedHandCursor"),
+ CFSTR("contextualMenuCursor"),
+ CFSTR("crosshairCursor"),
+ CFSTR("disappearingItemCursor"),
+ CFSTR("dragCopyCursor"),
+ CFSTR("dragLinkCursor"),
+ CFSTR("IBeamCursor"),
+ CFSTR("IBeamCursorForVerticalLayout"),
+ CFSTR("openHandCursor"),
+ CFSTR("operationNotAllowedCursor"),
+ CFSTR("pointingHandCursor"),
+ CFSTR("resizeDownCursor"),
+ CFSTR("resizeLeftCursor"),
+ CFSTR("resizeLeftRightCursor"),
+ CFSTR("resizeRightCursor"),
+ CFSTR("resizeUpCursor"),
+ CFSTR("resizeUpDownCursor"),
+};
+
+
/***********************************************************************
* send_mouse_input
*
@@ -90,6 +174,90 @@ static void send_mouse_input(HWND hwnd, UINT flags, int x, int y,
/***********************************************************************
+ * copy_system_cursor_name
+ */
+CFStringRef copy_system_cursor_name(ICONINFOEXW *info)
+{
+ static const WCHAR idW[] = {'%','h','u',0};
+ const struct system_cursors *cursors;
+ unsigned int i;
+ CFStringRef cursor_name = NULL;
+ HMODULE module;
+ HKEY key;
+ WCHAR *p, name[MAX_PATH * 2];
+
+ TRACE("info->szModName %s info->szResName %s info->wResID %hu\n", debugstr_w(info->szModName),
+ debugstr_w(info->szResName), info->wResID);
+
+ if (!info->szModName[0]) return NULL;
+
+ p = strrchrW(info->szModName, '\\');
+ strcpyW(name, p ? p + 1 : info->szModName);
+ p = name + strlenW(name);
+ *p++ = ',';
+ if (info->szResName[0]) strcpyW(p, info->szResName);
+ else sprintfW(p, idW, info->wResID);
+
+ /* @@ Wine registry key: HKCU\Software\Wine\Mac Driver\Cursors */
+ if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Mac Driver\\Cursors", &key))
+ {
+ WCHAR value[64];
+ DWORD size, ret;
+
+ value[0] = 0;
+ size = sizeof(value) / sizeof(WCHAR);
+ ret = RegQueryValueExW(key, name, NULL, NULL, (BYTE *)value, &size);
+ RegCloseKey(key);
+ if (!ret)
+ {
+ if (!value[0])
+ {
+ TRACE("registry forces standard cursor for %s\n", debugstr_w(name));
+ return NULL; /* force standard cursor */
+ }
+
+ cursor_name = CFStringCreateWithCharacters(NULL, value, strlenW(value));
+ if (!cursor_name)
+ {
+ WARN("CFStringCreateWithCharacters failed for %s\n", debugstr_w(value));
+ return NULL;
+ }
+
+ /* Make sure it's one of the appropriate NSCursor class methods. */
+ for (i = 0; i < sizeof(cocoa_cursor_names) / sizeof(cocoa_cursor_names[0]); i++)
+ if (CFEqual(cursor_name, cocoa_cursor_names[i]))
+ goto done;
+
+ WARN("%s mapped to invalid Cocoa cursor name %s\n", debugstr_w(name), debugstr_w(value));
+ CFRelease(cursor_name);
+ return NULL;
+ }
+ }
+
+ if (info->szResName[0]) goto done; /* only integer resources are supported here */
+ if (!(module = GetModuleHandleW(info->szModName))) goto done;
+
+ for (i = 0; i < sizeof(module_cursors)/sizeof(module_cursors[0]); i++)
+ if (GetModuleHandleW(module_cursors[i].name) == module) break;
+ if (i == sizeof(module_cursors)/sizeof(module_cursors[0])) goto done;
+
+ cursors = module_cursors[i].cursors;
+ for (i = 0; cursors[i].id; i++)
+ if (cursors[i].id == info->wResID)
+ {
+ cursor_name = CFRetain(cursors[i].name);
+ break;
+ }
+
+done:
+ if (cursor_name)
+ TRACE("%s -> %s\n", debugstr_w(name), debugstr_cf(cursor_name));
+ else
+ WARN("no system cursor found for %s\n", debugstr_w(name));
+ return cursor_name;
+}
+
+/***********************************************************************
* release_provider_cfdata
*
* Helper for create_monochrome_cursor. A CFData is used by two
@@ -580,8 +748,6 @@ void CDECL macdrv_SetCursor(HCURSOR cursor)
if (cursor)
{
ICONINFOEXW info;
- BITMAP bm;
- HDC hdc;
EnterCriticalSection(&cursor_cache_section);
if (cursor_cache)
@@ -606,28 +772,39 @@ void CDECL macdrv_SetCursor(HCURSOR cursor)
return;
}
- GetObjectW(info.hbmMask, sizeof(bm), &bm);
- if (!info.hbmColor) bm.bmHeight = max(1, bm.bmHeight / 2);
-
- /* make sure hotspot is valid */
- if (info.xHotspot >= bm.bmWidth || info.yHotspot >= bm.bmHeight)
+ if ((cursor_name = copy_system_cursor_name(&info)))
{
- info.xHotspot = bm.bmWidth / 2;
- info.yHotspot = bm.bmHeight / 2;
- }
-
- hdc = CreateCompatibleDC(0);
-
- if (info.hbmColor)
- {
- cursor_frames = create_color_cursor(hdc, &info, cursor, bm.bmWidth, bm.bmHeight);
DeleteObject(info.hbmColor);
+ DeleteObject(info.hbmMask);
}
else
- cursor_frames = create_monochrome_cursor(hdc, &info, bm.bmWidth, bm.bmHeight);
+ {
+ BITMAP bm;
+ HDC hdc;
+
+ GetObjectW(info.hbmMask, sizeof(bm), &bm);
+ if (!info.hbmColor) bm.bmHeight = max(1, bm.bmHeight / 2);
- DeleteObject(info.hbmMask);
- DeleteDC(hdc);
+ /* make sure hotspot is valid */
+ if (info.xHotspot >= bm.bmWidth || info.yHotspot >= bm.bmHeight)
+ {
+ info.xHotspot = bm.bmWidth / 2;
+ info.yHotspot = bm.bmHeight / 2;
+ }
+
+ hdc = CreateCompatibleDC(0);
+
+ if (info.hbmColor)
+ {
+ cursor_frames = create_color_cursor(hdc, &info, cursor, bm.bmWidth, bm.bmHeight);
+ DeleteObject(info.hbmColor);
+ }
+ else
+ cursor_frames = create_monochrome_cursor(hdc, &info, bm.bmWidth, bm.bmHeight);
+
+ DeleteObject(info.hbmMask);
+ DeleteDC(hdc);
+ }
if (cursor_name || cursor_frames)
{
More information about the wine-cvs
mailing list