From: Zhiyi Zhang Subject: [PATCH 3/7] winex11.drv: Use a separate virtual desktop display device handler. Message-Id: <0043924d-beb2-ce5b-7323-5c2f5064f857@codeweavers.com> Date: Thu, 3 Oct 2019 15:54:26 +0800 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: Zhiyi Zhang --- dlls/winex11.drv/desktop.c | 109 ++++++++++++++++++++++++++++++++++-- dlls/winex11.drv/display.c | 29 +++++----- dlls/winex11.drv/x11drv.h | 2 + dlls/winex11.drv/xinerama.c | 34 +++-------- 4 files changed, 132 insertions(+), 42 deletions(-) diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index e4eb61f7bd..7c2d4fd4bc 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -27,9 +27,14 @@ /* avoid conflict with field names in included win32 headers */ #undef Status #include "wine/debug.h" +#include "wine/heap.h" WINE_DEFAULT_DEBUG_CHANNEL(x11drv); +struct x11drv_display_device_handler desktop_handler; +static unsigned int desktop_width; +static unsigned int desktop_height; + /* data for resolution changing */ static struct x11drv_mode_info *dd_modes; static unsigned int dd_mode_count; @@ -146,6 +151,92 @@ 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 ); +} + +/* FIXME: 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; + + if (gpu_id) return FALSE; + + 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; + + if (adapter_id) return FALSE; + + 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 +248,18 @@ 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.pGetGpus = X11DRV_desktop_get_gpus; + desktop_handler.pGetAdapters = X11DRV_desktop_get_adapters; + desktop_handler.pGetMonitors = X11DRV_desktop_get_monitors; + desktop_handler.pFreeGpus = X11DRV_desktop_free_gpus; + desktop_handler.pFreeAdapters = X11DRV_desktop_free_adapters; + desktop_handler.pFreeMonitors = X11DRV_desktop_free_monitors; + TRACE("Display device functions are now handled by: Virtual Desktop\n"); X11DRV_DisplayDevices_Init( TRUE ); primary_rect = get_primary_monitor_rect(); @@ -311,8 +412,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(); diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c index 107719a26f..acf19bd8c6 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -103,7 +103,7 @@ 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; static RECT virtual_screen_rect; static RECT primary_monitor_rect; @@ -135,10 +135,10 @@ 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); } } @@ -433,6 +433,7 @@ void X11DRV_DisplayDevices_Init(BOOL force) { static const WCHAR init_mutexW[] = {'d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t',0}; HANDLE mutex; + struct x11drv_display_device_handler *handler; struct x11drv_gpu *gpus = NULL; struct x11drv_adapter *adapters = NULL; struct x11drv_monitor *monitors = NULL; @@ -445,6 +446,8 @@ void X11DRV_DisplayDevices_Init(BOOL force) WCHAR guidW[40]; WCHAR driverW[1024]; + handler = is_virtual_desktop() ? &desktop_handler : &host_handler; + mutex = CreateMutexW(NULL, FALSE, init_mutexW); WaitForSingleObject(mutex, INFINITE); @@ -462,7 +465,7 @@ void X11DRV_DisplayDevices_Init(BOOL force) goto done; } - TRACE("via %s\n", wine_dbgstr_a(handler.name)); + TRACE("via %s\n", wine_dbgstr_a(handler->name)); prepare_devices(video_hkey); @@ -470,7 +473,7 @@ void X11DRV_DisplayDevices_Init(BOOL force) monitor_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_MONITOR, NULL); /* Initialize GPUs */ - if (!handler.pGetGpus(&gpus, &gpu_count)) + if (!handler->pGetGpus(&gpus, &gpu_count)) goto done; TRACE("GPU count: %d\n", gpu_count); @@ -480,13 +483,13 @@ void X11DRV_DisplayDevices_Init(BOOL force) goto done; /* Initialize adapters */ - if (!handler.pGetAdapters(gpus[gpu].id, &adapters, &adapter_count)) + if (!handler->pGetAdapters(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.pGetMonitors(adapters[adapter].id, &monitors, &monitor_count)) + if (!handler->pGetMonitors(adapters[adapter].id, &monitors, &monitor_count)) goto done; TRACE("adapter: %#lx, monitor count: %d\n", adapters[adapter].id, monitor_count); @@ -502,12 +505,12 @@ void X11DRV_DisplayDevices_Init(BOOL force) goto done; } - handler.pFreeMonitors(monitors); + handler->pFreeMonitors(monitors); monitors = NULL; video_index++; } - handler.pFreeAdapters(adapters); + handler->pFreeAdapters(adapters); adapters = NULL; } @@ -522,9 +525,9 @@ done: ReleaseMutex(mutex); CloseHandle(mutex); if (gpus) - handler.pFreeGpus(gpus); + handler->pFreeGpus(gpus); if (adapters) - handler.pFreeAdapters(adapters); + handler->pFreeAdapters(adapters); if (monitors) - handler.pFreeMonitors(monitors); + handler->pFreeMonitors(monitors); } diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index cd2450e4b1..6ae9564858 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -746,6 +746,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; +/* Display devices 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; diff --git a/dlls/winex11.drv/xinerama.c b/dlls/winex11.drv/xinerama.c index ed5ec22315..dacc59fefb 100644 --- a/dlls/winex11.drv/xinerama.c +++ b/dlls/winex11.drv/xinerama.c @@ -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,27 +290,25 @@ 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()) + 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 ); + SetRect( &default_monitor.rcMonitor, 0, 0, width, height ); + SetRect( &default_monitor.rcWork, 0, 0, width, height ); + query_work_area( &default_monitor.rcWork ); nb_monitors = 1; monitors = &default_monitor; - desktop_mode = TRUE; } primary = get_primary(); /* coordinates (0,0) have to point to the primary monitor origin */ + SetRect( &rect, 0, 0, width, height ); OffsetRect( &rect, -primary->rcMonitor.left, -primary->rcMonitor.top ); for (i = 0; i < nb_monitors; i++) { @@ -336,8 +320,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.pGetGpus = xinerama_get_gpus; handler.pGetAdapters = xinerama_get_adapters; handler.pGetMonitors = xinerama_get_monitors; -- 2.23.0