|
| 1 | +#[cfg(target_os = "macos")] |
| 2 | +mod platform { |
| 3 | + use std::sync::OnceLock; |
| 4 | + |
| 5 | + use objc2::rc::Retained; |
| 6 | + use objc2::runtime::{AnyClass, AnyObject, ClassBuilder, Sel}; |
| 7 | + use objc2::{msg_send, msg_send_id, sel}; |
| 8 | + use objc2_foundation::MainThreadMarker; |
| 9 | + |
| 10 | + const CORE_EVENT_CLASS: u32 = 0x6165_7674; // 'aevt' |
| 11 | + const REOPEN_APPLICATION_EVENT: u32 = 0x7261_7070; // 'rapp' |
| 12 | + |
| 13 | + static HANDLER: OnceLock<Retained<AnyObject>> = OnceLock::new(); |
| 14 | + |
| 15 | + extern "C" fn handle_reopen( |
| 16 | + _this: &AnyObject, |
| 17 | + _cmd: Sel, |
| 18 | + _event: Option<&AnyObject>, |
| 19 | + _reply: Option<&AnyObject>, |
| 20 | + ) { |
| 21 | + crate::instance::signal_show_request(); |
| 22 | + } |
| 23 | + |
| 24 | + pub(super) fn install_reopen_handler() { |
| 25 | + let Some(_mtm) = MainThreadMarker::new() else { |
| 26 | + log::warn!("Cannot install macOS reopen handler: not on the main thread."); |
| 27 | + return; |
| 28 | + }; |
| 29 | + |
| 30 | + HANDLER.get_or_init(|| { |
| 31 | + let nsobject = AnyClass::get("NSObject").expect("NSObject class missing"); |
| 32 | + let handler_class = if let Some(mut builder) = |
| 33 | + ClassBuilder::new("ImpactorReopenHandler", nsobject) |
| 34 | + { |
| 35 | + unsafe { |
| 36 | + builder.add_method( |
| 37 | + sel!(handleReopen:withReplyEvent:), |
| 38 | + handle_reopen |
| 39 | + as extern "C" fn(&AnyObject, Sel, Option<&AnyObject>, Option<&AnyObject>), |
| 40 | + ); |
| 41 | + } |
| 42 | + builder.register() |
| 43 | + } else { |
| 44 | + AnyClass::get("ImpactorReopenHandler") |
| 45 | + .expect("ImpactorReopenHandler class missing") |
| 46 | + }; |
| 47 | + |
| 48 | + let handler: Retained<AnyObject> = unsafe { msg_send_id![handler_class, new] }; |
| 49 | + |
| 50 | + let Some(manager_class) = AnyClass::get("NSAppleEventManager") else { |
| 51 | + log::warn!("NSAppleEventManager class missing"); |
| 52 | + return handler; |
| 53 | + }; |
| 54 | + |
| 55 | + let manager: Retained<AnyObject> = |
| 56 | + unsafe { msg_send_id![manager_class, sharedAppleEventManager] }; |
| 57 | + |
| 58 | + unsafe { |
| 59 | + let _: () = msg_send![ |
| 60 | + &*manager, |
| 61 | + setEventHandler: &*handler |
| 62 | + andSelector: sel!(handleReopen:withReplyEvent:) |
| 63 | + forEventClass: CORE_EVENT_CLASS |
| 64 | + andEventID: REOPEN_APPLICATION_EVENT |
| 65 | + ]; |
| 66 | + } |
| 67 | + |
| 68 | + handler |
| 69 | + }); |
| 70 | + } |
| 71 | +} |
| 72 | + |
| 73 | +#[cfg(not(target_os = "macos"))] |
| 74 | +mod platform { |
| 75 | + pub(super) fn install_reopen_handler() {} |
| 76 | +} |
| 77 | + |
| 78 | +pub(crate) fn install_reopen_handler() { |
| 79 | + platform::install_reopen_handler(); |
| 80 | +} |
0 commit comments