cocoadisplay: use same scaling factor as the current view when switching to fullscreen on MacOS 10.15+

Fixes #794
This commit is contained in:
LD 2019-12-14 18:07:28 +01:00 committed by rdb
parent fccffb4932
commit 45461e667a

View File

@ -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);