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