SDL: Added handling for undefined window position on X11

From 4d9d343662496fd28e312a406f19150106566f8b Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 24 Feb 2023 17:49:45 -0800
Subject: [PATCH] Added handling for undefined window position on X11

---
 src/video/SDL_sysvideo.h              |  5 +++-
 src/video/SDL_video.c                 | 26 +++++++++++---------
 src/video/windows/SDL_windowsvideo.c  |  2 --
 src/video/windows/SDL_windowswindow.c | 35 +++------------------------
 src/video/x11/SDL_x11window.c         | 20 ++++++++++++---
 5 files changed, 38 insertions(+), 50 deletions(-)

diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index ddf0e62ab201..0fb800288a58 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -89,6 +89,10 @@ struct SDL_Window
     /* Stored position and size for windowed mode */
     SDL_Rect windowed;
 
+    /* Whether or not the intial position was defined */
+    SDL_bool undefined_x;
+    SDL_bool undefined_y;
+
     SDL_DisplayMode requested_fullscreen_mode;
     SDL_DisplayMode current_fullscreen_mode;
 
@@ -153,7 +157,6 @@ 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 82e51b00f579..90cc96770a19 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -168,14 +168,6 @@ static SDL_bool DisableUnsetFullscreenOnMinimize(_THIS)
     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 */
 
 #define SDL_WINDOWTEXTUREDATA "_SDL_WindowTextureData"
@@ -1631,6 +1623,8 @@ SDL_Window *SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint
 {
     SDL_Window *window;
     Uint32 type_flags, graphics_flags;
+    SDL_bool undefined_x = SDL_FALSE;
+    SDL_bool undefined_y = SDL_FALSE;
 
     if (_this == NULL) {
         /* Initialize the video system if needed */
@@ -1686,12 +1680,16 @@ 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_ISCENTERED(x) ||
-            (SDL_WINDOWPOS_ISUNDEFINED(x) && !HandlesUndefinedWindowPosition(_this))) {
+        if (SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISUNDEFINED(x)) {
+            if (SDL_WINDOWPOS_ISUNDEFINED(x)) {
+                undefined_x = SDL_TRUE;
+            }
             x = bounds.x + (bounds.w - w) / 2;
         }
-        if (SDL_WINDOWPOS_ISCENTERED(y) ||
-            (SDL_WINDOWPOS_ISUNDEFINED(y) && !HandlesUndefinedWindowPosition(_this))) {
+        if (SDL_WINDOWPOS_ISCENTERED(y) || SDL_WINDOWPOS_ISUNDEFINED(y)) {
+            if (SDL_WINDOWPOS_ISUNDEFINED(y)) {
+                undefined_y = SDL_TRUE;
+            }
             y = bounds.y + (bounds.h - h) / 2;
         }
     }
@@ -1750,6 +1748,8 @@ SDL_Window *SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint
     window->windowed.y = window->y = y;
     window->windowed.w = window->w = w;
     window->windowed.h = window->h = h;
+    window->undefined_x = undefined_x;
+    window->undefined_y = undefined_y;
 
     if (flags & SDL_WINDOW_FULLSCREEN) {
         SDL_VideoDisplay *display = SDL_GetVideoDisplayForWindow(window);
@@ -2202,6 +2202,8 @@ int SDL_SetWindowPosition(SDL_Window *window, int x, int y)
 
     window->windowed.x = x;
     window->windowed.y = y;
+    window->undefined_x = SDL_FALSE;
+    window->undefined_y = SDL_FALSE;
 
     if (SDL_WINDOW_FULLSCREEN_VISIBLE(window)) {
         if (!window->fullscreen_exclusive) {
diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c
index cd297cb2ddd1..9cb30d820b8f 100644
--- a/src/video/windows/SDL_windowsvideo.c
+++ b/src/video/windows/SDL_windowsvideo.c
@@ -260,8 +260,6 @@ 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 9c45da382760..0433f426499e 100644
--- a/src/video/windows/SDL_windowswindow.c
+++ b/src/video/windows/SDL_windowswindow.c
@@ -498,41 +498,12 @@ 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);
 
-    if (undefined_position) {
+    if (window->undefined_x && window->undefined_y &&
+        window->last_displayID == SDL_GetPrimaryDisplay()) {
+        undefined_position = SDL_TRUE;
         x = CW_USEDEFAULT;
         y = CW_USEDEFAULT; /* Not actually used */
     }
diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c
index ca94ae86065d..33a8cc4129b9 100644
--- a/src/video/x11/SDL_x11window.c
+++ b/src/video/x11/SDL_x11window.c
@@ -392,6 +392,7 @@ int X11_CreateWindow(_THIS, SDL_Window *window)
     Atom _NET_WM_PID;
     long fevent = 0;
     const char *hint = NULL;
+    SDL_bool undefined_position = SDL_FALSE;
 
 #if SDL_VIDEO_OPENGL_GLX || SDL_VIDEO_OPENGL_EGL
     const char *forced_visual_id = SDL_GetHint(SDL_HINT_VIDEO_X11_WINDOW_VISUALID);
@@ -527,6 +528,11 @@ int X11_CreateWindow(_THIS, SDL_Window *window)
                                 visual, AllocNone);
     }
 
+    if (window->undefined_x && window->undefined_y &&
+        window->last_displayID == SDL_GetPrimaryDisplay()) {
+        undefined_position = SDL_TRUE;
+    }
+
     /* Always create this with the window->windowed.* fields; if we're
        creating a windowed mode window, that's fine. If we're creating a
        fullscreen window, the window manager will want to know these values
@@ -554,9 +560,11 @@ int X11_CreateWindow(_THIS, SDL_Window *window)
         sizehints->min_height = sizehints->max_height = window->h;
         sizehints->flags |= (PMaxSize | PMinSize);
     }
-    sizehints->x = window->x;
-    sizehints->y = window->y;
-    sizehints->flags |= USPosition;
+    if (!undefined_position) {
+        sizehints->x = window->x;
+        sizehints->y = window->y;
+        sizehints->flags |= USPosition;
+    }
 
     /* Setup the input hints so we get keyboard input */
     wmhints = X11_XAllocWMHints();
@@ -636,6 +644,12 @@ int X11_CreateWindow(_THIS, SDL_Window *window)
     }
     windowdata = window->driverdata;
 
+    if (undefined_position) {
+        /* Record where the window ended up */
+        window->windowed.x = window->x;
+        window->windowed.y = window->y;
+    }
+
 #if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2 || SDL_VIDEO_OPENGL_EGL
     if ((window->flags & SDL_WINDOW_OPENGL) &&
         ((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) ||