SDL: Introduces Cocoa_GetWindowDisplayIndex. This enable a proper management for dpi when switching between retina and non-retina...

From 76afb8583b39305cf73191664c0015a8ee2400d4 Mon Sep 17 00:00:00 2001
From: Mirko Galimberti <[EMAIL REDACTED]>
Date: Mon, 25 Apr 2022 10:35:56 +0200
Subject: [PATCH] Introduces Cocoa_GetWindowDisplayIndex. This enable a proper
 management for dpi when switching between retina and non-retina displays.

---
 src/video/SDL_sysvideo.h          |  1 +
 src/video/SDL_video.c             | 95 ++++++++++++++++---------------
 src/video/cocoa/SDL_cocoavideo.m  |  1 +
 src/video/cocoa/SDL_cocoawindow.h |  1 +
 src/video/cocoa/SDL_cocoawindow.m | 30 ++++++++++
 5 files changed, 82 insertions(+), 46 deletions(-)

diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index 2384a64acc4..b68b92c3786 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -237,6 +237,7 @@ struct SDL_VideoDevice
     int (*SetWindowGammaRamp) (_THIS, SDL_Window * window, const Uint16 * ramp);
     int (*GetWindowGammaRamp) (_THIS, SDL_Window * window, Uint16 * ramp);
     void* (*GetWindowICCProfile) (_THIS, SDL_Window * window, size_t* size);
+    int (*GetWindowDisplayIndex)(_THIS, SDL_Window * window);
     void (*SetWindowMouseRect)(_THIS, SDL_Window * window);
     void (*SetWindowMouseGrab) (_THIS, SDL_Window * window, SDL_bool grabbed);
     void (*SetWindowKeyboardGrab) (_THIS, SDL_Window * window, SDL_bool grabbed);
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 93c803e70e3..2b896c44ba2 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -1060,61 +1060,64 @@ SDL_GetDisplay(int displayIndex)
 int
 SDL_GetWindowDisplayIndex(SDL_Window * window)
 {
-    int displayIndex;
-    int i, dist;
-    int closest = -1;
-    int closest_dist = 0x7FFFFFFF;
-    SDL_Point center;
-    SDL_Point delta;
-    SDL_Rect rect;
-
     CHECK_WINDOW_MAGIC(window, -1);
-
-    if (SDL_WINDOWPOS_ISUNDEFINED(window->x) ||
-        SDL_WINDOWPOS_ISCENTERED(window->x)) {
-        displayIndex = (window->x & 0xFFFF);
-        if (displayIndex >= _this->num_displays) {
-            displayIndex = 0;
+    if (_this->GetWindowDisplayIndex) {
+        return _this->GetWindowDisplayIndex(_this, window);
+    } else {
+        int displayIndex;
+        int i, dist;
+        int closest = -1;
+        int closest_dist = 0x7FFFFFFF;
+        SDL_Point center;
+        SDL_Point delta;
+        SDL_Rect rect;
+
+        if (SDL_WINDOWPOS_ISUNDEFINED(window->x) ||
+            SDL_WINDOWPOS_ISCENTERED(window->x)) {
+            displayIndex = (window->x & 0xFFFF);
+            if (displayIndex >= _this->num_displays) {
+                displayIndex = 0;
+            }
+            return displayIndex;
         }
-        return displayIndex;
-    }
-    if (SDL_WINDOWPOS_ISUNDEFINED(window->y) ||
-        SDL_WINDOWPOS_ISCENTERED(window->y)) {
-        displayIndex = (window->y & 0xFFFF);
-        if (displayIndex >= _this->num_displays) {
-            displayIndex = 0;
+        if (SDL_WINDOWPOS_ISUNDEFINED(window->y) ||
+            SDL_WINDOWPOS_ISCENTERED(window->y)) {
+            displayIndex = (window->y & 0xFFFF);
+            if (displayIndex >= _this->num_displays) {
+                displayIndex = 0;
+            }
+            return displayIndex;
         }
-        return displayIndex;
-    }
 
-    /* Find the display containing the window */
-    for (i = 0; i < _this->num_displays; ++i) {
-        SDL_VideoDisplay *display = &_this->displays[i];
+        /* Find the display containing the window */
+        for (i = 0; i < _this->num_displays; ++i) {
+            SDL_VideoDisplay *display = &_this->displays[i];
 
-        if (display->fullscreen_window == window) {
-            return i;
-        }
-    }
-    center.x = window->x + window->w / 2;
-    center.y = window->y + window->h / 2;
-    for (i = 0; i < _this->num_displays; ++i) {
-        SDL_GetDisplayBounds(i, &rect);
-        if (SDL_EnclosePoints(&center, 1, &rect, NULL)) {
-            return i;
+            if (display->fullscreen_window == window) {
+                return i;
+            }
         }
+        center.x = window->x + window->w / 2;
+        center.y = window->y + window->h / 2;
+        for (i = 0; i < _this->num_displays; ++i) {
+            SDL_GetDisplayBounds(i, &rect);
+            if (SDL_EnclosePoints(&center, 1, &rect, NULL)) {
+                return i;
+            }
 
-        delta.x = center.x - (rect.x + rect.w / 2);
-        delta.y = center.y - (rect.y + rect.h / 2);
-        dist = (delta.x*delta.x + delta.y*delta.y);
-        if (dist < closest_dist) {
-            closest = i;
-            closest_dist = dist;
+            delta.x = center.x - (rect.x + rect.w / 2);
+            delta.y = center.y - (rect.y + rect.h / 2);
+            dist = (delta.x*delta.x + delta.y*delta.y);
+            if (dist < closest_dist) {
+                closest = i;
+                closest_dist = dist;
+            }
         }
+        if (closest < 0) {
+            SDL_SetError("Couldn't find any displays");
+        }
+        return closest;
     }
-    if (closest < 0) {
-        SDL_SetError("Couldn't find any displays");
-    }
-    return closest;
 }
 
 SDL_VideoDisplay *
diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m
index 231b2de5c3f..74d85382936 100644
--- a/src/video/cocoa/SDL_cocoavideo.m
+++ b/src/video/cocoa/SDL_cocoavideo.m
@@ -103,6 +103,7 @@
     device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp;
     device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp;
     device->GetWindowICCProfile = Cocoa_GetWindowICCProfile;
+    device->GetWindowDisplayIndex = Cocoa_GetWindowDisplayIndex;
     device->SetWindowMouseRect = Cocoa_SetWindowMouseRect;
     device->SetWindowMouseGrab = Cocoa_SetWindowMouseGrab;
     device->SetWindowKeyboardGrab = Cocoa_SetWindowKeyboardGrab;
diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h
index a42d9c87b3e..f8363f327cf 100644
--- a/src/video/cocoa/SDL_cocoawindow.h
+++ b/src/video/cocoa/SDL_cocoawindow.h
@@ -153,6 +153,7 @@ extern void Cocoa_SetWindowAlwaysOnTop(_THIS, SDL_Window * window, SDL_bool on_t
 extern void Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
 extern int Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
 extern void* Cocoa_GetWindowICCProfile(_THIS, SDL_Window * window, size_t * size);
+extern int Cocoa_GetWindowDisplayIndex(_THIS, SDL_Window * window);
 extern int Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
 extern void Cocoa_SetWindowMouseRect(_THIS, SDL_Window * window);
 extern void Cocoa_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index bca8eb4dd23..ea520e4b877 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -2197,6 +2197,36 @@ - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
     return retIccProfileData;
 }
 
+int Cocoa_GetWindowDisplayIndex(_THIS, SDL_Window * window){
+    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+    /* Not recognized via CHECK_WINDOW_MAGIC */
+    if (data == NULL){
+        return 0;
+    }
+
+    /*
+     Considering that we already have the display coordinates in which the window is placed (described via displayframe)
+     instead of checking in which display the window is placed, we should check which SDL display matches the display described
+     via displayframe.
+    */
+    CGRect displayframe = data->nswindow.screen.frame;
+    SDL_Point display_center;
+    SDL_Rect sdl_display_rect;
+    
+    display_center.x = displayframe.origin.x + displayframe.size.width / 2;
+    display_center.y = displayframe.origin.y + displayframe.size.height / 2;
+    
+    for (int i = 0; i < SDL_GetNumVideoDisplays(); i++){
+        SDL_GetDisplayBounds(i, &sdl_display_rect);
+        if (SDL_EnclosePoints(&display_center, 1, &sdl_display_rect, NULL)) {
+            return i;
+        }
+    }
+    SDL_SetError("Couldn't find the display where the window is attached to.");
+    return -1;
+}
+
 int
 Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
 {