wayland: Work around a GNOME xdg_output scaling issue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index b3d241b..93420bf 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -294,6 +294,7 @@ xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output
driverdata->x = x;
driverdata->y = y;
+ driverdata->has_logical_position = SDL_TRUE;
}
static void
@@ -302,8 +303,25 @@ xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output,
{
SDL_WaylandOutputData* driverdata = data;
+ if (driverdata->width != 0 && driverdata->height != 0) {
+ /* FIXME: GNOME has a bug where the logical size does not account for
+ * scale, resulting in bogus viewport sizes.
+ *
+ * Until this is fixed, validate the scale, then override if necessary.
+ * -flibit
+ */
+ const float scale = (float) driverdata->width / (float) width;
+ if (scale != driverdata->scale_factor) {
+ SDL_LogWarn(
+ SDL_LOG_CATEGORY_VIDEO,
+ "xdg_output scale did not match, overriding with wl_output scale"
+ );
+ return;
+ }
+ }
driverdata->width = width;
driverdata->height = height;
+ driverdata->has_logical_size = SDL_TRUE;
}
static void
@@ -371,7 +389,7 @@ display_handle_geometry(void *data,
}
/* Apply the change from wl-output only if xdg-output is not supported */
- if (driverdata->xdg_output) {
+ if (driverdata->has_logical_position) {
driverdata->x = x;
driverdata->y = y;
}
@@ -428,7 +446,7 @@ display_handle_mode(void *data,
* Don't rotate this yet, wl-output coordinates are transformed in
* handle_done and xdg-output coordinates are pre-transformed.
*/
- if (!driverdata->xdg_output) {
+ if (!driverdata->has_logical_size) {
driverdata->width = width;
driverdata->height = height;
}
@@ -485,7 +503,7 @@ display_handle_done(void *data,
SDL_zero(mode);
mode.format = SDL_PIXELFORMAT_RGB888;
- if (driverdata->xdg_output) {
+ if (driverdata->has_logical_size) {
/* xdg-output dimensions are already transformed, so no need to rotate. */
mode.w = driverdata->width;
mode.h = driverdata->height;
diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h
index c3a8c13..dff2fe3 100644
--- a/src/video/wayland/SDL_waylandvideo.h
+++ b/src/video/wayland/SDL_waylandvideo.h
@@ -105,6 +105,7 @@ struct SDL_WaylandOutputData {
SDL_DisplayOrientation orientation;
int physical_width, physical_height;
float ddpi, hdpi, vdpi;
+ SDL_bool has_logical_position, has_logical_size;
int index;
SDL_VideoDisplay placeholder;
int wl_output_done_count;