From aa5bffa6d33da9a575f172c8af682075f4cccfe6 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Tue, 8 Sep 2026 15:34:14 -0400 Subject: [PATCH] wayland: Don't use a stale scaling factor The output integer scale may not be re-sent if the display geometry changed, but the scale factor didn't. Cache and restore it on the integer path, to prevent an old value from being used, and possibly rounded to zero if the old value was less than 1.0. --- src/video/wayland/SDL_waylandvideo.c | 20 +++++++++++++------- src/video/wayland/SDL_waylandvideo.h | 1 + 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 6b88ca8416..5b7b0b5c43 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -1070,22 +1070,27 @@ static void handle_wl_output_done(void *data, struct wl_output *output) internal->scale_factor = (double)native_mode.w / (double)internal->logical.width; } else { // ...otherwise, the 'native' pixel values are a multiple of the logical screen size. - internal->pixel.width = internal->logical.width * (int)internal->scale_factor; - internal->pixel.height = internal->logical.height * (int)internal->scale_factor; + internal->scale_factor = internal->integer_scale_factor; + internal->pixel.width = internal->logical.width * internal->integer_scale_factor; + internal->pixel.height = internal->logical.height * internal->integer_scale_factor; } } else { /* ...and the output viewport is not scaled in the global compositing * space, the output dimensions need to be divided by the scale factor. + * + * NOTE: This path is needed for old versions of GNOME that predate fractional scaling. */ - internal->logical.width /= (int)internal->scale_factor; - internal->logical.height /= (int)internal->scale_factor; + internal->scale_factor = internal->integer_scale_factor; + internal->logical.width /= internal->integer_scale_factor; + internal->logical.height /= internal->integer_scale_factor; } } else { /* Calculate the points from the pixel values, if xdg-output isn't present. * Use the native mode pixel values since they are pre-transformed. */ - internal->logical.width = native_mode.w / (int)internal->scale_factor; - internal->logical.height = native_mode.h / (int)internal->scale_factor; + internal->scale_factor = internal->integer_scale_factor; + internal->logical.width = native_mode.w / internal->integer_scale_factor; + internal->logical.height = native_mode.h / internal->integer_scale_factor; } // The scaled desktop mode @@ -1189,7 +1194,7 @@ static void handle_wl_output_done(void *data, struct wl_output *output) static void handle_wl_output_scale(void *data, struct wl_output *output, int32_t factor) { SDL_DisplayData *internal = (SDL_DisplayData *)data; - internal->scale_factor = factor; + internal->integer_scale_factor = factor; } static void handle_wl_output_name(void *data, struct wl_output *wl_output, const char *name) @@ -1245,6 +1250,7 @@ static bool Wayland_add_display(SDL_VideoData *d, uint32_t id, uint32_t version) data->output = output; data->registry_id = id; data->scale_factor = 1.0f; + data->integer_scale_factor = 1; wl_output_add_listener(output, &output_listener, data); SDL_WAYLAND_register_output(output); diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h index 74c8ed2363..76fd679408 100644 --- a/src/video/wayland/SDL_waylandvideo.h +++ b/src/video/wayland/SDL_waylandvideo.h @@ -119,6 +119,7 @@ struct SDL_DisplayData struct Wayland_ColorInfoState *color_info_state; char *wl_output_name; double scale_factor; + int integer_scale_factor; // The integer scale factor set by wl_output. Uint32 registry_id; struct