SDL: wayland: store and restore floating states

From 42452f8ca50034be370296719c7e552192d5bfb0 Mon Sep 17 00:00:00 2001
From: Christian Rauch <[EMAIL REDACTED]>
Date: Sun, 1 Aug 2021 13:51:30 +0100
Subject: [PATCH] wayland: store and restore floating states

Some Wayland compositors send (0,0) as "suggested" configure event sizes to
indicate that the client has to decide on its own which sizes to used. This
is commonly done when restoring from maximised, fullscreen or tiles states
to fullscreen.
We now store the last known floating states in a new set of variables and
restore them when we receive such a (0,0) configure event.
---
 src/video/wayland/SDL_waylandwindow.c | 31 +++++++++++++++++++++++----
 src/video/wayland/SDL_waylandwindow.h |  3 +++
 2 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index e47d34337..2f8784abd 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -214,11 +214,23 @@ handle_configure_xdg_toplevel(void *data,
     enum xdg_toplevel_state *state;
     SDL_bool fullscreen = SDL_FALSE;
     SDL_bool maximized = SDL_FALSE;
+    SDL_bool floating = SDL_TRUE;
     wl_array_for_each(state, states) {
-        if (*state == XDG_TOPLEVEL_STATE_FULLSCREEN) {
+        switch (*state) {
+        case XDG_TOPLEVEL_STATE_FULLSCREEN:
             fullscreen = SDL_TRUE;
-        } else if (*state == XDG_TOPLEVEL_STATE_MAXIMIZED) {
+            floating = SDL_FALSE;
+            break;
+        case XDG_TOPLEVEL_STATE_MAXIMIZED:
             maximized = SDL_TRUE;
+            floating = SDL_FALSE;
+            break;
+        case XDG_TOPLEVEL_STATE_TILED_LEFT:
+        case XDG_TOPLEVEL_STATE_TILED_RIGHT:
+        case XDG_TOPLEVEL_STATE_TILED_TOP:
+        case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
+            floating = SDL_FALSE;
+            break;
         }
     }
 
@@ -231,8 +243,8 @@ handle_configure_xdg_toplevel(void *data,
         }
 
         if (width == 0 || height == 0) {
-            width = window->windowed.w;
-            height = window->windowed.h;
+            width = wind->floating_width;
+            height = wind->floating_height;
         }
 
         /* xdg_toplevel spec states that this is a suggestion.
@@ -274,6 +286,12 @@ handle_configure_xdg_toplevel(void *data,
         return;
     }
 
+    if (floating) {
+        /* store current floating dimensions for restoring */
+        wind->floating_width = width;
+        wind->floating_height = height;
+    }
+
     wind->resize.width = width;
     wind->resize.height = height;
 }
@@ -1303,6 +1321,11 @@ 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;
+    }
+
     region = wl_compositor_create_region(data->compositor);
     wl_region_add(region, 0, 0, window->w, window->h);
     wl_surface_set_opaque_region(wind->surface, region);
diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h
index 90405fe20..8cc4d03e5 100644
--- a/src/video/wayland/SDL_waylandwindow.h
+++ b/src/video/wayland/SDL_waylandwindow.h
@@ -68,6 +68,9 @@ typedef struct {
     struct zwp_idle_inhibitor_v1 *idle_inhibitor;
     struct xdg_activation_token_v1 *activation_token;
 
+    /* floating dimensions for restoring from maximized and fullscreen */
+    int floating_width, floating_height;
+
     SDL_atomic_t swap_interval_ready;
 
 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH