Commit 914b5519 authored by Zhiyi Zhang's avatar Zhiyi Zhang Committed by Alexandre Julliard

winex11.drv: Use a separate virtual desktop display device handler.

If we want to query host monitor dimensions, we need to use XRandR or Xinerama handler. However when in virtual desktop mode, its display device handler overrides other handlers. So we need to separate them. Then we can implement features that require host monitor dimensions like checking whether the virtual desktop window is fullscreen. Signed-off-by: 's avatarZhiyi Zhang <zzhang@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 99d04772
......@@ -27,6 +27,7 @@
/* avoid conflict with field names in included win32 headers */
#undef Status
#include "wine/debug.h"
#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
......@@ -36,6 +37,8 @@ static unsigned int dd_mode_count;
static unsigned int max_width;
static unsigned int max_height;
static unsigned int desktop_width;
static unsigned int desktop_height;
static struct screen_size {
unsigned int width;
......@@ -146,6 +149,88 @@ static LONG X11DRV_desktop_SetCurrentMode(int mode)
return DISP_CHANGE_SUCCESSFUL;
}
static void query_desktop_work_area( RECT *rc_work )
{
static const WCHAR trayW[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d',0};
RECT rect;
HWND hwnd = FindWindowW( trayW, NULL );
if (!hwnd || !IsWindowVisible( hwnd )) return;
if (!GetWindowRect( hwnd, &rect )) return;
if (rect.top) rc_work->bottom = rect.top;
else rc_work->top = rect.bottom;
TRACE( "found tray %p %s work area %s\n", hwnd, wine_dbgstr_rect( &rect ), wine_dbgstr_rect( rc_work ) );
}
static BOOL X11DRV_desktop_get_gpus( struct x11drv_gpu **new_gpus, int *count )
{
static const WCHAR wine_adapterW[] = {'W','i','n','e',' ','A','d','a','p','t','e','r',0};
struct x11drv_gpu *gpu;
gpu = heap_calloc( 1, sizeof(*gpu) );
if (!gpu) return FALSE;
lstrcpyW( gpu->name, wine_adapterW );
*new_gpus = gpu;
*count = 1;
return TRUE;
}
static void X11DRV_desktop_free_gpus( struct x11drv_gpu *gpus )
{
heap_free( gpus );
}
/* TODO: Support multi-head virtual desktop */
static BOOL X11DRV_desktop_get_adapters( ULONG_PTR gpu_id, struct x11drv_adapter **new_adapters, int *count )
{
struct x11drv_adapter *adapter;
adapter = heap_calloc( 1, sizeof(*adapter) );
if (!adapter) return FALSE;
adapter->state_flags = DISPLAY_DEVICE_PRIMARY_DEVICE;
if (desktop_width && desktop_height)
adapter->state_flags |= DISPLAY_DEVICE_ATTACHED_TO_DESKTOP;
*new_adapters = adapter;
*count = 1;
return TRUE;
}
static void X11DRV_desktop_free_adapters( struct x11drv_adapter *adapters )
{
heap_free( adapters );
}
static BOOL X11DRV_desktop_get_monitors( ULONG_PTR adapter_id, struct x11drv_monitor **new_monitors, int *count )
{
static const WCHAR generic_nonpnp_monitorW[] = {
'G','e','n','e','r','i','c',' ',
'N','o','n','-','P','n','P',' ','M','o','n','i','t','o','r',0};
struct x11drv_monitor *monitor;
monitor = heap_calloc( 1, sizeof(*monitor) );
if (!monitor) return FALSE;
lstrcpyW( monitor->name, generic_nonpnp_monitorW );
SetRect( &monitor->rc_monitor, 0, 0, desktop_width, desktop_height );
SetRect( &monitor->rc_work, 0, 0, desktop_width, desktop_height );
query_desktop_work_area( &monitor->rc_work );
monitor->state_flags = DISPLAY_DEVICE_ATTACHED;
if (desktop_width && desktop_height)
monitor->state_flags |= DISPLAY_DEVICE_ACTIVE;
*new_monitors = monitor;
*count = 1;
return TRUE;
}
static void X11DRV_desktop_free_monitors( struct x11drv_monitor *monitors )
{
heap_free( monitors );
}
/***********************************************************************
* X11DRV_init_desktop
*
......@@ -157,8 +242,19 @@ void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height )
root_window = win;
managed_mode = FALSE; /* no managed windows in desktop mode */
xinerama_init( width, height );
desktop_width = width;
desktop_height = height;
/* Initialize virtual desktop mode display device handler */
desktop_handler.name = "Virtual Desktop";
desktop_handler.get_gpus = X11DRV_desktop_get_gpus;
desktop_handler.get_adapters = X11DRV_desktop_get_adapters;
desktop_handler.get_monitors = X11DRV_desktop_get_monitors;
desktop_handler.free_gpus = X11DRV_desktop_free_gpus;
desktop_handler.free_adapters = X11DRV_desktop_free_adapters;
desktop_handler.free_monitors = X11DRV_desktop_free_monitors;
desktop_handler.register_event_handlers = NULL;
TRACE("Display device functions are now handled by: Virtual Desktop\n");
X11DRV_DisplayDevices_Init( TRUE );
primary_rect = get_primary_monitor_rect();
......@@ -311,8 +407,8 @@ void X11DRV_resize_desktop( unsigned int width, unsigned int height )
struct desktop_resize_data resize_data;
resize_data.old_virtual_rect = get_virtual_screen_rect();
xinerama_init( width, height );
desktop_width = width;
desktop_height = height;
X11DRV_DisplayDevices_Init( TRUE );
resize_data.new_virtual_rect = get_virtual_screen_rect();
......
......@@ -103,7 +103,8 @@ static const WCHAR monitor_hardware_idW[] = {
'M','O','N','I','T','O','R','\\',
'D','e','f','a','u','l','t','_','M','o','n','i','t','o','r',0,0};
static struct x11drv_display_device_handler handler;
static struct x11drv_display_device_handler host_handler;
struct x11drv_display_device_handler desktop_handler;
/* Cached screen information, protected by screen_section */
static HKEY video_key;
......@@ -234,17 +235,19 @@ RECT get_primary_monitor_rect(void)
void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler *new_handler)
{
if (new_handler->priority > handler.priority)
if (new_handler->priority > host_handler.priority)
{
handler = *new_handler;
TRACE("Display device functions are now handled by: %s\n", handler.name);
host_handler = *new_handler;
TRACE("Display device functions are now handled by: %s\n", host_handler.name);
}
}
void X11DRV_DisplayDevices_RegisterEventHandlers(void)
{
if (handler.register_event_handlers)
handler.register_event_handlers();
struct x11drv_display_device_handler *handler = is_virtual_desktop() ? &desktop_handler : &host_handler;
if (handler->register_event_handlers)
handler->register_event_handlers();
}
/* Initialize a GPU instance and return its GUID string in guid_string and driver value in driver parameter */
......@@ -501,6 +504,7 @@ static void cleanup_devices(void)
void X11DRV_DisplayDevices_Init(BOOL force)
{
HANDLE mutex;
struct x11drv_display_device_handler *handler = is_virtual_desktop() ? &desktop_handler : &host_handler;
struct x11drv_gpu *gpus = NULL;
struct x11drv_adapter *adapters = NULL;
struct x11drv_monitor *monitors = NULL;
......@@ -526,7 +530,7 @@ void X11DRV_DisplayDevices_Init(BOOL force)
if (!force && disposition != REG_CREATED_NEW_KEY)
goto done;
TRACE("via %s\n", wine_dbgstr_a(handler.name));
TRACE("via %s\n", wine_dbgstr_a(handler->name));
prepare_devices(video_hkey);
......@@ -534,7 +538,7 @@ void X11DRV_DisplayDevices_Init(BOOL force)
monitor_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_MONITOR, NULL);
/* Initialize GPUs */
if (!handler.get_gpus(&gpus, &gpu_count))
if (!handler->get_gpus(&gpus, &gpu_count))
goto done;
TRACE("GPU count: %d\n", gpu_count);
......@@ -544,13 +548,13 @@ void X11DRV_DisplayDevices_Init(BOOL force)
goto done;
/* Initialize adapters */
if (!handler.get_adapters(gpus[gpu].id, &adapters, &adapter_count))
if (!handler->get_adapters(gpus[gpu].id, &adapters, &adapter_count))
goto done;
TRACE("GPU: %#lx %s, adapter count: %d\n", gpus[gpu].id, wine_dbgstr_w(gpus[gpu].name), adapter_count);
for (adapter = 0; adapter < adapter_count; adapter++)
{
if (!handler.get_monitors(adapters[adapter].id, &monitors, &monitor_count))
if (!handler->get_monitors(adapters[adapter].id, &monitors, &monitor_count))
goto done;
TRACE("adapter: %#lx, monitor count: %d\n", adapters[adapter].id, monitor_count);
......@@ -566,12 +570,12 @@ void X11DRV_DisplayDevices_Init(BOOL force)
goto done;
}
handler.free_monitors(monitors);
handler->free_monitors(monitors);
monitors = NULL;
video_index++;
}
handler.free_adapters(adapters);
handler->free_adapters(adapters);
adapters = NULL;
}
......@@ -582,9 +586,9 @@ done:
RegCloseKey(video_hkey);
release_display_device_init_mutex(mutex);
if (gpus)
handler.free_gpus(gpus);
handler->free_gpus(gpus);
if (adapters)
handler.free_adapters(adapters);
handler->free_adapters(adapters);
if (monitors)
handler.free_monitors(monitors);
handler->free_monitors(monitors);
}
......@@ -753,6 +753,8 @@ struct x11drv_display_device_handler
extern void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler *handler) DECLSPEC_HIDDEN;
extern void X11DRV_DisplayDevices_Init(BOOL force) DECLSPEC_HIDDEN;
extern void X11DRV_DisplayDevices_RegisterEventHandlers(void) DECLSPEC_HIDDEN;
/* Display device handler used in virtual desktop mode */
extern struct x11drv_display_device_handler desktop_handler DECLSPEC_HIDDEN;
/* XIM support */
extern BOOL X11DRV_InitXIM( const char *input_style ) DECLSPEC_HIDDEN;
......
......@@ -75,20 +75,6 @@ void query_work_area( RECT *rc_work )
}
}
static void query_desktop_work_area( RECT *rc_work )
{
static const WCHAR trayW[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d',0};
RECT rect;
HWND hwnd = FindWindowW( trayW, NULL );
if (!hwnd || !IsWindowVisible( hwnd )) return;
if (!GetWindowRect( hwnd, &rect )) return;
if (rect.top) rc_work->bottom = rect.top;
else rc_work->top = rect.bottom;
TRACE( "found tray %p %s work area %s\n", hwnd,
wine_dbgstr_rect( &rect ), wine_dbgstr_rect( rc_work ));
}
#ifdef SONAME_LIBXINERAMA
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
......@@ -304,22 +290,19 @@ void xinerama_init( unsigned int width, unsigned int height )
{
struct x11drv_display_device_handler handler;
MONITORINFOEXW *primary;
BOOL desktop_mode = FALSE;
int i;
RECT rect;
SetRect( &rect, 0, 0, width, height );
if (is_virtual_desktop())
return;
if (is_virtual_desktop() || !query_screens())
SetRect( &rect, 0, 0, width, height );
if (!query_screens())
{
default_monitor.rcWork = default_monitor.rcMonitor = rect;
if (!is_virtual_desktop())
query_work_area( &default_monitor.rcWork );
else
query_desktop_work_area( &default_monitor.rcWork );
query_work_area( &default_monitor.rcWork );
nb_monitors = 1;
monitors = &default_monitor;
desktop_mode = TRUE;
}
primary = get_primary();
......@@ -336,8 +319,8 @@ void xinerama_init( unsigned int width, unsigned int height )
(monitors[i].dwFlags & MONITORINFOF_PRIMARY) ? " (primary)" : "" );
}
handler.name = desktop_mode ? "Desktop" : "Xinerama";
handler.priority = desktop_mode ? 1000 : 100;
handler.name = "Xinerama";
handler.priority = 100;
handler.get_gpus = xinerama_get_gpus;
handler.get_adapters = xinerama_get_adapters;
handler.get_monitors = xinerama_get_monitors;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment