cocoadisplay: Fix fullscreen issues on M1 macs

The OpenGL-on-Metal drivers used on these machines don't support CGLSetFullScreenOnDisplay, so we need to disable it on those machines.  This also applies when running a x86_64 app through Rosetta 2, hence the sysctlbyname check.

Furthermore, we need to set the appropriate shielding level, which need not be `NSMainMenuWindowLevel+1`.

Fixes #1316

Co-authored-by: LD <laurent.deru@gmail.com>
This commit is contained in:
rdb 2022-12-06 16:56:02 +01:00
parent 45ac5029c0
commit 619050bb32

View File

@ -43,12 +43,35 @@
#import <OpenGL/OpenGL.h> #import <OpenGL/OpenGL.h>
#import <Carbon/Carbon.h> #import <Carbon/Carbon.h>
#include <sys/sysctl.h>
TypeHandle CocoaGraphicsWindow::_type_handle; TypeHandle CocoaGraphicsWindow::_type_handle;
#ifndef MAC_OS_X_VERSION_10_15 #ifndef MAC_OS_X_VERSION_10_15
#define NSAppKitVersionNumber10_14 1671 #define NSAppKitVersionNumber10_14 1671
#endif #endif
/**
* Returns true if this is an arm64-based mac.
*/
static int is_arm64_mac() {
#ifdef __aarch64__
return 1;
#elif defined(__x86_64__)
// Running in Rosetta 2?
static int ret = -1;
if (ret < 0) {
size_t size = sizeof(ret);
if (sysctlbyname("sysctl.proc_translated", &ret, &size, nullptr, 0) == -1) {
ret = 0;
}
}
return ret;
#else
return 0;
#endif
}
/** /**
* *
*/ */
@ -189,8 +212,17 @@ begin_frame(FrameMode mode, Thread *current_thread) {
// Set the drawable. // Set the drawable.
if (_properties.get_fullscreen()) { if (_properties.get_fullscreen()) {
// Fullscreen. // Fullscreen. Note that this call doesn't work with the newer
CGLSetFullScreenOnDisplay((CGLContextObj) [cocoagsg->_context CGLContextObj], CGDisplayIDToOpenGLDisplayMask(_display)); // Metal-based OpenGL drivers.
if (!is_arm64_mac()) {
CGLError err = CGLSetFullScreenOnDisplay((CGLContextObj) [cocoagsg->_context CGLContextObj], CGDisplayIDToOpenGLDisplayMask(_display));
if (err != kCGLNoError) {
cocoadisplay_cat.error()
<< "Failed call to CGLSetFullScreenOnDisplay with display mask "
<< CGDisplayIDToOpenGLDisplayMask(_display) << ": " << CGLErrorString(err) << "\n";
return false;
}
}
} else { } else {
// Although not recommended, it is technically possible to use the same // Although not recommended, it is technically possible to use the same
// context with multiple different-sized windows. If that happens, the // context with multiple different-sized windows. If that happens, the
@ -626,7 +658,7 @@ open_window() {
} }
if (_properties.get_fullscreen()) { if (_properties.get_fullscreen()) {
[_window setLevel: NSMainMenuWindowLevel + 1]; [_window setLevel: CGShieldingWindowLevel()];
} else { } else {
switch (_properties.get_z_order()) { switch (_properties.get_z_order()) {
case WindowProperties::Z_bottom: case WindowProperties::Z_bottom:
@ -859,7 +891,7 @@ set_properties_now(WindowProperties &properties) {
[_window setStyleMask:NSBorderlessWindowMask]; [_window setStyleMask:NSBorderlessWindowMask];
} }
[_window makeFirstResponder:_view]; [_window makeFirstResponder:_view];
[_window setLevel:NSMainMenuWindowLevel+1]; [_window setLevel:CGShieldingWindowLevel()];
[_window makeKeyAndOrderFront:nil]; [_window makeKeyAndOrderFront:nil];
} }
@ -898,7 +930,7 @@ set_properties_now(WindowProperties &properties) {
[_window setStyleMask:NSBorderlessWindowMask]; [_window setStyleMask:NSBorderlessWindowMask];
} }
[_window makeFirstResponder:_view]; [_window makeFirstResponder:_view];
[_window setLevel:NSMainMenuWindowLevel+1]; [_window setLevel:CGShieldingWindowLevel()];
[_window makeKeyAndOrderFront:nil]; [_window makeKeyAndOrderFront:nil];
} }