From adad7dcae09292adc4a0bf429fa75eafb21dbff3 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sun, 6 Apr 2025 12:29:41 -0400 Subject: [PATCH] x11/wayland: Ignore redundant restore and fullscreen leave requests when showing the window The window may be initially maximized or made fullscreen by the window manager for various reasons, such as automatically declaring a window that precisely fills the usable desktop space as maximized, or a "kiosk-mode" automatically making the window fullscreen. Don't redundantly make restored or unset fullscreen calls when initially showing a window, or the expected state can be unset. --- src/video/wayland/SDL_waylandwindow.c | 14 ++++++++++++++ src/video/wayland/SDL_waylandwindow.h | 1 + src/video/x11/SDL_x11events.c | 3 +++ src/video/x11/SDL_x11window.c | 9 +++++++++ src/video/x11/SDL_x11window.h | 1 + 5 files changed, 28 insertions(+) diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 523d2e4bb2..1fea144e17 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -2055,6 +2055,10 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) struct wl_callback *cb = wl_display_sync(_this->internal->display); wl_callback_add_listener(cb, &show_hide_sync_listener, (void*)((uintptr_t)window->id)); + data->showing_window = true; + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_SHOWN, 0, 0); + data->showing_window = false; + // Send an exposure event to signal that the client should draw. if (data->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME) { SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_EXPOSED, 0, 0); @@ -2277,6 +2281,11 @@ SDL_FullscreenResult Wayland_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Win return SDL_FULLSCREEN_FAILED; } + // Drop fullscreen leave requests when showing the window. + if (wind->showing_window && fullscreen == SDL_FULLSCREEN_OP_LEAVE) { + return SDL_FULLSCREEN_SUCCEEDED; + } + if (wind->show_hide_sync_required) { WAYLAND_wl_display_roundtrip(_this->internal->display); } @@ -2331,6 +2340,11 @@ void Wayland_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) { SDL_WindowData *wind = window->internal; + // Drop restore requests when showing the window. + if (wind->showing_window) { + return; + } + // Not currently fullscreen or maximized, and no state pending; nothing to do. if (!(window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MAXIMIZED)) && !wind->fullscreen_deadline_count && !wind->maximized_restored_deadline_count) { diff --git a/src/video/wayland/SDL_waylandwindow.h b/src/video/wayland/SDL_waylandwindow.h index 619fd79e6d..ee27f337b8 100644 --- a/src/video/wayland/SDL_waylandwindow.h +++ b/src/video/wayland/SDL_waylandwindow.h @@ -198,6 +198,7 @@ struct SDL_WindowData bool is_fullscreen; bool fullscreen_exclusive; bool drop_fullscreen_requests; + bool showing_window; bool fullscreen_was_positioned; bool show_hide_sync_required; bool scale_to_display; diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 43d6dd7283..96bf8c7a1b 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -508,6 +508,7 @@ static void X11_DispatchMapNotify(SDL_WindowData *data) SDL_Window *window = data->window; SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_SHOWN, 0, 0); + data->was_shown = true; // This may be sent when restoring a minimized window. if (window->flags & SDL_WINDOW_MINIMIZED) { @@ -528,6 +529,8 @@ static void X11_DispatchUnmapNotify(SDL_WindowData *data) if (!window->is_hiding) { SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_OCCLUDED, 0, 0); + } else { + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_HIDDEN, 0, 0); } } diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index d88487627e..ca340953ed 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -1773,6 +1773,11 @@ void X11_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) void X11_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) { + // Don't restore the window the first time it is being shown. + if (!window->internal->was_shown) { + return; + } + if (window->internal->pending_operation & (X11_PENDING_OP_FULLSCREEN | X11_PENDING_OP_MAXIMIZE | X11_PENDING_OP_MINIMIZE)) { SDL_SyncWindow(window); } @@ -1807,6 +1812,10 @@ static SDL_FullscreenResult X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this, Atom _NET_WM_STATE = data->videodata->atoms._NET_WM_STATE; Atom _NET_WM_STATE_FULLSCREEN = data->videodata->atoms._NET_WM_STATE_FULLSCREEN; + if (!data->was_shown && fullscreen == SDL_FULLSCREEN_OP_LEAVE) { + return SDL_FULLSCREEN_SUCCEEDED; + } + if (X11_IsWindowMapped(_this, window)) { XEvent e; diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index f1a73ab592..2d7b3239d3 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -115,6 +115,7 @@ struct SDL_WindowData bool previous_borders_nonzero; bool toggle_borders; bool fullscreen_borders_forced_on; + bool was_shown; SDL_HitTestResult hit_test_result; XPoint xim_spot;