From 2761ddc218da34fe6aa27531f7e04f9b988d56a2 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Sun, 8 Dec 2024 17:02:54 -0500 Subject: [PATCH] video: Prefer the window manager supplied coordinates for selecting a fullscreen display Unless there are pending client requested window coordinates, such as in the case where the position is set followed by immediately by entering fullscreen, prefer the true window coordinates as sent by the window manager to select a fullscreen display. Fixes the case where, if the window manager moves an already maximized window to another display, the window would be made fullscreen on the wrong display since the last floating coordinates would be used. --- src/events/SDL_windowevents.c | 1 + src/video/SDL_sysvideo.h | 2 +- src/video/SDL_video.c | 24 ++++++++++++------------ src/video/wayland/SDL_waylandwindow.c | 2 ++ src/video/x11/SDL_x11window.c | 10 ++++++++++ 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/events/SDL_windowevents.c b/src/events/SDL_windowevents.c index 01a09ab7eca6e..b31f3edd0d7c8 100644 --- a/src/events/SDL_windowevents.c +++ b/src/events/SDL_windowevents.c @@ -69,6 +69,7 @@ bool SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int data case SDL_EVENT_WINDOW_MOVED: window->undefined_x = false; window->undefined_y = false; + window->use_pending_position_for_fullscreen = false; if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { window->windowed.x = data1; window->windowed.y = data2; diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 38b27a7a37578..8649c7b500408 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -96,9 +96,9 @@ struct SDL_Window SDL_Surface *surface; bool surface_valid; - bool is_repositioning; // Set during an SDL_SetWindowPosition() call. bool is_hiding; bool restore_on_show; // Child was hidden recursively by the parent, restore when shown. + bool use_pending_position_for_fullscreen; bool is_destroying; bool is_dropping; // drag/drop in progress, expecting SDL_SendDropComplete(). diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 89c7294fbc157..6f47520edab2d 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1660,20 +1660,21 @@ SDL_VideoDisplay *SDL_GetVideoDisplayForFullscreenWindow(SDL_Window *window) displayID = window->current_fullscreen_mode.displayID; } - /* The floating position is used here as a very common pattern is - * SDL_SetWindowPosition() followed by SDL_SetWindowFullscreen() to make the - * window fullscreen desktop on a specific display. If the backend doesn't - * support changing the window position, or the compositor hasn't yet actually - * moved the window, the current position won't be updated at the time of the - * fullscreen call. + /* This is used to handle the very common pattern of SDL_SetWindowPosition() + * followed immediately by SDL_SetWindowFullscreen() to make the window fullscreen + * desktop on a specific display. If the backend doesn't support changing the + * window position, or an async window manager hasn't yet actually moved the window, + * the current position won't be updated at the time of the fullscreen call. */ if (!displayID) { - if (window->flags & SDL_WINDOW_FULLSCREEN && !window->is_repositioning) { - // This was a window manager initiated move, use the current position. - displayID = GetDisplayForRect(window->x, window->y, 1, 1); - } else { + if (window->use_pending_position_for_fullscreen) { + // The last coordinates were client requested; use the pending floating coordinates. displayID = GetDisplayForRect(window->floating.x, window->floating.y, window->floating.w, window->floating.h); } + else { + // The last coordinates were from the window manager; use the current position. + displayID = GetDisplayForRect(window->x, window->y, 1, 1); + } } if (!displayID) { // Use the primary display for a window if we can't find it anywhere else @@ -2806,11 +2807,10 @@ bool SDL_SetWindowPosition(SDL_Window *window, int x, int y) window->floating.y = y; window->undefined_x = false; window->undefined_y = false; + window->use_pending_position_for_fullscreen = true; if (_this->SetWindowPosition) { - window->is_repositioning = true; const bool result = _this->SetWindowPosition(_this, window); - window->is_repositioning = false; if (result) { SDL_SyncIfRequired(window); } diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 2bc185c019b1e..0fa54dcae82e8 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -2651,6 +2651,7 @@ bool Wayland_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window) RepositionPopup(window, false); return true; } else if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR || wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) { + const bool use_pending_position_for_fullscreen = window->use_pending_position_for_fullscreen; const int x = window->floating.x; const int y = window->floating.y; @@ -2671,6 +2672,7 @@ bool Wayland_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window) * * for positioning a desktop fullscreen window won't work without this. */ + window->use_pending_position_for_fullscreen = use_pending_position_for_fullscreen; window->floating.x = x; window->floating.y = y; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index 130bda3135578..1c6766a2f1a21 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -1060,7 +1060,17 @@ bool X11_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window) { // Sync any pending fullscreen or maximize events. if (window->internal->pending_operation & (X11_PENDING_OP_FULLSCREEN | X11_PENDING_OP_MAXIMIZE)) { + // Save state in case it is overwritten while synchronizing. + const bool use_client_fs_coords = window->use_pending_position_for_fullscreen; + const int x = window->floating.x; + const int y = window->floating.y; + X11_SyncWindow(_this, window); + + // Restore state that may have been overwritten while synchronizing. + window->use_pending_position_for_fullscreen = use_client_fs_coords; + window->floating.x = x; + window->floating.y = y; } // Position will be set when window is de-maximized