Skip to content

Commit

Permalink
fix(macos): ensure app delegate is defined (#775)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasfernog authored Jul 30, 2023
1 parent 75eb0c1 commit 494e458
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 24 deletions.
5 changes: 5 additions & 0 deletions .github/fix-macos-delegate-usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tao": patch
---

Ensure the macOS app delegate is defined before accessing it.
45 changes: 21 additions & 24 deletions src/platform_impl/macos/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,28 @@ impl<T> EventLoop<T> {
pub fn new() -> Self {
let panic_info: Rc<PanicInfo> = Default::default();
setup_control_flow_observers(Rc::downgrade(&panic_info));

let delegate = unsafe {
let is_main_thread: BOOL = msg_send!(class!(NSThread), isMainThread);
if is_main_thread == NO {
panic!("On macOS, `EventLoop` must be created on the main thread!");
}

// This must be done before `NSApp()` (equivalent to sending
// `sharedApplication`) is called anywhere else, or we'll end up
// with the wrong `NSApplication` class and the wrong thread could
// be marked as main.
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);
let _: () = msg_send![app, setDelegate:*delegate];
let _: () = msg_send![pool, drain];
delegate
};

EventLoop {
delegate: IdRef::new(nil),
delegate,
window_target: Rc::new(RootWindowTarget {
p: Default::default(),
_marker: PhantomData,
Expand All @@ -166,29 +186,6 @@ impl<T> EventLoop<T> {
where
F: FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),
{
// initialize app delegate if needed
if self.delegate.is_null() {
let delegate = unsafe {
let is_main_thread: BOOL = msg_send!(class!(NSThread), isMainThread);
if is_main_thread == NO {
panic!("On macOS, `EventLoop` must be created on the main thread!");
}

// This must be done before `NSApp()` (equivalent to sending
// `sharedApplication`) is called anywhere else, or we'll end up
// with the wrong `NSApplication` class and the wrong thread could
// be marked as main.
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);
let _: () = msg_send![app, setDelegate:*delegate];
let _: () = msg_send![pool, drain];
delegate
};
self.delegate = delegate;
}

// This transmute is always safe, in case it was reached through `run`, since our
// lifetime will be already 'static. In other cases caller should ensure that all data
// they passed to callback will actually outlive it, some apps just can't move
Expand Down

0 comments on commit 494e458

Please sign in to comment.