Bug#1148111: spice-gtk: Wayland mixed-DPI display scaling breaks after moving SPICE window between outputs

Alexander alexbtl at gmail.com
Thu Sep 17 05:26:56 BST 2026


Package: spice-gtk
Version: 0.42-4
Severity: normal
Tags: patch fixed-upstream
Forwarded: https://gitlab.freedesktop.org/spice/spice-gtk/-/work_items/204

Dear Maintainer,

On GTK3/Wayland with outputs using different scale factors, a SPICE
display can be rendered at the wrong size after its window is moved
from one output to another.

Reproducer used here:

1. Run virt-viewer/virt-manager natively on Wayland.
2. Use a mixed-DPI setup, e.g. internal eDP at 150% and external HDMI at 100%.
3. Open a SPICE guest window on the scaled display.
4. Move the window to the 100% display and resize it.

Observed: the guest framebuffer becomes approximately half-size /
incorrectly scaled in the destination window. Running virt-viewer
under XWayland with GDK_BACKEND=x11 avoids the issue.

Root cause: spice-gtk sets the Cairo surface device scale when the
primary surface is created, but GTK can later change
GtkWidget:scale-factor without recreating the Cairo surface. The
existing surface therefore retains a stale device scale. The EGL path
likewise needs its display resized on a scale-factor transition.

This is fixed upstream:

  Issue:  https://gitlab.freedesktop.org/spice/spice-gtk/-/work_items/204
  Commit: https://gitlab.freedesktop.org/spice/spice-gtk/-/commit/3f85c575b0fc7acd0c024ae0f331e09aa7ae0813

The upstream commit is authored by me and reviewed/committed by
Marc-André Lureau. Upstream master CI passed.

Downstream validation performed before filing:

- The patch below applies cleanly to Debian spice-gtk 0.42-4.
- It also applies cleanly to Ubuntu 0.42-4build2.
- A full Ubuntu 26.10 package build with the backport completed successfully.
- Its Meson test suite passed: 14/14 tests, 0 failures.
- Upstream master was separately built and tested both with EGL
disabled and enabled: 11/11 tests in each configuration.
- A real Wayland GL scanout test using SPICE gl=on and virtio-vga-gl
remained functional while GTK scale-factor changed 2 -> 1 -> 2.
- The original mixed-DPI reproduction on KDE Plasma Wayland was
verified fixed across repeated monitor transitions and window
resizing.

Please consider cherry-picking/backporting upstream commit 3f85c575
into Debian's 0.42 package instead of waiting for the next spice-gtk
upstream release.

DEP-3 patch follows.

Description: Update SPICE display scaling when GTK output scale changes
 On Wayland, moving a SpiceDisplay between outputs with different scale
 factors updates GtkWidget:scale-factor without recreating the existing Cairo
 surface. Re-apply the current device scale to the Cairo surface, resize the
 EGL display when enabled, and refresh the normal scaling state.
Origin: upstream,
https://gitlab.freedesktop.org/spice/spice-gtk/-/commit/3f85c575b0fc7acd0c024ae0f331e09aa7ae0813
Bug: https://gitlab.freedesktop.org/spice/spice-gtk/-/work_items/204
Forwarded: not-needed
Author: Alex <stp.blgm at gmail.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau at redhat.com>
Last-Update: 2026-09-17
---
diff --git a/src/spice-widget.c b/src/spice-widget.c
index 22cc5be..9ccb007 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -204,6 +204,29 @@ static void scaling_updated(SpiceDisplay *display)
     update_size_request(display);
 }

+static void scale_factor_changed(SpiceDisplay *display,
+                                 GParamSpec *pspec G_GNUC_UNUSED,
+                                 gpointer user_data G_GNUC_UNUSED)
+{
+    SpiceDisplayPrivate *d = display->priv;
+    gint scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(display));
+
+    /* The cairo surface persists while a Wayland window moves between
+     * outputs. Re-apply its device scale when GTK changes the widget scale
+     * factor so display scaling stays correct on mixed-DPI setups. */
+    if (d->canvas.surface != NULL) {
+        cairo_surface_set_device_scale(d->canvas.surface,
scale_factor, scale_factor);
+    }
+
+#ifdef HAVE_EGL
+    if (egl_enabled(d)) {
+        spice_egl_resize_display(display, d->ww * scale_factor, d->wh
* scale_factor);
+    }
+#endif
+
+    scaling_updated(display);
+}
+
 static void update_size_request(SpiceDisplay *display)
 {
     SpiceDisplayPrivate *d = display->priv;
@@ -718,6 +741,8 @@ static void spice_display_init(SpiceDisplay *display)
     g_signal_connect(display, "drag-data-received",
                      G_CALLBACK(drag_data_received_callback), NULL);
     g_signal_connect(display, "size-allocate",
G_CALLBACK(size_allocate), NULL);
+    g_signal_connect(display, "notify::scale-factor",
+                     G_CALLBACK(scale_factor_changed), NULL);

     gtk_widget_add_events(widget,
                           GDK_POINTER_MOTION_MASK |

Regards,
Alex



More information about the pkg-gnome-maintainers mailing list