diff --git a/.changes/retain-ns-menu.md b/.changes/retain-ns-menu.md new file mode 100644 index 0000000..739e63f --- /dev/null +++ b/.changes/retain-ns-menu.md @@ -0,0 +1,5 @@ +--- +"muda": patch +--- + +Manually retain/release NSMenu reference. diff --git a/src/platform_impl/macos/mod.rs b/src/platform_impl/macos/mod.rs index 084926d..a968690 100644 --- a/src/platform_impl/macos/mod.rs +++ b/src/platform_impl/macos/mod.rs @@ -47,20 +47,29 @@ extern "C" { #[allow(non_upper_case_globals)] const NSAboutPanelOptionCopyright: &str = "Copyright"; -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct Menu { id: u32, ns_menu: id, children: Rc>>>>, } +impl Drop for Menu { + fn drop(&mut self) { + unsafe { + let _: () = msg_send![self.ns_menu, release]; + } + } +} + impl Menu { pub fn new() -> Self { Self { id: COUNTER.next(), ns_menu: unsafe { - let ns_menu = NSMenu::alloc(nil).autorelease(); + let ns_menu = NSMenu::new(nil); ns_menu.setAutoenablesItems(NO); + let _: () = msg_send![ns_menu, retain]; ns_menu }, children: Rc::new(RefCell::new(Vec::new())), @@ -173,7 +182,18 @@ pub struct MenuChild { // submenu fields pub children: Option>>>, ns_menus: HashMap>, - ns_menu: (u32, id), + ns_menu: NsMenuRef, +} + +#[derive(Debug)] +struct NsMenuRef(u32, id); + +impl Drop for NsMenuRef { + fn drop(&mut self) { + unsafe { + let _: () = msg_send![self.1, release]; + } + } } impl Default for MenuChild { @@ -191,7 +211,7 @@ impl Default for MenuChild { native_icon: Default::default(), children: Default::default(), ns_menus: Default::default(), - ns_menu: (0, 0 as _), + ns_menu: NsMenuRef(0, 0 as _), } } } @@ -215,7 +235,11 @@ impl MenuChild { text: strip_mnemonic(text), enabled, children: Some(Vec::new()), - ns_menu: (COUNTER.next(), unsafe { NSMenu::alloc(nil).autorelease() }), + ns_menu: NsMenuRef(COUNTER.next(), unsafe { + let menu = NSMenu::new(nil); + let _: () = msg_send![menu, retain]; + menu + }), ..Default::default() } }