[Spice-devel] [RFC PATCH spice-gtk v2 17/20] Send SpiceMsgcMainMonitorsConfig instead of VDAgentMonitorsConfig

Lukáš Hrázký lhrazky at redhat.com
Thu Aug 16 16:26:46 UTC 2018


TODO This patch does not use a capability to send the old version of the
monitors config message (the VDAgentMonitorsConfig one) in case of an
old server.

Sends the SpiceMsgcMainMonitorsConfig as the monitors_config message,
which contains the unique (channel_id, monitor_id) identification pair
to identify the monitors_configs with. The message is meant for the
server only, which needs to translate the ID pair to a guest_output_id
in case it needs to send the monitors_config to the vd_agent.

Signed-off-by: Lukáš Hrázký <lhrazky at redhat.com>
---
 src/channel-main.c       | 183 +++++++++++++++++++++++++++++----------
 subprojects/spice-common |   2 +-
 2 files changed, 137 insertions(+), 48 deletions(-)

diff --git a/src/channel-main.c b/src/channel-main.c
index 44137b9..cff9595 100644
--- a/src/channel-main.c
+++ b/src/channel-main.c
@@ -1054,6 +1054,53 @@ static void monitors_align(VDAgentMonConfig *monitors, int nmonitors)
     g_free(sorted_monitors);
 }
 
+static int monitors_cmp_smh(const void *p1, const void *p2, gpointer user_data)
+{
+    const SpiceMainHead *m1 = p1;
+    const SpiceMainHead *m2 = p2;
+    double d1 = sqrt(m1->x * m1->x + m1->y * m1->y);
+    double d2 = sqrt(m2->x * m2->x + m2->y * m2->y);
+    int diff = d1 - d2;
+
+    return diff == 0 ? (char*)p1 - (char*)p2 : diff;
+}
+
+static void monitors_align_smh(SpiceMainHead *monitors, int nmonitors)
+{
+    gint i, j, x = 0;
+    guint32 used = 0;
+    SpiceMainHead *sorted_monitors;
+
+    if (nmonitors == 0)
+        return;
+
+    /* sort by distance from origin */
+    sorted_monitors = g_memdup(monitors, nmonitors * sizeof(SpiceMainHead));
+    g_qsort_with_data(sorted_monitors, nmonitors, sizeof(SpiceMainHead), monitors_cmp_smh, NULL);
+
+    /* super-KISS ltr alignment, feel free to improve */
+    for (i = 0; i < nmonitors; i++) {
+        /* Find where this monitor is in the sorted order */
+        for (j = 0; j < nmonitors; j++) {
+            /* Avoid using the same entry twice, this happens with older
+               virt-viewer versions which always set x and y to 0 */
+            if (used & (1 << j))
+                continue;
+            if (memcmp(&monitors[j], &sorted_monitors[i],
+                       sizeof(SpiceMainHead)) == 0)
+                break;
+        }
+        used |= 1 << j;
+        monitors[j].x = x;
+        monitors[j].y = 0;
+        x += monitors[j].width;
+        if (monitors[j].width || monitors[j].height)
+            SPICE_DEBUG("#%d +%u+%u-%ux%u", j, monitors[j].x, monitors[j].y,
+                        monitors[j].width, monitors[j].height);
+    }
+    g_free(sorted_monitors);
+}
+
 
 #define agent_msg_queue(Channel, Type, Size, Data) \
     agent_msg_queue_many((Channel), (Type), (Data), (Size), NULL)
@@ -1087,69 +1134,111 @@ gboolean spice_main_send_monitor_config(SpiceMainChannel *channel)
  **/
 gboolean spice_main_channel_send_monitor_config(SpiceMainChannel *channel)
 {
-    SpiceMainChannelPrivate *c;
-    VDAgentMonitorsConfig *mon;
-    int i, j, monitors;
-    size_t size;
-
     g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(channel), FALSE);
-    c = channel->priv;
+
+    SpiceMainChannelPrivate *c = channel->priv;
     g_return_val_if_fail(c->agent_connected, FALSE);
 
     GArray *monitor_configs = spice_session_get_monitor_configs(
         spice_channel_get_session(SPICE_CHANNEL(channel)));
 
-    if (spice_main_channel_agent_test_capability(channel, VD_AGENT_CAP_SPARSE_MONITORS_CONFIG)) {
-        monitors = monitor_configs->len;
-    } else {
-        monitors = 0;
+    if (false /* TODO add capability for the old version of the message in this if branch */) {
+        VDAgentMonitorsConfig *mon;
+        int i, j, monitors;
+        size_t size;
+
+        if (spice_main_channel_agent_test_capability(channel, VD_AGENT_CAP_SPARSE_MONITORS_CONFIG)) {
+            monitors = monitor_configs->len;
+        } else {
+            monitors = 0;
+            for (i = 0; i < monitor_configs->len; i++) {
+                if (g_array_index(monitor_configs, SpiceMonitorConfig, i).enabled) {
+                    monitors += 1;
+                }
+            }
+        }
+
+        size = sizeof(VDAgentMonitorsConfig) + sizeof(VDAgentMonConfig) * monitors;
+        mon = g_malloc0(size);
+
+        mon->num_of_monitors = monitors;
+        if (c->disable_display_position == FALSE ||
+            c->disable_display_align == FALSE)
+            mon->flags |= VD_AGENT_CONFIG_MONITORS_FLAG_USE_POS;
+
+        CHANNEL_DEBUG(channel, "Sending new monitors config to the vd_agent:");
+        j = 0;
         for (i = 0; i < monitor_configs->len; i++) {
-            if (g_array_index(monitor_configs, SpiceMonitorConfig, i).enabled) {
-                monitors += 1;
+            SpiceMonitorConfig *mc = &g_array_index(monitor_configs, SpiceMonitorConfig, i);
+            if (!mc->enabled) {
+                if (spice_main_channel_agent_test_capability(channel,
+                                                             VD_AGENT_CAP_SPARSE_MONITORS_CONFIG))
+                    j++;
+                continue;
             }
+            mon->monitors[j].depth  = c->display_color_depth ? c->display_color_depth : 32;
+            mon->monitors[j].width  = mc->width;
+            mon->monitors[j].height = mc->height;
+            mon->monitors[j].x = mc->x;
+            mon->monitors[j].y = mc->y;
+            CHANNEL_DEBUG(channel, "   monitor #%d: %ux%u+%d+%d @ %u bpp", j,
+                          mon->monitors[j].width, mon->monitors[j].height,
+                          mon->monitors[j].x, mon->monitors[j].y,
+                          mon->monitors[j].depth);
+            j++;
         }
-    }
 
-    size = sizeof(VDAgentMonitorsConfig) + sizeof(VDAgentMonConfig) * monitors;
-    mon = g_malloc0(size);
+        if (c->disable_display_align == FALSE)
+            monitors_align(mon->monitors, mon->num_of_monitors);
 
-    mon->num_of_monitors = monitors;
-    if (c->disable_display_position == FALSE ||
-        c->disable_display_align == FALSE)
-        mon->flags |= VD_AGENT_CONFIG_MONITORS_FLAG_USE_POS;
+        agent_msg_queue(channel, VD_AGENT_MONITORS_CONFIG, size, mon);
+        g_free(mon);
 
-    CHANNEL_DEBUG(channel, "sending new monitors config to guest");
-    j = 0;
-    for (i = 0; i < monitor_configs->len; i++) {
-        SpiceMonitorConfig *mc = &g_array_index(monitor_configs, SpiceMonitorConfig, i);
-        if (!mc->enabled) {
-            if (spice_main_channel_agent_test_capability(channel,
-                                                         VD_AGENT_CAP_SPARSE_MONITORS_CONFIG))
-                j++;
-            continue;
+        spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
+        if (c->timer_id != 0) {
+            g_source_remove(c->timer_id);
+            c->timer_id = 0;
         }
-        mon->monitors[j].depth  = c->display_color_depth ? c->display_color_depth : 32;
-        mon->monitors[j].width  = mc->width;
-        mon->monitors[j].height = mc->height;
-        mon->monitors[j].x = mc->x;
-        mon->monitors[j].y = mc->y;
-        CHANNEL_DEBUG(channel, "monitor #%d: %ux%u+%d+%d @ %u bpp", j,
-                      mon->monitors[j].width, mon->monitors[j].height,
-                      mon->monitors[j].x, mon->monitors[j].y,
-                      mon->monitors[j].depth);
-        j++;
-    }
+    } else {
+        size_t size = sizeof(SpiceMsgcMainMonitorsConfig) + sizeof(SpiceMainHead) * monitor_configs->len;
+        SpiceMsgcMainMonitorsConfig *msg = g_malloc0(size);
 
-    if (c->disable_display_align == FALSE)
-        monitors_align(mon->monitors, mon->num_of_monitors);
+        msg->count = monitor_configs->len;
 
-    agent_msg_queue(channel, VD_AGENT_MONITORS_CONFIG, size, mon);
-    g_free(mon);
+        if (c->disable_display_position == FALSE ||
+            c->disable_display_align == FALSE) {
+            msg->flags |= VD_AGENT_CONFIG_MONITORS_FLAG_USE_POS;
+        }
 
-    spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
-    if (c->timer_id != 0) {
-        g_source_remove(c->timer_id);
-        c->timer_id = 0;
+        CHANNEL_DEBUG(channel, "Sending new monitors config to the server:");
+
+        for (size_t i = 0; i < monitor_configs->len; i++) {
+            SpiceMonitorConfig *mc = &g_array_index(monitor_configs, SpiceMonitorConfig, i);
+
+            msg->heads[i].channel_id = mc->channel_id;
+            msg->heads[i].monitor_id = mc->monitor_id;
+            msg->heads[i].depth = c->display_color_depth ? c->display_color_depth : 32;
+            msg->heads[i].width = mc->width;
+            msg->heads[i].height = mc->height;
+            msg->heads[i].x = mc->x;
+            msg->heads[i].y = mc->y;
+
+            CHANNEL_DEBUG(channel, "   monitor channel_id %u, monitor_id %u: %ux%u+%u+%u @ %u bpp",
+                          msg->heads[i].channel_id, msg->heads[i].monitor_id,
+                          msg->heads[i].width, msg->heads[i].height,
+                          msg->heads[i].x, msg->heads[i].y,
+                          msg->heads[i].depth);
+        }
+
+        if (c->disable_display_align == FALSE) {
+            monitors_align_smh(msg->heads, msg->count);
+        }
+
+        SpiceMsgOut *out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MAIN_MONITORS_CONFIG);
+        out->marshallers->msgc_main_monitors_config(out->marshaller, msg);
+        spice_msg_out_send(out);
+
+        g_free(msg);
     }
 
     return TRUE;
diff --git a/subprojects/spice-common b/subprojects/spice-common
index f82a6c5..0af835f 160000
--- a/subprojects/spice-common
+++ b/subprojects/spice-common
@@ -1 +1 @@
-Subproject commit f82a6c5349a9a71485910bd3a57fe588c49d74f8
+Subproject commit 0af835f10e4dd51773dbeeb784fda4364b745874
-- 
2.18.0



More information about the Spice-devel mailing list