SDL: Added handling for undefined window position on Windows

From 3bfd59660833ee09344b9408aaaa082d509ca54a Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 24 Feb 2023 17:06:47 -0800
Subject: [PATCH] Added handling for undefined window position on Windows

---
 src/video/SDL_sysvideo.h              |  1 +
 src/video/SDL_video.c                 | 24 +++++++++++---
 src/video/windows/SDL_windowsvideo.c  |  2 ++
 src/video/windows/SDL_windowswindow.c | 47 +++++++++++++++++++++++++--
 4 files changed, 67 insertions(+), 7 deletions(-)

diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index 1a6e4c5ba0cc..ddf0e62ab201 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -153,6 +153,7 @@ typedef enum
 {
     VIDEO_DEVICE_QUIRK_MODE_SWITCHING_EMULATED = 0x01,
     VIDEO_DEVICE_QUIRK_DISABLE_UNSET_FULLSCREEN_ON_MINIMIZE = 0x02,
+    VIDEO_DEVICE_QUIRK_HANDLES_UNDEFINED_WINDOW_POSITION = 0x04,
 } DeviceQuirkFlags;
 
 struct SDL_VideoDevice
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 431adfde83e7..82e51b00f579 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -154,12 +154,26 @@ extern SDL_bool Cocoa_SetWindowFullscreenSpace(SDL_Window *window, SDL_bool stat
 /* Convenience functions for reading driver flags */
 static SDL_bool ModeSwitchingEmulated(_THIS)
 {
-    return !!(_this->quirk_flags & VIDEO_DEVICE_QUIRK_MODE_SWITCHING_EMULATED);
+    if (_this->quirk_flags & VIDEO_DEVICE_QUIRK_MODE_SWITCHING_EMULATED) {
+        return SDL_TRUE;
+    }
+    return SDL_FALSE;
 }
 
 static SDL_bool DisableUnsetFullscreenOnMinimize(_THIS)
 {
-    return !!(_this->quirk_flags & VIDEO_DEVICE_QUIRK_DISABLE_UNSET_FULLSCREEN_ON_MINIMIZE);
+    if (_this->quirk_flags & VIDEO_DEVICE_QUIRK_DISABLE_UNSET_FULLSCREEN_ON_MINIMIZE) {
+        return SDL_TRUE;
+    }
+    return SDL_FALSE;
+}
+
+static SDL_bool HandlesUndefinedWindowPosition(_THIS)
+{
+    if (_this->quirk_flags & VIDEO_DEVICE_QUIRK_HANDLES_UNDEFINED_WINDOW_POSITION) {
+        return SDL_TRUE;
+    }
+    return SDL_FALSE;
 }
 
 /* Support for framebuffer emulation using an accelerated renderer */
@@ -1672,10 +1686,12 @@ SDL_Window *SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint
 
         SDL_zero(bounds);
         SDL_GetDisplayBounds(displayID, &bounds);
-        if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISCENTERED(x)) {
+        if (SDL_WINDOWPOS_ISCENTERED(x) ||
+            (SDL_WINDOWPOS_ISUNDEFINED(x) && !HandlesUndefinedWindowPosition(_this))) {
             x = bounds.x + (bounds.w - w) / 2;
         }
-        if (SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(y)) {
+        if (SDL_WINDOWPOS_ISCENTERED(y) ||
+            (SDL_WINDOWPOS_ISUNDEFINED(y) && !HandlesUndefinedWindowPosition(_this))) {
             y = bounds.y + (bounds.h - h) / 2;
         }
     }
diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c
index 9cb30d820b8f..cd297cb2ddd1 100644
--- a/src/video/windows/SDL_windowsvideo.c
+++ b/src/video/windows/SDL_windowsvideo.c
@@ -260,6 +260,8 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
 
     device->free = WIN_DeleteDevice;
 
+    device->quirk_flags = VIDEO_DEVICE_QUIRK_HANDLES_UNDEFINED_WINDOW_POSITION;
+
     return device;
 }
 
diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c
index 06e125cc0964..9c45da382760 100644
--- a/src/video/windows/SDL_windowswindow.c
+++ b/src/video/windows/SDL_windowswindow.c
@@ -490,6 +490,7 @@ int WIN_CreateWindow(_THIS, SDL_Window *window)
     DWORD style = STYLE_BASIC;
     int x, y;
     int w, h;
+    SDL_bool undefined_position = SDL_FALSE;
 
     if (window->flags & SDL_WINDOW_SKIP_TASKBAR) {
         parent = CreateWindow(SDL_Appname, TEXT(""), STYLE_BASIC, 0, 0, 32, 32, NULL, NULL, SDL_Instance, NULL);
@@ -497,12 +498,46 @@ int WIN_CreateWindow(_THIS, SDL_Window *window)
 
     style |= GetWindowStyle(window);
 
+    /* Make sure we have valid coordinates for the AdjustWindowRect call below */
+    x = window->x;
+    y = window->y;
+    if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISUNDEFINED(y)) {
+        SDL_DisplayID displayID = 0;
+        SDL_Rect bounds;
+
+        if (SDL_WINDOWPOS_ISUNDEFINED(x) && (x & 0xFFFF)) {
+            displayID = (x & 0xFFFF);
+        } else if (SDL_WINDOWPOS_ISUNDEFINED(y) && (y & 0xFFFF)) {
+            displayID = (y & 0xFFFF);
+        }
+        if (displayID == 0 || SDL_GetDisplayIndex(displayID) < 0) {
+            displayID = SDL_GetPrimaryDisplay();
+        }
+
+        SDL_zero(bounds);
+        SDL_GetDisplayBounds(displayID, &bounds);
+        if (SDL_WINDOWPOS_ISUNDEFINED(x)) {
+            window->x = window->windowed.x = bounds.x + (bounds.w - window->w) / 2;
+        }
+        if (SDL_WINDOWPOS_ISUNDEFINED(y)) {
+            window->y = window->windowed.y = bounds.y + (bounds.h - window->h) / 2;
+        }
+        if (displayID == SDL_GetPrimaryDisplay() &&
+            SDL_WINDOWPOS_ISUNDEFINED(x) && SDL_WINDOWPOS_ISUNDEFINED(y)) {
+            /* We can use CW_USEDEFAULT for the position */
+            undefined_position = SDL_TRUE;
+        }
+    }
+
     /* Figure out what the window area will be */
     WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_FALSE);
 
-    hwnd =
-        CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, parent, NULL,
-                     SDL_Instance, NULL);
+    if (undefined_position) {
+        x = CW_USEDEFAULT;
+        y = CW_USEDEFAULT; /* Not actually used */
+    }
+
+    hwnd = CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, parent, NULL, SDL_Instance, NULL);
     if (!hwnd) {
         return WIN_SetError("Couldn't create window");
     }
@@ -517,6 +552,12 @@ int WIN_CreateWindow(_THIS, SDL_Window *window)
         return -1;
     }
 
+    if (undefined_position) {
+        /* Record where the window ended up */
+        window->windowed.x = window->x;
+        window->windowed.y = window->y;
+    }
+
     /* Inform Windows of the frame change so we can respond to WM_NCCALCSIZE */
     SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);