[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