Cocoa: Replace global autorelease pool with blocks

This is another small step towards having GLFW play nice with other
toolkits sharing the same process, including AppKit.

Any macOS platform function that touches Cocoa must now wrap itself in
an autoreleasepool block.

Since GLFW no longer provides an autoreleasepool outside of its
functions, THIS MAY BREAK EXISTING CODE MIXING GLFW AND COCOA.  Sorry!
Please add your own autoreleasepool blocks as needed.

Fixes #1107.
Closes #1114.
diff --git a/src/cocoa_init.m b/src/cocoa_init.m
index 25039e3..30dd1f5 100644
--- a/src/cocoa_init.m
+++ b/src/cocoa_init.m
@@ -479,7 +479,8 @@
 
 int _glfwPlatformInit(void)
 {
-    _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
+    @autoreleasepool {
+
     _glfw.ns.helper = [[GLFWHelper alloc] init];
 
     [NSThread detachNewThreadSelector:@selector(doNothing:)
@@ -542,10 +543,14 @@
 
     _glfwPollMonitorsNS();
     return GLFW_TRUE;
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformTerminate(void)
 {
+    @autoreleasepool {
+
     if (_glfw.ns.inputSource)
     {
         CFRelease(_glfw.ns.inputSource);
@@ -586,8 +591,7 @@
     _glfwTerminateNSGL();
     _glfwTerminateJoysticksNS();
 
-    [_glfw.ns.autoreleasePool release];
-    _glfw.ns.autoreleasePool = nil;
+    } // autoreleasepool
 }
 
 const char* _glfwPlatformGetVersionString(void)
diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m
index 37e8fd1..acaba8c 100644
--- a/src/cocoa_monitor.m
+++ b/src/cocoa_monitor.m
@@ -387,17 +387,23 @@
 
 void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
 {
+    @autoreleasepool {
+
     const CGRect bounds = CGDisplayBounds(monitor->ns.displayID);
 
     if (xpos)
         *xpos = (int) bounds.origin.x;
     if (ypos)
         *ypos = (int) bounds.origin.y;
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
                                          float* xscale, float* yscale)
 {
+    @autoreleasepool {
+
     if (!refreshMonitorScreen(monitor))
         return;
 
@@ -408,12 +414,16 @@
         *xscale = (float) (pixels.size.width / points.size.width);
     if (yscale)
         *yscale = (float) (pixels.size.height / points.size.height);
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
                                      int* xpos, int* ypos,
                                      int* width, int* height)
 {
+    @autoreleasepool {
+
     if (!refreshMonitorScreen(monitor))
         return;
 
@@ -427,10 +437,14 @@
         *width = frameRect.size.width;
     if (height)
         *height = frameRect.size.height;
+
+    } // autoreleasepool
 }
 
 GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
 {
+    @autoreleasepool {
+
     CFArrayRef modes;
     CFIndex found, i, j;
     GLFWvidmode* result;
@@ -469,10 +483,14 @@
     CFRelease(modes);
     CVDisplayLinkRelease(link);
     return result;
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
 {
+    @autoreleasepool {
+
     CGDisplayModeRef displayMode;
     CVDisplayLinkRef link;
 
@@ -483,10 +501,14 @@
     CGDisplayModeRelease(displayMode);
 
     CVDisplayLinkRelease(link);
+
+    } // autoreleasepool
 }
 
 GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
 {
+    @autoreleasepool {
+
     uint32_t i, size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
     CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue));
 
@@ -508,10 +530,14 @@
 
     free(values);
     return GLFW_TRUE;
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
 {
+    @autoreleasepool {
+
     int i;
     CGGammaValue* values = calloc(ramp->size * 3, sizeof(CGGammaValue));
 
@@ -529,6 +555,8 @@
                                 values + ramp->size * 2);
 
     free(values);
+
+    } // autoreleasepool
 }
 
 
diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h
index 4f3cebc..7f18849 100644
--- a/src/cocoa_platform.h
+++ b/src/cocoa_platform.h
@@ -104,7 +104,6 @@
 {
     CGEventSourceRef    eventSource;
     id                  delegate;
-    id                  autoreleasePool;
     GLFWbool            finishedLaunching;
     GLFWbool            cursorHidden;
     TISInputSourceRef   inputSource;
diff --git a/src/cocoa_window.m b/src/cocoa_window.m
index 6ee8a09..1170277 100644
--- a/src/cocoa_window.m
+++ b/src/cocoa_window.m
@@ -910,6 +910,8 @@
                               const _GLFWctxconfig* ctxconfig,
                               const _GLFWfbconfig* fbconfig)
 {
+    @autoreleasepool {
+
     if (!_glfw.ns.finishedLaunching)
     {
         [NSApp run];
@@ -952,10 +954,14 @@
     }
 
     return GLFW_TRUE;
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformDestroyWindow(_GLFWwindow* window)
 {
+    @autoreleasepool {
+
     if (_glfw.ns.disabledCursorWindow == window)
         _glfw.ns.disabledCursorWindow = NULL;
 
@@ -977,16 +983,17 @@
     [window->ns.object close];
     window->ns.object = nil;
 
-    [_glfw.ns.autoreleasePool drain];
-    _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char *title)
 {
+    @autoreleasepool {
     [window->ns.object setTitle:@(title)];
     // HACK: Set the miniwindow title explicitly as setTitle: doesn't update it
     //       if the window lacks NSWindowStyleMaskTitled
     [window->ns.object setMiniwindowTitle:@(title)];
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
@@ -997,6 +1004,8 @@
 
 void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
 {
+    @autoreleasepool {
+
     const NSRect contentRect =
         [window->ns.object contentRectForFrameRect:[window->ns.object frame]];
 
@@ -1004,28 +1013,40 @@
         *xpos = contentRect.origin.x;
     if (ypos)
         *ypos = _glfwTransformYNS(contentRect.origin.y + contentRect.size.height);
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y)
 {
+    @autoreleasepool {
+
     const NSRect contentRect = [window->ns.view frame];
     const NSRect dummyRect = NSMakeRect(x, _glfwTransformYNS(y + contentRect.size.height), 0, 0);
     const NSRect frameRect = [window->ns.object frameRectForContentRect:dummyRect];
     [window->ns.object setFrameOrigin:frameRect.origin];
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
 {
+    @autoreleasepool {
+
     const NSRect contentRect = [window->ns.view frame];
 
     if (width)
         *width = contentRect.size.width;
     if (height)
         *height = contentRect.size.height;
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
 {
+    @autoreleasepool {
+
     if (window->monitor)
     {
         if (window->monitor->window == window)
@@ -1033,12 +1054,16 @@
     }
     else
         [window->ns.object setContentSize:NSMakeSize(width, height)];
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
                                       int minwidth, int minheight,
                                       int maxwidth, int maxheight)
 {
+    @autoreleasepool {
+
     if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
         [window->ns.object setContentMinSize:NSMakeSize(0, 0)];
     else
@@ -1048,18 +1073,24 @@
         [window->ns.object setContentMaxSize:NSMakeSize(DBL_MAX, DBL_MAX)];
     else
         [window->ns.object setContentMaxSize:NSMakeSize(maxwidth, maxheight)];
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
 {
+    @autoreleasepool {
     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
 }
 
 void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
 {
+    @autoreleasepool {
+
     const NSRect contentRect = [window->ns.view frame];
     const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
 
@@ -1067,12 +1098,16 @@
         *width = (int) fbRect.size.width;
     if (height)
         *height = (int) fbRect.size.height;
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
                                      int* left, int* top,
                                      int* right, int* bottom)
 {
+    @autoreleasepool {
+
     const NSRect contentRect = [window->ns.view frame];
     const NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect];
 
@@ -1086,11 +1121,15 @@
                  contentRect.origin.x - contentRect.size.width;
     if (bottom)
         *bottom = contentRect.origin.y - frameRect.origin.y;
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
                                         float* xscale, float* yscale)
 {
+    @autoreleasepool {
+
     const NSRect points = [window->ns.view frame];
     const NSRect pixels = [window->ns.view convertRectToBacking:points];
 
@@ -1098,51 +1137,66 @@
         *xscale = (float) (pixels.size.width / points.size.width);
     if (yscale)
         *yscale = (float) (pixels.size.height / points.size.height);
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformIconifyWindow(_GLFWwindow* window)
 {
+    @autoreleasepool {
     [window->ns.object miniaturize:nil];
+    } // autoreleasepool
 }
 
 void _glfwPlatformRestoreWindow(_GLFWwindow* window)
 {
+    @autoreleasepool {
     if ([window->ns.object isMiniaturized])
         [window->ns.object deminiaturize:nil];
     else if ([window->ns.object isZoomed])
         [window->ns.object zoom:nil];
+    } // autoreleasepool
 }
 
 void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
 {
+    @autoreleasepool {
     if (![window->ns.object isZoomed])
         [window->ns.object zoom:nil];
+    } // autoreleasepool
 }
 
 void _glfwPlatformShowWindow(_GLFWwindow* window)
 {
+    @autoreleasepool {
     [window->ns.object orderFront:nil];
+    } // autoreleasepool
 }
 
 void _glfwPlatformHideWindow(_GLFWwindow* window)
 {
+    @autoreleasepool {
     [window->ns.object orderOut:nil];
+    } // autoreleasepool
 }
 
 void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
 {
+    @autoreleasepool {
     [NSApp requestUserAttention:NSInformationalRequest];
+    } // autoreleasepool
 }
 
 void _glfwPlatformFocusWindow(_GLFWwindow* window)
 {
+    @autoreleasepool {
     // 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
 }
 
 void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
@@ -1151,6 +1205,8 @@
                                    int width, int height,
                                    int refreshRate)
 {
+    @autoreleasepool {
+
     if (window->monitor == monitor)
     {
         if (monitor)
@@ -1232,30 +1288,42 @@
         //       title property but the miniwindow title property is unaffected
         [window->ns.object setTitle:[window->ns.object miniwindowTitle]];
     }
+
+    } // autoreleasepool
 }
 
 int _glfwPlatformWindowFocused(_GLFWwindow* window)
 {
+    @autoreleasepool {
     return [window->ns.object isKeyWindow];
+    } // autoreleasepool
 }
 
 int _glfwPlatformWindowIconified(_GLFWwindow* window)
 {
+    @autoreleasepool {
     return [window->ns.object isMiniaturized];
+    } // autoreleasepool
 }
 
 int _glfwPlatformWindowVisible(_GLFWwindow* window)
 {
+    @autoreleasepool {
     return [window->ns.object isVisible];
+    } // autoreleasepool
 }
 
 int _glfwPlatformWindowMaximized(_GLFWwindow* window)
 {
+    @autoreleasepool {
     return [window->ns.object isZoomed];
+    } // autoreleasepool
 }
 
 int _glfwPlatformWindowHovered(_GLFWwindow* window)
 {
+    @autoreleasepool {
+
     const NSPoint point = [NSEvent mouseLocation];
 
     if ([NSWindow windowNumberAtPoint:point belowWindowWithWindowNumber:0] !=
@@ -1266,40 +1334,54 @@
 
     return NSPointInRect(point,
         [window->ns.object convertRectToScreen:[window->ns.view bounds]]);
+
+    } // autoreleasepool
 }
 
 int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
 {
+    @autoreleasepool {
     return ![window->ns.object isOpaque] && ![window->ns.view isOpaque];
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
 {
+    @autoreleasepool {
     [window->ns.object setStyleMask:getStyleMask(window)];
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
 {
+    @autoreleasepool {
     [window->ns.object setStyleMask:getStyleMask(window)];
     [window->ns.object makeFirstResponder:window->ns.view];
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
 {
+    @autoreleasepool {
     if (enabled)
         [window->ns.object setLevel:NSFloatingWindowLevel];
     else
         [window->ns.object setLevel:NSNormalWindowLevel];
+    } // autoreleasepool
 }
 
 float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
 {
+    @autoreleasepool {
     return (float) [window->ns.object alphaValue];
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
 {
+    @autoreleasepool {
     [window->ns.object setAlphaValue:opacity];
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
@@ -1313,6 +1395,8 @@
 
 void _glfwPlatformPollEvents(void)
 {
+    @autoreleasepool {
+
     for (;;)
     {
         NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
@@ -1325,12 +1409,13 @@
         [NSApp sendEvent:event];
     }
 
-    [_glfw.ns.autoreleasePool drain];
-    _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
+    } // autoreleasepool
 }
 
 void _glfwPlatformWaitEvents(void)
 {
+    @autoreleasepool {
+
     // I wanted to pass NO to dequeue:, and rely on PollEvents to
     // dequeue and send.  For reasons not at all clear to me, passing
     // NO to dequeue: causes this method never to return.
@@ -1341,10 +1426,14 @@
     [NSApp sendEvent:event];
 
     _glfwPlatformPollEvents();
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformWaitEventsTimeout(double timeout)
 {
+    @autoreleasepool {
+
     NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
     NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
                                         untilDate:date
@@ -1354,11 +1443,14 @@
         [NSApp sendEvent:event];
 
     _glfwPlatformPollEvents();
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformPostEmptyEvent(void)
 {
-    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    @autoreleasepool {
+
     NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
                                         location:NSMakePoint(0, 0)
                                    modifierFlags:0
@@ -1369,11 +1461,14 @@
                                            data1:0
                                            data2:0];
     [NSApp postEvent:event atStart:YES];
-    [pool drain];
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
 {
+    @autoreleasepool {
+
     const NSRect contentRect = [window->ns.view frame];
     const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
 
@@ -1381,10 +1476,14 @@
         *xpos = pos.x;
     if (ypos)
         *ypos = contentRect.size.height - pos.y - 1;
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
 {
+    @autoreleasepool {
+
     updateCursorImage(window);
 
     const NSRect contentRect = [window->ns.view frame];
@@ -1407,16 +1506,22 @@
         CGWarpMouseCursorPosition(CGPointMake(globalPoint.x,
                                               _glfwTransformYNS(globalPoint.y)));
     }
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
 {
+    @autoreleasepool {
     if (_glfwPlatformWindowFocused(window))
         updateCursorMode(window);
+    } // autoreleasepool
 }
 
 const char* _glfwPlatformGetScancodeName(int scancode)
 {
+    @autoreleasepool {
+
     UInt32 deadKeyState = 0;
     UniChar characters[8];
     UniCharCount characterCount = 0;
@@ -1449,6 +1554,8 @@
     CFRelease(string);
 
     return _glfw.ns.keyName;
+
+    } // autoreleasepool
 }
 
 int _glfwPlatformGetKeyScancode(int key)
@@ -1460,6 +1567,8 @@
                               const GLFWimage* image,
                               int xhot, int yhot)
 {
+    @autoreleasepool {
+
     NSImage* native;
     NSBitmapImageRep* rep;
 
@@ -1494,10 +1603,14 @@
         return GLFW_FALSE;
 
     return GLFW_TRUE;
+
+    } // autoreleasepool
 }
 
 int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
 {
+    @autoreleasepool {
+
     if (shape == GLFW_ARROW_CURSOR)
         cursor->ns.object = [NSCursor arrowCursor];
     else if (shape == GLFW_IBEAM_CURSOR)
@@ -1520,29 +1633,39 @@
 
     [cursor->ns.object retain];
     return GLFW_TRUE;
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
 {
+    @autoreleasepool {
     if (cursor->ns.object)
         [(NSCursor*) cursor->ns.object release];
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
 {
+    @autoreleasepool {
     if (cursorInContentArea(window))
         updateCursorImage(window);
+    } // autoreleasepool
 }
 
 void _glfwPlatformSetClipboardString(const char* string)
 {
+    @autoreleasepool {
     NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
     [pasteboard declareTypes:@[NSPasteboardTypeString] owner:nil];
     [pasteboard setString:@(string) forType:NSPasteboardTypeString];
+    } // autoreleasepool
 }
 
 const char* _glfwPlatformGetClipboardString(void)
 {
+    @autoreleasepool {
+
     NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
 
     if (![[pasteboard types] containsObject:NSPasteboardTypeString])
@@ -1564,6 +1687,8 @@
     _glfw.ns.clipboardString = _glfw_strdup([object UTF8String]);
 
     return _glfw.ns.clipboardString;
+
+    } // autoreleasepool
 }
 
 void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
@@ -1587,6 +1712,8 @@
                                           const VkAllocationCallbacks* allocator,
                                           VkSurfaceKHR* surface)
 {
+    @autoreleasepool {
+
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
     VkResult err;
     VkMacOSSurfaceCreateInfoMVK sci;
@@ -1639,6 +1766,8 @@
 #else
     return VK_ERROR_EXTENSION_NOT_PRESENT;
 #endif
+
+    } // autoreleasepool
 }
 
 
diff --git a/src/nsgl_context.m b/src/nsgl_context.m
index ec1012e..f3bf242 100644
--- a/src/nsgl_context.m
+++ b/src/nsgl_context.m
@@ -33,27 +33,37 @@
 
 static void makeContextCurrentNSGL(_GLFWwindow* window)
 {
+    @autoreleasepool {
+
     if (window)
         [window->context.nsgl.object makeCurrentContext];
     else
         [NSOpenGLContext clearCurrentContext];
 
     _glfwPlatformSetTls(&_glfw.contextSlot, window);
+
+    } // autoreleasepool
 }
 
 static void swapBuffersNSGL(_GLFWwindow* window)
 {
+    @autoreleasepool {
     // ARP appears to be unnecessary, but this is future-proof
     [window->context.nsgl.object flushBuffer];
+    } // autoreleasepool
 }
 
 static void swapIntervalNSGL(int interval)
 {
+    @autoreleasepool {
+
     _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
 
     GLint sync = interval;
     [window->context.nsgl.object setValues:&sync
                               forParameter:NSOpenGLContextParameterSwapInterval];
+
+    } // autoreleasepool
 }
 
 static int extensionSupportedNSGL(const char* extension)
@@ -80,11 +90,15 @@
 //
 static void destroyContextNSGL(_GLFWwindow* window)
 {
+    @autoreleasepool {
+
     [window->context.nsgl.pixelFormat release];
     window->context.nsgl.pixelFormat = nil;
 
     [window->context.nsgl.object release];
     window->context.nsgl.object = nil;
+
+    } // autoreleasepool
 }