SDL: libdecor: use same fullscreen/maximised restore logic as for xdg-toplevel

From cfcdfb7be9f5c97a51ddef9ad3677a604856266b Mon Sep 17 00:00:00 2001
From: Christian Rauch <[EMAIL REDACTED]>
Date: Sun, 1 Aug 2021 18:14:53 +0100
Subject: [PATCH] libdecor: use same fullscreen/maximised restore logic as for
 xdg-toplevel

---
 src/video/wayland/SDL_waylandwindow.c | 75 +++++++++++++++++++--------
 1 file changed, 54 insertions(+), 21 deletions(-)

diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 2f8784abd..71f0da059 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -320,12 +320,18 @@ decoration_frame_configure(struct libdecor_frame *frame,
     enum libdecor_window_state window_state;
     struct libdecor_state *state;
 
+    SDL_bool fullscreen = SDL_FALSE;
+    SDL_bool maximized = SDL_FALSE;
+
     /* window size */
     if (!libdecor_configuration_get_content_size(configuration, frame, &width, &height)) {
-        width = window->w;
-        height = window->h;
+        width = wind->floating_width;
+        height = wind->floating_height;
     }
 
+    width = (width == 0) ? window->w : width;
+    height = (height == 0) ? window->h : height;
+
     wind->resize.width = width;
     wind->resize.height = height;
 
@@ -342,38 +348,65 @@ decoration_frame_configure(struct libdecor_frame *frame,
         window_state = LIBDECOR_WINDOW_STATE_NONE;
     }
 
-   /* Always send maximized/restored/focus events; if the event is redundant it will
-     * automatically be discarded (see src/events/SDL_windowevents.c).
-     *
-     * No, we do not get minimize events from libdecor.
-     */
-    if (window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN) {
-        window->flags |= SDL_WINDOW_FULLSCREEN;
-    } else {
+    /* translate libdecor to SDL states */
+    switch (window_state) {
+    case LIBDECOR_WINDOW_STATE_FULLSCREEN:
+        fullscreen = SDL_TRUE;
+        break;
+    case LIBDECOR_WINDOW_STATE_MAXIMIZED:
+        maximized = SDL_TRUE;
+        break;
+    }
+
+    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;
+        }
+
+        if (width == 0 || height == 0) {
+            width = wind->floating_width;
+            height = wind->floating_height;
+        }
+
+        if ((window->flags & SDL_WINDOW_RESIZABLE)) {
+            if (window->max_w > 0) {
+                width = SDL_min(width, window->max_w);
+            }
+            width = SDL_max(width, window->min_w);
+
+            if (window->max_h > 0) {
+                height = SDL_min(height, window->max_h);
+            }
+            height = SDL_max(height, window->min_h);
         } else {
-            SDL_SendWindowEvent(window,
-                                (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) ?
-                                    SDL_WINDOWEVENT_MAXIMIZED :
-                                    SDL_WINDOWEVENT_RESTORED,
-                                0, 0);
+            wind->resize.width = window->w;
+            wind->resize.height = window->h;
+            return;
         }
-        window->flags &= ~SDL_WINDOW_FULLSCREEN;
     }
-    SDL_SendWindowEvent(window,
-                        (window_state & LIBDECOR_WINDOW_STATE_ACTIVE) ?
-                            SDL_WINDOWEVENT_FOCUS_GAINED :
-                            SDL_WINDOWEVENT_FOCUS_LOST,
-                        0, 0);
+
+    if (!fullscreen) {
+        SDL_SendWindowEvent(window,
+                            maximized ?
+                                SDL_WINDOWEVENT_MAXIMIZED :
+                                SDL_WINDOWEVENT_RESTORED,
+                            0, 0);
+    }
 
     /* commit frame state */
     state = libdecor_state_new(width, height);
     libdecor_frame_commit(frame, state, configuration);
     libdecor_state_free(state);
 
+    /* store floating dimensions */
+    if (libdecor_frame_is_floating(frame)) {
+        wind->floating_width = width;
+        wind->floating_height = height;
+    }
+
     /* Update the resize capability. Since this will change the capabilities and
      * commit a new frame state with the last known content dimension, this has
      * to be called after the new state has been commited and the new content