diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm index 5f7dfde474..a14f099d3e 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm @@ -45,6 +45,10 @@ TypeHandle CocoaGraphicsWindow::_type_handle; +#ifndef MAC_OS_X_VERSION_10_15 +#define NSAppKitVersionNumber10_14 1671 +#endif + /** * */ @@ -1107,7 +1111,28 @@ set_properties_now(WindowProperties &properties) { #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 CGDisplayModeRef CocoaGraphicsWindow:: find_display_mode(int width, int height) { - CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, NULL); + CFDictionaryRef options = NULL; + // On macOS 10.15+ (Catalina), we want to select the display mode with the + // samescaling factor as the current view to avoid cropping or scaling issues. + // This is a workaround until HiDPI display or scaling factor is properly + // handled. CGDisplayCopyAllDisplayModes() does not return upscaled display + // mode unless explicitly asked with kCGDisplayShowDuplicateLowResolutionModes + // (which is undocumented...). +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 + if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_14) { + const CFStringRef dictkeys[] = {kCGDisplayShowDuplicateLowResolutionModes}; + const CFBooleanRef dictvalues[] = {kCFBooleanTrue}; + options = CFDictionaryCreate(NULL, + (const void **)dictkeys, + (const void **)dictvalues, + 1, + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } +#endif + CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, options); + CFRelease(options); + size_t num_modes = CFArrayGetCount(modes); CGDisplayModeRef mode; @@ -1116,14 +1141,22 @@ find_display_mode(int width, int height) { int refresh_rate; mode = CGDisplayCopyDisplayMode(_display); +#if __MAC_OS_X_VERSION_MAX_ALLOWED < 1080 // First check if the current mode is adequate. if (CGDisplayModeGetWidth(mode) == width && CGDisplayModeGetHeight(mode) == height) { return mode; } +#endif current_pixel_encoding = CGDisplayModeCopyPixelEncoding(mode); refresh_rate = CGDisplayModeGetRefreshRate(mode); +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 + // Calculate the pixel width and height of the fullscreen mode we want using + // the currentdisplay mode dimensions and pixel dimensions. + size_t expected_pixel_width = (size_t(width) * CGDisplayModeGetPixelWidth(mode)) / CGDisplayModeGetWidth(mode); + size_t expected_pixel_height = (size_t(height) * CGDisplayModeGetPixelHeight(mode)) / CGDisplayModeGetHeight(mode); +#endif CGDisplayModeRelease(mode); for (size_t i = 0; i < num_modes; ++i) { @@ -1131,9 +1164,17 @@ find_display_mode(int width, int height) { CFStringRef pixel_encoding = CGDisplayModeCopyPixelEncoding(mode); + // As explained above, we want to select the fullscreen display mode using + // the same scaling factor, but only for MacOS 10.15+ To do this we check + // the mode width and heightbut also actual pixel widh and height. if (CGDisplayModeGetWidth(mode) == width && CGDisplayModeGetHeight(mode) == height && CGDisplayModeGetRefreshRate(mode) == refresh_rate && +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 + (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_14 || + (CGDisplayModeGetPixelWidth(mode) == expected_pixel_width && + CGDisplayModeGetPixelHeight(mode) == expected_pixel_height)) && +#endif CFStringCompare(pixel_encoding, current_pixel_encoding, 0) == kCFCompareEqualTo) { CFRetain(mode);