SDL: Fixing window being incorrect size when using win+shift+arrow to move new big picture mode between displays

From c8dfc6b4757470bbb5b3678ee9a37bf8c9a74267 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 19 Jan 2023 07:43:01 -0800
Subject: [PATCH] Fixing window being incorrect size when using win+shift+arrow
 to move new big picture mode between displays

*When changing the display of a window, if it's a fullscreen window, resize it to the size of the new display

CR: @saml
---
 src/events/SDL_windowevents.c         |  4 ++++
 src/video/SDL_sysvideo.h              |  1 +
 src/video/SDL_video.c                 | 30 +++++++++++++++++++++++++++
 src/video/windows/SDL_windowsevents.c | 12 +++++++++++
 4 files changed, 47 insertions(+)

diff --git a/src/events/SDL_windowevents.c b/src/events/SDL_windowevents.c
index 3d108ac6c388..f6bc8ece8154 100644
--- a/src/events/SDL_windowevents.c
+++ b/src/events/SDL_windowevents.c
@@ -175,6 +175,10 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent,
         window->flags &= ~SDL_WINDOW_INPUT_FOCUS;
         SDL_OnWindowFocusLost(window);
         break;
+    case SDL_WINDOWEVENT_DISPLAY_CHANGED:
+        SDL_assert(data1 == window->display_index);
+        SDL_OnWindowDisplayChanged(window);
+        break;
     default:
         break;
     }
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index 525a84f5b58e..86329d9d312d 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -504,6 +504,7 @@ extern void SDL_OnWindowEnter(SDL_Window *window);
 extern void SDL_OnWindowLeave(SDL_Window *window);
 extern void SDL_OnWindowFocusGained(SDL_Window *window);
 extern void SDL_OnWindowFocusLost(SDL_Window *window);
+extern void SDL_OnWindowDisplayChanged(SDL_Window *window);
 extern void SDL_UpdateWindowGrab(SDL_Window *window);
 extern SDL_Window *SDL_GetFocusWindow(void);
 
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 569c845fb43d..a0272cf71983 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -2919,6 +2919,36 @@ void SDL_OnWindowHidden(SDL_Window *window)
     SDL_UpdateFullscreenMode(window, SDL_FALSE);
 }
 
+void SDL_OnWindowDisplayChanged(SDL_Window *window)
+{
+    if (window->flags & SDL_WINDOW_FULLSCREEN) {
+        SDL_Rect rect;
+
+        if (FULLSCREEN_VISIBLE(window) && (window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
+            window->last_fullscreen_flags = 0;
+            SDL_UpdateFullscreenMode(window, SDL_TRUE);
+        }
+
+        if (SDL_GetDisplayBounds(window->display_index, &rect) == 0) {
+            int old_w = window->w;
+            int old_h = window->h;
+            window->x = rect.x;
+            window->y = rect.y;
+            window->w = rect.w;
+            window->h = rect.h;
+            window->fullscreen_mode.w = rect.w;
+            window->fullscreen_mode.h = rect.h;
+            if (_this->SetWindowSize) {
+                _this->SetWindowSize(_this, window);
+            }
+
+            if (window->w != old_w || window->h != old_h) {
+                SDL_OnWindowResized(window);
+            }
+        }
+    }
+}
+
 void SDL_OnWindowResized(SDL_Window *window)
 {
     int display_index = SDL_GetWindowDisplayIndex(window);
diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index e3d1153372ac..5ea9fbc553cc 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/src/video/windows/SDL_windowsevents.c
@@ -1266,6 +1266,18 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 
         SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, x, y);
 
+        // Moving the window from one display to another can change the size of the window (in the handling of SDL_WINDOWEVENT_MOVED), so we need to re-query the bounds
+        if (GetClientRect(hwnd, &rect)) {
+            ClientToScreen(hwnd, (LPPOINT)&rect);
+            ClientToScreen(hwnd, (LPPOINT)&rect + 1);
+
+            WIN_UpdateClipCursor(data->window);
+
+            x = rect.left;
+            y = rect.top;
+            WIN_ScreenPointToSDL(&x, &y);
+        }
+
         /* Convert client area width/height from pixels to dpi-scaled points */
         w = rect.right - rect.left;
         h = rect.bottom - rect.top;