Browse Source

video: Fix window manager initiated fullscreen window moves

Distinguish between and handle fullscreen window moves initiated by the window manager vs the application to avoid cases where the window snaps back to the original display when moved due to the use of old coordinates.
Frank Praznik 1 year ago
parent
commit
8d25c2d260
2 changed files with 11 additions and 3 deletions
  1. 1 0
      src/video/SDL_sysvideo.h
  2. 10 3
      src/video/SDL_video.c

+ 1 - 0
src/video/SDL_sysvideo.h

@@ -86,6 +86,7 @@ struct SDL_Window
     SDL_Surface *surface;
     SDL_bool surface_valid;
 
+    SDL_bool is_repositioning; /* Set during an SDL_SetWindowPosition() call. */
     SDL_bool is_hiding;
     SDL_bool restore_on_show; /* Child was hidden recursively by the parent, restore when shown. */
     SDL_bool is_destroying;

+ 10 - 3
src/video/SDL_video.c

@@ -1402,14 +1402,19 @@ SDL_VideoDisplay *SDL_GetVideoDisplayForFullscreenWindow(SDL_Window *window)
     }
 
     /* The floating position is used here as a very common pattern is
-     * SDL_SetWindowPosition() followed by SDL_SetWindowFullscreen to make the
+     * 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 actual position won't be updated at the time of the
+     * moved the window, the current position won't be updated at the time of the
      * fullscreen call.
      */
     if (!displayID) {
-        displayID = GetDisplayForRect(window->floating.x, window->floating.y, window->w, window->h);
+        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, window->w, window->h);
+        } else {
+            displayID = GetDisplayForRect(window->floating.x, window->floating.y, window->w, window->h);
+        }
     }
     if (!displayID) {
         /* Use the primary display for a window if we can't find it anywhere else */
@@ -2500,7 +2505,9 @@ int SDL_SetWindowPosition(SDL_Window *window, int x, int y)
     window->undefined_y = SDL_FALSE;
 
     if (_this->SetWindowPosition) {
+        window->is_repositioning = SDL_TRUE;
         const int ret = _this->SetWindowPosition(_this, window);
+        window->is_repositioning = SDL_FALSE;
         if (!ret) {
             SDL_SyncIfRequired(window);
         }