Hello!
The following patch series from staging is required here for multiple games to display on the correct screen when switching to full-screen mode.
I thus want to suggest these patches for inclusion into wine. I've tested the patches since multiple versions of wine now.
It seems there's one (minor) annoyance with these: I have two very different displays attached: One 28" 4k monitor, and one 42" FHD TV.
With this setup, some applications display very tiny fonts only on the TV display. It seems that DPI are incorrectly inferred from the display description. It shouldn't be a problem with very similar displays attached to the graphic card. Some Linux applications suffer the same problem, so it's probably nothing that Wine could easily fix. Especially, I had to make my 4k display implicitly the primary display in the Xorg configuration for applications to pickup the correct DPI for font size calculation (which is 144 dpi instead of 96 dpi).
Thanks, Kai
Ken Thomases (4): gdi32: Also accept "\.\DISPLAY<n>" devices names with <n> other than 1 as display devices. winex11: Make GetMonitorInfo() give a different device name (.\DISPLAY<n>) to each monitor user32: Implement EnumDisplayDevicesW() based on EnumDisplayMonitors() and GetMonitorInfoW(). winemac: Make GetMonitorInfo() give a different device name (\.\DISPLAY<n>) to each monitor.
Sebastian Lackner (1): user32: Return a more reasonable display DeviceID.
dlls/gdi32/driver.c | 32 ++++++++++++-- dlls/user32/misc.c | 101 ++++++++++++++++++++++++++++++++++++++------ dlls/user32/tests/monitor.c | 16 +++++-- dlls/winemac.drv/display.c | 10 +++-- dlls/winex11.drv/xinerama.c | 12 +++++- 5 files changed, 146 insertions(+), 25 deletions(-)
From: Ken Thomases ken@codeweavers.com
--- dlls/gdi32/driver.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-)
diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index c81a2e103d..de6247074d 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -109,6 +109,32 @@ static const struct gdi_dc_funcs *get_display_driver(void) }
+/********************************************************************** + * is_display_device + */ +static BOOL is_display_device( LPCWSTR name ) +{ + static const WCHAR display_deviceW[] = {'\','\','.','\','D','I','S','P','L','A','Y'}; + const WCHAR *p = name; + + if (strncmpiW( name, display_deviceW, sizeof(display_deviceW) / sizeof(WCHAR) )) + return FALSE; + + p += sizeof(display_deviceW) / sizeof(WCHAR); + + if (!isdigitW( *p++ )) + return FALSE; + + for (; *p; p++) + { + if (!isdigitW( *p )) + return FALSE; + } + + return TRUE; +} + + /********************************************************************** * DRIVER_load_driver */ @@ -117,10 +143,9 @@ const struct gdi_dc_funcs *DRIVER_load_driver( LPCWSTR name ) HMODULE module; struct graphics_driver *driver, *new_driver; static const WCHAR displayW[] = { 'd','i','s','p','l','a','y',0 }; - static const WCHAR display1W[] = {'\','\','.','\','D','I','S','P','L','A','Y','1',0};
/* display driver is a special case */ - if (!strcmpiW( name, displayW ) || !strcmpiW( name, display1W )) return get_display_driver(); + if (!strcmpiW( name, displayW ) || is_display_device( name )) return get_display_driver();
if ((module = GetModuleHandleW( name ))) { @@ -826,13 +851,12 @@ BOOL DRIVER_GetDriverName( LPCWSTR device, LPWSTR driver, DWORD size ) { static const WCHAR displayW[] = { 'd','i','s','p','l','a','y',0 }; static const WCHAR devicesW[] = { 'd','e','v','i','c','e','s',0 }; - static const WCHAR display1W[] = {'\','\','.','\','D','I','S','P','L','A','Y','1',0}; static const WCHAR empty_strW[] = { 0 }; WCHAR *p;
/* display is a special case */ if (!strcmpiW( device, displayW ) || - !strcmpiW( device, display1W )) + is_display_device( device )) { lstrcpynW( driver, displayW, size ); return TRUE;
From: Ken Thomases ken@codeweavers.com
--- dlls/winex11.drv/xinerama.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/dlls/winex11.drv/xinerama.c b/dlls/winex11.drv/xinerama.c index 0419535d49..24542f4380 100644 --- a/dlls/winex11.drv/xinerama.c +++ b/dlls/winex11.drv/xinerama.c @@ -30,6 +30,7 @@ #include "wine/library.h" #include "x11drv.h" #include "wine/debug.h" +#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
@@ -43,6 +44,7 @@ static MONITORINFOEXW default_monitor = MONITORINFOF_PRIMARY, /* dwFlags */ { '\','\','.','\','D','I','S','P','L','A','Y','1',0 } /* szDevice */ }; +static const WCHAR monitor_deviceW[] = { '\','\','.','\','D','I','S','P','L','A','Y','%','d',0 };
static MONITORINFOEXW *monitors; static int nb_monitors; @@ -141,6 +143,8 @@ static int query_screens(void) if (monitors != &default_monitor) HeapFree( GetProcessHeap(), 0, monitors ); if ((monitors = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*monitors) ))) { + int device = 2; /* 1 is reserved for primary */ + nb_monitors = count; for (i = 0; i < nb_monitors; i++) { @@ -152,11 +156,15 @@ static int query_screens(void) monitors[i].dwFlags = 0; if (!IntersectRect( &monitors[i].rcWork, &rc_work, &monitors[i].rcMonitor )) monitors[i].rcWork = monitors[i].rcMonitor; - /* FIXME: using the same device name for all monitors for now */ - lstrcpyW( monitors[i].szDevice, default_monitor.szDevice ); }
get_primary()->dwFlags |= MONITORINFOF_PRIMARY; + + for (i = 0; i < nb_monitors; i++) + { + snprintfW( monitors[i].szDevice, sizeof(monitors[i].szDevice) / sizeof(WCHAR), + monitor_deviceW, (monitors[i].dwFlags & MONITORINFOF_PRIMARY) ? 1 : device++ ); + } } else count = 0;
From: Ken Thomases ken@codeweavers.com
--- dlls/user32/misc.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 84 insertions(+), 12 deletions(-)
diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c index d28cd9fd05..a6b7644020 100644 --- a/dlls/user32/misc.c +++ b/dlls/user32/misc.c @@ -243,11 +243,74 @@ DWORD WINAPI SetLogonNotifyWindow(HWINSTA hwinsta,HWND hwnd) return 1; }
-static const WCHAR primary_device_name[] = {'\','\','.','\','D','I','S','P','L','A','Y','1',0}; -static const WCHAR primary_device_string[] = {'X','1','1',' ','W','i','n','d','o','w','i','n','g',' ', - 'S','y','s','t','e','m',0}; -static const WCHAR primary_device_deviceid[] = {'P','C','I','\','V','E','N','_','0','0','0','0','&', +static const WCHAR adapter_device_string[] = {'W','i','n','e',' ','D','i','s','p','l','a','y',' ', + 'A','d','a','p','t','e','r',0}; +static const WCHAR adapter_device_deviceid[] = {'P','C','I','\','V','E','N','_','0','0','0','0','&', 'D','E','V','_','0','0','0','0',0}; +static const WCHAR display_device_name[] = {'%','s','\','M','o','n','i','t','o','r','0',0}; +static const WCHAR display_device_string[] = {'W','i','n','e',' ','D','i','s','p','l','a','y',0}; +static const WCHAR display_device_deviceid[] = {'M','O','N','I','T','O','R','\','W','I','N','E','%','0','4','d',0}; + +struct display_devices_enum_info +{ + LPCWSTR adapter; + DWORD target; + DWORD non_primary_seen; + LPDISPLAY_DEVICEW device; +}; + +/*********************************************************************** + * display_devices_enum + * + * Helper callback for EnumDisplayDevicesW() + */ +static BOOL CALLBACK display_devices_enum( HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lp ) +{ + struct display_devices_enum_info *info = (struct display_devices_enum_info *)lp; + MONITORINFOEXW mon_info; + BOOL match; + + mon_info.cbSize = sizeof(mon_info); + GetMonitorInfoW( monitor, (MONITORINFO*)&mon_info ); + + if (!(mon_info.dwFlags & MONITORINFOF_PRIMARY)) + info->non_primary_seen++; + + if (info->adapter) + { + match = !strcmpiW( info->adapter, mon_info.szDevice ); + if (match) + { + snprintfW( info->device->DeviceName, sizeof(info->device->DeviceName) / sizeof(WCHAR), + display_device_name, mon_info.szDevice ); + lstrcpynW( info->device->DeviceString, display_device_string, sizeof(info->device->DeviceString) / sizeof(WCHAR) ); + + if (info->device->cb >= offsetof(DISPLAY_DEVICEW, DeviceID) + sizeof(info->device->DeviceID)) + { + snprintfW( info->device->DeviceID, sizeof(info->device->DeviceID) / sizeof(WCHAR), + display_device_deviceid, (mon_info.dwFlags & MONITORINFOF_PRIMARY) ? 0 : info->non_primary_seen ); + } + } + } + else + { + if (mon_info.dwFlags & MONITORINFOF_PRIMARY) + match = (info->target == 0); + else + match = (info->target == info->non_primary_seen); + + if (match) + { + lstrcpynW( info->device->DeviceName, mon_info.szDevice, sizeof(info->device->DeviceName) / sizeof(WCHAR) ); + lstrcpynW( info->device->DeviceString, adapter_device_string, sizeof(info->device->DeviceString) / sizeof(WCHAR) ); + + if (info->device->cb >= offsetof(DISPLAY_DEVICEW, DeviceID) + sizeof(info->device->DeviceID)) + lstrcpynW( info->device->DeviceID, adapter_device_deviceid, sizeof(info->device->DeviceID) / sizeof(WCHAR) ); + } + } + + return !match; +}
/*********************************************************************** * EnumDisplayDevicesA (USER32.@) @@ -288,24 +351,33 @@ BOOL WINAPI EnumDisplayDevicesA( LPCSTR lpDevice, DWORD i, LPDISPLAY_DEVICEA lpD BOOL WINAPI EnumDisplayDevicesW( LPCWSTR lpDevice, DWORD i, LPDISPLAY_DEVICEW lpDisplayDevice, DWORD dwFlags ) { - FIXME("(%s,%d,%p,0x%08x), stub!\n",debugstr_w(lpDevice),i,lpDisplayDevice,dwFlags); + struct display_devices_enum_info info;
- if (i) + TRACE("(%s,%d,%p,0x%08x)\n",debugstr_w(lpDevice),i,lpDisplayDevice,dwFlags); + + if (lpDevice && i) return FALSE;
- memcpy(lpDisplayDevice->DeviceName, primary_device_name, sizeof(primary_device_name)); - memcpy(lpDisplayDevice->DeviceString, primary_device_string, sizeof(primary_device_string)); - lpDisplayDevice->StateFlags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | - DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_VGA_COMPATIBLE;
- if(lpDisplayDevice->cb >= offsetof(DISPLAY_DEVICEW, DeviceID) + sizeof(lpDisplayDevice->DeviceID)) - memcpy(lpDisplayDevice->DeviceID, primary_device_deviceid, sizeof(primary_device_deviceid)); + if (!lpDevice && i == 0) + lpDisplayDevice->StateFlags |= DISPLAY_DEVICE_PRIMARY_DEVICE; + + info.adapter = lpDevice; + info.target = i; + info.non_primary_seen = 0; + info.device = lpDisplayDevice; + if (EnumDisplayMonitors( 0, NULL, display_devices_enum, (LPARAM)&info )) + return FALSE; + if(lpDisplayDevice->cb >= offsetof(DISPLAY_DEVICEW, DeviceKey) + sizeof(lpDisplayDevice->DeviceKey)) lpDisplayDevice->DeviceKey[0] = 0;
+ TRACE("DeviceName %s DeviceString %s DeviceID %s DeviceKey %s\n", debugstr_w(lpDisplayDevice->DeviceName), + debugstr_w(lpDisplayDevice->DeviceString), debugstr_w(lpDisplayDevice->DeviceID), debugstr_w(lpDisplayDevice->DeviceKey)); + return TRUE; }
From: Ken Thomases ken@codeweavers.com
--- dlls/winemac.drv/display.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 00ad7738bb..af60a7d5b3 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -1262,7 +1262,7 @@ done: */ BOOL CDECL macdrv_GetMonitorInfo(HMONITOR monitor, LPMONITORINFO info) { - static const WCHAR adapter_name[] = { '\','\','.','\','D','I','S','P','L','A','Y','1',0 }; + static const WCHAR adapter_name[] = { '\','\','.','\','D','I','S','P','L','A','Y','%','d',0 }; struct macdrv_display *displays; int num_displays; CGDirectDisplayID display_id; @@ -1292,10 +1292,12 @@ BOOL CDECL macdrv_GetMonitorInfo(HMONITOR monitor, LPMONITORINFO info) info->dwFlags = (i == 0) ? MONITORINFOF_PRIMARY : 0;
if (info->cbSize >= sizeof(MONITORINFOEXW)) - lstrcpyW(((MONITORINFOEXW*)info)->szDevice, adapter_name); + snprintfW(((MONITORINFOEXW*)info)->szDevice, sizeof(((MONITORINFOEXW*)info)->szDevice) / sizeof(WCHAR), + adapter_name, i + 1);
- TRACE(" -> rcMonitor %s rcWork %s dwFlags %08x\n", wine_dbgstr_rect(&info->rcMonitor), - wine_dbgstr_rect(&info->rcWork), info->dwFlags); + TRACE(" -> rcMonitor %s rcWork %s dwFlags %08x szDevice %s\n", wine_dbgstr_rect(&info->rcMonitor), + wine_dbgstr_rect(&info->rcWork), info->dwFlags, + info->cbSize >= sizeof(MONITORINFOEXW) ? debugstr_w(((MONITORINFOEXW*)info)->szDevice) : "n/a"); } else {
From: Sebastian Lackner sebastian@fds-team.de
--- dlls/user32/misc.c | 7 ++++++- dlls/user32/tests/monitor.c | 16 +++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c index a6b7644020..c1c812dbd5 100644 --- a/dlls/user32/misc.c +++ b/dlls/user32/misc.c @@ -249,7 +249,12 @@ static const WCHAR adapter_device_deviceid[] = {'P','C','I','\','V','E','N','_' 'D','E','V','_','0','0','0','0',0}; static const WCHAR display_device_name[] = {'%','s','\','M','o','n','i','t','o','r','0',0}; static const WCHAR display_device_string[] = {'W','i','n','e',' ','D','i','s','p','l','a','y',0}; -static const WCHAR display_device_deviceid[] = {'M','O','N','I','T','O','R','\','W','I','N','E','%','0','4','d',0}; +static const WCHAR display_device_deviceid[] = {'M','O','N','I','T','O','R','\', + 'D','e','f','a','u','l','t','_','M','o','n','i','t','o','r','\', + '{','4','D','3','6','E','9','6','E','-','E','3','2','5','-', + '1','1','C','E','-','B','F','C','1','-', + '0','8','0','0','2','B','E','1','0','3','1','8','}','\', + '%','0','4','d',0};
struct display_devices_enum_info { diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c index f4c1a4b17c..14fedd08d8 100644 --- a/dlls/user32/tests/monitor.c +++ b/dlls/user32/tests/monitor.c @@ -89,12 +89,12 @@ static void test_enumdisplaydevices(void) }
dd.cb = sizeof(dd); - while(1) + for (num = 0;; num++) { - BOOL ret; HDC dc; ret = pEnumDisplayDevicesA(NULL, num, &dd, 0); if(!ret) break; + if(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { strcpy(primary_device_name, dd.DeviceName); @@ -107,7 +107,6 @@ static void test_enumdisplaydevices(void) ok(dc != NULL, "Failed to CreateDC("%s") err=%d\n", dd.DeviceName, GetLastError()); DeleteDC(dc); } - num++; }
if (primary_num == -1 || !pEnumDisplayMonitors || !pGetMonitorInfoA) @@ -122,6 +121,17 @@ static void test_enumdisplaydevices(void) ok(!strcmp(primary_monitor_device_name, primary_device_name), "monitor device name %s, device name %s\n", primary_monitor_device_name, primary_device_name); + + dd.cb = sizeof(dd); + for (num = 0;; num++) + { + ret = pEnumDisplayDevicesA(primary_device_name, num, &dd, 0); + if (!ret) break; + + dd.DeviceID[63] = 0; + ok(!strcasecmp(dd.DeviceID, "Monitor\Default_Monitor\{4D36E96E-E325-11CE-BFC1-08002BE10318}\"), + "DeviceID "%s" does not start with "Monitor\Default_Monitor\..." prefix\n", dd.DeviceID); + } }
struct vid_mode