mirror of
https://github.com/glfw/glfw.git
synced 2026-09-22 08:50:15 +00:00
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.
This commit is contained in:
+136
-7
@@ -910,6 +910,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
if (!_glfw.ns.finishedLaunching)
|
||||
{
|
||||
[NSApp run];
|
||||
@@ -952,10 +954,14 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
if (_glfw.ns.disabledCursorWindow == window)
|
||||
_glfw.ns.disabledCursorWindow = NULL;
|
||||
|
||||
@@ -977,16 +983,17 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
[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 _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||
|
||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
const NSRect contentRect =
|
||||
[window->ns.object contentRectForFrameRect:[window->ns.object frame]];
|
||||
|
||||
@@ -1004,28 +1013,40 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||
*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 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||
}
|
||||
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 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||
[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 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh
|
||||
*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 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||
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 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
||||
*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 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
int width, int height,
|
||||
int refreshRate)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
if (window->monitor == monitor)
|
||||
{
|
||||
if (monitor)
|
||||
@@ -1232,30 +1288,42 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
// 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 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
||||
|
||||
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 @@ GLFWbool _glfwPlatformRawMouseMotionSupported(void)
|
||||
|
||||
void _glfwPlatformPollEvents(void)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
for (;;)
|
||||
{
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||
@@ -1325,12 +1409,13 @@ void _glfwPlatformPollEvents(void)
|
||||
[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 @@ void _glfwPlatformWaitEvents(void)
|
||||
[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 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||
[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 @@ void _glfwPlatformPostEmptyEvent(void)
|
||||
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 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||
*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 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
||||
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 @@ const char* _glfwPlatformGetScancodeName(int scancode)
|
||||
CFRelease(string);
|
||||
|
||||
return _glfw.ns.keyName;
|
||||
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
int _glfwPlatformGetKeyScancode(int key)
|
||||
@@ -1460,6 +1567,8 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
NSImage* native;
|
||||
NSBitmapImageRep* rep;
|
||||
|
||||
@@ -1494,10 +1603,14 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
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 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
|
||||
[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 @@ const char* _glfwPlatformGetClipboardString(void)
|
||||
_glfw.ns.clipboardString = _glfw_strdup([object UTF8String]);
|
||||
|
||||
return _glfw.ns.clipboardString;
|
||||
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
@@ -1587,6 +1712,8 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
const VkAllocationCallbacks* allocator,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
|
||||
VkResult err;
|
||||
VkMacOSSurfaceCreateInfoMVK sci;
|
||||
@@ -1639,6 +1766,8 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
#else
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
#endif
|
||||
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user