Browse Source

spice-gtk: fix monitors config size mismatch

Fixes #5832
osy 3 ngày trước cách đây
mục cha
commit
9fefd160e4
1 tập tin đã thay đổi với 98 bổ sung0 xóa
  1. 98 0
      patches/spice-gtk-0.42.patch

+ 98 - 0
patches/spice-gtk-0.42.patch

@@ -926,3 +926,101 @@ index daff1aa..61e60fa 100644
 -- 
 2.41.0
 
+From 00cdb145ca1f34e47a1c8ba0d933595709318f85 Mon Sep 17 00:00:00 2001
+From: osy <osy@turing.llc>
+Date: Sun, 17 Aug 2025 19:32:49 -0700
+Subject: [PATCH] main: only send physical size when used
+
+Since introducing physical size support four years ago, the
+feature has been broken on Linux. In VDAgent, there is a
+check on the size of VDAgentMonitorsConfig that does not
+account for FLAG_PHYSICAL_SIZE. This was fixed in VDAgent
+in commit 3660acfcbaaca9c66dca5ef09205bd7c1d70b98c but until
+that fix is released and all the Linux distros pick it up,
+the feature will still be broken.
+
+In the meantime, this change will ignore monitor physical
+size config if it is not used and the client can implement
+logic to detect when it is safe to send it.
+---
+ src/channel-main.c | 41 ++++++++++++++++++++++++++++-------------
+ 1 file changed, 28 insertions(+), 13 deletions(-)
+
+diff --git a/src/channel-main.c b/src/channel-main.c
+index 7830f6f..d4d1a1e 100644
+--- a/src/channel-main.c
++++ b/src/channel-main.c
+@@ -1119,6 +1119,7 @@ gboolean spice_main_channel_send_monitor_config(SpiceMainChannel *channel)
+     VDAgentMonitorsConfig *mon;
+     int i, j, monitors;
+     size_t size;
++    gboolean has_physical_size;
+ 
+     g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(channel), FALSE);
+     c = channel->priv;
+@@ -1134,8 +1135,18 @@ gboolean spice_main_channel_send_monitor_config(SpiceMainChannel *channel)
+         }
+     }
+ 
+-    size = sizeof(VDAgentMonitorsConfig) +
+-        (sizeof(VDAgentMonConfig) + sizeof(VDAgentMonitorMM)) * monitors;
++    /* only enable sending physical size if needed */
++    has_physical_size = FALSE;
++    for (i = 0; i < SPICE_N_ELEMENTS(c->display); i++) {
++        if (c->display[i].width_mm || c->display[i].height_mm) {
++            has_physical_size = TRUE;
++        }
++    }
++
++    size = sizeof(VDAgentMonitorsConfig) + sizeof(VDAgentMonConfig) * monitors;
++    if (has_physical_size) {
++        size += sizeof(VDAgentMonitorMM) * monitors;
++    }
+     mon = g_malloc0(size);
+ 
+     mon->num_of_monitors = monitors;
+@@ -1143,7 +1154,9 @@ gboolean spice_main_channel_send_monitor_config(SpiceMainChannel *channel)
+         c->disable_display_align == FALSE)
+         mon->flags |= VD_AGENT_CONFIG_MONITORS_FLAG_USE_POS;
+ 
+-    mon->flags |= VD_AGENT_CONFIG_MONITORS_FLAG_PHYSICAL_SIZE;
++    if (has_physical_size) {
++        mon->flags |= VD_AGENT_CONFIG_MONITORS_FLAG_PHYSICAL_SIZE;
++    }
+ 
+     CHANNEL_DEBUG(channel, "sending new monitors config to guest");
+     j = 0;
+@@ -1166,18 +1179,20 @@ gboolean spice_main_channel_send_monitor_config(SpiceMainChannel *channel)
+         j++;
+     }
+ 
+-    VDAgentMonitorMM *mm = (void *)&mon->monitors[monitors];
+-    for (i = 0, j = 0; i < SPICE_N_ELEMENTS(c->display); i++) {
+-        if (c->display[i].display_state != DISPLAY_ENABLED) {
+-            if (spice_main_channel_agent_test_capability(channel,
+-                                                         VD_AGENT_CAP_SPARSE_MONITORS_CONFIG)) {
+-                j++;
++    if (has_physical_size) {
++        VDAgentMonitorMM *mm = (void *)&mon->monitors[monitors];
++        for (i = 0, j = 0; i < SPICE_N_ELEMENTS(c->display); i++) {
++            if (c->display[i].display_state != DISPLAY_ENABLED) {
++                if (spice_main_channel_agent_test_capability(channel,
++                                                             VD_AGENT_CAP_SPARSE_MONITORS_CONFIG)) {
++                    j++;
++                }
++                continue;
+             }
+-            continue;
++            mm[j].width = c->display[i].width_mm;
++            mm[j].height = c->display[i].height_mm;
++            j++;
+         }
+-        mm[j].width = c->display[i].width_mm;
+-        mm[j].height = c->display[i].height_mm;
+-        j++;
+     }
+ 
+     if (c->disable_display_align == FALSE)
+-- 
+2.41.0
+