wayland: Always assume configure is wrong for non-resizable windows. Configure events from compositors have an extremely annoying habit of giving us completely bogus sizes, from all sorts of places. Thankfully, the protocol gives us the ability to completely ignore the width/height and just stick with what we know, so for all windows that are not meant to be resized, pretend we never even got the width/height at all, the compositor is required to respect our dimensions whether they match configure's suggestion or not.
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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index eb31ebb..0003abe 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -183,6 +183,7 @@ handle_configure_xdg_toplevel(void *data,
{
SDL_WindowData *wind = (SDL_WindowData *)data;
SDL_Window *window = wind->sdlwindow;
+ SDL_WaylandOutputData *driverdata;
enum xdg_toplevel_state *state;
SDL_bool fullscreen = SDL_FALSE;
@@ -209,15 +210,31 @@ handle_configure_xdg_toplevel(void *data,
}
}
+ driverdata = (SDL_WaylandOutputData *) SDL_GetDisplayForWindow(window)->driverdata;
+
if (!fullscreen) {
if (window->flags & SDL_WINDOW_FULLSCREEN) {
/* We might need to re-enter fullscreen after being restored from minimized */
- SDL_WaylandOutputData *driverdata = (SDL_WaylandOutputData *) SDL_GetDisplayForWindow(window)->driverdata;
SetFullscreen(window, driverdata->output);
- fullscreen = SDL_TRUE;
+
+ /* Foolishly do what the compositor says here. If it's wrong, don't
+ * blame us, we were explicitly instructed to do this.
+ */
+ window->w = width;
+ window->h = height;
+
+ /* This part is good though. */
+ if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
+ wind->scale_factor = driverdata->scale_factor;
+ }
+
+ return;
}
if (width == 0 || height == 0) {
+ /* This usually happens when we're being restored from a
+ * non-floating state, so use the cached floating size here.
+ */
width = wind->floating_width;
height = wind->floating_height;
}
@@ -235,6 +252,12 @@ handle_configure_xdg_toplevel(void *data,
height = SDL_min(height, window->max_h);
}
height = SDL_max(height, window->min_h);
+ } else if (floating) {
+ /* If we're a fixed-size window, we know our size for sure.
+ * Always assume the configure is wrong.
+ */
+ width = window->windowed.w;
+ height = window->windowed.h;
}
/* Always send a maximized/restore event; if the event is redundant it will
@@ -242,28 +265,33 @@ handle_configure_xdg_toplevel(void *data,
*
* No, we do not get minimize events from xdg-shell.
*/
- if (!fullscreen) {
- SDL_SendWindowEvent(window,
- maximized ?
- SDL_WINDOWEVENT_MAXIMIZED :
- SDL_WINDOWEVENT_RESTORED,
- 0, 0);
+ SDL_SendWindowEvent(window,
+ maximized ?
+ SDL_WINDOWEVENT_MAXIMIZED :
+ SDL_WINDOWEVENT_RESTORED,
+ 0, 0);
+
+ /* Store current floating dimensions for restoring */
+ if (floating) {
+ wind->floating_width = width;
+ wind->floating_height = height;
}
- }
- if (width == 0 || height == 0) {
- return;
- }
+ /* Store this now so the xdg_surface configure knows what to resize to */
+ window->w = width;
+ window->h = height;
+ } else {
+ /* For fullscreen, foolishly do what the compositor says. If it's wrong,
+ * don't blame us, we were explicitly instructed to do this.
+ */
+ window->w = width;
+ window->h = height;
- if (floating) {
- /* store current floating dimensions for restoring */
- wind->floating_width = width;
- wind->floating_height = height;
+ /* This part is good though. */
+ if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
+ wind->scale_factor = driverdata->scale_factor;
+ }
}
-
- /* Store this now so the xdg_surface configure knows what to resize to */
- window->w = width;
- window->h = height;
}
static void
@@ -286,6 +314,7 @@ decoration_frame_configure(struct libdecor_frame *frame,
{
SDL_WindowData *wind = (SDL_WindowData *)user_data;
SDL_Window *window = wind->sdlwindow;
+ SDL_WaylandOutputData *driverdata;
struct libdecor_state *state;
enum libdecor_window_state window_state;
@@ -311,10 +340,11 @@ decoration_frame_configure(struct libdecor_frame *frame,
}
floating = !(fullscreen || maximized || tiled);
+ driverdata = (SDL_WaylandOutputData *) SDL_GetDisplayForWindow(window)->driverdata;
+
if (!fullscreen) {
if (window->flags & SDL_WINDOW_FULLSCREEN) {
/* We might need to re-enter fullscreen after being restored from minimized */
- SDL_WaylandOutputData *driverdata = (SDL_WaylandOutputData *) SDL_GetDisplayForWindow(window)->driverdata;
SetFullscreen(window, driverdata->output);
fullscreen = SDL_TRUE;
}
@@ -340,17 +370,46 @@ decoration_frame_configure(struct libdecor_frame *frame,
SDL_WINDOWEVENT_FOCUS_LOST,
0, 0);
- /* This will never set 0 for width/height unless the function returns false */
- if (!libdecor_configuration_get_content_size(configuration, frame, &width, &height)) {
- if (floating) {
- width = wind->floating_width;
- height = wind->floating_height;
- } else {
+ /* For fullscreen or fixed-size windows we know our size.
+ * Always assume the configure is wrong.
+ */
+ if (fullscreen) {
+ /* FIXME: We have been explicitly told to respect the fullscreen size
+ * parameters here, even though they are known to be wrong on GNOME at
+ * bare minimum. If this is wrong, don't blame us, we were explicitly
+ * told to do this.
+ */
+ if (!libdecor_configuration_get_content_size(configuration, frame,
+ &width, &height)) {
width = window->w;
height = window->h;
}
- } else if (floating) {
- /* store current floating dimensions for restoring */
+
+ /* This part is good though. */
+ if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
+ wind->scale_factor = driverdata->scale_factor;
+ }
+ } else if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
+ width = window->windowed.w;
+ height = window->windowed.h;
+ } else {
+ /* This will never set 0 for width/height unless the function returns false */
+ if (!libdecor_configuration_get_content_size(configuration, frame, &width, &height)) {
+ if (floating) {
+ /* This usually happens when we're being restored from a
+ * non-floating state, so use the cached floating size here.
+ */
+ width = wind->floating_width;
+ height = wind->floating_height;
+ } else {
+ width = window->w;
+ height = window->h;
+ }
+ }
+ }
+
+ /* Store current floating dimensions for restoring */
+ if (floating) {
wind->floating_width = width;
wind->floating_height = height;
}
@@ -948,23 +1007,6 @@ Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
SetFullscreen(window, fullscreen ? output : NULL);
WAYLAND_wl_display_flush(viddata->display);
-#ifdef HAVE_LIBDECOR_H
- /* For libdecor we _have_ to dispatch immediately, because libdecor state
- * strongly depends on the "current" state of the window. For example, if an
- * application calls SetWindowSize right after this, libdecor will still
- * think the window is fullscreen and not floating because configuration has
- * not yet occurred, so the call will get completely ignored! So, take the
- * time penalty and ensure that libdecor state matches SDL state.
- *
- * TODO: If Wayland_SetWindowSize ever stops checking for floating state,
- * this can be removed.
- *
- * -flibit
- */
- if (viddata->shell.libdecor && (window->flags & SDL_WINDOW_SHOWN)) {
- WAYLAND_wl_display_dispatch(viddata->display);
- }
-#endif
}
void
@@ -1317,10 +1359,9 @@ void Wayland_SetWindowSize(_THIS, SDL_Window * window)
}
#endif
- if (!(window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MAXIMIZED))) {
- wind->floating_width = window->w;
- wind->floating_height = window->h;
- }
+ /* windowed is unconditionally set, so we can trust it here */
+ wind->floating_width = window->windowed.w;
+ wind->floating_height = window->windowed.h;
region = wl_compositor_create_region(data->compositor);
wl_region_add(region, 0, 0, window->w, window->h);