[Spice-devel] [PATCH linux vdagent 07/10] Use guest output map to determine xrandr output

Jonathon Jongsma jjongsma at redhat.com
Thu Dec 13 22:46:29 UTC 2018


instead of using the spice display id directly as the xrandr output,
look it up using our new guest output map
---
 src/vdagent/x11-randr.c | 79 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 70 insertions(+), 9 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 925fea8..e5e0048 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -390,6 +390,28 @@ static int xrandr_add_and_set(struct vdagent_x11 *x11, int output_index, int x,
     return 1;
 }
 
+// Looks up the xrandr output id associated with the given spice display id
+static RROutput get_xrandr_output_for_display_id(struct vdagent_x11 *x11, int display_id)
+{
+    guint map_size = g_hash_table_size(x11->guest_output_map);
+    if (map_size == 0) {
+        // we never got a device info message from the server, so just use old
+        // assumptions that the spice display id is equal to the index into the
+        // array of xrandr outputs
+        if (display_id < x11->randr.res->noutput) {
+            return x11->randr.res->outputs[display_id];
+        }
+    } else {
+        gpointer value;
+        if (g_hash_table_lookup_extended(x11->guest_output_map, GINT_TO_POINTER(display_id), NULL, &value)) {
+            return *(gint64*)value;
+        }
+    }
+
+    // unable to find a valid output id
+    return -1;
+}
+
 static void xrandr_disable_nth_output(struct vdagent_x11 *x11, int output_index)
 {
     Status s;
@@ -766,6 +788,17 @@ void vdagent_x11_handle_graphics_device_info(struct vdagent_x11 *x11, uint8_t *d
     }
 }
 
+static int get_output_index_for_display_id(struct vdagent_x11 *x11, int display_id)
+{
+    RROutput oid = get_xrandr_output_for_display_id(x11, display_id);
+    for (int i = 0; i < x11->randr.res->noutput; i++) {
+        if (oid == x11->randr.res->outputs[i]) {
+            return i;
+        }
+    }
+    return -1;
+}
+
 /*
  * Set monitor configuration according to client request.
  *
@@ -841,13 +874,32 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 *x11,
     g_unlink(config);
     g_free(config);
 
-    for (i = mon_config->num_of_monitors; i < x11->randr.res->noutput; i++)
-        xrandr_disable_nth_output(x11, i);
+    // disable all outputs that don't have associated entries in the MonitorConfig
+    for (i = 0; i < x11->randr.res->noutput; i++) {
+        bool disable = true;
+        // check if this xrandr output is represented by an item in mon_config
+        for (int j = 0; j < mon_config->num_of_monitors; j++) {
+            // j represents the display id of an enabled monitor. Check whether
+            // an enabled xrandr output is represented by this id.
+            RROutput oid = get_xrandr_output_for_display_id(x11, j);
+            if (oid == x11->randr.res->outputs[i]) {
+                disable = false;
+            }
+        }
+        if (disable) {
+            xrandr_disable_nth_output(x11, i);
+        }
+    }
 
-    /* First, disable disabled CRTCs... */
+    /* disable CRTCs that are present but explicitly disabled in the
+     * MonitorConfig */
     for (i = 0; i < mon_config->num_of_monitors; ++i) {
         if (!monitor_enabled(&mon_config->monitors[i])) {
-            xrandr_disable_nth_output(x11, i);
+            int output_index = get_output_index_for_display_id(x11, i);
+            if (output_index != -1)
+                xrandr_disable_nth_output(x11, output_index);
+            else
+                syslog(LOG_WARNING, "Unable to find a guest output index for spice display %i", i);
         }
     }
 
@@ -870,7 +922,11 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 *x11,
                 syslog(LOG_DEBUG, "Disabling monitor %d: %dx%d+%d+%d > (%d,%d)",
                        i, width, height, x, y, primary_w, primary_h);
 
-            xrandr_disable_nth_output(x11, i);
+            int output_index = get_output_index_for_display_id(x11, i);
+            if (output_index != -1)
+                xrandr_disable_nth_output(x11, output_index);
+            else
+                syslog(LOG_WARNING, "Unable to find a guest output index for spice display %i", i);
         }
     }
 
@@ -922,11 +978,16 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 *x11,
                    i, width, height, x, y);
         }
 
-        if (!xrandr_add_and_set(x11, i, x, y, width, height) &&
+        int output_index = get_output_index_for_display_id(x11, i);
+        if (output_index != -1) {
+            if (!xrandr_add_and_set(x11, output_index, x, y, width, height) &&
                 enabled_monitors(mon_config) == 1) {
-            set_screen_to_best_size(x11, width, height,
-                                    &primary_w, &primary_h);
-            break;
+                set_screen_to_best_size(x11, width, height,
+                                        &primary_w, &primary_h);
+                break;
+            }
+        } else {
+            syslog(LOG_WARNING, "Unable to find a guest output index for spice display %i", i);
         }
     }
 
-- 
2.17.2



More information about the Spice-devel mailing list