[Spice-devel] [PATCH vdagent-win] vdagent: fix cursor position sync on multimon rhbz#757819

Arnon Gilboa agilboa at redhat.com
Wed Jan 4 02:55:08 PST 2012


On any change of the display settings, driven by client message or guest user,
normalize all display positions to non-negative coordinates, and update total
width and height of the virtual desktop.

The bug was due to wrong handling of (non-primary) displays positioned on
negative coordinates.
---
 vdagent/desktop_layout.cpp |   52 +++++++++++++++++++++++++++----------------
 vdagent/desktop_layout.h   |    1 +
 2 files changed, 34 insertions(+), 19 deletions(-)

diff --git a/vdagent/desktop_layout.cpp b/vdagent/desktop_layout.cpp
index 0eada52..0ba7248 100644
--- a/vdagent/desktop_layout.cpp
+++ b/vdagent/desktop_layout.cpp
@@ -44,10 +44,6 @@ void DesktopLayout::get_displays()
     DEVMODE mode;
     DWORD display_id;
     DWORD dev_id = 0;
-    LONG min_x = 0;
-    LONG min_y = 0;
-    LONG max_x = 0;
-    LONG max_y = 0;
     bool attached;
 
     lock();
@@ -81,22 +77,10 @@ void DesktopLayout::get_displays()
         attached = !!(dev_info.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP);
         EnumDisplaySettings(dev_info.DeviceName, ENUM_CURRENT_SETTINGS, &mode);
         _displays[display_id] = new DisplayMode(mode.dmPosition.x, mode.dmPosition.y,
-                                            mode.dmPelsWidth, mode.dmPelsHeight,
-                                            mode.dmBitsPerPel, attached);
-        if (attached) {
-            min_x = min(min_x, mode.dmPosition.x);
-            min_y = min(min_y, mode.dmPosition.y);
-            max_x = max(max_x, mode.dmPosition.x + (LONG)mode.dmPelsWidth);
-            max_y = max(max_y, mode.dmPosition.y + (LONG)mode.dmPelsHeight);
-        }
-    }
-    if (min_x || min_y) {
-        for (Displays::iterator iter = _displays.begin(); iter != _displays.end(); iter++) {
-            (*iter)->move_pos(-min_x, -min_y);
-        }
+                                                mode.dmPelsWidth, mode.dmPelsHeight,
+                                                mode.dmBitsPerPel, attached);
     }
-    _total_width = max_x - min_x;
-    _total_height = max_y - min_y;
+    normalize_displays_pos();
     unlock();
 }
 
@@ -147,10 +131,40 @@ void DesktopLayout::set_displays()
     }
     if (dev_sets) {
         ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
+        normalize_displays_pos();
     }
     unlock();
 }
 
+// Normalize all display positions to non-negative coordinates and update total width and height of
+// the virtual desktop. Caller is responsible to lock() & unlock().
+void DesktopLayout::normalize_displays_pos()
+{
+    Displays::iterator iter;
+    DisplayMode* mode;
+    LONG min_x = 0;
+    LONG min_y = 0;
+    LONG max_x = 0;
+    LONG max_y = 0;
+
+    for (iter = _displays.begin(); iter != _displays.end(); iter++) {
+        mode = *iter;
+        if (mode->_attached) {
+            min_x = min(min_x, mode->_pos_x);
+            min_y = min(min_y, mode->_pos_y);
+            max_x = max(max_x, mode->_pos_x + (LONG)mode->_width);
+            max_y = max(max_y, mode->_pos_y + (LONG)mode->_height);
+        }
+    }
+    if (min_x || min_y) {
+        for (iter = _displays.begin(); iter != _displays.end(); iter++) {
+            (*iter)->move_pos(-min_x, -min_y);
+        }
+    }
+    _total_width = max_x - min_x;
+    _total_height = max_y - min_y;
+}
+
 bool DesktopLayout::consistent_displays()
 {
     DISPLAY_DEVICE dev_info;
diff --git a/vdagent/desktop_layout.h b/vdagent/desktop_layout.h
index caab84f..c43ff03 100644
--- a/vdagent/desktop_layout.h
+++ b/vdagent/desktop_layout.h
@@ -73,6 +73,7 @@ public:
 
 private:
     void clean_displays();
+    void normalize_displays_pos();
     static bool consistent_displays();
     static bool is_attached(LPCTSTR dev_name);
     static bool get_qxl_device_id(WCHAR* device_key, DWORD* device_id);
-- 
1.7.4.1



More information about the Spice-devel mailing list