winex11.drv: Support virtual desktop display mode enumeration using the new display settings handler interface.

Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zhiyi Zhang 2020-07-22 15:24:41 +08:00 committed by Alexandre Julliard
parent dd13b27410
commit 0b0ac41981
3 changed files with 109 additions and 1 deletions

View File

@ -168,6 +168,72 @@ static BOOL X11DRV_desktop_get_id( const WCHAR *device_name, ULONG_PTR *id )
return TRUE;
}
static void add_desktop_mode( DEVMODEW *mode, DWORD depth, DWORD width, DWORD height )
{
mode->dmSize = sizeof(*mode);
mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY;
mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
mode->dmBitsPerPel = depth;
mode->dmPelsWidth = width;
mode->dmPelsHeight = height;
mode->u2.dmDisplayFlags = 0;
mode->dmDisplayFrequency = 60;
}
static BOOL X11DRV_desktop_get_modes( ULONG_PTR id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count )
{
UINT depth_idx, size_idx, mode_idx = 0;
UINT screen_width, screen_height;
RECT primary_rect;
DEVMODEW *modes;
primary_rect = get_primary_monitor_rect();
screen_width = primary_rect.right - primary_rect.left;
screen_height = primary_rect.bottom - primary_rect.top;
/* Allocate memory for modes in different color depths */
if (!(modes = heap_calloc( (ARRAY_SIZE(screen_sizes) + 2) * DEPTH_COUNT, sizeof(*modes))) )
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
for (depth_idx = 0; depth_idx < DEPTH_COUNT; ++depth_idx)
{
for (size_idx = 0; size_idx < ARRAY_SIZE(screen_sizes); ++size_idx)
{
if (screen_sizes[size_idx].width > max_width ||
screen_sizes[size_idx].height > max_height)
continue;
if (screen_sizes[size_idx].width == max_width &&
screen_sizes[size_idx].height == max_height)
continue;
if (screen_sizes[size_idx].width == screen_width &&
screen_sizes[size_idx].height == screen_height)
continue;
add_desktop_mode( &modes[mode_idx++], depths[depth_idx], screen_sizes[size_idx].width,
screen_sizes[size_idx].height );
}
add_desktop_mode( &modes[mode_idx++], depths[depth_idx], screen_width, screen_height );
if (max_width != screen_width || max_height != screen_height)
add_desktop_mode( &modes[mode_idx++], depths[depth_idx], max_width, max_height );
}
*new_modes = modes;
*mode_count = mode_idx;
return TRUE;
}
static void X11DRV_desktop_free_modes( DEVMODEW *modes )
{
heap_free( modes );
}
static BOOL X11DRV_desktop_get_current_mode( ULONG_PTR id, DEVMODEW *mode )
{
RECT primary_rect = get_primary_monitor_rect();
@ -309,6 +375,8 @@ void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height )
settings_handler.name = "Virtual Desktop";
settings_handler.priority = 1000;
settings_handler.get_id = X11DRV_desktop_get_id;
settings_handler.get_modes = X11DRV_desktop_get_modes;
settings_handler.free_modes = X11DRV_desktop_free_modes;
settings_handler.get_current_mode = X11DRV_desktop_get_current_mode;
X11DRV_Settings_SetHandler( &settings_handler );
}

View File

@ -42,6 +42,7 @@ static unsigned int dd_max_modes = 0;
*/
static const unsigned int depths_24[] = {8, 16, 24};
static const unsigned int depths_32[] = {8, 16, 32};
const unsigned int *depths;
/* pointers to functions that actually do the hard stuff */
static int (*pGetCurrentMode)(void);
@ -158,6 +159,9 @@ static LONG X11DRV_nores_SetCurrentMode(int mode)
void X11DRV_Settings_Init(void)
{
RECT primary = get_host_primary_monitor_rect();
depths = screen_bpp == 32 ? depths_32 : depths_24;
X11DRV_Settings_SetHandlers("NoRes",
X11DRV_nores_GetCurrentMode,
X11DRV_nores_SetCurrentMode,
@ -321,10 +325,12 @@ BOOL CDECL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmo
{
static const WCHAR dev_name[CCHDEVICENAME] =
{ 'W','i','n','e',' ','X','1','1',' ','d','r','i','v','e','r',0 };
DEVMODEW *modes;
UINT mode_count;
ULONG_PTR id;
/* Use the new interface if it is available */
if (!handler.name || (n != ENUM_REGISTRY_SETTINGS && n != ENUM_CURRENT_SETTINGS))
if (!handler.name)
goto old_interface;
if (n == ENUM_REGISTRY_SETTINGS)
@ -347,6 +353,23 @@ BOOL CDECL X11DRV_EnumDisplaySettingsEx( LPCWSTR name, DWORD n, LPDEVMODEW devmo
goto done;
}
if (!handler.get_id(name, &id) || !handler.get_modes(id, flags, &modes, &mode_count))
{
ERR("Failed to get %s supported display modes.\n", wine_dbgstr_w(name));
return FALSE;
}
if (n >= mode_count)
{
WARN("handler:%s device:%s mode index:%#x not found.\n", handler.name, wine_dbgstr_w(name), n);
handler.free_modes(modes);
SetLastError(ERROR_NO_MORE_FILES);
return FALSE;
}
memcpy(devmode, (BYTE *)modes + (sizeof(*modes) + modes[0].dmDriverExtra) * n, sizeof(*devmode));
handler.free_modes(modes);
done:
/* Set generic fields */
devmode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod);

View File

@ -657,6 +657,9 @@ struct x11drv_mode_info
unsigned int refresh_rate;
};
#define DEPTH_COUNT 3
extern const unsigned int *depths DECLSPEC_HIDDEN;
/* Required functions for changing and enumerating display settings */
struct x11drv_settings_handler
{
@ -672,6 +675,20 @@ struct x11drv_settings_handler
* Return FALSE if the device can not be found and TRUE on success */
BOOL (*get_id)(const WCHAR *device_name, ULONG_PTR *id);
/* get_modes() will be called to get a list of supported modes of the device of id in modes
* with respect to flags, which could be 0, EDS_RAWMODE or EDS_ROTATEDMODE. If the implementation
* uses dmDriverExtra then every DEVMODEW in the list must have the same dmDriverExtra value
*
* Following fields in DEVMODE must be valid:
* dmSize, dmDriverExtra, dmFields, dmDisplayOrientation, dmBitsPerPel, dmPelsWidth, dmPelsHeight,
* dmDisplayFlags and dmDisplayFrequency
*
* Return FALSE on failure with parameters unchanged and error code set. Return TRUE on success */
BOOL (*get_modes)(ULONG_PTR id, DWORD flags, DEVMODEW **modes, UINT *mode_count);
/* free_modes() will be called to free the mode list returned from get_modes() */
void (*free_modes)(DEVMODEW *modes);
/* get_current_mode() will be called to get the current display mode of the device of id
*
* Following fields in DEVMODE must be valid: