Change handling of NSAutoreleasePool

GUI toolkits such as wxWidgets and Qt provide their own NSAutoreleasePool
objects. To avoid pool corruption, it is required that the pools be nested,
which the previous implementation did not guarantee. Furthermore, autorelease
pools should always be drained in the same context (function, loop, etc.) that
they are created, which was not the case with the previous implementation
(https://developer.apple.com/documentation/foundation/nsautoreleasepool).

This commit removes long-lived autorelease pools, and instead each function that
calls into the Cocoa API creates its own autorelease pool (using the new C++
AutoreleasePool wrapper object).

Should fix crashes in issue #1549 and similar.
This commit is contained in:
jqdg 2021-08-24 13:52:15 -07:00 committed by Lukas Dürrenberger
parent eeeda74ec1
commit c80cbb9c97
10 changed files with 129 additions and 110 deletions

View File

@ -182,7 +182,7 @@ elseif(SFML_OS_MACOSX)
${SRCROOT}/OSX/WindowImplCocoa.hpp ${SRCROOT}/OSX/WindowImplCocoa.hpp
${SRCROOT}/OSX/WindowImplCocoa.mm ${SRCROOT}/OSX/WindowImplCocoa.mm
${SRCROOT}/OSX/WindowImplDelegateProtocol.h ${SRCROOT}/OSX/WindowImplDelegateProtocol.h
${SRCROOT}/OSX/AutoreleasePoolWrapper.h ${SRCROOT}/OSX/AutoreleasePoolWrapper.hpp
${SRCROOT}/OSX/AutoreleasePoolWrapper.mm ${SRCROOT}/OSX/AutoreleasePoolWrapper.mm
) )
source_group("mac" FILES ${PLATFORM_SRC}) source_group("mac" FILES ${PLATFORM_SRC})

View File

@ -23,15 +23,54 @@
// //
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////// #ifndef SFML_AUTORELEASEPOOL_HPP
/// \brief Ensure one autorelease pool is available on this thread #define SFML_AUTORELEASEPOOL_HPP
///
////////////////////////////////////////////////////////////
void ensureThreadHasPool(void);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Drain the thread's pool but keep it alive /// Predefine OBJ-C classes
////////////////////////////////////////////////////////////
#ifdef __OBJC__
@class NSAutoreleasePool;
typedef NSAutoreleasePool* NSAutoreleasePoolRef;
#else // If C++
typedef void* NSAutoreleasePoolRef;
#endif
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Wraps an NSAutoreleasePool that is created when the object is
/// constructed and is drained when the object is destroyed.
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void drainThreadPool(void); class AutoreleasePool
{
public:
////////////////////////////////////////////////////////////
/// \brief Construct a new NSAutoreleasePool.
///
////////////////////////////////////////////////////////////
AutoreleasePool();
////////////////////////////////////////////////////////////
/// \brief Destructor. Drains the autorelease pool.
///
////////////////////////////////////////////////////////////
~AutoreleasePool();
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
NSAutoreleasePoolRef pool; ///< The autorelease pool.
};
} // namespace sf
#endif // SFML_AUTORELEASEPOOL_HPP

View File

@ -26,80 +26,25 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <cassert>
#include <pthread.h>
#import <SFML/Window/OSX/AutoreleasePoolWrapper.h> #include <SFML/Window/OSX/AutoreleasePoolWrapper.hpp>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
namespace sf
//////////////////////////////////////////////////////////// {
/// Here we manage one and only one pool by thread. This prevents draining one
/// pool and making other pools invalid which can lead to a crash on 10.5 and an ////////////////////////////////////////////////////////
/// annoying message on 10.6 (*** attempt to pop an unknown autorelease pool). AutoreleasePool::AutoreleasePool()
/// {
//////////////////////////////////////////////////////////// pool = [[NSAutoreleasePool alloc] init];
}
////////////////////////////////////////////////////////////
// Private data ////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////// AutoreleasePool::~AutoreleasePool()
static pthread_key_t poolKey;
static pthread_once_t initOnceToken = PTHREAD_ONCE_INIT;
////////////////////////////////////////////////////////////
/// \brief (local function) Drain one more time the pool
/// but this time don't create a new one.
///
////////////////////////////////////////////////////////////
static void destroyPool(void* data)
{ {
NSAutoreleasePool* pool = (NSAutoreleasePool*)data;
[pool drain]; [pool drain];
} }
} // namespace sf
////////////////////////////////////////////////////////////
/// \brief (local function) Init the pthread key for the pool
///
////////////////////////////////////////////////////////////
static void createPoolKey(void)
{
pthread_key_create(&poolKey, destroyPool);
}
////////////////////////////////////////////////////////////
/// \brief (local function) Store a new pool for this thread
///
////////////////////////////////////////////////////////////
static void createNewPool(void)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
pthread_setspecific(poolKey, pool);
}
////////////////////////////////////////////////////////////
void ensureThreadHasPool(void)
{
pthread_once(&initOnceToken, createPoolKey);
if (pthread_getspecific(poolKey) == NULL)
{
createNewPool();
}
}
////////////////////////////////////////////////////////////
void drainThreadPool(void)
{
void* data = pthread_getspecific(poolKey);
assert(data != NULL);
// Drain the pool but keep it alive by creating a new one
destroyPool(data);
createNewPool();
}

View File

@ -25,6 +25,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/OSX/AutoreleasePoolWrapper.hpp>
#include <SFML/Window/OSX/ClipboardImpl.hpp> #include <SFML/Window/OSX/ClipboardImpl.hpp>
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
@ -37,6 +38,7 @@ namespace priv
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
String ClipboardImpl::getString() String ClipboardImpl::getString()
{ {
AutoreleasePool pool;
NSPasteboard* pboard = [NSPasteboard generalPasteboard]; NSPasteboard* pboard = [NSPasteboard generalPasteboard];
NSString* data = [pboard stringForType:NSPasteboardTypeString]; NSString* data = [pboard stringForType:NSPasteboardTypeString];
@ -50,6 +52,7 @@ String ClipboardImpl::getString()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void ClipboardImpl::setString(const String& text) void ClipboardImpl::setString(const String& text)
{ {
AutoreleasePool pool;
std::basic_string<Uint8> utf8 = text.toUtf8(); std::basic_string<Uint8> utf8 = text.toUtf8();
NSString* data = [[NSString alloc] initWithBytes:utf8.data() NSString* data = [[NSString alloc] initWithBytes:utf8.data()
length:utf8.length() length:utf8.length()

View File

@ -27,8 +27,8 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/OSX/CursorImpl.hpp> #include <SFML/Window/OSX/CursorImpl.hpp>
#include <SFML/Window/OSX/AutoreleasePoolWrapper.hpp>
#import <SFML/Window/OSX/AutoreleasePoolWrapper.h>
#import <SFML/Window/OSX/NSImage+raw.h> #import <SFML/Window/OSX/NSImage+raw.h>
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
@ -53,17 +53,13 @@ namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
CursorImpl::CursorImpl() : CursorImpl::CursorImpl() : m_cursor(nil) {}
m_cursor(nil)
{
// Just ask for a pool
ensureThreadHasPool();
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
CursorImpl::~CursorImpl() CursorImpl::~CursorImpl()
{ {
AutoreleasePool pool;
[m_cursor release]; [m_cursor release];
} }
@ -71,6 +67,7 @@ CursorImpl::~CursorImpl()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot) bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot)
{ {
AutoreleasePool pool;
if (m_cursor) if (m_cursor)
{ {
[m_cursor release]; [m_cursor release];
@ -89,6 +86,7 @@ bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hot
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool CursorImpl::loadFromSystem(Cursor::Type type) bool CursorImpl::loadFromSystem(Cursor::Type type)
{ {
AutoreleasePool pool;
NSCursor* newCursor = nil; NSCursor* newCursor = nil;
switch (type) switch (type)

View File

@ -28,6 +28,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/VideoMode.hpp> #include <SFML/Window/VideoMode.hpp>
#include <SFML/Window/Window.hpp> #include <SFML/Window/Window.hpp>
#include <SFML/Window/OSX/AutoreleasePoolWrapper.hpp>
#include <SFML/Window/OSX/InputImpl.hpp> #include <SFML/Window/OSX/InputImpl.hpp>
#include <SFML/Window/OSX/HIDInputManager.hpp> #include <SFML/Window/OSX/HIDInputManager.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
@ -125,6 +126,7 @@ SFOpenGLView* getSFOpenGLViewFromSFMLWindow(const WindowBase& window)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool InputImpl::isKeyPressed(Keyboard::Key key) bool InputImpl::isKeyPressed(Keyboard::Key key)
{ {
AutoreleasePool pool;
return HIDInputManager::getInstance().isKeyPressed(key); return HIDInputManager::getInstance().isKeyPressed(key);
} }
@ -139,6 +141,7 @@ void InputImpl::setVirtualKeyboardVisible(bool /*visible*/)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool InputImpl::isMouseButtonPressed(Mouse::Button button) bool InputImpl::isMouseButtonPressed(Mouse::Button button)
{ {
AutoreleasePool pool;
NSUInteger state = [NSEvent pressedMouseButtons]; NSUInteger state = [NSEvent pressedMouseButtons];
NSUInteger flag = 1 << button; NSUInteger flag = 1 << button;
return (state & flag) != 0; return (state & flag) != 0;
@ -148,6 +151,7 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Vector2i InputImpl::getMousePosition() Vector2i InputImpl::getMousePosition()
{ {
AutoreleasePool pool;
// Reverse Y axis to match SFML coord. // Reverse Y axis to match SFML coord.
NSPoint pos = [NSEvent mouseLocation]; NSPoint pos = [NSEvent mouseLocation];
pos.y = sf::VideoMode::getDesktopMode().height - pos.y; pos.y = sf::VideoMode::getDesktopMode().height - pos.y;
@ -160,6 +164,7 @@ Vector2i InputImpl::getMousePosition()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Vector2i InputImpl::getMousePosition(const WindowBase& relativeTo) Vector2i InputImpl::getMousePosition(const WindowBase& relativeTo)
{ {
AutoreleasePool pool;
SFOpenGLView* view = getSFOpenGLViewFromSFMLWindow(relativeTo); SFOpenGLView* view = getSFOpenGLViewFromSFMLWindow(relativeTo);
// No view ? // No view ?
@ -177,6 +182,7 @@ Vector2i InputImpl::getMousePosition(const WindowBase& relativeTo)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void InputImpl::setMousePosition(const Vector2i& position) void InputImpl::setMousePosition(const Vector2i& position)
{ {
AutoreleasePool pool;
// Here we don't need to reverse the coordinates. // Here we don't need to reverse the coordinates.
int scale = [[NSScreen mainScreen] backingScaleFactor]; int scale = [[NSScreen mainScreen] backingScaleFactor];
CGPoint pos = CGPointMake(position.x / scale, position.y / scale); CGPoint pos = CGPointMake(position.x / scale, position.y / scale);
@ -195,6 +201,7 @@ void InputImpl::setMousePosition(const Vector2i& position)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void InputImpl::setMousePosition(const Vector2i& position, const WindowBase& relativeTo) void InputImpl::setMousePosition(const Vector2i& position, const WindowBase& relativeTo)
{ {
AutoreleasePool pool;
SFOpenGLView* view = getSFOpenGLViewFromSFMLWindow(relativeTo); SFOpenGLView* view = getSFOpenGLViewFromSFMLWindow(relativeTo);
// No view ? // No view ?

View File

@ -27,6 +27,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/JoystickImpl.hpp> #include <SFML/Window/JoystickImpl.hpp>
#include <SFML/Window/OSX/AutoreleasePoolWrapper.hpp>
#include <SFML/Window/OSX/HIDInputManager.hpp> #include <SFML/Window/OSX/HIDInputManager.hpp>
#include <SFML/Window/OSX/HIDJoystickManager.hpp> #include <SFML/Window/OSX/HIDJoystickManager.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
@ -106,6 +107,7 @@ void JoystickImpl::cleanup()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool JoystickImpl::isConnected(unsigned int index) bool JoystickImpl::isConnected(unsigned int index)
{ {
AutoreleasePool pool;
bool state = false; // Is the index-th joystick connected? bool state = false; // Is the index-th joystick connected?
// First, let's check if the device was previously detected: // First, let's check if the device was previously detected:
@ -180,6 +182,7 @@ bool JoystickImpl::isConnected(unsigned int index)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool JoystickImpl::open(unsigned int index) bool JoystickImpl::open(unsigned int index)
{ {
AutoreleasePool pool;
m_index = index; m_index = index;
m_hat = NULL; m_hat = NULL;
Location deviceLoc = m_locationIDs[index]; // The device we need to load Location deviceLoc = m_locationIDs[index]; // The device we need to load
@ -325,6 +328,7 @@ bool JoystickImpl::open(unsigned int index)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void JoystickImpl::close() void JoystickImpl::close()
{ {
AutoreleasePool pool;
for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it) for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it)
CFRelease(*it); CFRelease(*it);
m_buttons.clear(); m_buttons.clear();
@ -345,6 +349,7 @@ void JoystickImpl::close()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
JoystickCaps JoystickImpl::getCapabilities() const JoystickCaps JoystickImpl::getCapabilities() const
{ {
AutoreleasePool pool;
JoystickCaps caps; JoystickCaps caps;
// Buttons: // Buttons:
@ -364,6 +369,7 @@ JoystickCaps JoystickImpl::getCapabilities() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Joystick::Identification JoystickImpl::getIdentification() const Joystick::Identification JoystickImpl::getIdentification() const
{ {
AutoreleasePool pool;
return m_identification; return m_identification;
} }
@ -371,6 +377,7 @@ Joystick::Identification JoystickImpl::getIdentification() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
JoystickState JoystickImpl::update() JoystickState JoystickImpl::update()
{ {
AutoreleasePool pool;
static const JoystickState disconnectedState; // return this if joystick was disconnected static const JoystickState disconnectedState; // return this if joystick was disconnected
JoystickState state; // otherwise return that JoystickState state; // otherwise return that
state.connected = true; state.connected = true;

View File

@ -52,6 +52,8 @@
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
+(void)setUpMenuBar +(void)setUpMenuBar
{ {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
[SFApplication sharedApplication]; // Make sure NSApp exists [SFApplication sharedApplication]; // Make sure NSApp exists
// Set the main menu bar // Set the main menu bar
@ -76,6 +78,8 @@
NSMenu* windowMenu = [[SFApplication newWindowMenu] autorelease]; NSMenu* windowMenu = [[SFApplication newWindowMenu] autorelease];
[windowItem setSubmenu:windowMenu]; [windowItem setSubmenu:windowMenu];
[NSApp setWindowsMenu:windowMenu]; [NSApp setWindowsMenu:windowMenu];
[pool drain];
} }
@ -98,6 +102,8 @@
// -------------------- // --------------------
// Quit AppName Command+Q // Quit AppName Command+Q
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSString* appName = [SFApplication applicationName]; NSString* appName = [SFApplication applicationName];
// APPLE MENU // APPLE MENU
@ -154,6 +160,8 @@
action:@selector(terminate:) action:@selector(terminate:)
keyEquivalent:@"q"]; keyEquivalent:@"q"];
[pool drain];
return appleMenu; return appleMenu;
} }

View File

@ -26,14 +26,13 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/OSX/AutoreleasePoolWrapper.hpp>
#include <SFML/Window/OSX/SFContext.hpp> #include <SFML/Window/OSX/SFContext.hpp>
#include <SFML/Window/OSX/WindowImplCocoa.hpp> #include <SFML/Window/OSX/WindowImplCocoa.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#include <dlfcn.h> #include <dlfcn.h>
#include <stdint.h> #include <stdint.h>
#import <SFML/Window/OSX/AutoreleasePoolWrapper.h>
namespace sf namespace sf
{ {
namespace priv namespace priv
@ -46,9 +45,7 @@ m_context(0),
m_view(0), m_view(0),
m_window(0) m_window(0)
{ {
// Ask for a pool. AutoreleasePool pool;
ensureThreadHasPool();
// Create the context // Create the context
createContext(shared, createContext(shared,
VideoMode::getDesktopMode().bitsPerPixel, VideoMode::getDesktopMode().bitsPerPixel,
@ -63,9 +60,7 @@ m_context(0),
m_view(0), m_view(0),
m_window(0) m_window(0)
{ {
// Ask for a pool. AutoreleasePool pool;
ensureThreadHasPool();
// Create the context. // Create the context.
createContext(shared, bitsPerPixel, settings); createContext(shared, bitsPerPixel, settings);
@ -82,12 +77,10 @@ m_context(0),
m_view(0), m_view(0),
m_window(0) m_window(0)
{ {
AutoreleasePool pool;
// Ensure the process is setup in order to create a valid window. // Ensure the process is setup in order to create a valid window.
WindowImplCocoa::setUpProcess(); WindowImplCocoa::setUpProcess();
// Ask for a pool.
ensureThreadHasPool();
// Create the context. // Create the context.
createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, settings); createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, settings);
@ -106,6 +99,7 @@ m_window(0)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SFContext::~SFContext() SFContext::~SFContext()
{ {
AutoreleasePool pool;
// Notify unshared OpenGL resources of context destruction // Notify unshared OpenGL resources of context destruction
cleanupUnsharedResources(); cleanupUnsharedResources();
@ -124,6 +118,7 @@ SFContext::~SFContext()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlFunctionPointer SFContext::getFunction(const char* name) GlFunctionPointer SFContext::getFunction(const char* name)
{ {
AutoreleasePool pool;
static void* image = NULL; static void* image = NULL;
if (!image) if (!image)
@ -136,6 +131,7 @@ GlFunctionPointer SFContext::getFunction(const char* name)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool SFContext::makeCurrent(bool current) bool SFContext::makeCurrent(bool current)
{ {
AutoreleasePool pool;
if (current) if (current)
{ {
[m_context makeCurrentContext]; [m_context makeCurrentContext];
@ -152,6 +148,7 @@ bool SFContext::makeCurrent(bool current)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SFContext::display() void SFContext::display()
{ {
AutoreleasePool pool;
[m_context flushBuffer]; [m_context flushBuffer];
} }
@ -159,6 +156,7 @@ void SFContext::display()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SFContext::setVerticalSyncEnabled(bool enabled) void SFContext::setVerticalSyncEnabled(bool enabled)
{ {
AutoreleasePool pool;
GLint swapInterval = enabled ? 1 : 0; GLint swapInterval = enabled ? 1 : 0;
[m_context setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; [m_context setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
@ -170,6 +168,7 @@ void SFContext::createContext(SFContext* shared,
unsigned int bitsPerPixel, unsigned int bitsPerPixel,
const ContextSettings& settings) const ContextSettings& settings)
{ {
AutoreleasePool pool;
// Save the settings. (OpenGL version is updated elsewhere.) // Save the settings. (OpenGL version is updated elsewhere.)
m_settings = settings; m_settings = settings;

View File

@ -26,10 +26,10 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/OSX/AutoreleasePoolWrapper.hpp>
#include <SFML/Window/OSX/WindowImplCocoa.hpp> #include <SFML/Window/OSX/WindowImplCocoa.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#import <SFML/Window/OSX/AutoreleasePoolWrapper.h>
#import <SFML/Window/OSX/cpp_objc_conversion.h> #import <SFML/Window/OSX/cpp_objc_conversion.h>
#import <SFML/Window/OSX/Scaling.h> #import <SFML/Window/OSX/Scaling.h>
#import <SFML/Window/OSX/SFApplication.h> #import <SFML/Window/OSX/SFApplication.h>
@ -59,6 +59,7 @@ namespace
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
void hideMouseCursor() void hideMouseCursor()
{ {
AutoreleasePool pool;
if (!isCursorHidden) if (!isCursorHidden)
{ {
[NSCursor hide]; [NSCursor hide];
@ -70,6 +71,7 @@ void hideMouseCursor()
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
void showMouseCursor() void showMouseCursor()
{ {
AutoreleasePool pool;
if (isCursorHidden) if (isCursorHidden)
{ {
[NSCursor unhide]; [NSCursor unhide];
@ -84,9 +86,7 @@ void showMouseCursor()
WindowImplCocoa::WindowImplCocoa(WindowHandle handle) : WindowImplCocoa::WindowImplCocoa(WindowHandle handle) :
m_showCursor(true) m_showCursor(true)
{ {
// Ask for a pool. AutoreleasePool pool;
ensureThreadHasPool();
// Treat the handle as it real type // Treat the handle as it real type
id nsHandle = (id)handle; id nsHandle = (id)handle;
if ([nsHandle isKindOfClass:[NSWindow class]]) if ([nsHandle isKindOfClass:[NSWindow class]])
@ -126,12 +126,10 @@ WindowImplCocoa::WindowImplCocoa(VideoMode mode,
const ContextSettings& /*settings*/) : const ContextSettings& /*settings*/) :
m_showCursor(true) m_showCursor(true)
{ {
AutoreleasePool pool;
// Transform the app process. // Transform the app process.
setUpProcess(); setUpProcess();
// Ask for a pool.
ensureThreadHasPool();
// Use backing size // Use backing size
scaleInWidthHeight(mode, nil); scaleInWidthHeight(mode, nil);
@ -147,8 +145,12 @@ m_showCursor(true)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImplCocoa::~WindowImplCocoa() WindowImplCocoa::~WindowImplCocoa()
{ {
AutoreleasePool pool;
[m_delegate closeWindow]; [m_delegate closeWindow];
// Tell the window/view controller (and the OpenGL view) that the delegate
// (this object) no longer exists to prevent events being sent to the window
// after it has been deleted.
[m_delegate setRequesterTo:0];
[m_delegate release]; [m_delegate release];
// Put the next window in front, if any. // Put the next window in front, if any.
@ -159,16 +161,13 @@ WindowImplCocoa::~WindowImplCocoa()
if ([nextWindow isVisible]) if ([nextWindow isVisible])
[nextWindow makeKeyAndOrderFront:nil]; [nextWindow makeKeyAndOrderFront:nil];
} }
drainThreadPool(); // Make sure everything was freed
// This solve some issue when sf::Window::Create is called for the
// second time (nothing was render until the function was called again)
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::applyContext(NSOpenGLContextRef context) const void WindowImplCocoa::applyContext(NSOpenGLContextRef context) const
{ {
AutoreleasePool pool;
[m_delegate applyContext:context]; [m_delegate applyContext:context];
} }
@ -176,6 +175,7 @@ void WindowImplCocoa::applyContext(NSOpenGLContextRef context) const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::setUpProcess(void) void WindowImplCocoa::setUpProcess(void)
{ {
AutoreleasePool pool;
static bool isTheProcessSetAsApplication = false; static bool isTheProcessSetAsApplication = false;
if (!isTheProcessSetAsApplication) if (!isTheProcessSetAsApplication)
@ -398,8 +398,8 @@ void WindowImplCocoa::textEntered(unichar charcode)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::processEvents() void WindowImplCocoa::processEvents()
{ {
AutoreleasePool pool;
[m_delegate processEvent]; [m_delegate processEvent];
drainThreadPool(); // Reduce memory footprint
} }
#pragma mark #pragma mark
@ -408,6 +408,7 @@ void WindowImplCocoa::processEvents()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowHandle WindowImplCocoa::getSystemHandle() const WindowHandle WindowImplCocoa::getSystemHandle() const
{ {
AutoreleasePool pool;
return [m_delegate getSystemHandle]; return [m_delegate getSystemHandle];
} }
@ -415,6 +416,7 @@ WindowHandle WindowImplCocoa::getSystemHandle() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Vector2i WindowImplCocoa::getPosition() const Vector2i WindowImplCocoa::getPosition() const
{ {
AutoreleasePool pool;
NSPoint pos = [m_delegate position]; NSPoint pos = [m_delegate position];
sf::Vector2i ret(pos.x, pos.y); sf::Vector2i ret(pos.x, pos.y);
scaleOutXY(ret, m_delegate); scaleOutXY(ret, m_delegate);
@ -425,6 +427,7 @@ Vector2i WindowImplCocoa::getPosition() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::setPosition(const Vector2i& position) void WindowImplCocoa::setPosition(const Vector2i& position)
{ {
AutoreleasePool pool;
sf::Vector2i backingPosition = position; sf::Vector2i backingPosition = position;
scaleInXY(backingPosition, m_delegate); scaleInXY(backingPosition, m_delegate);
[m_delegate setWindowPositionToX:backingPosition.x Y:backingPosition.y]; [m_delegate setWindowPositionToX:backingPosition.x Y:backingPosition.y];
@ -434,6 +437,7 @@ void WindowImplCocoa::setPosition(const Vector2i& position)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Vector2u WindowImplCocoa::getSize() const Vector2u WindowImplCocoa::getSize() const
{ {
AutoreleasePool pool;
NSSize size = [m_delegate size]; NSSize size = [m_delegate size];
Vector2u ret(size.width, size.height); Vector2u ret(size.width, size.height);
scaleOutXY(ret, m_delegate); scaleOutXY(ret, m_delegate);
@ -453,6 +457,7 @@ void WindowImplCocoa::setSize(const Vector2u& size)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::setTitle(const String& title) void WindowImplCocoa::setTitle(const String& title)
{ {
AutoreleasePool pool;
[m_delegate changeTitle:sfStringToNSString(title)]; [m_delegate changeTitle:sfStringToNSString(title)];
} }
@ -460,6 +465,7 @@ void WindowImplCocoa::setTitle(const String& title)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::setIcon(unsigned int width, unsigned int height, const Uint8* pixels) void WindowImplCocoa::setIcon(unsigned int width, unsigned int height, const Uint8* pixels)
{ {
AutoreleasePool pool;
[m_delegate setIconTo:width by:height with:pixels]; [m_delegate setIconTo:width by:height with:pixels];
} }
@ -467,6 +473,7 @@ void WindowImplCocoa::setIcon(unsigned int width, unsigned int height, const Uin
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::setVisible(bool visible) void WindowImplCocoa::setVisible(bool visible)
{ {
AutoreleasePool pool;
if (visible) if (visible)
[m_delegate showWindow]; [m_delegate showWindow];
else else
@ -477,6 +484,7 @@ void WindowImplCocoa::setVisible(bool visible)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::setMouseCursorVisible(bool visible) void WindowImplCocoa::setMouseCursorVisible(bool visible)
{ {
AutoreleasePool pool;
m_showCursor = visible; m_showCursor = visible;
// If the mouse is over the window, we apply the new setting // If the mouse is over the window, we apply the new setting
@ -493,6 +501,7 @@ void WindowImplCocoa::setMouseCursorVisible(bool visible)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::setMouseCursorGrabbed(bool grabbed) void WindowImplCocoa::setMouseCursorGrabbed(bool grabbed)
{ {
AutoreleasePool pool;
[m_delegate setCursorGrabbed:grabbed]; [m_delegate setCursorGrabbed:grabbed];
} }
@ -500,6 +509,7 @@ void WindowImplCocoa::setMouseCursorGrabbed(bool grabbed)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::setMouseCursor(const CursorImpl& cursor) void WindowImplCocoa::setMouseCursor(const CursorImpl& cursor)
{ {
AutoreleasePool pool;
[m_delegate setCursor:cursor.m_cursor]; [m_delegate setCursor:cursor.m_cursor];
} }
@ -507,6 +517,7 @@ void WindowImplCocoa::setMouseCursor(const CursorImpl& cursor)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::setKeyRepeatEnabled(bool enabled) void WindowImplCocoa::setKeyRepeatEnabled(bool enabled)
{ {
AutoreleasePool pool;
if (enabled) if (enabled)
[m_delegate enableKeyRepeat]; [m_delegate enableKeyRepeat];
else else
@ -517,6 +528,7 @@ void WindowImplCocoa::setKeyRepeatEnabled(bool enabled)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplCocoa::requestFocus() void WindowImplCocoa::requestFocus()
{ {
AutoreleasePool pool;
[m_delegate requestFocus]; [m_delegate requestFocus];
} }
@ -524,6 +536,7 @@ void WindowImplCocoa::requestFocus()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool WindowImplCocoa::hasFocus() const bool WindowImplCocoa::hasFocus() const
{ {
AutoreleasePool pool;
return [m_delegate hasFocus]; return [m_delegate hasFocus];
} }