Zhiyi Zhang : winex11.drv: Support detaching adapters.

Alexandre Julliard julliard at winehq.org
Thu Jul 30 15:31:25 CDT 2020


Module: wine
Branch: master
Commit: d13b61b7385a6a380fb91720c511b194926fa0ca
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=d13b61b7385a6a380fb91720c511b194926fa0ca

Author: Zhiyi Zhang <zzhang at codeweavers.com>
Date:   Mon Jul 27 16:01:04 2020 +0800

winex11.drv: Support detaching adapters.

Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/user32/tests/monitor.c |  4 ++--
 dlls/winex11.drv/settings.c | 56 ++++++++++++++++++++++++++++++++++-----------
 dlls/winex11.drv/xrandr.c   | 21 +++++++++++++++++
 3 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c
index 0d32dbfeef..85fb2f080a 100644
--- a/dlls/user32/tests/monitor.c
+++ b/dlls/user32/tests/monitor.c
@@ -612,10 +612,10 @@ static void test_ChangeDisplaySettingsEx(void)
         dd.cb = sizeof(dd);
         res = EnumDisplayDevicesA(NULL, devices[device].index, &dd, 0);
         ok(res, "EnumDisplayDevicesA %s failed, error %#x\n", devices[device].name, GetLastError());
-        todo_wine ok(!(dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP), "Expect device %s detached.\n", devices[device].name);
+        ok(!(dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP), "Expect device %s detached.\n", devices[device].name);
 
         count = GetSystemMetrics(SM_CMONITORS);
-        todo_wine ok(count == old_count - 1, "Expect monitor count %d, got %d\n", old_count - 1, count);
+        ok(count == old_count - 1, "Expect monitor count %d, got %d\n", old_count - 1, count);
     }
 
     /* Test changing each adapter to every available mode */
diff --git a/dlls/winex11.drv/settings.c b/dlls/winex11.drv/settings.c
index 56f55e78b4..7c7d950718 100644
--- a/dlls/winex11.drv/settings.c
+++ b/dlls/winex11.drv/settings.c
@@ -805,27 +805,33 @@ static void place_all_displays(struct x11drv_display_setting *displays, INT disp
     }
 }
 
-static LONG apply_display_settings(struct x11drv_display_setting *displays, INT display_count)
+static LONG apply_display_settings(struct x11drv_display_setting *displays, INT display_count, BOOL do_attach)
 {
     DEVMODEW *full_mode;
+    BOOL attached_mode;
     INT display_idx;
     LONG ret;
 
     for (display_idx = 0; display_idx < display_count; ++display_idx)
     {
-        if (is_detached_mode(&displays[display_idx].desired_mode))
-        {
-            FIXME("Detaching %s is currently unsupported.\n",
-                  wine_dbgstr_w(displays[display_idx].desired_mode.dmDeviceName));
+        attached_mode = !is_detached_mode(&displays[display_idx].desired_mode);
+        if ((attached_mode && !do_attach) || (!attached_mode && do_attach))
             continue;
-        }
 
-        full_mode = get_full_mode(displays[display_idx].id, &displays[display_idx].desired_mode);
-        if (!full_mode)
-            return DISP_CHANGE_BADMODE;
+        if (attached_mode)
+        {
+            full_mode = get_full_mode(displays[display_idx].id, &displays[display_idx].desired_mode);
+            if (!full_mode)
+                return DISP_CHANGE_BADMODE;
+
+            full_mode->dmFields |= DM_POSITION;
+            full_mode->u1.s2.dmPosition = displays[display_idx].desired_mode.u1.s2.dmPosition;
+        }
+        else
+        {
+            full_mode = &displays[display_idx].desired_mode;
+        }
 
-        full_mode->dmFields |= DM_POSITION;
-        full_mode->u1.s2.dmPosition = displays[display_idx].desired_mode.u1.s2.dmPosition;
         TRACE("handler:%s changing %s to position:(%d,%d) resolution:%ux%u frequency:%uHz "
               "depth:%ubits orientation:%#x.\n", handler.name,
               wine_dbgstr_w(displays[display_idx].desired_mode.dmDeviceName),
@@ -834,7 +840,8 @@ static LONG apply_display_settings(struct x11drv_display_setting *displays, INT
               full_mode->u1.s2.dmDisplayOrientation);
 
         ret = handler.set_current_mode(displays[display_idx].id, full_mode);
-        heap_free(full_mode);
+        if (attached_mode)
+            heap_free(full_mode);
         if (ret != DISP_CHANGE_SUCCESSFUL)
             return ret;
     }
@@ -842,6 +849,19 @@ static LONG apply_display_settings(struct x11drv_display_setting *displays, INT
     return DISP_CHANGE_SUCCESSFUL;
 }
 
+static BOOL all_detached_settings(const struct x11drv_display_setting *displays, INT display_count)
+{
+    INT display_idx;
+
+    for (display_idx = 0; display_idx < display_count; ++display_idx)
+    {
+        if (!is_detached_mode(&displays[display_idx].desired_mode))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
 /***********************************************************************
  *		ChangeDisplaySettingsEx  (X11DRV.@)
  *
@@ -888,9 +908,19 @@ LONG CDECL X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode,
         return DISP_CHANGE_SUCCESSFUL;
     }
 
+    if (all_detached_settings(displays, display_count))
+    {
+        WARN("Detaching all displays is not permitted.\n");
+        heap_free(displays);
+        return DISP_CHANGE_SUCCESSFUL;
+    }
+
     place_all_displays(displays, display_count);
 
-    ret = apply_display_settings(displays, display_count);
+    /* Detach displays first to free up CRTCs */
+    ret = apply_display_settings(displays, display_count, FALSE);
+    if (ret == DISP_CHANGE_SUCCESSFUL)
+        ret = apply_display_settings(displays, display_count, TRUE);
     if (ret == DISP_CHANGE_SUCCESSFUL)
         X11DRV_DisplayDevices_Update(TRUE);
     heap_free(displays);
diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c
index 4fbb2e540d..67fd285182 100644
--- a/dlls/winex11.drv/xrandr.c
+++ b/dlls/winex11.drv/xrandr.c
@@ -1306,6 +1306,27 @@ static LONG xrandr14_set_current_mode( ULONG_PTR id, DEVMODEW *mode )
     if (!output_info || output_info->connection != RR_Connected)
         goto done;
 
+    if (is_detached_mode(mode))
+    {
+        /* Already detached */
+        if (!output_info->crtc)
+        {
+            ret = DISP_CHANGE_SUCCESSFUL;
+            goto done;
+        }
+
+        /* Execute detach operation */
+        status = pXRRSetCrtcConfig( gdi_display, screen_resources, output_info->crtc,
+                                    CurrentTime, 0, 0, None, RR_Rotate_0, NULL, 0 );
+        if (status == RRSetConfigSuccess)
+        {
+            get_screen_size( screen_resources, &screen_width, &screen_height );
+            set_screen_size( screen_width, screen_height );
+            ret = DISP_CHANGE_SUCCESSFUL;
+        }
+        goto done;
+    }
+
     /* Attached */
     if (output_info->crtc)
     {




More information about the wine-cvs mailing list