Use the physical desktop size in pixels rather than the native resolution on macOS

It seems like some Macs (5K iMacs at least) don't have kDisplayModeNativeFlag set
This commit is contained in:
Cameron Gutman
2020-05-09 16:34:48 -07:00
parent dc3c565ec0
commit 8fe3474589
+36 -17
View File
@@ -83,35 +83,54 @@ bool StreamUtils::getRealDesktopMode(int displayIndex, SDL_DisplayMode* mode)
return false; return false;
} }
SDL_zerop(mode); // Grab the (possibly scaled) desktop resolution
if (SDL_GetDesktopDisplayMode(displayIndex, mode) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_GetDesktopDisplayMode() failed: %s",
SDL_GetError());
return false;
}
// This is required to ensure we get the high DPI display modes
const CFStringRef dictKeys[] = {kCGDisplayShowDuplicateLowResolutionModes};
const CFBooleanRef dictValues[] = {kCFBooleanTrue};
CFDictionaryRef dict = CFDictionaryCreate(NULL,
(const void**)dictKeys,
(const void**)dictValues,
SDL_arraysize(dictValues),
&kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
// Retina displays have non-native resolutions both below and above (!) their // Retina displays have non-native resolutions both below and above (!) their
// native resolution, so it's impossible for us to figure out what's actually // native resolution, so it's impossible for us to figure out what's actually
// native on macOS using the SDL API alone. We'll talk to CoreGraphics to // native on macOS using the SDL API alone. We'll talk to CoreGraphics to
// find the correct resolution and match it in our SDL list. // find the correct resolution and match it in our SDL list.
CFArrayRef modeList = CGDisplayCopyAllDisplayModes(displayIds[displayIndex], nullptr); CFArrayRef modeList = CGDisplayCopyAllDisplayModes(displayIds[displayIndex], dict);
CFRelease(dict);
// Get the physical size of the matching logical resolution
CFIndex count = CFArrayGetCount(modeList); CFIndex count = CFArrayGetCount(modeList);
for (CFIndex i = 0; i < count; i++) { for (CFIndex i = 0; i < count; i++) {
auto cgMode = (CGDisplayModeRef)(CFArrayGetValueAtIndex(modeList, i)); auto cgMode = (CGDisplayModeRef)(CFArrayGetValueAtIndex(modeList, i));
if ((CGDisplayModeGetIOFlags(cgMode) & kDisplayModeNativeFlag) != 0) {
mode->w = static_cast<int>(CGDisplayModeGetWidth(cgMode));
mode->h = static_cast<int>(CGDisplayModeGetHeight(cgMode));
break;
}
}
CFRelease(modeList);
// Now find the SDL mode that matches the CG native mode auto modeWidth = static_cast<int>(CGDisplayModeGetWidth(cgMode));
for (int i = 0; i < SDL_GetNumDisplayModes(displayIndex); i++) { auto modeHeight = static_cast<int>(CGDisplayModeGetHeight(cgMode));
SDL_DisplayMode thisMode; if (mode->w == modeWidth && mode->h == modeHeight) {
if (SDL_GetDisplayMode(displayIndex, i, &thisMode) == 0) { SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
if (thisMode.w == mode->w && thisMode.h == mode->h && "Matching desktop resolution is: %zux%zu (scaled size: %zux%zu) (flags: %x)",
thisMode.refresh_rate >= mode->refresh_rate) { CGDisplayModeGetPixelWidth(cgMode),
*mode = thisMode; CGDisplayModeGetPixelHeight(cgMode),
CGDisplayModeGetWidth(cgMode),
CGDisplayModeGetHeight(cgMode),
CGDisplayModeGetIOFlags(cgMode));
mode->w = static_cast<int>(CGDisplayModeGetPixelWidth(cgMode));
mode->h = static_cast<int>(CGDisplayModeGetPixelHeight(cgMode));
break; break;
} }
} }
}
CFRelease(modeList);
#else #else
if (SDL_GetDesktopDisplayMode(displayIndex, mode) != 0) { if (SDL_GetDesktopDisplayMode(displayIndex, mode) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,