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