SDL: Added support for undefined or centered position for shaped windows

From 680d0f043a8a3defec3ad7a2c8f64e0c6d6c636c Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 10 Oct 2022 09:26:49 -0700
Subject: [PATCH] Added support for undefined or centered position for shaped
 windows

Fixes https://github.com/libsdl-org/SDL/issues/6359
---
 src/video/SDL_shape.c | 46 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 40 insertions(+), 6 deletions(-)

diff --git a/src/video/SDL_shape.c b/src/video/SDL_shape.c
index 919ae959866e..c099ae1792f0 100644
--- a/src/video/SDL_shape.c
+++ b/src/video/SDL_shape.c
@@ -257,20 +257,54 @@ SDL_FreeShapeTree(SDL_ShapeTree** shape_tree)
 int
 SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode)
 {
+    SDL_VideoDevice *_this = SDL_GetVideoDevice();
     int result;
-    if(window == NULL || !SDL_IsShapedWindow(window))
+
+    if (window == NULL || !SDL_IsShapedWindow(window)) {
         /* The window given was not a shapeable window. */
         return SDL_NONSHAPEABLE_WINDOW;
-    if(shape == NULL)
+    }
+    if (shape == NULL) {
         /* Invalid shape argument. */
         return SDL_INVALID_SHAPE_ARGUMENT;
+    }
 
-    if(shape_mode != NULL)
+    if (shape_mode != NULL) {
         window->shaper->mode = *shape_mode;
-    result = SDL_GetVideoDevice()->shape_driver.SetWindowShape(window->shaper,shape,shape_mode);
+    }
+    result = _this->shape_driver.SetWindowShape(window->shaper, shape, shape_mode);
     window->shaper->hasshape = SDL_TRUE;
-    if(window->shaper->userx != 0 && window->shaper->usery != 0) {
-        SDL_SetWindowPosition(window,window->shaper->userx,window->shaper->usery);
+    if (window->shaper->userx != 0 && window->shaper->usery != 0) {
+        int x = window->shaper->userx;
+        int y = window->shaper->usery;
+
+        if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISUNDEFINED(y) ||
+            SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
+            int displayIndex;
+            SDL_Rect bounds;
+
+            if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISCENTERED(x)) {
+                displayIndex = (x & 0xFFFF);
+                if (displayIndex >= _this->num_displays) {
+                    displayIndex = 0;
+                }
+            } else if (SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(y)) {
+                displayIndex = (y & 0xFFFF);
+                if (displayIndex >= _this->num_displays) {
+                    displayIndex = 0;
+                }
+                return displayIndex;
+            }
+
+            SDL_GetDisplayBounds(displayIndex, &bounds);
+            if (SDL_WINDOWPOS_ISUNDEFINED(x) || SDL_WINDOWPOS_ISCENTERED(x)) {
+                window->x = bounds.x + (bounds.w - window->w) / 2;
+            }
+            if (SDL_WINDOWPOS_ISUNDEFINED(y) || SDL_WINDOWPOS_ISCENTERED(y)) {
+                window->y = bounds.y + (bounds.h - window->h) / 2;
+            }
+        }
+        SDL_SetWindowPosition(window, x, y);
         window->shaper->userx = 0;
         window->shaper->usery = 0;
     }