diff --git a/src/events/SDL_windowevents.c b/src/events/SDL_windowevents.c index 01a09ab7ec..b31f3edd0d 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 38b27a7a37..8649c7b500 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 89c7294fbc..6f47520eda 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 2bc185c019..0fa54dcae8 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 130bda3135..1c6766a2f1 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