From 62fb5a398a28929b8c26e7750a018eaf93257848 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Tue, 14 Jul 2026 10:41:34 +0000 Subject: [PATCH 1/5] Cocoa/NSGL: Port backend to build on Mac OS X 10.6 with GCC, GL 2.0 only GCC (as shipped for 10.6) lacks clang-only Objective-C features used throughout the Cocoa backend, and the 10.6 SDK is missing several APIs introduced in later releases: - Replace all @autoreleasepool {} blocks with explicit NSAutoreleasePool alloc/init/release, since @autoreleasepool is clang-only sugar. - Replace modern literals (@[], @{}, @(), dictionary/array subscripting) with classic NSArray/NSDictionary/NSString factory-method calls. - Replace the block-based (^{}) local key-up event monitor, which requires a blocks-capable compiler, with a GLFWApplication subclass overriding -sendEvent: to forward Cmd+KeyUp to the key window. - Guard 10.7+/10.8+-only APIs (convertRectToBacking:, backingScaleFactor, scrollingDeltaX/Y, hasPreciseScrollingDeltas, setWantsBestResolutionOpenGLSurface:, kCGLPFASupportsAutomaticGraphicsSwitching, NSWindowCollectionBehaviorFullScreenPrimary/ Managed) behind MAC_OS_X_VERSION_MAX_ALLOWED checks with 10.6-appropriate fallbacks (no HiDPI, plain scroll deltas, default collection behavior). - Remove the NSOpenGLPFAOpenGLProfile/core-profile pixel format code path, since profile selection does not exist on the 10.6 SDK, and hard-reject any requested OpenGL version above 2.1 in NSGL context creation. Only src/cocoa_*, src/nsgl_context.m, and src/context.c were in scope; context.c required no changes as it is platform-generic. Rebased onto 3.5.1, where upstream commit 8b574030 (Cocoa: Remove support for OS X 10.10 Yosemite) dropped several guards this port relies on; they are restored here as part of the port: - Guard the now-unconditional CAMetalLayer #import and the direct [CAMetalLayer layer] Vulkan surface creation (10.11+ SDK only), returning VK_ERROR_EXTENSION_NOT_PRESENT on older SDKs. - Re-guard -windowDidChangeOcclusionState:, since NSWindowOcclusionStateVisible is missing from pre-10.9 SDKs. - Keep upstream's new window->title source for -setTitle: but use -stringWithUTF8String: instead of the clang-only @() boxed literal. - Drop the NSOpenGLPFAOpenGLProfile selection upstream unguarded, as before; NSGL still hard-rejects any context version above 2.1. --- src/cocoa_init.m | 73 ++++++---- src/cocoa_monitor.m | 41 +++--- src/cocoa_platform.h | 10 +- src/cocoa_window.m | 325 +++++++++++++++++++++++++++---------------- src/nsgl_context.m | 77 +++++----- 5 files changed, 322 insertions(+), 204 deletions(-) diff --git a/src/cocoa_init.m b/src/cocoa_init.m index 95d6289e..d5784e42 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -89,7 +89,7 @@ static void createMenuBar(void) for (size_t i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++) { - id name = bundleInfo[nameKeys[i]]; + id name = [bundleInfo objectForKey:nameKeys[i]]; if (name && [name isKindOfClass:[NSString class]] && ![name isEqualToString:@""]) @@ -103,7 +103,7 @@ static void createMenuBar(void) { char** progname = _NSGetProgname(); if (progname && *progname) - appName = @(*progname); + appName = [NSString stringWithUTF8String:*progname]; else appName = @"GLFW Application"; } @@ -394,6 +394,34 @@ static GLFWbool initializeTIS(void) @end // GLFWHelper +// GLFW application class +// +// NOTE: This exists (instead of using -[NSEvent addLocalMonitorForEventsMatchingMask:handler:]) +// so that forwarding Cmd+KeyUp events to the key window does not require +// an Objective-C block, which is unavailable without a blocks-capable +// compiler such as clang +// +@interface GLFWApplication : NSApplication +@end + +@implementation GLFWApplication + +- (void)sendEvent:(NSEvent *)event +{ + // NOTE: This replaces the block-based local event monitor used upstream, + // which always forwarded Cmd+KeyUp to the key window and then let + // the event continue through the normal dispatch path below + if ([event type] == NSEventTypeKeyUp && + ([event modifierFlags] & NSEventModifierFlagCommand)) + { + [[self keyWindow] sendEvent:event]; + } + + [super sendEvent:event]; +} + +@end // GLFWApplication + @interface GLFWApplicationDelegate : NSObject @end @@ -538,7 +566,7 @@ GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform) int _glfwInitCocoa(void) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; _glfw.ns.helper = [[GLFWHelper alloc] init]; @@ -546,35 +574,30 @@ int _glfwInitCocoa(void) toTarget:_glfw.ns.helper withObject:nil]; - [NSApplication sharedApplication]; + // NOTE: -[GLFWApplication sendEvent:] handles forwarding Cmd+KeyUp events + // to the key window, replacing the block-based local event monitor + // used upstream, so that this does not require a blocks-capable + // compiler + [GLFWApplication sharedApplication]; _glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init]; if (_glfw.ns.delegate == nil) { _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create application delegate"); + [pool release]; return GLFW_FALSE; } [NSApp setDelegate:_glfw.ns.delegate]; - NSEvent* (^block)(NSEvent*) = ^ NSEvent* (NSEvent* event) - { - if ([event modifierFlags] & NSEventModifierFlagCommand) - [[NSApp keyWindow] sendEvent:event]; - - return event; - }; - - _glfw.ns.keyUpMonitor = - [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp - handler:block]; - if (_glfw.hints.init.ns.chdir) changeToResourcesDirectory(); // Press and Hold prevents some keys from emitting repeated characters - NSDictionary* defaults = @{@"ApplePressAndHoldEnabled":@NO}; + NSDictionary* defaults = + [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] + forKey:@"ApplePressAndHoldEnabled"]; [[NSUserDefaults standardUserDefaults] registerDefaults:defaults]; [[NSNotificationCenter defaultCenter] @@ -587,12 +610,18 @@ int _glfwInitCocoa(void) _glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); if (!_glfw.ns.eventSource) + { + [pool release]; return GLFW_FALSE; + } CGEventSourceSetLocalEventsSuppressionInterval(_glfw.ns.eventSource, 0.0); if (!initializeTIS()) + { + [pool release]; return GLFW_FALSE; + } _glfwPollMonitorsCocoa(); @@ -603,14 +632,13 @@ int _glfwInitCocoa(void) if (_glfw.hints.init.ns.menubar) [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + [pool release]; return GLFW_TRUE; - - } // autoreleasepool } void _glfwTerminateCocoa(void) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (_glfw.ns.inputSource) { @@ -644,9 +672,6 @@ void _glfwTerminateCocoa(void) _glfw.ns.helper = nil; } - if (_glfw.ns.keyUpMonitor) - [NSEvent removeMonitor:_glfw.ns.keyUpMonitor]; - _glfw_free(_glfw.ns.clipboardString); _glfwTerminateNSGL(); @@ -655,7 +680,7 @@ void _glfwTerminateCocoa(void) memset(&_glfw.ns, 0, sizeof(_glfw.ns)); - } // autoreleasepool + [pool release]; } #endif // _GLFW_COCOA diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 620a8cfb..e53f291f 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -324,7 +324,8 @@ void _glfwPollMonitorsCocoa(void) for (screen in [NSScreen screens]) { - NSNumber* screenNumber = [screen deviceDescription][@"NSScreenNumber"]; + NSNumber* screenNumber = + [[screen deviceDescription] objectForKey:@"NSScreenNumber"]; // HACK: Compare unit numbers instead of display IDs to work around // display replacement on machines with automatic graphics @@ -450,7 +451,7 @@ void _glfwFreeMonitorCocoa(_GLFWmonitor* monitor) void _glfwGetMonitorPosCocoa(_GLFWmonitor* monitor, int* xpos, int* ypos) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; const CGRect bounds = CGDisplayBounds(monitor->ns.displayID); @@ -459,13 +460,13 @@ void _glfwGetMonitorPosCocoa(_GLFWmonitor* monitor, int* xpos, int* ypos) if (ypos) *ypos = (int) bounds.origin.y; - } // autoreleasepool + [pool release]; } void _glfwGetMonitorContentScaleCocoa(_GLFWmonitor* monitor, float* xscale, float* yscale) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (!monitor->ns.screen) { @@ -474,21 +475,27 @@ void _glfwGetMonitorContentScaleCocoa(_GLFWmonitor* monitor, } const NSRect points = [monitor->ns.screen frame]; + // NOTE: Mac OS X 10.6 has no backing-store scale concept; see the note in + // cocoa_window.m +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 const NSRect pixels = [monitor->ns.screen convertRectToBacking:points]; +#else + const NSRect pixels = points; +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ if (xscale) *xscale = (float) (pixels.size.width / points.size.width); if (yscale) *yscale = (float) (pixels.size.height / points.size.height); - } // autoreleasepool + [pool release]; } void _glfwGetMonitorWorkareaCocoa(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (!monitor->ns.screen) { @@ -507,12 +514,12 @@ void _glfwGetMonitorWorkareaCocoa(_GLFWmonitor* monitor, if (height) *height = frameRect.size.height; - } // autoreleasepool + [pool release]; } GLFWvidmode* _glfwGetVideoModesCocoa(_GLFWmonitor* monitor, int* count) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; *count = 0; @@ -545,32 +552,31 @@ GLFWvidmode* _glfwGetVideoModesCocoa(_GLFWmonitor* monitor, int* count) } CFRelease(modes); + [pool release]; return result; - - } // autoreleasepool } GLFWbool _glfwGetVideoModeCocoa(_GLFWmonitor* monitor, GLFWvidmode *mode) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; CGDisplayModeRef native = CGDisplayCopyDisplayMode(monitor->ns.displayID); if (!native) { _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to query display mode"); + [pool release]; return GLFW_FALSE; } *mode = vidmodeFromCGDisplayMode(native, monitor->ns.fallbackRefreshRate); CGDisplayModeRelease(native); + [pool release]; return GLFW_TRUE; - - } // autoreleasepool } GLFWbool _glfwGetGammaRampCocoa(_GLFWmonitor* monitor, GLFWgammaramp* ramp) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; uint32_t size = CGDisplayGammaTableCapacity(monitor->ns.displayID); CGGammaValue* values = _glfw_calloc(size * 3, sizeof(CGGammaValue)); @@ -592,14 +598,13 @@ GLFWbool _glfwGetGammaRampCocoa(_GLFWmonitor* monitor, GLFWgammaramp* ramp) } _glfw_free(values); + [pool release]; return GLFW_TRUE; - - } // autoreleasepool } void _glfwSetGammaRampCocoa(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; CGGammaValue* values = _glfw_calloc(ramp->size * 3, sizeof(CGGammaValue)); @@ -618,7 +623,7 @@ void _glfwSetGammaRampCocoa(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) _glfw_free(values); - } // autoreleasepool + [pool release]; } diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 175372d6..41421839 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -62,6 +62,7 @@ typedef void* id; #define NSEventModifierFlagOption NSAlternateKeyMask #define NSEventModifierFlagShift NSShiftKeyMask #define NSEventTypeApplicationDefined NSApplicationDefined + #define NSEventTypeKeyUp NSKeyUp #define NSWindowStyleMaskBorderless NSBorderlessWindowMask #define NSWindowStyleMaskClosable NSClosableWindowMask #define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask @@ -69,6 +70,14 @@ typedef void* id; #define NSWindowStyleMaskTitled NSTitledWindowMask #endif +// NOTE: The Lion full-screen window collection behaviors have no pre-10.7 +// equivalent names, so on such SDKs they are mapped to the default, +// pre-Lion-full-screen-aware behavior instead of being renamed +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 + #define NSWindowCollectionBehaviorFullScreenPrimary NSWindowCollectionBehaviorDefault + #define NSWindowCollectionBehaviorManaged NSWindowCollectionBehaviorDefault +#endif + // NOTE: Many Cocoa dynamically linked constants have been renamed and we need // to build across SDK versions where one is unavailable or deprecated. // We use the newer names in code and replace them with the older names if @@ -169,7 +178,6 @@ typedef struct _GLFWlibraryNS IOHIDManagerRef hidManager; id unicodeData; id helper; - id keyUpMonitor; id nibObjects; char keynames[GLFW_KEY_LAST + 1][17]; diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 61049808..545ff073 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -28,7 +28,11 @@ #if defined(_GLFW_COCOA) -#import +// NOTE: CAMetalLayer was added in the 10.11 SDK and does not exist on +// Mac OS X 10.6 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 + #import +#endif #include #include @@ -245,7 +249,14 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; } const NSRect contentRect = [window->ns.view frame]; + // NOTE: -convertRectToBacking: was added in the 10.7 SDK; Mac OS X 10.6 has + // no backing-store scale concept, so the framebuffer is always the + // same size as the content rect in points +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect]; +#else + const NSRect fbRect = contentRect; +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ if (fbRect.size.width != window->ns.fbWidth || fbRect.size.height != window->ns.fbHeight) @@ -312,6 +323,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)windowDidChangeOcclusionState:(NSNotification* )notification { + // NOTE: NSWindowOcclusionStateVisible was added in the 10.9 SDK +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 if ([window->ns.object respondsToSelector:@selector(occlusionState)]) { if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible) @@ -319,6 +332,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; else window->ns.occluded = GLFW_TRUE; } +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ } @end @@ -351,7 +365,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; markedText = [[NSMutableAttributedString alloc] init]; [self updateTrackingAreas]; - [self registerForDraggedTypes:@[NSPasteboardTypeURL]]; + [self registerForDraggedTypes:[NSArray arrayWithObject:NSPasteboardTypeURL]]; } return self; @@ -505,6 +519,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; _glfwInputCursorEnter(window, GLFW_TRUE); } +// NOTE: -viewDidChangeBackingProperties is only ever invoked by AppKit on +// Mac OS X 10.7.4 and above, and relies on -convertRectToBacking: and +// -backingScaleFactor, neither of which exist on the 10.6 SDK, so this +// method is compiled out entirely for that target +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - (void)viewDidChangeBackingProperties { const NSRect contentRect = [window->ns.view frame]; @@ -530,6 +549,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height); } } +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ - (void)drawRect:(NSRect)rect { @@ -567,7 +587,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods); - [self interpretKeyEvents:@[event]]; + [self interpretKeyEvents:[NSArray arrayWithObject:event]]; } - (void)flagsChanged:(NSEvent *)event @@ -629,6 +649,10 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)scrollWheel:(NSEvent *)event { + // NOTE: -scrollingDeltaX/Y and -hasPreciseScrollingDeltas are 10.7+ + // trackpad APIs that do not exist on the 10.6 SDK, which only + // provides the plain -deltaX/-deltaY pair used below +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 double deltaX = [event scrollingDeltaX]; double deltaY = [event scrollingDeltaY]; @@ -637,6 +661,10 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; deltaX *= 0.1; deltaY *= 0.1; } +#else + double deltaX = [event deltaX]; + double deltaY = [event deltaY]; +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ if (fabs(deltaX) > 0.0 || fabs(deltaY) > 0.0) _glfwInputScroll(window, deltaX, deltaY); @@ -657,8 +685,10 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; _glfwInputCursorPos(window, pos.x, contentRect.size.height - pos.y); NSPasteboard* pasteboard = [sender draggingPasteboard]; - NSDictionary* options = @{NSPasteboardURLReadingFileURLsOnlyKey:@YES}; - NSArray* urls = [pasteboard readObjectsForClasses:@[[NSURL class]] + NSDictionary* options = + [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] + forKey:NSPasteboardURLReadingFileURLsOnlyKey]; + NSArray* urls = [pasteboard readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:options]; const NSUInteger count = [urls count]; if (count) @@ -666,7 +696,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; char** paths = _glfw_calloc(count, sizeof(char*)); for (NSUInteger i = 0; i < count; i++) - paths[i] = _glfw_strdup([urls[i] fileSystemRepresentation]); + paths[i] = _glfw_strdup([[urls objectAtIndex:i] fileSystemRepresentation]); _glfwInputDrop(window, (int) count, (const char**) paths); @@ -898,7 +928,10 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, } if (strlen(wndconfig->ns.frameName)) - [window->ns.object setFrameAutosaveName:@(wndconfig->ns.frameName)]; + { + [window->ns.object setFrameAutosaveName: + [NSString stringWithUTF8String:wndconfig->ns.frameName]]; + } window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window]; window->ns.scaleFramebuffer = wndconfig->scaleFramebuffer; @@ -912,7 +945,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, [window->ns.object setContentView:window->ns.view]; [window->ns.object makeFirstResponder:window->ns.view]; - [window->ns.object setTitle:@(window->title)]; + [window->ns.object setTitle:[NSString stringWithUTF8String:window->title]]; [window->ns.object setDelegate:window->ns.delegate]; [window->ns.object setAcceptsMouseMovedEvents:YES]; [window->ns.object setRestorable:NO]; @@ -950,19 +983,28 @@ GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (!createNativeWindow(window, wndconfig, fbconfig)) + { + [pool release]; return GLFW_FALSE; + } if (ctxconfig->client != GLFW_NO_API) { if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API) { if (!_glfwInitNSGL()) + { + [pool release]; return GLFW_FALSE; + } if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig)) + { + [pool release]; return GLFW_FALSE; + } } else if (ctxconfig->source == GLFW_EGL_CONTEXT_API) { @@ -972,20 +1014,35 @@ GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window, window->ns.layer = [window->ns.view layer]; if (!_glfwInitEGL()) + { + [pool release]; return GLFW_FALSE; + } if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) + { + [pool release]; return GLFW_FALSE; + } } else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API) { if (!_glfwInitOSMesa()) + { + [pool release]; return GLFW_FALSE; + } if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig)) + { + [pool release]; return GLFW_FALSE; + } } if (!_glfwRefreshContextAttribs(window, ctxconfig)) + { + [pool release]; return GLFW_FALSE; + } } if (wndconfig->mousePassthrough) @@ -1010,14 +1067,13 @@ GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window, } } + [pool release]; return GLFW_TRUE; - - } // autoreleasepool } void _glfwDestroyWindowCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (_glfw.ns.disabledCursorWindow == window) _glfw.ns.disabledCursorWindow = NULL; @@ -1043,18 +1099,18 @@ void _glfwDestroyWindowCocoa(_GLFWwindow* window) // HACK: Allow Cocoa to catch up before returning _glfwPollEventsCocoa(); - } // autoreleasepool + [pool release]; } void _glfwSetWindowTitleCocoa(_GLFWwindow* window, const char* title) { - @autoreleasepool { - NSString* string = @(title); + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSString* string = [NSString stringWithUTF8String:title]; [window->ns.object setTitle:string]; // HACK: Set the miniwindow title explicitly as setTitle: doesn't update it // if the window lacks NSWindowStyleMaskTitled [window->ns.object setMiniwindowTitle:string]; - } // autoreleasepool + [pool release]; } void _glfwSetWindowIconCocoa(_GLFWwindow* window, @@ -1066,7 +1122,7 @@ void _glfwSetWindowIconCocoa(_GLFWwindow* window, void _glfwGetWindowPosCocoa(_GLFWwindow* window, int* xpos, int* ypos) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; const NSRect contentRect = [window->ns.object contentRectForFrameRect:[window->ns.object frame]]; @@ -1076,24 +1132,24 @@ void _glfwGetWindowPosCocoa(_GLFWwindow* window, int* xpos, int* ypos) if (ypos) *ypos = _glfwTransformYCocoa(contentRect.origin.y + contentRect.size.height - 1); - } // autoreleasepool + [pool release]; } void _glfwSetWindowPosCocoa(_GLFWwindow* window, int x, int y) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; const NSRect contentRect = [window->ns.view frame]; const NSRect dummyRect = NSMakeRect(x, _glfwTransformYCocoa(y + contentRect.size.height - 1), 0, 0); const NSRect frameRect = [window->ns.object frameRectForContentRect:dummyRect]; [window->ns.object setFrameOrigin:frameRect.origin]; - } // autoreleasepool + [pool release]; } void _glfwGetWindowSizeCocoa(_GLFWwindow* window, int* width, int* height) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; const NSRect contentRect = [window->ns.view frame]; @@ -1102,12 +1158,12 @@ void _glfwGetWindowSizeCocoa(_GLFWwindow* window, int* width, int* height) if (height) *height = contentRect.size.height; - } // autoreleasepool + [pool release]; } void _glfwSetWindowSizeCocoa(_GLFWwindow* window, int width, int height) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (window->monitor) { @@ -1124,14 +1180,14 @@ void _glfwSetWindowSizeCocoa(_GLFWwindow* window, int width, int height) display:YES]; } - } // autoreleasepool + [pool release]; } void _glfwSetWindowSizeLimitsCocoa(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) [window->ns.object setContentMinSize:NSMakeSize(0, 0)]; @@ -1143,39 +1199,45 @@ void _glfwSetWindowSizeLimitsCocoa(_GLFWwindow* window, else [window->ns.object setContentMaxSize:NSMakeSize(maxwidth, maxheight)]; - } // autoreleasepool + [pool release]; } void _glfwSetWindowAspectRatioCocoa(_GLFWwindow* window, int numer, int denom) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE) [window->ns.object setResizeIncrements:NSMakeSize(1.0, 1.0)]; else [window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)]; - } // autoreleasepool + [pool release]; } void _glfwGetFramebufferSizeCocoa(_GLFWwindow* window, int* width, int* height) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; const NSRect contentRect = [window->ns.view frame]; + // NOTE: Mac OS X 10.6 has no backing-store scale concept; see the note in + // windowDidResize: above +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect]; +#else + const NSRect fbRect = contentRect; +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ if (width) *width = (int) fbRect.size.width; if (height) *height = (int) fbRect.size.height; - } // autoreleasepool + [pool release]; } void _glfwGetWindowFrameSizeCocoa(_GLFWwindow* window, int* left, int* top, int* right, int* bottom) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; const NSRect contentRect = [window->ns.view frame]; const NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect]; @@ -1191,81 +1253,87 @@ void _glfwGetWindowFrameSizeCocoa(_GLFWwindow* window, if (bottom) *bottom = contentRect.origin.y - frameRect.origin.y; - } // autoreleasepool + [pool release]; } void _glfwGetWindowContentScaleCocoa(_GLFWwindow* window, float* xscale, float* yscale) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; const NSRect points = [window->ns.view frame]; + // NOTE: Mac OS X 10.6 has no backing-store scale concept; content scale + // is always 1.0 there +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 const NSRect pixels = [window->ns.view convertRectToBacking:points]; +#else + const NSRect pixels = points; +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ if (xscale) *xscale = (float) (pixels.size.width / points.size.width); if (yscale) *yscale = (float) (pixels.size.height / points.size.height); - } // autoreleasepool + [pool release]; } void _glfwIconifyWindowCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [window->ns.object miniaturize:nil]; - } // autoreleasepool + [pool release]; } void _glfwRestoreWindowCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if ([window->ns.object isMiniaturized]) [window->ns.object deminiaturize:nil]; else if ([window->ns.object isZoomed]) [window->ns.object zoom:nil]; - } // autoreleasepool + [pool release]; } void _glfwMaximizeWindowCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (![window->ns.object isZoomed]) [window->ns.object zoom:nil]; - } // autoreleasepool + [pool release]; } void _glfwShowWindowCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [window->ns.object orderFront:nil]; - } // autoreleasepool + [pool release]; } void _glfwHideWindowCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [window->ns.object orderOut:nil]; - } // autoreleasepool + [pool release]; } void _glfwRequestWindowAttentionCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [NSApp requestUserAttention:NSInformationalRequest]; - } // autoreleasepool + [pool release]; } void _glfwFocusWindowCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; // Make us the active application // HACK: This is here to prevent applications using only hidden windows from // being activated, but should probably not be done every time any // window is shown [NSApp activateIgnoringOtherApps:YES]; [window->ns.object makeKeyAndOrderFront:nil]; - } // autoreleasepool + [pool release]; } void _glfwSetWindowMonitorCocoa(_GLFWwindow* window, @@ -1274,7 +1342,7 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window, int width, int height, int refreshRate) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (window->monitor == monitor) { @@ -1295,6 +1363,7 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window, [window->ns.object setFrame:frameRect display:YES]; } + [pool release]; return; } @@ -1393,70 +1462,67 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window, [window->ns.object setTitle:[window->ns.object miniwindowTitle]]; } - } // autoreleasepool + [pool release]; } GLFWbool _glfwWindowFocusedCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [pool release]; return [window->ns.object isKeyWindow]; - } // autoreleasepool } GLFWbool _glfwWindowIconifiedCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [pool release]; return [window->ns.object isMiniaturized]; - } // autoreleasepool } GLFWbool _glfwWindowVisibleCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [pool release]; return [window->ns.object isVisible]; - } // autoreleasepool } GLFWbool _glfwWindowMaximizedCocoa(_GLFWwindow* window) { - @autoreleasepool { - - if (window->resizable) - return [window->ns.object isZoomed]; - else - return GLFW_FALSE; - - } // autoreleasepool + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + const GLFWbool maximized = + window->resizable ? [window->ns.object isZoomed] : GLFW_FALSE; + [pool release]; + return maximized; } GLFWbool _glfwWindowHoveredCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; const NSPoint point = [NSEvent mouseLocation]; if ([NSWindow windowNumberAtPoint:point belowWindowWithWindowNumber:0] != [window->ns.object windowNumber]) { + [pool release]; return GLFW_FALSE; } + [pool release]; return NSMouseInRect(point, [window->ns.object convertRectToScreen:[window->ns.view frame]], NO); - - } // autoreleasepool } GLFWbool _glfwFramebufferTransparentCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [pool release]; return ![window->ns.object isOpaque] && ![window->ns.view isOpaque]; - } // autoreleasepool } void _glfwSetWindowResizableCocoa(_GLFWwindow* window, GLFWbool enabled) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; const NSUInteger styleMask = [window->ns.object styleMask]; if (enabled) @@ -1475,12 +1541,12 @@ void _glfwSetWindowResizableCocoa(_GLFWwindow* window, GLFWbool enabled) [window->ns.object setCollectionBehavior:behavior]; } - } // autoreleasepool + [pool release]; } void _glfwSetWindowDecoratedCocoa(_GLFWwindow* window, GLFWbool enabled) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSUInteger styleMask = [window->ns.object styleMask]; if (enabled) @@ -1497,38 +1563,38 @@ void _glfwSetWindowDecoratedCocoa(_GLFWwindow* window, GLFWbool enabled) [window->ns.object setStyleMask:styleMask]; [window->ns.object makeFirstResponder:window->ns.view]; - } // autoreleasepool + [pool release]; } void _glfwSetWindowFloatingCocoa(_GLFWwindow* window, GLFWbool enabled) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (enabled) [window->ns.object setLevel:NSFloatingWindowLevel]; else [window->ns.object setLevel:NSNormalWindowLevel]; - } // autoreleasepool + [pool release]; } void _glfwSetWindowMousePassthroughCocoa(_GLFWwindow* window, GLFWbool enabled) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [window->ns.object setIgnoresMouseEvents:enabled]; - } + [pool release]; } float _glfwGetWindowOpacityCocoa(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [pool release]; return (float) [window->ns.object alphaValue]; - } // autoreleasepool } void _glfwSetWindowOpacityCocoa(_GLFWwindow* window, float opacity) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [window->ns.object setAlphaValue:opacity]; - } // autoreleasepool + [pool release]; } void _glfwSetRawMouseMotionCocoa(_GLFWwindow *window, GLFWbool enabled) @@ -1544,7 +1610,7 @@ GLFWbool _glfwRawMouseMotionSupportedCocoa(void) void _glfwPollEventsCocoa(void) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; for (;;) { @@ -1558,12 +1624,12 @@ void _glfwPollEventsCocoa(void) [NSApp sendEvent:event]; } - } // autoreleasepool + [pool release]; } void _glfwWaitEventsCocoa(void) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; // I wanted to pass NO to dequeue:, and rely on PollEvents to // dequeue and send. For reasons not at all clear to me, passing @@ -1576,12 +1642,12 @@ void _glfwWaitEventsCocoa(void) _glfwPollEventsCocoa(); - } // autoreleasepool + [pool release]; } void _glfwWaitEventsTimeoutCocoa(double timeout) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout]; NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny @@ -1593,12 +1659,12 @@ void _glfwWaitEventsTimeoutCocoa(double timeout) _glfwPollEventsCocoa(); - } // autoreleasepool + [pool release]; } void _glfwPostEmptyEventCocoa(void) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined location:NSMakePoint(0, 0) @@ -1611,12 +1677,12 @@ void _glfwPostEmptyEventCocoa(void) data2:0]; [NSApp postEvent:event atStart:YES]; - } // autoreleasepool + [pool release]; } void _glfwGetCursorPosCocoa(_GLFWwindow* window, double* xpos, double* ypos) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; const NSRect contentRect = [window->ns.view frame]; // NOTE: The returned location uses base 0,1 not 0,0 @@ -1627,12 +1693,12 @@ void _glfwGetCursorPosCocoa(_GLFWwindow* window, double* xpos, double* ypos) if (ypos) *ypos = contentRect.size.height - pos.y; - } // autoreleasepool + [pool release]; } void _glfwSetCursorPosCocoa(_GLFWwindow* window, double x, double y) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; updateCursorImage(window); @@ -1663,12 +1729,12 @@ void _glfwSetCursorPosCocoa(_GLFWwindow* window, double x, double y) if (window->cursorMode != GLFW_CURSOR_DISABLED) CGAssociateMouseAndMouseCursorPosition(true); - } // autoreleasepool + [pool release]; } void _glfwSetCursorModeCocoa(_GLFWwindow* window, int mode) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (mode == GLFW_CURSOR_CAPTURED) { @@ -1679,22 +1745,26 @@ void _glfwSetCursorModeCocoa(_GLFWwindow* window, int mode) if (_glfwWindowFocusedCocoa(window)) updateCursorMode(window); - } // autoreleasepool + [pool release]; } const char* _glfwGetScancodeNameCocoa(int scancode) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (scancode < 0 || scancode > 0xff) { _glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode %i", scancode); + [pool release]; return NULL; } const int key = _glfw.ns.keycodes[scancode]; if (key == GLFW_KEY_UNKNOWN) + { + [pool release]; return NULL; + } UInt32 deadKeyState = 0; UniChar characters[4]; @@ -1711,11 +1781,15 @@ const char* _glfwGetScancodeNameCocoa(int scancode) &characterCount, characters) != noErr) { + [pool release]; return NULL; } if (!characterCount) + { + [pool release]; return NULL; + } CFStringRef string = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, characters, @@ -1727,9 +1801,8 @@ const char* _glfwGetScancodeNameCocoa(int scancode) kCFStringEncodingUTF8); CFRelease(string); + [pool release]; return _glfw.ns.keynames[key]; - - } // autoreleasepool } int _glfwGetKeyScancodeCocoa(int key) @@ -1741,7 +1814,7 @@ GLFWbool _glfwCreateCursorCocoa(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSImage* native; NSBitmapImageRep* rep; @@ -1760,7 +1833,10 @@ GLFWbool _glfwCreateCursorCocoa(_GLFWcursor* cursor, bitsPerPixel:32]; if (rep == nil) + { + [pool release]; return GLFW_FALSE; + } memcpy([rep bitmapData], image->pixels, image->width * image->height * 4); @@ -1774,16 +1850,18 @@ GLFWbool _glfwCreateCursorCocoa(_GLFWcursor* cursor, [rep release]; if (cursor->ns.object == nil) + { + [pool release]; return GLFW_FALSE; + } + [pool release]; return GLFW_TRUE; - - } // autoreleasepool } GLFWbool _glfwCreateStandardCursorCocoa(_GLFWcursor* cursor, int shape) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; SEL cursorSelector = NULL; @@ -1846,43 +1924,44 @@ GLFWbool _glfwCreateStandardCursorCocoa(_GLFWcursor* cursor, int shape) { _glfwInputError(GLFW_CURSOR_UNAVAILABLE, "Cocoa: Standard cursor shape unavailable"); + [pool release]; return GLFW_FALSE; } [cursor->ns.object retain]; + [pool release]; return GLFW_TRUE; - - } // autoreleasepool } void _glfwDestroyCursorCocoa(_GLFWcursor* cursor) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (cursor->ns.object) [(NSCursor*) cursor->ns.object release]; - } // autoreleasepool + [pool release]; } void _glfwSetCursorCocoa(_GLFWwindow* window, _GLFWcursor* cursor) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (cursorInContentArea(window)) updateCursorImage(window); - } // autoreleasepool + [pool release]; } void _glfwSetClipboardStringCocoa(const char* string) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; - [pasteboard declareTypes:@[NSPasteboardTypeString] owner:nil]; - [pasteboard setString:@(string) forType:NSPasteboardTypeString]; - } // autoreleasepool + [pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil]; + [pasteboard setString:[NSString stringWithUTF8String:string] + forType:NSPasteboardTypeString]; + [pool release]; } const char* _glfwGetClipboardStringCocoa(void) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; @@ -1890,6 +1969,7 @@ const char* _glfwGetClipboardStringCocoa(void) { _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "Cocoa: Failed to retrieve string from pasteboard"); + [pool release]; return NULL; } @@ -1898,15 +1978,15 @@ const char* _glfwGetClipboardStringCocoa(void) { _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to retrieve object from pasteboard"); + [pool release]; return NULL; } _glfw_free(_glfw.ns.clipboardString); _glfw.ns.clipboardString = _glfw_strdup([object UTF8String]); + [pool release]; return _glfw.ns.clipboardString; - - } // autoreleasepool } EGLenum _glfwGetEGLPlatformCocoa(EGLint** attribs) @@ -1976,14 +2056,18 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + // NOTE: CAMetalLayer was added in the 10.11 SDK and does not exist on + // Mac OS X 10.6, so Vulkan surface creation is compiled out there +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 // NOTE: Create the layer here as makeBackingLayer should not return nil window->ns.layer = [CAMetalLayer layer]; if (!window->ns.layer) { _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create layer for view"); + [pool release]; return VK_ERROR_EXTENSION_NOT_PRESENT; } @@ -2006,6 +2090,7 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, { _glfwInputError(GLFW_API_UNAVAILABLE, "Cocoa: Vulkan instance missing VK_EXT_metal_surface extension"); + [pool release]; return VK_ERROR_EXTENSION_NOT_PRESENT; } @@ -2026,6 +2111,7 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, { _glfwInputError(GLFW_API_UNAVAILABLE, "Cocoa: Vulkan instance missing VK_MVK_macos_surface extension"); + [pool release]; return VK_ERROR_EXTENSION_NOT_PRESENT; } @@ -2043,9 +2129,12 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, _glfwGetVulkanResultString(err)); } + [pool release]; return err; - - } // autoreleasepool +#else + [pool release]; + return VK_ERROR_EXTENSION_NOT_PRESENT; +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ } diff --git a/src/nsgl_context.m b/src/nsgl_context.m index cc676171..2b2494c8 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -34,7 +34,7 @@ static void makeContextCurrentNSGL(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; if (window) [window->context.nsgl.object makeCurrentContext]; @@ -43,12 +43,12 @@ static void makeContextCurrentNSGL(_GLFWwindow* window) _glfwPlatformSetTls(&_glfw.contextSlot, window); - } // autoreleasepool + [pool release]; } static void swapBuffersNSGL(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; // HACK: Simulate vsync with usleep as NSGL swap interval does not apply to // windows with a non-visible occlusion state @@ -74,12 +74,12 @@ static void swapBuffersNSGL(_GLFWwindow* window) [window->context.nsgl.object flushBuffer]; - } // autoreleasepool + [pool release]; } static void swapIntervalNSGL(int interval) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); assert(window != NULL); @@ -87,7 +87,7 @@ static void swapIntervalNSGL(int interval) [window->context.nsgl.object setValues:&interval forParameter:NSOpenGLContextParameterSwapInterval]; - } // autoreleasepool + [pool release]; } static int extensionSupportedNSGL(const char* extension) @@ -112,7 +112,7 @@ static GLFWglproc getProcAddressNSGL(const char* procname) static void destroyContextNSGL(_GLFWwindow* window) { - @autoreleasepool { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [window->context.nsgl.pixelFormat release]; window->context.nsgl.pixelFormat = nil; @@ -120,7 +120,7 @@ static void destroyContextNSGL(_GLFWwindow* window) [window->context.nsgl.object release]; window->context.nsgl.object = nil; - } // autoreleasepool + [pool release]; } @@ -160,20 +160,10 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, return GLFW_FALSE; } - if (ctxconfig->major > 2) - { - if (ctxconfig->major == 3 && ctxconfig->minor < 2) - { - _glfwInputError(GLFW_VERSION_UNAVAILABLE, - "NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1 but may support 3.2 and above"); - return GLFW_FALSE; - } - } - - if (ctxconfig->major >= 3 && ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE) + if (ctxconfig->major > 2 || (ctxconfig->major == 2 && ctxconfig->minor > 1)) { _glfwInputError(GLFW_VERSION_UNAVAILABLE, - "NSGL: The compatibility profile is not available on macOS"); + "NSGL: OpenGL 2.1 or below is the only version available on Mac OS X 10.6"); return GLFW_FALSE; } @@ -209,35 +199,32 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, // Info.plist for unbundled applications // HACK: This assumes that NSOpenGLPixelFormat will remain // a straightforward wrapper of its CGL counterpart + // NOTE: kCGLPFASupportsAutomaticGraphicsSwitching was added in the + // 10.8 SDK and does not exist on Mac OS X 10.6 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 ADD_ATTRIB(kCGLPFASupportsAutomaticGraphicsSwitching); +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ } - if (ctxconfig->major >= 4) - { - SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core); - } - else if (ctxconfig->major >= 3) - { - SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); - } + // NOTE: OpenGL profile selection (NSOpenGLPFAOpenGLProfile) was added in + // the 10.7 SDK; Mac OS X 10.6 only ever provides a legacy context, + // which is all that is requested above, so there is nothing to add + // here for this target - if (ctxconfig->major <= 2) - { - if (fbconfig->auxBuffers != GLFW_DONT_CARE) - SET_ATTRIB(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers); + if (fbconfig->auxBuffers != GLFW_DONT_CARE) + SET_ATTRIB(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers); - if (fbconfig->accumRedBits != GLFW_DONT_CARE && - fbconfig->accumGreenBits != GLFW_DONT_CARE && - fbconfig->accumBlueBits != GLFW_DONT_CARE && - fbconfig->accumAlphaBits != GLFW_DONT_CARE) - { - const int accumBits = fbconfig->accumRedBits + - fbconfig->accumGreenBits + - fbconfig->accumBlueBits + - fbconfig->accumAlphaBits; + if (fbconfig->accumRedBits != GLFW_DONT_CARE && + fbconfig->accumGreenBits != GLFW_DONT_CARE && + fbconfig->accumBlueBits != GLFW_DONT_CARE && + fbconfig->accumAlphaBits != GLFW_DONT_CARE) + { + const int accumBits = fbconfig->accumRedBits + + fbconfig->accumGreenBits + + fbconfig->accumBlueBits + + fbconfig->accumAlphaBits; - SET_ATTRIB(NSOpenGLPFAAccumSize, accumBits); - } + SET_ATTRIB(NSOpenGLPFAAccumSize, accumBits); } if (fbconfig->redBits != GLFW_DONT_CARE && @@ -332,7 +319,11 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, forParameter:NSOpenGLContextParameterSurfaceOpacity]; } + // NOTE: -setWantsBestResolutionOpenGLSurface: was added in the 10.7 SDK + // and Mac OS X 10.6 has no HiDPI/backing-store scale concept +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 [window->ns.view setWantsBestResolutionOpenGLSurface:window->ns.scaleFramebuffer]; +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ [window->context.nsgl.object setView:window->ns.view]; -- 2.43.0