[PATCH 2/5] winex11.drv: Use a separate virtual desktop display device handler.

Zhiyi Zhang zzhang at codeweavers.com
Tue Nov 5 07:04:27 CST 2019


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 <zzhang at codeweavers.com>
---
 dlls/winex11.drv/desktop.c  | 102 ++++++++++++++++++++++++++++++++++--
 dlls/winex11.drv/display.c  |  34 ++++++------
 dlls/winex11.drv/x11drv.h   |   2 +
 dlls/winex11.drv/xinerama.c |  31 +++--------
 4 files changed, 127 insertions(+), 42 deletions(-)

diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c
index e4eb61f7bd..a3b2f0cbf2 100644
--- a/dlls/winex11.drv/desktop.c
+++ b/dlls/winex11.drv/desktop.c
@@ -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 */
+    desktop_width = width;
+    desktop_height = height;
 
-    xinerama_init( width, 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();
 
diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c
index ee867343ae..d3ee653f21 100644
--- a/dlls/winex11.drv/display.c
+++ b/dlls/winex11.drv/display.c
@@ -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);
 }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index a96f57dc37..4a6de9053d 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -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;
diff --git a/dlls/winex11.drv/xinerama.c b/dlls/winex11.drv/xinerama.c
index bd607f3006..4903f52b23 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,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;
-- 
2.23.0




More information about the wine-devel mailing list