[Spice-devel] [PATCH spice vdagent] vdagent: use best match for resolution change

Arnon Gilboa agilboa at redhat.com
Tue Dec 14 06:48:23 PST 2010


similar handling as linux agent
---
 vdagent/desktop_layout.cpp |   85 ++++++++++++++++++++++++++++----------------
 vdagent/desktop_layout.h   |    4 ++-
 2 files changed, 57 insertions(+), 32 deletions(-)

diff --git a/vdagent/desktop_layout.cpp b/vdagent/desktop_layout.cpp
index 32502bc..7040434 100644
--- a/vdagent/desktop_layout.cpp
+++ b/vdagent/desktop_layout.cpp
@@ -106,25 +106,28 @@ void DesktopLayout::set_displays()
     dev_info.cb = sizeof(dev_info);
     ZeroMemory(&dev_mode, sizeof(dev_mode));
     dev_mode.dmSize = sizeof(dev_mode);
-    while (EnumDisplayDevices(NULL, dev_id, &dev_info, 0)) {
-        if (wcsstr(dev_info.DeviceString, L"QXL")) {
-            if (!get_qxl_device_id(dev_info.DeviceKey, &qxl_id)) {
-                vd_printf("get_qxl_device_id failed");
-                break;
-            }
-            if (qxl_id >= _displays.size()) {
-                vd_printf("qxl_id %u out of range, #displays %u", qxl_id, _displays.size());
-                break;
-            }
-            //FIXME: always set pos?
-            init_dev_mode(&dev_mode, _displays.at(qxl_id), true);
-            LONG ret = ChangeDisplaySettingsEx(dev_info.DeviceName, &dev_mode, NULL,
-                                               CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
-            if (ret == DISP_CHANGE_SUCCESSFUL) {
-                dev_sets++;
-            }
+    while (EnumDisplayDevices(NULL, dev_id++, &dev_info, 0)) {
+        if (!wcsstr(dev_info.DeviceString, L"QXL")) {
+            continue;
+        }
+        if (!get_qxl_device_id(dev_info.DeviceKey, &qxl_id)) {
+            vd_printf("get_qxl_device_id failed");
+            break;
+        }
+        if (qxl_id >= _displays.size()) {
+            vd_printf("qxl_id %u out of range, #displays %u", qxl_id, _displays.size());
+            break;
+        }
+        if (!init_dev_mode(dev_info.DeviceName, &dev_mode, _displays.at(qxl_id), true)) {
+            vd_printf("No suitable mode found for display %S", dev_info.DeviceName);
+            break;
+        }
+        vd_printf("Set display mode %ux%u", dev_mode.dmPelsWidth, dev_mode.dmPelsHeight);
+        LONG ret = ChangeDisplaySettingsEx(dev_info.DeviceName, &dev_mode, NULL,
+                                           CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
+        if (ret == DISP_CHANGE_SUCCESSFUL) {
+            dev_sets++;
         }
-        dev_id++;
     }
     if (dev_sets) {
         ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
@@ -173,23 +176,43 @@ bool DesktopLayout::get_qxl_device_id(WCHAR* device_key, DWORD* device_id)
     return key_found;
 }
 
-void DesktopLayout::init_dev_mode(DEVMODE* dev_mode, DisplayMode* mode, bool set_pos)
+bool DesktopLayout::init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode, DisplayMode* mode,
+                                  bool set_pos)
 {
+    DWORD closest_diff = -1;
+    DWORD best = -1;
+
     ZeroMemory(dev_mode, sizeof(DEVMODE));
     dev_mode->dmSize = sizeof(DEVMODE);
-    if (mode && mode->get_attached()) {
-        dev_mode->dmBitsPerPel = mode->get_depth();
-        dev_mode->dmPelsWidth = mode->get_width();
-        dev_mode->dmPelsHeight = mode->get_height();
-        dev_mode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
-        if (set_pos) {
-            dev_mode->dmPosition.x = mode->get_pos_x();
-            dev_mode->dmPosition.y = mode->get_pos_y();
-            dev_mode->dmFields |= DM_POSITION;
-        }
-    } else {
-        //detach monitor
+    if (!mode || !mode->_attached) {
+        //Detach monitor
         dev_mode->dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_POSITION;
+        return true;
+    }
+    //Find the closest size which will fit within the monitor
+    for (DWORD i = 0; EnumDisplaySettings(dev_name, i, dev_mode); i++) {
+        if (dev_mode->dmPelsWidth > mode->_width ||
+            dev_mode->dmPelsHeight > mode->_height ||
+            dev_mode->dmBitsPerPel != mode->_depth) {
+            continue;
+        }
+        DWORD wdiff = mode->_width - dev_mode->dmPelsWidth;
+        DWORD hdiff = mode->_height - dev_mode->dmPelsHeight;
+        DWORD diff = wdiff * wdiff + hdiff * hdiff;
+        if (diff < closest_diff) {
+            closest_diff = diff;
+            best = i;
+        }
+    }
+    if (best == -1 || !EnumDisplaySettings(dev_name, best, dev_mode)) {
+        return false;
+    }
+    dev_mode->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+    if (set_pos) {
+        dev_mode->dmPosition.x = mode->_pos_x;
+        dev_mode->dmPosition.y = mode->_pos_y;
+        dev_mode->dmFields |= DM_POSITION;
     }
+    return true;
 }
 
diff --git a/vdagent/desktop_layout.h b/vdagent/desktop_layout.h
index a43ee49..f3294b5 100644
--- a/vdagent/desktop_layout.h
+++ b/vdagent/desktop_layout.h
@@ -52,6 +52,8 @@ private:
     DWORD _height;
     DWORD _depth;
     bool _attached;
+
+    friend class DesktopLayout;
 };
 
 typedef std::vector<DisplayMode*> Displays;
@@ -73,7 +75,7 @@ private:
     void clean_displays();
     static bool is_attached(LPCTSTR dev_name);
     static bool get_qxl_device_id(WCHAR* device_key, DWORD* device_id);
-    static void init_dev_mode(DEVMODE* dev_mode, DisplayMode* mode, bool set_pos);
+    static bool init_dev_mode(LPCTSTR dev_name, DEVMODE* dev_mode, DisplayMode* mode, bool set_pos);
 
 private:
     mutex_t _mutex;
-- 
1.5.5.6



More information about the Spice-devel mailing list