macOS: Calculate correct DPI by not using backingScaleFactor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
diff --git a/src/video/cocoa/SDL_cocoamodes.m b/src/video/cocoa/SDL_cocoamodes.m
index dce7169..0daa3b6 100644
--- a/src/video/cocoa/SDL_cocoamodes.m
+++ b/src/video/cocoa/SDL_cocoamodes.m
@@ -454,28 +454,70 @@ Cocoa_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdp
/* we need the backingScaleFactor for Retina displays, which is only exposed through NSScreen, not CGDisplay, afaik, so find our screen... */
CGFloat scaleFactor = 1.0f;
NSArray *screens = [NSScreen screens];
+ NSSize displayNativeSize;
+ displayNativeSize.width = (int) CGDisplayPixelsWide(data->display);
+ displayNativeSize.height = (int) CGDisplayPixelsHigh(data->display);
+
for (NSScreen *screen in screens) {
const CGDirectDisplayID dpyid = (const CGDirectDisplayID ) [[[screen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
if (dpyid == data->display) {
- if ([screen respondsToSelector:@selector(backingScaleFactor)]) { // Mac OS X 10.7 and later
+
+ /* Neither CGDisplayScreenSize(description's NSScreenNumber) nor [NSScreen backingScaleFactor] can calculate the correct dpi in macOS. E.g. backingScaleFactor is always 2 in all display modes for rMBP 16" */
+ if (@available(macOS 10.8, *)) {
+ CFStringRef dmKeys[1] = { kCGDisplayShowDuplicateLowResolutionModes };
+ CFBooleanRef dmValues[1] = { kCFBooleanTrue };
+ CFDictionaryRef dmOptions = CFDictionaryCreate(kCFAllocatorDefault, (const void**) dmKeys, (const void**) dmValues, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
+ CFArrayRef allDisplayModes = CGDisplayCopyAllDisplayModes(dpyid, dmOptions);
+ CFIndex n = CFArrayGetCount(allDisplayModes);
+ for(CFIndex i = 0; i < n; ++i) {
+ CGDisplayModeRef m = (CGDisplayModeRef)CFArrayGetValueAtIndex(allDisplayModes, i);
+ CGFloat width = CGDisplayModeGetPixelWidth(m);
+ CGFloat height = CGDisplayModeGetPixelHeight(m);
+ CGFloat HiDPIWidth = CGDisplayModeGetWidth(m);
+
+ BOOL isNative = (CGDisplayModeGetIOFlags(m) & kDisplayModeNativeFlag) ? true : false;
+ CFRelease(m);
+
+ //Only check 1x mode
+ if(width == HiDPIWidth) {
+ if(isNative) {
+ displayNativeSize.width = width;
+ displayNativeSize.height = height;
+ break;
+ }
+
+ //Get the largest size even if kDisplayModeNativeFlag is not present e.g. iMac 27-Inch with 5K Retina
+ if(width > displayNativeSize.width) {
+ displayNativeSize.width = width;
+ displayNativeSize.height = height;
+ }
+ }
+ }
+ CFRelease(allDisplayModes);
+ CFRelease(dmOptions);
+ } else if (@available(macOS 10.7, *)) {
+ // fallback for 10.7
scaleFactor = [screen backingScaleFactor];
+ displayNativeSize.width = displayNativeSize.width * scaleFactor;
+ displayNativeSize.height = displayNativeSize.height * scaleFactor;
break;
}
+
}
}
const CGSize displaySize = CGDisplayScreenSize(data->display);
- const int pixelWidth = (int) CGDisplayPixelsWide(data->display);
- const int pixelHeight = (int) CGDisplayPixelsHigh(data->display);
+ const int pixelWidth = displayNativeSize.width;
+ const int pixelHeight = displayNativeSize.height;
if (ddpi) {
- *ddpi = (SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH)) * scaleFactor;
+ *ddpi = (SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH));
}
if (hdpi) {
- *hdpi = (pixelWidth * MM_IN_INCH / displaySize.width) * scaleFactor;
+ *hdpi = (pixelWidth * MM_IN_INCH / displaySize.width);
}
if (vdpi) {
- *vdpi = (pixelHeight * MM_IN_INCH / displaySize.height) * scaleFactor;
+ *vdpi = (pixelHeight * MM_IN_INCH / displaySize.height);
}
return 0;