SDL: wayland: Refactor toplevel mapping, implement HideWindow

From 8e3ec34d34af6aa3348b0dd9bbd3d8dee246e819 Mon Sep 17 00:00:00 2001
From: Ethan Lee <[EMAIL REDACTED]>
Date: Tue, 20 Apr 2021 12:40:40 -0400
Subject: [PATCH] wayland: Refactor toplevel mapping, implement HideWindow

---
 src/video/wayland/SDL_waylandevents.c |  34 +++-
 src/video/wayland/SDL_waylandvideo.c  |   1 +
 src/video/wayland/SDL_waylandwindow.c | 256 +++++++++++++++++---------
 src/video/wayland/SDL_waylandwindow.h |   1 +
 4 files changed, 197 insertions(+), 95 deletions(-)

diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index 2657a276e..ec288cadc 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -331,11 +331,21 @@ ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
         switch (rc) {
             case SDL_HITTEST_DRAGGABLE:
                 if (input->display->shell.xdg) {
-                    xdg_toplevel_move(window_data->shell_surface.xdg.roleobj.toplevel, input->seat, serial);
+                    if (window_data->shell_surface.xdg.roleobj.toplevel) {
+                        xdg_toplevel_move(window_data->shell_surface.xdg.roleobj.toplevel,
+                                          input->seat,
+                                          serial);
+                    }
                 } else if (input->display->shell.zxdg) {
-                    zxdg_toplevel_v6_move(window_data->shell_surface.zxdg.roleobj.toplevel, input->seat, serial);
+                    if (window_data->shell_surface.zxdg.roleobj.toplevel) {
+                        zxdg_toplevel_v6_move(window_data->shell_surface.zxdg.roleobj.toplevel,
+                                              input->seat,
+                                              serial);
+                    }
                 } else {
-                    wl_shell_surface_move(window_data->shell_surface.wl, input->seat, serial);
+                    if (window_data->shell_surface.wl) {
+                        wl_shell_surface_move(window_data->shell_surface.wl, input->seat, serial);
+                    }
                 }
                 return SDL_TRUE;
 
@@ -348,11 +358,23 @@ ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
             case SDL_HITTEST_RESIZE_BOTTOMLEFT:
             case SDL_HITTEST_RESIZE_LEFT:
                 if (input->display->shell.xdg) {
-                    xdg_toplevel_resize(window_data->shell_surface.xdg.roleobj.toplevel, input->seat, serial, directions_zxdg[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
+                    if (window_data->shell_surface.xdg.roleobj.toplevel) {
+                        xdg_toplevel_resize(window_data->shell_surface.xdg.roleobj.toplevel,
+                                            input->seat,
+                                            serial,
+                                            directions_zxdg[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
+                    }
                 } else if (input->display->shell.zxdg) {
-                    zxdg_toplevel_v6_resize(window_data->shell_surface.zxdg.roleobj.toplevel, input->seat, serial, directions_zxdg[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
+                    if (window_data->shell_surface.zxdg.roleobj.toplevel) {
+                        zxdg_toplevel_v6_resize(window_data->shell_surface.zxdg.roleobj.toplevel,
+                                                input->seat,
+                                                serial,
+                                                directions_zxdg[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
+                    }
                 } else {
-                    wl_shell_surface_resize(window_data->shell_surface.wl, input->seat, serial, directions_wl[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
+                    if (window_data->shell_surface.wl) {
+                        wl_shell_surface_resize(window_data->shell_surface.wl, input->seat, serial, directions_wl[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
+                    }
                 }
                 return SDL_TRUE;
 
diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index 3f66a6771..759e0b16a 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -198,6 +198,7 @@ Wayland_CreateDevice(int devindex)
 
     device->CreateSDLWindow = Wayland_CreateWindow;
     device->ShowWindow = Wayland_ShowWindow;
+    device->HideWindow = Wayland_HideWindow;
     device->SetWindowFullscreen = Wayland_SetWindowFullscreen;
     device->MaximizeWindow = Wayland_MaximizeWindow;
     device->MinimizeWindow = Wayland_MinimizeWindow;
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 9a810479e..c06616bd7 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -67,6 +67,9 @@ CommitMinMaxDimensions(SDL_Window *window)
     }
 
     if (data->shell.xdg) {
+        if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
+            return; /* Can't do anything yet, wait for ShowWindow */
+        }
         xdg_toplevel_set_min_size(wind->shell_surface.xdg.roleobj.toplevel,
                                   min_width,
                                   min_height);
@@ -74,6 +77,9 @@ CommitMinMaxDimensions(SDL_Window *window)
                                   max_width,
                                   max_height);
     } else if (data->shell.zxdg) {
+        if (wind->shell_surface.zxdg.roleobj.toplevel == NULL) {
+            return; /* Can't do anything yet, wait for ShowWindow */
+        }
         zxdg_toplevel_v6_set_min_size(wind->shell_surface.zxdg.roleobj.toplevel,
                                       min_width,
                                       min_height);
@@ -97,18 +103,27 @@ SetFullscreen(SDL_Window *window, struct wl_output *output)
     CommitMinMaxDimensions(window);
 
     if (viddata->shell.xdg) {
+        if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
+            return; /* Can't do anything yet, wait for ShowWindow */
+        }
         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 (wind->shell_surface.zxdg.roleobj.toplevel == NULL) {
+            return; /* Can't do anything yet, wait for ShowWindow */
+        }
         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 (wind->shell_surface.wl == NULL) {
+            return; /* Can't do anything yet, wait for ShowWindow */
+        }
         if (output) {
             wl_shell_surface_set_fullscreen(wind->shell_surface.wl,
                                             WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
@@ -603,9 +618,21 @@ Wayland_SetWindowModalFor(_THIS, SDL_Window *modal_window, SDL_Window *parent_wi
     SDL_WindowData *parent_data = parent_window->driverdata;
 
     if (viddata->shell.xdg) {
+        if (modal_data->shell_surface.xdg.roleobj.toplevel == NULL) {
+            return SDL_SetError("Modal window was hidden");
+        }
+        if (parent_data->shell_surface.xdg.roleobj.toplevel == NULL) {
+            return SDL_SetError("Parent window was hidden");
+        }
         xdg_toplevel_set_parent(modal_data->shell_surface.xdg.roleobj.toplevel,
                                 parent_data->shell_surface.xdg.roleobj.toplevel);
     } else if (viddata->shell.zxdg) {
+        if (modal_data->shell_surface.zxdg.roleobj.toplevel == NULL) {
+            return SDL_SetError("Modal window was hidden");
+        }
+        if (parent_data->shell_surface.zxdg.roleobj.toplevel == NULL) {
+            return SDL_SetError("Parent window was hidden");
+        }
         zxdg_toplevel_v6_set_parent(modal_data->shell_surface.zxdg.roleobj.toplevel,
                                     parent_data->shell_surface.zxdg.roleobj.toplevel);
     } else {
@@ -618,8 +645,112 @@ Wayland_SetWindowModalFor(_THIS, SDL_Window *modal_window, SDL_Window *parent_wi
 
 void Wayland_ShowWindow(_THIS, SDL_Window *window)
 {
-    SDL_WaylandOutputData *driverdata = (SDL_WaylandOutputData *) SDL_GetDisplayForWindow(window)->driverdata;
-    SetFullscreen(window, (window->flags & SDL_WINDOW_FULLSCREEN) ? driverdata->output : NULL);
+    SDL_VideoData *c = _this->driverdata;
+    SDL_WindowData *data = window->driverdata;
+    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
+
+    /* Detach any previous buffers before resetting everything, otherwise when
+     * calling this a second time you'll get an annoying protocol error
+     */
+    wl_surface_attach(data->surface, NULL, 0, 0);
+    wl_surface_commit(data->surface);
+
+    /* Create the shell surface and map the toplevel */
+    if (c->shell.xdg) {
+        data->shell_surface.xdg.surface = xdg_wm_base_get_xdg_surface(c->shell.xdg, data->surface);
+        xdg_surface_set_user_data(data->shell_surface.xdg.surface, data);
+        xdg_surface_add_listener(data->shell_surface.xdg.surface, &shell_surface_listener_xdg, data);
+
+        /* !!! FIXME: add popup role */
+        data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
+        xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
+        xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
+
+        /* Create the window decorations */
+        if (c->decoration_manager) {
+            data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(c->decoration_manager, data->shell_surface.xdg.roleobj.toplevel);
+        }
+    } else if (c->shell.zxdg) {
+        data->shell_surface.zxdg.surface = zxdg_shell_v6_get_xdg_surface(c->shell.zxdg, data->surface);
+        zxdg_surface_v6_set_user_data(data->shell_surface.zxdg.surface, data);
+        zxdg_surface_v6_add_listener(data->shell_surface.zxdg.surface, &shell_surface_listener_zxdg, data);
+
+        /* !!! FIXME: add popup role */
+        data->shell_surface.zxdg.roleobj.toplevel = zxdg_surface_v6_get_toplevel(data->shell_surface.zxdg.surface);
+        zxdg_toplevel_v6_add_listener(data->shell_surface.zxdg.roleobj.toplevel, &toplevel_listener_zxdg, data);
+        zxdg_toplevel_v6_set_app_id(data->shell_surface.zxdg.roleobj.toplevel, c->classname);
+    } else {
+        data->shell_surface.wl = wl_shell_get_shell_surface(c->shell.wl, data->surface);
+        wl_shell_surface_set_class(data->shell_surface.wl, c->classname);
+        wl_shell_surface_set_user_data(data->shell_surface.wl, data);
+        wl_shell_surface_add_listener(data->shell_surface.wl, &shell_surface_listener_wl, data);
+    }
+
+    /* Restore state that was set prior to this call */
+    Wayland_SetWindowTitle(_this, window);
+    Wayland_SetWindowBordered(_this, window, (window->flags & SDL_WINDOW_BORDERLESS) == 0);
+    if (window->flags & SDL_WINDOW_MAXIMIZED) {
+        Wayland_MaximizeWindow(_this, window);
+    }
+    if (window->flags & SDL_WINDOW_MINIMIZED) {
+        Wayland_MinimizeWindow(_this, window);
+    }
+    Wayland_SetWindowFullscreen(_this, window, display, (window->flags & SDL_WINDOW_FULLSCREEN) != 0);
+
+    /* We have to wait until the surface gets a "configure" event, or use of
+     * this surface will fail. This is a new rule for xdg_shell.
+     */
+    if (c->shell.xdg) {
+        if (data->shell_surface.xdg.surface) {
+            while (!data->shell_surface.xdg.initial_configure_seen) {
+                WAYLAND_wl_display_flush(c->display);
+                WAYLAND_wl_display_dispatch(c->display);
+            }
+        }
+    } else if (c->shell.zxdg) {
+        if (data->shell_surface.zxdg.surface) {
+            while (!data->shell_surface.zxdg.initial_configure_seen) {
+                WAYLAND_wl_display_flush(c->display);
+                WAYLAND_wl_display_dispatch(c->display);
+            }
+        }
+    }
+}
+
+void Wayland_HideWindow(_THIS, SDL_Window *window)
+{
+    SDL_VideoData *data = _this->driverdata;
+    SDL_WindowData *wind = window->driverdata;
+
+    if (wind->server_decoration) {
+       zxdg_toplevel_decoration_v1_destroy(wind->server_decoration);
+       wind->server_decoration = NULL;
+    }
+
+    if (data->shell.xdg) {
+        if (wind->shell_surface.xdg.roleobj.toplevel) {
+            xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel);
+            wind->shell_surface.xdg.roleobj.toplevel = NULL;
+        }
+        if (wind->shell_surface.xdg.surface) {
+            xdg_surface_destroy(wind->shell_surface.xdg.surface);
+            wind->shell_surface.xdg.surface = NULL;
+        }
+    } else if (data->shell.zxdg) {
+        if (wind->shell_surface.zxdg.roleobj.toplevel) {
+            zxdg_toplevel_v6_destroy(wind->shell_surface.zxdg.roleobj.toplevel);
+            wind->shell_surface.zxdg.roleobj.toplevel = NULL;
+        }
+        if (wind->shell_surface.zxdg.surface) {
+            zxdg_surface_v6_destroy(wind->shell_surface.zxdg.surface);
+            wind->shell_surface.zxdg.surface = NULL;
+        }
+    } else {
+        if (wind->shell_surface.wl) {
+            wl_shell_surface_destroy(wind->shell_surface.wl);
+            wind->shell_surface.wl = NULL;
+        }
+    }
 }
 
 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
@@ -704,10 +835,19 @@ Wayland_RestoreWindow(_THIS, SDL_Window * window)
 
     /* Note that xdg-shell does NOT provide a way to unset minimize! */
     if (viddata->shell.xdg) {
+        if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
+            return; /* Can't do anything yet, wait for ShowWindow */
+        }
         xdg_toplevel_unset_maximized(wind->shell_surface.xdg.roleobj.toplevel);
     } else if (viddata->shell.zxdg) {
+        if (wind->shell_surface.zxdg.roleobj.toplevel == NULL) {
+            return; /* Can't do anything yet, wait for ShowWindow */
+        }
         zxdg_toplevel_v6_unset_maximized(wind->shell_surface.zxdg.roleobj.toplevel);
     } else {
+        if (wind->shell_surface.wl == NULL) {
+            return; /* Can't do anything yet, wait for ShowWindow */
+        }
         wl_shell_surface_set_toplevel(wind->shell_surface.wl);
     }
 
@@ -738,10 +878,19 @@ Wayland_MaximizeWindow(_THIS, SDL_Window * window)
     SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
 
     if (viddata->shell.xdg) {
+        if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
+            return; /* Can't do anything yet, wait for ShowWindow */
+        }
         xdg_toplevel_set_maximized(wind->shell_surface.xdg.roleobj.toplevel);
     } else if (viddata->shell.zxdg) {
+        if (wind->shell_surface.zxdg.roleobj.toplevel == NULL) {
+            return; /* Can't do anything yet, wait for ShowWindow */
+        }
         zxdg_toplevel_v6_set_maximized(wind->shell_surface.zxdg.roleobj.toplevel);
     } else {
+        if (wind->shell_surface.wl == NULL) {
+            return; /* Can't do anything yet, wait for ShowWindow */
+        }
         wl_shell_surface_set_maximized(wind->shell_surface.wl, NULL);
     }
 
@@ -755,8 +904,14 @@ Wayland_MinimizeWindow(_THIS, SDL_Window * window)
     SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
 
     if (viddata->shell.xdg) {
+        if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
+            return; /* Can't do anything yet, wait for ShowWindow */
+        }
         xdg_toplevel_set_minimized(wind->shell_surface.xdg.roleobj.toplevel);
     } else if (viddata->shell.zxdg) {
+        if (wind->shell_surface.zxdg.roleobj.toplevel == NULL) {
+            return; /* Can't do anything yet, wait for ShowWindow */
+        }
         zxdg_toplevel_v6_set_minimized(wind->shell_surface.zxdg.roleobj.toplevel);
     }
 
@@ -841,23 +996,6 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
         wl_compositor_create_surface(c->compositor);
     wl_surface_add_listener(data->surface, &surface_listener, data);
 
-    if (c->shell.xdg) {
-        data->shell_surface.xdg.surface = xdg_wm_base_get_xdg_surface(c->shell.xdg, data->surface);
-        /* !!! FIXME: add popup role */
-        data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
-        xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
-        xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
-    } else if (c->shell.zxdg) {
-        data->shell_surface.zxdg.surface = zxdg_shell_v6_get_xdg_surface(c->shell.zxdg, data->surface);
-        /* !!! FIXME: add popup role */
-        data->shell_surface.zxdg.roleobj.toplevel = zxdg_surface_v6_get_toplevel(data->shell_surface.zxdg.surface);
-        zxdg_toplevel_v6_add_listener(data->shell_surface.zxdg.roleobj.toplevel, &toplevel_listener_zxdg, data);
-        zxdg_toplevel_v6_set_app_id(data->shell_surface.zxdg.roleobj.toplevel, c->classname);
-    } else {
-        data->shell_surface.wl = wl_shell_get_shell_surface(c->shell.wl, data->surface);
-        wl_shell_surface_set_class(data->shell_surface.wl, c->classname);
-    }
-
 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
     if (c->surface_extension) {
         data->extended_surface = qt_surface_extension_get_extended_surface(
@@ -880,23 +1018,6 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
         }
     }
 
-    if (c->shell.xdg) {
-        if (data->shell_surface.xdg.surface) {
-            xdg_surface_set_user_data(data->shell_surface.xdg.surface, data);
-            xdg_surface_add_listener(data->shell_surface.xdg.surface, &shell_surface_listener_xdg, data);
-        }
-    } else if (c->shell.zxdg) {
-        if (data->shell_surface.zxdg.surface) {
-            zxdg_surface_v6_set_user_data(data->shell_surface.zxdg.surface, data);
-            zxdg_surface_v6_add_listener(data->shell_surface.zxdg.surface, &shell_surface_listener_zxdg, data);
-        }
-    } else {
-        if (data->shell_surface.wl) {
-            wl_shell_surface_set_user_data(data->shell_surface.wl, data);
-            wl_shell_surface_add_listener(data->shell_surface.wl, &shell_surface_listener_wl, data);
-        }
-    }
-
 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
     if (data->extended_surface) {
         qt_extended_surface_set_user_data(data->extended_surface, data);
@@ -905,15 +1026,6 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
     }
 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
 
-    if (c->decoration_manager && c->shell.xdg && data->shell_surface.xdg.surface) {
-        data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(c->decoration_manager, data->shell_surface.xdg.roleobj.toplevel);
-        if (data->server_decoration) {
-            const SDL_bool bordered = (window->flags & SDL_WINDOW_BORDERLESS) == 0;
-            const enum zxdg_toplevel_decoration_v1_mode mode = bordered ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
-            zxdg_toplevel_decoration_v1_set_mode(data->server_decoration, mode);
-        }
-    }
-
     region = wl_compositor_create_region(c->compositor);
     wl_region_add(region, 0, 0, window->w, window->h);
     wl_surface_set_opaque_region(data->surface, region);
@@ -923,28 +1035,9 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
         Wayland_input_lock_pointer(c->input);
     }
 
-    /* This will call wl_surface_commit */
-    CommitMinMaxDimensions(window);
+    wl_surface_commit(data->surface);
     WAYLAND_wl_display_flush(c->display);
 
-    /* we have to wait until the surface gets a "configure" event, or
-       use of this surface will fail. This is a new rule for xdg_shell. */
-    if (c->shell.xdg) {
-        if (data->shell_surface.xdg.surface) {
-            while (!data->shell_surface.xdg.initial_configure_seen) {
-                WAYLAND_wl_display_flush(c->display);
-                WAYLAND_wl_display_dispatch(c->display);
-            }
-        }
-    } else if (c->shell.zxdg) {
-        if (data->shell_surface.zxdg.surface) {
-            while (!data->shell_surface.zxdg.initial_configure_seen) {
-                WAYLAND_wl_display_flush(c->display);
-                WAYLAND_wl_display_dispatch(c->display);
-            }
-        }
-    }
-
     /* We may need to create an idle inhibitor for this new window */
     Wayland_SuspendScreenSaver(_this);
 
@@ -1027,10 +1120,19 @@ void Wayland_SetWindowTitle(_THIS, SDL_Window * window)
 
     if (window->title != NULL) {
         if (viddata->shell.xdg) {
+            if (wind->shell_surface.xdg.roleobj.toplevel == NULL) {
+                return; /* Can't do anything yet, wait for ShowWindow */
+            }
             xdg_toplevel_set_title(wind->shell_surface.xdg.roleobj.toplevel, window->title);
         } else if (viddata->shell.zxdg) {
+            if (wind->shell_surface.zxdg.roleobj.toplevel == NULL) {
+                return; /* Can't do anything yet, wait for ShowWindow */
+            }
             zxdg_toplevel_v6_set_title(wind->shell_surface.zxdg.roleobj.toplevel, window->title);
         } else {
+            if (wind->shell_surface.wl == NULL) {
+                return; /* Can'd do anything yet, wait for ShowWindow */
+            }
             wl_shell_surface_set_title(wind->shell_surface.wl, window->title);
         }
     }
@@ -1089,34 +1191,10 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window)
             WAYLAND_wl_egl_window_destroy(wind->egl_window);
         }
 
-        if (wind->server_decoration) {
-           zxdg_toplevel_decoration_v1_destroy(wind->server_decoration);
-        }
-
         if (wind->idle_inhibitor) {
             zwp_idle_inhibitor_v1_destroy(wind->idle_inhibitor);
         }
 
-        if (data->shell.xdg) {
-            if (wind->shell_surface.xdg.roleobj.toplevel) {
-                xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel);
-            }
-            if (wind->shell_surface.zxdg.surface) {
-                xdg_surface_destroy(wind->shell_surface.xdg.surface);
-            }
-        } else if (data->shell.zxdg) {
-            if (wind->shell_surface.zxdg.roleobj.toplevel) {
-                zxdg_toplevel_v6_destroy(wind->shell_surface.zxdg.roleobj.toplevel);
-            }
-            if (wind->shell_surface.zxdg.surface) {
-                zxdg_surface_v6_destroy(wind->shell_surface.zxdg.surface);
-            }
-        } else {
-            if (wind->shell_surface.wl) {
-                wl_shell_surface_destroy(wind->shell_surface.wl);
-            }
-        }
-
         SDL_free(wind->outputs);
 
 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h
index a4c990257..baddeabb8 100644
--- a/src/video/wayland/SDL_waylandwindow.h
+++ b/src/video/wayland/SDL_waylandwindow.h
@@ -85,6 +85,7 @@ typedef struct {
 } SDL_WindowData;
 
 extern void Wayland_ShowWindow(_THIS, SDL_Window *window);
+extern void Wayland_HideWindow(_THIS, SDL_Window *window);
 extern void Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
                                         SDL_VideoDisplay * _display,
                                         SDL_bool fullscreen);