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-graphics = "0.22"
|
||||
dispatch = "0.2.0"
|
||||
scopeguard = "1.1"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies.core-video-sys]
|
||||
version = "0.1.4"
|
||||
|
|
|
@ -15,11 +15,12 @@ use std::{
|
|||
use cocoa::{
|
||||
appkit::{NSApp, NSApplication, NSWindow},
|
||||
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::{
|
||||
dpi::LogicalSize,
|
||||
|
@ -403,7 +404,7 @@ impl AppState {
|
|||
};
|
||||
|
||||
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)
|
||||
&& !dialog_open
|
||||
&& !dialog_is_closing
|
||||
|
@ -412,7 +413,7 @@ impl AppState {
|
|||
// To stop event loop immediately, we need to post some event here.
|
||||
post_dummy_event(app);
|
||||
}
|
||||
pool.drain();
|
||||
});
|
||||
|
||||
if window_count > 0 {
|
||||
let window: id = msg_send![windows, objectAtIndex:0];
|
||||
|
|
|
@ -14,10 +14,9 @@ use std::{
|
|||
use cocoa::{
|
||||
appkit::{NSApp, NSEventType::NSApplicationDefined},
|
||||
base::{id, nil, YES},
|
||||
foundation::{NSAutoreleasePool, NSPoint},
|
||||
foundation::NSPoint,
|
||||
};
|
||||
|
||||
use scopeguard::defer;
|
||||
use objc::rc::autoreleasepool;
|
||||
|
||||
use crate::{
|
||||
event::Event,
|
||||
|
@ -115,9 +114,9 @@ impl<T> EventLoop<T> {
|
|||
let app: id = msg_send![APP_CLASS.0, sharedApplication];
|
||||
|
||||
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![pool, drain];
|
||||
});
|
||||
delegate
|
||||
};
|
||||
let panic_info: Rc<PanicInfo> = Default::default();
|
||||
|
@ -162,9 +161,7 @@ impl<T> EventLoop<T> {
|
|||
|
||||
self._callback = Some(Rc::clone(&callback));
|
||||
|
||||
unsafe {
|
||||
let pool = NSAutoreleasePool::new(nil);
|
||||
defer!(pool.drain());
|
||||
autoreleasepool(|| unsafe {
|
||||
let app = NSApp();
|
||||
assert_ne!(app, nil);
|
||||
|
||||
|
@ -180,7 +177,7 @@ impl<T> EventLoop<T> {
|
|||
resume_unwind(panic);
|
||||
}
|
||||
AppState::exit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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::base::{nil, selector};
|
||||
use cocoa::foundation::{NSAutoreleasePool, NSProcessInfo, NSString};
|
||||
use cocoa::foundation::{NSProcessInfo, NSString};
|
||||
use objc::{
|
||||
rc::autoreleasepool,
|
||||
runtime::{Object, Sel},
|
||||
|
@ -13,11 +14,11 @@ struct KeyEquivalent<'a> {
|
|||
|
||||
pub fn initialize() {
|
||||
autoreleasepool(|| unsafe {
|
||||
let menubar = NSMenu::new(nil).autorelease();
|
||||
let app_menu_item = NSMenuItem::new(nil).autorelease();
|
||||
menubar.addItem_(app_menu_item);
|
||||
let menubar = IdRef::new(NSMenu::new(nil));
|
||||
let app_menu_item = IdRef::new(NSMenuItem::new(nil));
|
||||
menubar.addItem_(*app_menu_item);
|
||||
let app = NSApp();
|
||||
app.setMainMenu_(menubar);
|
||||
app.setMainMenu_(*menubar);
|
||||
|
||||
let app_menu = NSMenu::new(nil);
|
||||
let process_name = NSProcessInfo::processInfo(nil).processName();
|
||||
|
|
|
@ -25,6 +25,7 @@ pub use self::{
|
|||
use crate::{
|
||||
error::OsError as RootOsError, event::DeviceId as RootDeviceId, window::WindowAttributes,
|
||||
};
|
||||
use objc::rc::autoreleasepool;
|
||||
|
||||
pub(crate) use crate::icon::NoIcon as PlatformIcon;
|
||||
|
||||
|
@ -69,7 +70,7 @@ impl Window {
|
|||
attributes: WindowAttributes,
|
||||
pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
||||
) -> Result<Self, RootOsError> {
|
||||
let (window, _delegate) = UnownedWindow::new(attributes, pl_attribs)?;
|
||||
let (window, _delegate) = autoreleasepool(|| UnownedWindow::new(attributes, pl_attribs))?;
|
||||
Ok(Window { window, _delegate })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::ops::{BitAnd, Deref};
|
|||
use cocoa::{
|
||||
appkit::{NSApp, NSWindowStyleMask},
|
||||
base::{id, nil},
|
||||
foundation::{NSAutoreleasePool, NSPoint, NSRect, NSString, NSUInteger},
|
||||
foundation::{NSPoint, NSRect, NSString, NSUInteger},
|
||||
};
|
||||
use core_graphics::display::CGDisplay;
|
||||
use objc::runtime::{Class, Object, Sel, BOOL, YES};
|
||||
|
@ -61,9 +61,7 @@ impl Drop for IdRef {
|
|||
fn drop(&mut self) {
|
||||
if self.0 != nil {
|
||||
unsafe {
|
||||
let pool = NSAutoreleasePool::new(nil);
|
||||
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 =
|
||||
msg_send![class!(NSNotificationCenter), defaultCenter];
|
||||
let notification_name =
|
||||
NSString::alloc(nil).init_str("NSViewFrameDidChangeNotification");
|
||||
IdRef::new(NSString::alloc(nil).init_str("NSViewFrameDidChangeNotification"));
|
||||
let _: () = msg_send![
|
||||
notification_center,
|
||||
addObserver: this
|
||||
|
|
|
@ -38,11 +38,12 @@ use cocoa::{
|
|||
NSRequestUserAttentionType, NSScreen, NSView, NSWindow, NSWindowButton, NSWindowStyleMask,
|
||||
},
|
||||
base::{id, nil},
|
||||
foundation::{NSAutoreleasePool, NSDictionary, NSPoint, NSRect, NSSize},
|
||||
foundation::{NSDictionary, NSPoint, NSRect, NSSize},
|
||||
};
|
||||
use core_graphics::display::{CGDisplay, CGDisplayMode};
|
||||
use objc::{
|
||||
declare::ClassDecl,
|
||||
rc::autoreleasepool,
|
||||
runtime::{Class, Object, Sel, BOOL, NO, YES},
|
||||
};
|
||||
|
||||
|
@ -118,8 +119,7 @@ fn create_window(
|
|||
attrs: &WindowAttributes,
|
||||
pl_attrs: &PlatformSpecificWindowBuilderAttributes,
|
||||
) -> Option<IdRef> {
|
||||
unsafe {
|
||||
let pool = NSAutoreleasePool::new(nil);
|
||||
autoreleasepool(|| unsafe {
|
||||
let screen = match attrs.fullscreen {
|
||||
Some(Fullscreen::Borderless(Some(RootMonitorHandle { inner: ref monitor })))
|
||||
| Some(Fullscreen::Exclusive(RootVideoMode {
|
||||
|
@ -241,9 +241,8 @@ fn create_window(
|
|||
}
|
||||
ns_window
|
||||
});
|
||||
pool.drain();
|
||||
res
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
struct WindowClass(*const Class);
|
||||
|
@ -336,17 +335,11 @@ impl UnownedWindow {
|
|||
}
|
||||
trace!("Creating new window");
|
||||
|
||||
let pool = unsafe { NSAutoreleasePool::new(nil) };
|
||||
let ns_window = create_window(&win_attribs, &pl_attribs).ok_or_else(|| {
|
||||
unsafe { pool.drain() };
|
||||
os_error!(OsError::CreationError("Couldn't create `NSWindow`"))
|
||||
})?;
|
||||
let ns_window = create_window(&win_attribs, &pl_attribs)
|
||||
.ok_or_else(|| os_error!(OsError::CreationError("Couldn't create `NSWindow`")))?;
|
||||
|
||||
let (ns_view, cursor_state) =
|
||||
unsafe { create_view(*ns_window, &pl_attribs) }.ok_or_else(|| {
|
||||
unsafe { pool.drain() };
|
||||
os_error!(OsError::CreationError("Couldn't create `NSView`"))
|
||||
})?;
|
||||
let (ns_view, cursor_state) = unsafe { create_view(*ns_window, &pl_attribs) }
|
||||
.ok_or_else(|| os_error!(OsError::CreationError("Couldn't create `NSView`")))?;
|
||||
|
||||
// Configure the new view as the "key view" for the window
|
||||
unsafe {
|
||||
|
@ -422,8 +415,6 @@ impl UnownedWindow {
|
|||
window.set_maximized(maximized);
|
||||
}
|
||||
|
||||
unsafe { pool.drain() };
|
||||
|
||||
Ok((window, delegate))
|
||||
}
|
||||
|
||||
|
|
|
@ -7,10 +7,11 @@ use std::{
|
|||
use cocoa::{
|
||||
appkit::{self, NSApplicationPresentationOptions, NSView, NSWindow},
|
||||
base::{id, nil},
|
||||
foundation::{NSAutoreleasePool, NSUInteger},
|
||||
foundation::NSUInteger,
|
||||
};
|
||||
use objc::{
|
||||
declare::ClassDecl,
|
||||
rc::autoreleasepool,
|
||||
runtime::{Class, Object, Sel, BOOL, NO, YES},
|
||||
};
|
||||
|
||||
|
@ -274,11 +275,11 @@ extern "C" fn window_will_close(this: &Object, _: Sel, _: id) {
|
|||
trace!("Triggered `windowWillClose:`");
|
||||
with_state(this, |state| unsafe {
|
||||
// `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
|
||||
// be called after the window closes.
|
||||
let () = msg_send![*state.ns_window, setDelegate: nil];
|
||||
pool.drain();
|
||||
});
|
||||
state.emit_event(WindowEvent::Destroyed);
|
||||
});
|
||||
trace!("Completed `windowWillClose:`");
|
||||
|
|
Loading…
Reference in a new issue