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