[PATCH 2/6] winex11.drv: Migrate the virtual desktop display settings handler to a new interface.

Zhiyi Zhang zzhang at codeweavers.com
Wed Jul 22 02:24:30 CDT 2020


The old display settings handler interface can only support one adapter.

Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/winex11.drv/desktop.c  | 41 +++++++++++++++++++++++++++++++
 dlls/winex11.drv/settings.c | 48 +++++++++++++++++++++++++++++++++++++
 dlls/winex11.drv/x11drv.h   | 27 +++++++++++++++++++++
 3 files changed, 116 insertions(+)

diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c
index b5894d5e028..d3dcf90fb9d 100644
--- a/dlls/winex11.drv/desktop.c
+++ b/dlls/winex11.drv/desktop.c
@@ -2,6 +2,7 @@
  * X11DRV desktop window handling
  *
  * Copyright 2001 Alexandre Julliard
+ * Copyright 2020 Zhiyi Zhang for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -22,6 +23,9 @@
 #include <X11/cursorfont.h>
 #include <X11/Xlib.h>
 
+#define NONAMELESSSTRUCT
+#define NONAMELESSUNION
+
 #include "x11drv.h"
 
 /* avoid conflict with field names in included win32 headers */
@@ -152,6 +156,35 @@ static LONG X11DRV_desktop_SetCurrentMode(int mode)
     return DISP_CHANGE_SUCCESSFUL;
 }
 
+/* Virtual desktop display settings handler */
+static BOOL X11DRV_desktop_get_id( const WCHAR *device_name, ULONG_PTR *id )
+{
+    WCHAR primary_adapter[CCHDEVICENAME];
+
+    if (!get_primary_adapter( primary_adapter ) || lstrcmpiW( primary_adapter, device_name ))
+        return FALSE;
+
+    *id = 0;
+    return TRUE;
+}
+
+static BOOL X11DRV_desktop_get_current_mode( ULONG_PTR id, DEVMODEW *mode )
+{
+    RECT primary_rect = get_primary_monitor_rect();
+
+    mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
+                     DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION;
+    mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
+    mode->dmBitsPerPel = screen_bpp;
+    mode->dmPelsWidth = primary_rect.right - primary_rect.left;
+    mode->dmPelsHeight = primary_rect.bottom - primary_rect.top;
+    mode->u2.dmDisplayFlags = 0;
+    mode->dmDisplayFrequency = 60;
+    mode->u1.s2.dmPosition.x = 0;
+    mode->u1.s2.dmPosition.y = 0;
+    return TRUE;
+}
+
 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};
@@ -242,6 +275,7 @@ static void X11DRV_desktop_free_monitors( struct x11drv_monitor *monitors )
 void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height )
 {
     RECT primary_rect = get_host_primary_monitor_rect();
+    struct x11drv_settings_handler settings_handler;
 
     root_window = win;
     managed_mode = FALSE;  /* no managed windows in desktop mode */
@@ -270,6 +304,13 @@ void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height )
     make_modes();
     X11DRV_Settings_AddDepthModes();
     dd_mode_count = X11DRV_Settings_GetModeCount();
+
+    /* TODO: Remove the old display settings handler once the migration to the new interface is done */
+    settings_handler.name = "Virtual Desktop";
+    settings_handler.priority = 1000;
+    settings_handler.get_id = X11DRV_desktop_get_id;
+    settings_handler.get_current_mode = X11DRV_desktop_get_current_mode;
+    X11DRV_Settings_SetHandler( &settings_handler );
 }
 
 
diff --git a/dlls/winex11.drv/settings.c b/dlls/winex11.drv/settings.c
index bbbb6fdf0a3..e0dee951543 100644
--- a/dlls/winex11.drv/settings.c
+++ b/dlls/winex11.drv/settings.c
@@ -2,6 +2,7 @@
  * Wine X11drv display settings functions
  *
  * Copyright 2003 Alexander James Pasadyn
+ * Copyright 2020 Zhiyi Zhang for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -125,6 +126,18 @@ unsigned int X11DRV_Settings_GetModeCount(void)
     return dd_mode_count;
 }
 
+/* TODO: Remove the old display settings handler interface once all backends are migrated to the new interface */
+static struct x11drv_settings_handler handler;
+
+void X11DRV_Settings_SetHandler(const struct x11drv_settings_handler *new_handler)
+{
+    if (new_handler->priority > handler.priority)
+    {
+        handler = *new_handler;
+        TRACE("Display settings are now handled by: %s.\n", handler.name);
+    }
+}
+
 /***********************************************************************
  * Default handlers if resolution switching is not enabled
  *
@@ -308,7 +321,42 @@ 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 };
+    ULONG_PTR id;
 
+    /* Use the new interface if it is available */
+    if (!handler.name || (n != ENUM_REGISTRY_SETTINGS && n != ENUM_CURRENT_SETTINGS))
+        goto old_interface;
+
+    if (n == ENUM_REGISTRY_SETTINGS)
+    {
+        if (!read_registry_settings(name, devmode))
+        {
+            ERR("Failed to get %s registry display settings.\n", wine_dbgstr_w(name));
+            return FALSE;
+        }
+        goto done;
+    }
+
+    if (n == ENUM_CURRENT_SETTINGS)
+    {
+        if (!handler.get_id(name, &id) || !handler.get_current_mode(id, devmode))
+        {
+            ERR("Failed to get %s current display settings.\n", wine_dbgstr_w(name));
+            return FALSE;
+        }
+        goto done;
+    }
+
+done:
+    /* Set generic fields */
+    devmode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod);
+    devmode->dmDriverExtra = 0;
+    devmode->dmSpecVersion = DM_SPECVERSION;
+    devmode->dmDriverVersion = DM_SPECVERSION;
+    lstrcpyW(devmode->dmDeviceName, dev_name);
+    return TRUE;
+
+old_interface:
     devmode->dmSize = FIELD_OFFSET(DEVMODEW, dmICMMethod);
     devmode->dmSpecVersion = DM_SPECVERSION;
     devmode->dmDriverVersion = DM_SPECVERSION;
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 9bbb48f1eeb..49059e09b70 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -657,6 +657,33 @@ struct x11drv_mode_info
     unsigned int refresh_rate;
 };
 
+/* Required functions for changing and enumerating display settings */
+struct x11drv_settings_handler
+{
+    /* A name to tell what host driver is used */
+    const char *name;
+
+    /* Higher priority can override handlers with a lower priority */
+    UINT priority;
+
+    /* get_id() will be called to map a device name, e.g., \\.\DISPLAY1 to a driver specific id.
+     * Following functions use this id to identify the device.
+     *
+     * Return FALSE if the device can not be found and TRUE on success */
+    BOOL (*get_id)(const WCHAR *device_name, ULONG_PTR *id);
+
+    /* get_current_mode() will be called to get the current display mode of the device of id
+     *
+     * Following fields in DEVMODE must be valid:
+     * dmFields, dmDisplayOrientation, dmBitsPerPel, dmPelsWidth, dmPelsHeight, dmDisplayFlags,
+     * dmDisplayFrequency and dmPosition
+     *
+     * Return FALSE on failure with parameters unchanged and error code set. Return TRUE on success */
+    BOOL (*get_current_mode)(ULONG_PTR id, DEVMODEW *mode);
+};
+
+extern void X11DRV_Settings_SetHandler(const struct x11drv_settings_handler *handler) DECLSPEC_HIDDEN;
+
 extern void X11DRV_init_desktop( Window win, unsigned int width, unsigned int height ) DECLSPEC_HIDDEN;
 extern void X11DRV_resize_desktop(BOOL) DECLSPEC_HIDDEN;
 extern BOOL is_virtual_desktop(void) DECLSPEC_HIDDEN;
-- 
2.25.1




More information about the wine-devel mailing list