Commit 19236b462a8af09670c9fd5490cea293d3fc2b75

Cameron Gutman 2021-01-21T21:49:13

Implement support for minimizing windows on Wayland This required a bit of extra code to deal with the transition from minimized back to fullscreen

diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index 73f181a..e5be532 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -197,6 +197,7 @@ Wayland_CreateDevice(int devindex)
     device->ShowWindow = Wayland_ShowWindow;
     device->SetWindowFullscreen = Wayland_SetWindowFullscreen;
     device->MaximizeWindow = Wayland_MaximizeWindow;
+    device->MinimizeWindow = Wayland_MinimizeWindow;
     device->SetWindowGrab = Wayland_SetWindowGrab;
     device->RestoreWindow = Wayland_RestoreWindow;
     device->SetWindowBordered = Wayland_SetWindowBordered;
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 89fb403..cba97fd 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -42,6 +42,37 @@ static float get_window_scale_factor(SDL_Window *window) {
       return ((SDL_WindowData*)window->driverdata)->scale_factor;
 }
 
+static void
+SetFullscreen(SDL_Window *window, struct wl_output *output)
+{
+    SDL_WindowData *wind = window->driverdata;
+    SDL_VideoData *viddata = wind->waylandData;
+
+    if (viddata->shell.xdg) {
+        if (output) {
+            xdg_toplevel_set_fullscreen(wind->shell_surface.xdg.roleobj.toplevel, output);
+        } else {
+            xdg_toplevel_unset_fullscreen(wind->shell_surface.xdg.roleobj.toplevel);
+        }
+    } else if (viddata->shell.zxdg) {
+        if (output) {
+            zxdg_toplevel_v6_set_fullscreen(wind->shell_surface.zxdg.roleobj.toplevel, output);
+        } else {
+            zxdg_toplevel_v6_unset_fullscreen(wind->shell_surface.zxdg.roleobj.toplevel);
+        }
+    } else {
+        if (output) {
+            wl_shell_surface_set_fullscreen(wind->shell_surface.wl,
+                                            WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
+                                            0, output);
+        } else {
+            wl_shell_surface_set_toplevel(wind->shell_surface.wl);
+        }
+    }
+
+    WAYLAND_wl_display_flush(viddata->display);
+}
+
 /* On modern desktops, we probably will use the xdg-shell protocol instead
    of wl_shell, but wl_shell might be useful on older Wayland installs that
    don't have the newer protocol, or embedded things that don't have a full
@@ -168,6 +199,12 @@ handle_configure_zxdg_toplevel(void *data,
     }
 
     if (!fullscreen) {
+        if (window->flags & SDL_WINDOW_FULLSCREEN) {
+            /* We might need to re-enter fullscreen after being restored from minimized */
+            struct wl_output *output = (struct wl_output *) window->fullscreen_mode.driverdata;
+            SetFullscreen(window, output);
+        }
+
         if (width == 0 || height == 0) {
             width = window->windowed.w;
             height = window->windowed.h;
@@ -278,6 +315,12 @@ handle_configure_xdg_toplevel(void *data,
      }
 
     if (!fullscreen) {
+        if (window->flags & SDL_WINDOW_FULLSCREEN) {
+            /* We might need to re-enter fullscreen after being restored from minimized */
+            struct wl_output *output = (struct wl_output *) window->fullscreen_mode.driverdata;
+            SetFullscreen(window, output);
+        }
+
         if (width == 0 || height == 0) {
             width = window->windowed.w;
             height = window->windowed.h;
@@ -474,41 +517,10 @@ Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
     return 0;  /* just succeed, the real work is done elsewhere. */
 }
 
-static void
-SetFullscreen(_THIS, SDL_Window * window, struct wl_output *output)
-{
-    const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata;
-    SDL_WindowData *wind = window->driverdata;
-
-    if (viddata->shell.xdg) {
-        if (output) {
-            xdg_toplevel_set_fullscreen(wind->shell_surface.xdg.roleobj.toplevel, output);
-        } else {
-            xdg_toplevel_unset_fullscreen(wind->shell_surface.xdg.roleobj.toplevel);
-        }
-    } else if (viddata->shell.zxdg) {
-        if (output) {
-            zxdg_toplevel_v6_set_fullscreen(wind->shell_surface.zxdg.roleobj.toplevel, output);
-        } else {
-            zxdg_toplevel_v6_unset_fullscreen(wind->shell_surface.zxdg.roleobj.toplevel);
-        }
-    } else {
-        if (output) {
-            wl_shell_surface_set_fullscreen(wind->shell_surface.wl,
-                                            WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
-                                            0, output);
-        } else {
-            wl_shell_surface_set_toplevel(wind->shell_surface.wl);
-        }
-    }
-
-    WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
-}
-
 void Wayland_ShowWindow(_THIS, SDL_Window *window)
 {
     struct wl_output *output = (struct wl_output *) window->fullscreen_mode.driverdata;
-    SetFullscreen(_this, window, (window->flags & SDL_WINDOW_FULLSCREEN) ? output : NULL);
+    SetFullscreen(window, (window->flags & SDL_WINDOW_FULLSCREEN) ? output : NULL);
 }
 
 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
@@ -582,7 +594,7 @@ Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
                             SDL_VideoDisplay * _display, SDL_bool fullscreen)
 {
     struct wl_output *output = ((SDL_WaylandOutputData*) _display->driverdata)->output;
-    SetFullscreen(_this, window, fullscreen ? output : NULL);
+    SetFullscreen(window, fullscreen ? output : NULL);
 }
 
 void
@@ -632,6 +644,21 @@ Wayland_MaximizeWindow(_THIS, SDL_Window * window)
 }
 
 void
+Wayland_MinimizeWindow(_THIS, SDL_Window * window)
+{
+    SDL_WindowData *wind = window->driverdata;
+    SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
+
+    if (viddata->shell.xdg) {
+        xdg_toplevel_set_minimized(wind->shell_surface.xdg.roleobj.toplevel);
+    } else if (viddata->shell.zxdg) {
+        zxdg_toplevel_v6_set_minimized(wind->shell_surface.zxdg.roleobj.toplevel);
+    }
+
+    WAYLAND_wl_display_flush(viddata->display);
+}
+
+void
 Wayland_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
 {
     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h
index 6e33062..4a7472c 100644
--- a/src/video/wayland/SDL_waylandwindow.h
+++ b/src/video/wayland/SDL_waylandwindow.h
@@ -89,6 +89,7 @@ extern void Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
                                         SDL_VideoDisplay * _display,
                                         SDL_bool fullscreen);
 extern void Wayland_MaximizeWindow(_THIS, SDL_Window * window);
+extern void Wayland_MinimizeWindow(_THIS, SDL_Window * window);
 extern void Wayland_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
 extern void Wayland_RestoreWindow(_THIS, SDL_Window * window);
 extern void Wayland_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);