SDL: video: Ensure that all references to a destroyed fullscreen window are removed

From 310f21bf84af9c0f840a42446ad91a1542a8d5b0 Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Tue, 13 Feb 2024 09:42:54 -0500
Subject: [PATCH] video: Ensure that all references to a destroyed fullscreen
 window are removed

Windowing systems that receive fullscreen state changes asynchronously may not receive a configure event notifying SDL that the window has left fullscreen when the window is being destroyed. Ensure that no display holds a reference to a destroyed fullscreen window.
---
 src/video/SDL_video.c                 | 7 +++++++
 src/video/wayland/SDL_waylandwindow.c | 6 ++++++
 2 files changed, 13 insertions(+)

diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 87f8f9b4646b..3804a95d96f6 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -3651,6 +3651,13 @@ void SDL_DestroyWindow(SDL_Window *window)
         SDL_HideWindow(window);
     }
 
+    /* Make sure the destroyed window isn't referenced by any display as a fullscreen window. */
+    for (int i = 0; i < _this->num_displays; ++i) {
+        if (_this->displays[i]->fullscreen_window == window) {
+            _this->displays[i]->fullscreen_window = NULL;
+        }
+    }
+
     /* Make sure this window no longer has focus */
     if (SDL_GetKeyboardFocus() == window) {
         SDL_SetKeyboardFocus(NULL);
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 9555e6cc97f2..df6443870ba8 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -2518,6 +2518,12 @@ void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
     SDL_VideoData *data = _this->driverdata;
     SDL_WindowData *wind = window->driverdata;
 
+    /* Roundtrip before destroying the window to make sure that it has received input leave events, so that
+     * no internal structures are left pointing to the destroyed window. */
+    if (wind->show_hide_sync_required) {
+        WAYLAND_wl_display_roundtrip(data->display);
+    }
+
     if (data && wind) {
 #ifdef SDL_VIDEO_OPENGL_EGL
         if (wind->egl_surface) {