Ken Thomases : winemac: Implement EnumDisplaySettingsEx().

Alexandre Julliard julliard at winehq.org
Mon Feb 18 13:27:05 CST 2013


Module: wine
Branch: master
Commit: 4f4ac0cafcf0a1db61939bd146d8f6d077b3be7b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=4f4ac0cafcf0a1db61939bd146d8f6d077b3be7b

Author: Ken Thomases <ken at codeweavers.com>
Date:   Sun Feb 17 19:28:42 2013 -0600

winemac: Implement EnumDisplaySettingsEx().

---

 dlls/winemac.drv/display.c        |  221 +++++++++++++++++++++++++++++++++++++
 dlls/winemac.drv/winemac.drv.spec |    1 +
 2 files changed, 222 insertions(+), 0 deletions(-)

diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c
index 2a96631..afa0646 100644
--- a/dlls/winemac.drv/display.c
+++ b/dlls/winemac.drv/display.c
@@ -23,10 +23,22 @@
 
 #include "macdrv.h"
 #include "winuser.h"
+#include "winreg.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(display);
 
 
+static CFArrayRef modes;
+static CRITICAL_SECTION modes_section;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+    0, 0, &modes_section,
+    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": modes_section") }
+};
+static CRITICAL_SECTION modes_section = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+
 static inline HMONITOR display_id_to_monitor(CGDirectDisplayID display_id)
 {
     return (HMONITOR)(UINT_PTR)display_id;
@@ -38,6 +50,73 @@ static inline CGDirectDisplayID monitor_to_display_id(HMONITOR handle)
 }
 
 
+static BOOL get_display_device_reg_key(char *key, unsigned len)
+{
+    static const char display_device_guid_prop[] = "__wine_display_device_guid";
+    static const char video_path[] = "System\\CurrentControlSet\\Control\\Video\\{";
+    static const char display0[] = "}\\0000";
+    ATOM guid_atom;
+
+    assert(len >= sizeof(video_path) + sizeof(display0) + 40);
+
+    guid_atom = HandleToULong(GetPropA(GetDesktopWindow(), display_device_guid_prop));
+    if (!guid_atom) return FALSE;
+
+    memcpy(key, video_path, sizeof(video_path));
+
+    if (!GlobalGetAtomNameA(guid_atom, key + strlen(key), 40))
+        return FALSE;
+
+    strcat(key, display0);
+
+    TRACE("display device key %s\n", wine_dbgstr_a(key));
+    return TRUE;
+}
+
+
+static BOOL read_registry_settings(DEVMODEW *dm)
+{
+    char wine_mac_reg_key[128];
+    HKEY hkey;
+    DWORD type, size;
+    BOOL ret = TRUE;
+
+    dm->dmFields = 0;
+
+    if (!get_display_device_reg_key(wine_mac_reg_key, sizeof(wine_mac_reg_key)))
+        return FALSE;
+
+    if (RegOpenKeyExA(HKEY_CURRENT_CONFIG, wine_mac_reg_key, 0, KEY_READ, &hkey))
+        return FALSE;
+
+#define query_value(name, data) \
+    size = sizeof(DWORD); \
+    if (RegQueryValueExA(hkey, name, 0, &type, (LPBYTE)(data), &size) || \
+        type != REG_DWORD || size != sizeof(DWORD)) \
+        ret = FALSE
+
+    query_value("DefaultSettings.BitsPerPel", &dm->dmBitsPerPel);
+    dm->dmFields |= DM_BITSPERPEL;
+    query_value("DefaultSettings.XResolution", &dm->dmPelsWidth);
+    dm->dmFields |= DM_PELSWIDTH;
+    query_value("DefaultSettings.YResolution", &dm->dmPelsHeight);
+    dm->dmFields |= DM_PELSHEIGHT;
+    query_value("DefaultSettings.VRefresh", &dm->dmDisplayFrequency);
+    dm->dmFields |= DM_DISPLAYFREQUENCY;
+    query_value("DefaultSettings.Flags", &dm->dmDisplayFlags);
+    dm->dmFields |= DM_DISPLAYFLAGS;
+    query_value("DefaultSettings.XPanning", &dm->dmPosition.x);
+    query_value("DefaultSettings.YPanning", &dm->dmPosition.y);
+    query_value("DefaultSettings.Orientation", &dm->dmDisplayOrientation);
+    query_value("DefaultSettings.FixedOutput", &dm->dmDisplayFixedOutput);
+
+#undef query_value
+
+    RegCloseKey(hkey);
+    return ret;
+}
+
+
 static int display_mode_bits_per_pixel(CGDisplayModeRef display_mode)
 {
     CFStringRef pixel_encoding;
@@ -144,6 +223,148 @@ BOOL CDECL macdrv_EnumDisplayMonitors(HDC hdc, LPRECT rect, MONITORENUMPROC proc
 
 
 /***********************************************************************
+ *              EnumDisplaySettingsEx  (MACDRV.@)
+ *
+ */
+BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode,
+                                        LPDEVMODEW devmode, DWORD flags)
+{
+    static const WCHAR dev_name[CCHDEVICENAME] =
+        { 'W','i','n','e',' ','M','a','c',' ','d','r','i','v','e','r',0 };
+    struct macdrv_display *displays = NULL;
+    int num_displays;
+    CGDisplayModeRef display_mode;
+    double rotation;
+    uint32_t io_flags;
+
+    TRACE("%s, %u, %p + %hu, %08x\n", debugstr_w(devname), mode, devmode, devmode->dmSize, flags);
+
+    memcpy(devmode->dmDeviceName, dev_name, sizeof(dev_name));
+    devmode->dmSpecVersion = DM_SPECVERSION;
+    devmode->dmDriverVersion = DM_SPECVERSION;
+    devmode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod);
+    devmode->dmDriverExtra = 0;
+    memset(&devmode->dmFields, 0, devmode->dmSize - FIELD_OFFSET(DEVMODEW, dmFields));
+
+    if (mode == ENUM_REGISTRY_SETTINGS)
+    {
+        TRACE("mode %d (registry) -- getting default mode\n", mode);
+        return read_registry_settings(devmode);
+    }
+
+    if (macdrv_get_displays(&displays, &num_displays))
+        goto failed;
+
+    if (mode == ENUM_CURRENT_SETTINGS)
+    {
+        TRACE("mode %d (current) -- getting current mode\n", mode);
+        display_mode = CGDisplayCopyDisplayMode(displays[0].displayID);
+    }
+    else
+    {
+        EnterCriticalSection(&modes_section);
+
+        if (mode == 0 || !modes)
+        {
+            if (modes) CFRelease(modes);
+            modes = CGDisplayCopyAllDisplayModes(displays[0].displayID, NULL);
+        }
+
+        display_mode = NULL;
+        if (modes)
+        {
+            if (flags & EDS_RAWMODE)
+            {
+                if (mode < CFArrayGetCount(modes))
+                    display_mode = (CGDisplayModeRef)CFRetain(CFArrayGetValueAtIndex(modes, mode));
+            }
+            else
+            {
+                DWORD count, i, safe_modes = 0;
+                count = CFArrayGetCount(modes);
+                for (i = 0; i < count; i++)
+                {
+                    CGDisplayModeRef candidate = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i);
+                    io_flags = CGDisplayModeGetIOFlags(candidate);
+                    if ((io_flags & kDisplayModeValidFlag) &&
+                        (io_flags & kDisplayModeSafeFlag))
+                    {
+                        safe_modes++;
+                        if (safe_modes > mode)
+                        {
+                            display_mode = (CGDisplayModeRef)CFRetain(candidate);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        LeaveCriticalSection(&modes_section);
+    }
+
+    if (!display_mode)
+        goto failed;
+
+    /* We currently only report modes for the primary display, so it's at (0, 0). */
+    devmode->dmPosition.x = 0;
+    devmode->dmPosition.y = 0;
+    devmode->dmFields |= DM_POSITION;
+
+    rotation = CGDisplayRotation(displays[0].displayID);
+    devmode->dmDisplayOrientation = ((int)((rotation / 90) + 0.5)) % 4;
+    devmode->dmFields |= DM_DISPLAYORIENTATION;
+
+    io_flags = CGDisplayModeGetIOFlags(display_mode);
+    if (io_flags & kDisplayModeStretchedFlag)
+        devmode->dmDisplayFixedOutput = DMDFO_STRETCH;
+    else
+        devmode->dmDisplayFixedOutput = DMDFO_CENTER;
+    devmode->dmFields |= DM_DISPLAYFIXEDOUTPUT;
+
+    devmode->dmBitsPerPel = display_mode_bits_per_pixel(display_mode);
+    if (devmode->dmBitsPerPel)
+        devmode->dmFields |= DM_BITSPERPEL;
+
+    devmode->dmPelsWidth = CGDisplayModeGetWidth(display_mode);
+    devmode->dmPelsHeight = CGDisplayModeGetHeight(display_mode);
+    devmode->dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
+
+    devmode->dmDisplayFlags = 0;
+    if (io_flags & kDisplayModeInterlacedFlag)
+        devmode->dmDisplayFlags |= DM_INTERLACED;
+    devmode->dmFields |= DM_DISPLAYFLAGS;
+
+    devmode->dmDisplayFrequency = CGDisplayModeGetRefreshRate(display_mode);
+    if (!devmode->dmDisplayFrequency)
+        devmode->dmDisplayFrequency = 60;
+    devmode->dmFields |= DM_DISPLAYFREQUENCY;
+
+    CFRelease(display_mode);
+    macdrv_free_displays(displays);
+
+    TRACE("mode %d -- %dx%dx%dbpp @%d Hz", mode,
+          devmode->dmPelsWidth, devmode->dmPelsHeight, devmode->dmBitsPerPel,
+          devmode->dmDisplayFrequency);
+    if (devmode->dmDisplayOrientation)
+        TRACE(" rotated %u degrees", devmode->dmDisplayOrientation * 90);
+    if (devmode->dmDisplayFixedOutput == DMDFO_STRETCH)
+        TRACE(" stretched");
+    if (devmode->dmDisplayFlags & DM_INTERLACED)
+        TRACE(" interlaced");
+    TRACE("\n");
+
+    return TRUE;
+
+failed:
+    TRACE("mode %d -- not present\n", mode);
+    if (displays) macdrv_free_displays(displays);
+    SetLastError(ERROR_NO_MORE_FILES);
+    return FALSE;
+}
+
+
+/***********************************************************************
  *              GetMonitorInfo  (MACDRV.@)
  */
 BOOL CDECL macdrv_GetMonitorInfo(HMONITOR monitor, LPMONITORINFO info)
diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec
index 57b1e5a..d841283 100644
--- a/dlls/winemac.drv/winemac.drv.spec
+++ b/dlls/winemac.drv/winemac.drv.spec
@@ -10,6 +10,7 @@
 @ cdecl CreateWindow(long) macdrv_CreateWindow
 @ cdecl DestroyWindow(long) macdrv_DestroyWindow
 @ cdecl EnumDisplayMonitors(long ptr ptr long) macdrv_EnumDisplayMonitors
+@ cdecl EnumDisplaySettingsEx(ptr long ptr long) macdrv_EnumDisplaySettingsEx
 @ cdecl GetKeyboardLayout(long) macdrv_GetKeyboardLayout
 @ cdecl GetKeyboardLayoutName(ptr) macdrv_GetKeyboardLayoutName
 @ cdecl GetKeyNameText(long ptr long) macdrv_GetKeyNameText




More information about the wine-cvs mailing list