[PATCH] user32: Improve EnumDisplayDevices
Andrew Eikum
aeikum at codeweavers.com
Wed Feb 7 14:34:03 CST 2018
Turns out Ken already did this (better) almost 4 years ago, so
nevermind:
https://www.winehq.org/pipermail/wine-devel/2014-March/103665.html
Andrew
On Wed, Feb 07, 2018 at 01:18:49PM -0600, Andrew Eikum wrote:
> Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
> ---
> On my 2-monitor setup this results in:
>
> for device 0, got name: \\.\DISPLAY1, string: X11 Windowing System, flags: 0x15
> for device 0 sub 0, got name: \\.\DISPLAY1\Monitor0, string: Generic PnP Monitor, flags: 0x3
>
> for device 1, got name: \\.\DISPLAY1, string: X11 Windowing System, flags: 0x11
> for device 1 sub 0, got name: \\.\DISPLAY1\Monitor0, string: Generic PnP Monitor, flags: 0x3
>
> Which nearly matches Windows 10 on the same hardware. The differences
> are the 2nd device should be DISPLAY2, not DISPLAY1; and the primary
> adapter comes 2nd on Windows.
>
> However, DISPLAY1 is hard-coded at least in gdi32, winex11, and
> winemac, so I hard-coded it here as well. This results in both
> monitors and adapters having the same name, which is clumsy. But it is
> sufficient to fix Unity games displaying on the non-primary monitor by
> default.
>
> dlls/user32/misc.c | 94 ++++++++++++++++++++++++++++++++++++++++++++----------
> include/wingdi.h | 6 +++-
> 2 files changed, 82 insertions(+), 18 deletions(-)
>
> diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c
> index 895ccce312..96d5212725 100644
> --- a/dlls/user32/misc.c
> +++ b/dlls/user32/misc.c
> @@ -243,11 +243,13 @@ 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',' ',
> +static const WCHAR device_name[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y','1',0};
> +static const WCHAR 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 monitor_string[] = {'G','e','n','e','r','i','c',' ','P','n','P',' ','M','o','n','i','t','o','r',0};
> +static const WCHAR device_deviceid[] = {'P','C','I','\\','V','E','N','_','0','0','0','0','&',
> 'D','E','V','_','0','0','0','0',0};
> +static const WCHAR monitor0W[] = {'\\','M','o','n','i','t','o','r','0',0};
>
> /***********************************************************************
> * EnumDisplayDevicesA (USER32.@)
> @@ -282,29 +284,87 @@ BOOL WINAPI EnumDisplayDevicesA( LPCSTR lpDevice, DWORD i, LPDISPLAY_DEVICEA lpD
> return TRUE;
> }
>
> +struct edd_enum_info
> +{
> + UINT idx;
> + UINT desired;
> + HMONITOR hmon;
> +};
> +
> +static BOOL CALLBACK edd_enum( HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lp )
> +{
> + struct edd_enum_info *info = (struct edd_enum_info *)lp;
> + if (info->idx == info->desired)
> + {
> + info->hmon = monitor;
> + return FALSE;
> + }
> + info->idx++;
> + return TRUE;
> +}
> +
> /***********************************************************************
> * EnumDisplayDevicesW (USER32.@)
> */
> 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);
> + TRACE("(%s, %d, %p, 0x%08x)\n", debugstr_w(lpDevice), i, lpDisplayDevice, dwFlags);
>
> - if (i)
> + if (!lpDisplayDevice)
> 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(lpDisplayDevice->cb >= offsetof(DISPLAY_DEVICEW, DeviceKey) + sizeof(lpDisplayDevice->DeviceKey))
> - lpDisplayDevice->DeviceKey[0] = 0;
> + if (!lpDevice)
> + {
> + struct edd_enum_info info = {0};
> + MONITORINFO monitor = {0};
> +
> + /* one adapter per monitor */
> + info.desired = i;
> + EnumDisplayMonitors(0, NULL, edd_enum, (LPARAM)&info);
> +
> + if (info.hmon == NULL)
> + return FALSE;
> +
> + monitor.cbSize = sizeof(monitor);
> + if (!GetMonitorInfoW(info.hmon, &monitor))
> + return FALSE;
> +
> + memcpy(lpDisplayDevice->DeviceName, device_name, sizeof(device_name));
> + memcpy(lpDisplayDevice->DeviceString, device_string, sizeof(device_string));
> +
> + lpDisplayDevice->StateFlags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP |
> + DISPLAY_DEVICE_VGA_COMPATIBLE;
> +
> + if (monitor.dwFlags & MONITORINFOF_PRIMARY)
> + lpDisplayDevice->StateFlags |= DISPLAY_DEVICE_PRIMARY_DEVICE;
> +
> + if (lpDisplayDevice->cb >= offsetof(DISPLAY_DEVICEW, DeviceID) + sizeof(lpDisplayDevice->DeviceID))
> + memcpy(lpDisplayDevice->DeviceID, device_deviceid, sizeof(device_deviceid));
> + if (lpDisplayDevice->cb >= offsetof(DISPLAY_DEVICEW, DeviceKey) + sizeof(lpDisplayDevice->DeviceKey))
> + lpDisplayDevice->DeviceKey[0] = 0;
> + }
> + else
> + {
> + if (i != 0)
> + /* one monitor per adapter */
> + return FALSE;
> +
> + if (strcmpW(lpDevice, device_name) != 0)
> + return FALSE;
> +
> + strcpyW(lpDisplayDevice->DeviceName, lpDevice);
> + strcatW(lpDisplayDevice->DeviceName, monitor0W);
> +
> + memcpy(lpDisplayDevice->DeviceString, monitor_string, sizeof(monitor_string));
> +
> + lpDisplayDevice->StateFlags = DISPLAY_DEVICE_ACTIVE | DISPLAY_DEVICE_ATTACHED;
> +
> + if (lpDisplayDevice->cb >= offsetof(DISPLAY_DEVICEW, DeviceID) + sizeof(lpDisplayDevice->DeviceID))
> + memcpy(lpDisplayDevice->DeviceID, device_deviceid, sizeof(device_deviceid));
> + if (lpDisplayDevice->cb >= offsetof(DISPLAY_DEVICEW, DeviceKey) + sizeof(lpDisplayDevice->DeviceKey))
> + lpDisplayDevice->DeviceKey[0] = 0;
> + }
>
> return TRUE;
> }
> diff --git a/include/wingdi.h b/include/wingdi.h
> index 1851654194..03b7ed2ce4 100644
> --- a/include/wingdi.h
> +++ b/include/wingdi.h
> @@ -3318,13 +3318,17 @@ DECL_WINELIB_TYPE_AW(DISPLAY_DEVICE)
> DECL_WINELIB_TYPE_AW(PDISPLAY_DEVICE)
> DECL_WINELIB_TYPE_AW(LPDISPLAY_DEVICE)
>
> -/* DISPLAY_DEVICE.StateFlags (?)*/
> +/* DISPLAY_DEVICE.StateFlags, adapter flags */
> #define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001
> #define DISPLAY_DEVICE_MULTI_DRIVER 0x00000002
> #define DISPLAY_DEVICE_PRIMARY_DEVICE 0x00000004
> #define DISPLAY_DEVICE_MIRRORING_DRIVER 0x00000008
> #define DISPLAY_DEVICE_VGA_COMPATIBLE 0x00000010
>
> +/* DISPLAY_DEVICE.StateFlags, monitor flags */
> +#define DISPLAY_DEVICE_ACTIVE 0x00000001
> +#define DISPLAY_DEVICE_ATTACHED 0x00000002
> +
> typedef struct DISPLAYCONFIG_DESKTOP_IMAGE_INFO
> {
> POINTL PathSourceSize;
> --
> 2.16.1
>
>
>
More information about the wine-devel
mailing list