mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-11 13:31:29 +11:00
Use objc's autoreleasepool instead of manually with NSAutoreleasePool (#1936)
Ensures the pools are released even if we panic
This commit is contained in:
parent
657b4fd59e
commit
982ad46c83
|
@ -48,7 +48,6 @@ cocoa = "0.24"
|
||||||
core-foundation = "0.9"
|
core-foundation = "0.9"
|
||||||
core-graphics = "0.22"
|
core-graphics = "0.22"
|
||||||
dispatch = "0.2.0"
|
dispatch = "0.2.0"
|
||||||
scopeguard = "1.1"
|
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies.core-video-sys]
|
[target.'cfg(target_os = "macos")'.dependencies.core-video-sys]
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
|
|
@ -15,11 +15,12 @@ use std::{
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::{NSApp, NSApplication, NSWindow},
|
appkit::{NSApp, NSApplication, NSWindow},
|
||||||
base::{id, nil},
|
base::{id, nil},
|
||||||
foundation::{NSAutoreleasePool, NSSize},
|
foundation::NSSize,
|
||||||
|
};
|
||||||
|
use objc::{
|
||||||
|
rc::autoreleasepool,
|
||||||
|
runtime::{Object, YES},
|
||||||
};
|
};
|
||||||
use objc::runtime::YES;
|
|
||||||
|
|
||||||
use objc::runtime::Object;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::LogicalSize,
|
dpi::LogicalSize,
|
||||||
|
@ -403,7 +404,7 @@ impl AppState {
|
||||||
};
|
};
|
||||||
|
|
||||||
let dialog_is_closing = HANDLER.dialog_is_closing.load(Ordering::SeqCst);
|
let dialog_is_closing = HANDLER.dialog_is_closing.load(Ordering::SeqCst);
|
||||||
let pool = NSAutoreleasePool::new(nil);
|
autoreleasepool(|| {
|
||||||
if !INTERRUPT_EVENT_LOOP_EXIT.load(Ordering::SeqCst)
|
if !INTERRUPT_EVENT_LOOP_EXIT.load(Ordering::SeqCst)
|
||||||
&& !dialog_open
|
&& !dialog_open
|
||||||
&& !dialog_is_closing
|
&& !dialog_is_closing
|
||||||
|
@ -412,7 +413,7 @@ impl AppState {
|
||||||
// To stop event loop immediately, we need to post some event here.
|
// To stop event loop immediately, we need to post some event here.
|
||||||
post_dummy_event(app);
|
post_dummy_event(app);
|
||||||
}
|
}
|
||||||
pool.drain();
|
});
|
||||||
|
|
||||||
if window_count > 0 {
|
if window_count > 0 {
|
||||||
let window: id = msg_send![windows, objectAtIndex:0];
|
let window: id = msg_send![windows, objectAtIndex:0];
|
||||||
|
|
|
@ -14,10 +14,9 @@ use std::{
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::{NSApp, NSEventType::NSApplicationDefined},
|
appkit::{NSApp, NSEventType::NSApplicationDefined},
|
||||||
base::{id, nil, YES},
|
base::{id, nil, YES},
|
||||||
foundation::{NSAutoreleasePool, NSPoint},
|
foundation::NSPoint,
|
||||||
};
|
};
|
||||||
|
use objc::rc::autoreleasepool;
|
||||||
use scopeguard::defer;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
event::Event,
|
event::Event,
|
||||||
|
@ -115,9 +114,9 @@ impl<T> EventLoop<T> {
|
||||||
let app: id = msg_send![APP_CLASS.0, sharedApplication];
|
let app: id = msg_send![APP_CLASS.0, sharedApplication];
|
||||||
|
|
||||||
let delegate = IdRef::new(msg_send![APP_DELEGATE_CLASS.0, new]);
|
let delegate = IdRef::new(msg_send![APP_DELEGATE_CLASS.0, new]);
|
||||||
let pool = NSAutoreleasePool::new(nil);
|
autoreleasepool(|| {
|
||||||
let _: () = msg_send![app, setDelegate:*delegate];
|
let _: () = msg_send![app, setDelegate:*delegate];
|
||||||
let _: () = msg_send![pool, drain];
|
});
|
||||||
delegate
|
delegate
|
||||||
};
|
};
|
||||||
let panic_info: Rc<PanicInfo> = Default::default();
|
let panic_info: Rc<PanicInfo> = Default::default();
|
||||||
|
@ -162,9 +161,7 @@ impl<T> EventLoop<T> {
|
||||||
|
|
||||||
self._callback = Some(Rc::clone(&callback));
|
self._callback = Some(Rc::clone(&callback));
|
||||||
|
|
||||||
unsafe {
|
autoreleasepool(|| unsafe {
|
||||||
let pool = NSAutoreleasePool::new(nil);
|
|
||||||
defer!(pool.drain());
|
|
||||||
let app = NSApp();
|
let app = NSApp();
|
||||||
assert_ne!(app, nil);
|
assert_ne!(app, nil);
|
||||||
|
|
||||||
|
@ -180,7 +177,7 @@ impl<T> EventLoop<T> {
|
||||||
resume_unwind(panic);
|
resume_unwind(panic);
|
||||||
}
|
}
|
||||||
AppState::exit();
|
AppState::exit();
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_proxy(&self) -> Proxy<T> {
|
pub fn create_proxy(&self) -> Proxy<T> {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
use super::util::IdRef;
|
||||||
use cocoa::appkit::{NSApp, NSApplication, NSEventModifierFlags, NSMenu, NSMenuItem};
|
use cocoa::appkit::{NSApp, NSApplication, NSEventModifierFlags, NSMenu, NSMenuItem};
|
||||||
use cocoa::base::{nil, selector};
|
use cocoa::base::{nil, selector};
|
||||||
use cocoa::foundation::{NSAutoreleasePool, NSProcessInfo, NSString};
|
use cocoa::foundation::{NSProcessInfo, NSString};
|
||||||
use objc::{
|
use objc::{
|
||||||
rc::autoreleasepool,
|
rc::autoreleasepool,
|
||||||
runtime::{Object, Sel},
|
runtime::{Object, Sel},
|
||||||
|
@ -13,11 +14,11 @@ struct KeyEquivalent<'a> {
|
||||||
|
|
||||||
pub fn initialize() {
|
pub fn initialize() {
|
||||||
autoreleasepool(|| unsafe {
|
autoreleasepool(|| unsafe {
|
||||||
let menubar = NSMenu::new(nil).autorelease();
|
let menubar = IdRef::new(NSMenu::new(nil));
|
||||||
let app_menu_item = NSMenuItem::new(nil).autorelease();
|
let app_menu_item = IdRef::new(NSMenuItem::new(nil));
|
||||||
menubar.addItem_(app_menu_item);
|
menubar.addItem_(*app_menu_item);
|
||||||
let app = NSApp();
|
let app = NSApp();
|
||||||
app.setMainMenu_(menubar);
|
app.setMainMenu_(*menubar);
|
||||||
|
|
||||||
let app_menu = NSMenu::new(nil);
|
let app_menu = NSMenu::new(nil);
|
||||||
let process_name = NSProcessInfo::processInfo(nil).processName();
|
let process_name = NSProcessInfo::processInfo(nil).processName();
|
||||||
|
|
|
@ -25,6 +25,7 @@ pub use self::{
|
||||||
use crate::{
|
use crate::{
|
||||||
error::OsError as RootOsError, event::DeviceId as RootDeviceId, window::WindowAttributes,
|
error::OsError as RootOsError, event::DeviceId as RootDeviceId, window::WindowAttributes,
|
||||||
};
|
};
|
||||||
|
use objc::rc::autoreleasepool;
|
||||||
|
|
||||||
pub(crate) use crate::icon::NoIcon as PlatformIcon;
|
pub(crate) use crate::icon::NoIcon as PlatformIcon;
|
||||||
|
|
||||||
|
@ -69,7 +70,7 @@ impl Window {
|
||||||
attributes: WindowAttributes,
|
attributes: WindowAttributes,
|
||||||
pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
||||||
) -> Result<Self, RootOsError> {
|
) -> Result<Self, RootOsError> {
|
||||||
let (window, _delegate) = UnownedWindow::new(attributes, pl_attribs)?;
|
let (window, _delegate) = autoreleasepool(|| UnownedWindow::new(attributes, pl_attribs))?;
|
||||||
Ok(Window { window, _delegate })
|
Ok(Window { window, _delegate })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::ops::{BitAnd, Deref};
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::{NSApp, NSWindowStyleMask},
|
appkit::{NSApp, NSWindowStyleMask},
|
||||||
base::{id, nil},
|
base::{id, nil},
|
||||||
foundation::{NSAutoreleasePool, NSPoint, NSRect, NSString, NSUInteger},
|
foundation::{NSPoint, NSRect, NSString, NSUInteger},
|
||||||
};
|
};
|
||||||
use core_graphics::display::CGDisplay;
|
use core_graphics::display::CGDisplay;
|
||||||
use objc::runtime::{Class, Object, Sel, BOOL, YES};
|
use objc::runtime::{Class, Object, Sel, BOOL, YES};
|
||||||
|
@ -61,9 +61,7 @@ impl Drop for IdRef {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.0 != nil {
|
if self.0 != nil {
|
||||||
unsafe {
|
unsafe {
|
||||||
let pool = NSAutoreleasePool::new(nil);
|
|
||||||
let () = msg_send![self.0, release];
|
let () = msg_send![self.0, release];
|
||||||
pool.drain();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,7 +289,7 @@ extern "C" fn init_with_winit(this: &Object, _sel: Sel, state: *mut c_void) -> i
|
||||||
let notification_center: &Object =
|
let notification_center: &Object =
|
||||||
msg_send![class!(NSNotificationCenter), defaultCenter];
|
msg_send![class!(NSNotificationCenter), defaultCenter];
|
||||||
let notification_name =
|
let notification_name =
|
||||||
NSString::alloc(nil).init_str("NSViewFrameDidChangeNotification");
|
IdRef::new(NSString::alloc(nil).init_str("NSViewFrameDidChangeNotification"));
|
||||||
let _: () = msg_send![
|
let _: () = msg_send![
|
||||||
notification_center,
|
notification_center,
|
||||||
addObserver: this
|
addObserver: this
|
||||||
|
|
|
@ -38,11 +38,12 @@ use cocoa::{
|
||||||
NSRequestUserAttentionType, NSScreen, NSView, NSWindow, NSWindowButton, NSWindowStyleMask,
|
NSRequestUserAttentionType, NSScreen, NSView, NSWindow, NSWindowButton, NSWindowStyleMask,
|
||||||
},
|
},
|
||||||
base::{id, nil},
|
base::{id, nil},
|
||||||
foundation::{NSAutoreleasePool, NSDictionary, NSPoint, NSRect, NSSize},
|
foundation::{NSDictionary, NSPoint, NSRect, NSSize},
|
||||||
};
|
};
|
||||||
use core_graphics::display::{CGDisplay, CGDisplayMode};
|
use core_graphics::display::{CGDisplay, CGDisplayMode};
|
||||||
use objc::{
|
use objc::{
|
||||||
declare::ClassDecl,
|
declare::ClassDecl,
|
||||||
|
rc::autoreleasepool,
|
||||||
runtime::{Class, Object, Sel, BOOL, NO, YES},
|
runtime::{Class, Object, Sel, BOOL, NO, YES},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -118,8 +119,7 @@ fn create_window(
|
||||||
attrs: &WindowAttributes,
|
attrs: &WindowAttributes,
|
||||||
pl_attrs: &PlatformSpecificWindowBuilderAttributes,
|
pl_attrs: &PlatformSpecificWindowBuilderAttributes,
|
||||||
) -> Option<IdRef> {
|
) -> Option<IdRef> {
|
||||||
unsafe {
|
autoreleasepool(|| unsafe {
|
||||||
let pool = NSAutoreleasePool::new(nil);
|
|
||||||
let screen = match attrs.fullscreen {
|
let screen = match attrs.fullscreen {
|
||||||
Some(Fullscreen::Borderless(Some(RootMonitorHandle { inner: ref monitor })))
|
Some(Fullscreen::Borderless(Some(RootMonitorHandle { inner: ref monitor })))
|
||||||
| Some(Fullscreen::Exclusive(RootVideoMode {
|
| Some(Fullscreen::Exclusive(RootVideoMode {
|
||||||
|
@ -241,9 +241,8 @@ fn create_window(
|
||||||
}
|
}
|
||||||
ns_window
|
ns_window
|
||||||
});
|
});
|
||||||
pool.drain();
|
|
||||||
res
|
res
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WindowClass(*const Class);
|
struct WindowClass(*const Class);
|
||||||
|
@ -336,17 +335,11 @@ impl UnownedWindow {
|
||||||
}
|
}
|
||||||
trace!("Creating new window");
|
trace!("Creating new window");
|
||||||
|
|
||||||
let pool = unsafe { NSAutoreleasePool::new(nil) };
|
let ns_window = create_window(&win_attribs, &pl_attribs)
|
||||||
let ns_window = create_window(&win_attribs, &pl_attribs).ok_or_else(|| {
|
.ok_or_else(|| os_error!(OsError::CreationError("Couldn't create `NSWindow`")))?;
|
||||||
unsafe { pool.drain() };
|
|
||||||
os_error!(OsError::CreationError("Couldn't create `NSWindow`"))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let (ns_view, cursor_state) =
|
let (ns_view, cursor_state) = unsafe { create_view(*ns_window, &pl_attribs) }
|
||||||
unsafe { create_view(*ns_window, &pl_attribs) }.ok_or_else(|| {
|
.ok_or_else(|| os_error!(OsError::CreationError("Couldn't create `NSView`")))?;
|
||||||
unsafe { pool.drain() };
|
|
||||||
os_error!(OsError::CreationError("Couldn't create `NSView`"))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Configure the new view as the "key view" for the window
|
// Configure the new view as the "key view" for the window
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -422,8 +415,6 @@ impl UnownedWindow {
|
||||||
window.set_maximized(maximized);
|
window.set_maximized(maximized);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { pool.drain() };
|
|
||||||
|
|
||||||
Ok((window, delegate))
|
Ok((window, delegate))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,11 @@ use std::{
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::{self, NSApplicationPresentationOptions, NSView, NSWindow},
|
appkit::{self, NSApplicationPresentationOptions, NSView, NSWindow},
|
||||||
base::{id, nil},
|
base::{id, nil},
|
||||||
foundation::{NSAutoreleasePool, NSUInteger},
|
foundation::NSUInteger,
|
||||||
};
|
};
|
||||||
use objc::{
|
use objc::{
|
||||||
declare::ClassDecl,
|
declare::ClassDecl,
|
||||||
|
rc::autoreleasepool,
|
||||||
runtime::{Class, Object, Sel, BOOL, NO, YES},
|
runtime::{Class, Object, Sel, BOOL, NO, YES},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -274,11 +275,11 @@ extern "C" fn window_will_close(this: &Object, _: Sel, _: id) {
|
||||||
trace!("Triggered `windowWillClose:`");
|
trace!("Triggered `windowWillClose:`");
|
||||||
with_state(this, |state| unsafe {
|
with_state(this, |state| unsafe {
|
||||||
// `setDelegate:` retains the previous value and then autoreleases it
|
// `setDelegate:` retains the previous value and then autoreleases it
|
||||||
let pool = NSAutoreleasePool::new(nil);
|
autoreleasepool(|| {
|
||||||
// Since El Capitan, we need to be careful that delegate methods can't
|
// Since El Capitan, we need to be careful that delegate methods can't
|
||||||
// be called after the window closes.
|
// be called after the window closes.
|
||||||
let () = msg_send![*state.ns_window, setDelegate: nil];
|
let () = msg_send![*state.ns_window, setDelegate: nil];
|
||||||
pool.drain();
|
});
|
||||||
state.emit_event(WindowEvent::Destroyed);
|
state.emit_event(WindowEvent::Destroyed);
|
||||||
});
|
});
|
||||||
trace!("Completed `windowWillClose:`");
|
trace!("Completed `windowWillClose:`");
|
||||||
|
|
Loading…
Reference in a new issue