From 494e4585d1177b12bdaacbb3aa381d0514f5252f Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Sun, 30 Jul 2023 07:05:25 -0700 Subject: [PATCH] fix(macos): ensure app delegate is defined (#775) --- .github/fix-macos-delegate-usage.md | 5 +++ src/platform_impl/macos/event_loop.rs | 45 +++++++++++++-------------- 2 files changed, 26 insertions(+), 24 deletions(-) create mode 100644 .github/fix-macos-delegate-usage.md diff --git a/.github/fix-macos-delegate-usage.md b/.github/fix-macos-delegate-usage.md new file mode 100644 index 000000000..8fb31ef75 --- /dev/null +++ b/.github/fix-macos-delegate-usage.md @@ -0,0 +1,5 @@ +--- +"tao": patch +--- + +Ensure the macOS app delegate is defined before accessing it. \ No newline at end of file diff --git a/src/platform_impl/macos/event_loop.rs b/src/platform_impl/macos/event_loop.rs index 6c8c85231..d2faba4be 100644 --- a/src/platform_impl/macos/event_loop.rs +++ b/src/platform_impl/macos/event_loop.rs @@ -139,8 +139,28 @@ impl EventLoop { pub fn new() -> Self { let panic_info: Rc = 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, @@ -166,29 +186,6 @@ impl EventLoop { where F: FnMut(Event<'_, T>, &RootWindowTarget, &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