From 6bcde52d8880565b907f3e80c317517514010c4a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 24 Jul 2022 20:19:16 +0900 Subject: [PATCH] Further adjust implementation of `Cocoa_GetWindowDisplayIndex` As discussed in PR review, there may be an off-chance that the index returned doesn't match up with SDL's display indexing. This change ensures that the indices match and adds a safety check for off-screen windows. --- src/video/SDL_video.c | 13 +++++++++++-- src/video/cocoa/SDL_cocoawindow.m | 30 +++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 1e520b24b..144326f54 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1071,11 +1071,20 @@ SDL_GetDisplay(int displayIndex) int SDL_GetWindowDisplayIndex(SDL_Window * window) { + int displayIndex = -1; + CHECK_WINDOW_MAGIC(window, -1); if (_this->GetWindowDisplayIndex) { - return _this->GetWindowDisplayIndex(_this, window); + displayIndex = _this->GetWindowDisplayIndex(_this, window); + } + + /* A backend implementation may fail to get a display index for the window + * (for example if the window is off-screen), but other code may expect it + * to succeed in that situation, so we fall back to a generic position- + * based implementation in that case. */ + if (displayIndex >= 0) { + return displayIndex; } else { - int displayIndex; int i, dist; int closest = -1; int closest_dist = 0x7FFFFFFF; diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 3f5c04631..157353cf0 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -2230,25 +2230,37 @@ int Cocoa_GetWindowDisplayIndex(_THIS, SDL_Window * window) { @autoreleasepool { + NSScreen *screen; SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata; /* Not recognized via CHECK_WINDOW_MAGIC */ - if (data == NULL){ + if (data == nil) { return 0; } - NSArray *screens = [NSScreen screens]; + /* NSWindow.screen may be nil when the window is off-screen. */ + screen = data.nswindow.screen; - int index = 0; - for (NSScreen *screen in screens) { - if (screen == data.nswindow.screen) - return index; + if (screen != nil) { + CGDirectDisplayID displayid; + int i; - index++; + /* https://developer.apple.com/documentation/appkit/nsscreen/1388360-devicedescription?language=objc */ + displayid = [[screen.deviceDescription objectForKey:@"NSScreenNumber"] unsignedIntValue]; + + for (i = 0; i < _this->num_displays; i++) { + SDL_DisplayData *displaydata = (SDL_DisplayData *)_this->displays[i].driverdata; + if (displaydata != NULL && displaydata->display == displayid) { + return i; + } + } } - SDL_SetError("Couldn't find the display where the window is attached."); - return -1; + /* Other code may expect SDL_GetWindowDisplayIndex to always return a valid + * index for a window. The higher level GetWindowDisplayIndex code will fall + * back to a generic position-based query if the backend implementation + * fails. */ + return SDL_SetError("Couldn't find the display where the window is located."); }} int