diff --git a/Cargo.lock b/Cargo.lock index fcd637d..480e113 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3418,6 +3418,8 @@ dependencies = [ "egui", "log", "muda", + "objc2 0.6.5", + "objc2-app-kit 0.3.2", "rfd", "serde_json", "soundcraft-engine", diff --git a/apps/soundcraft/Cargo.toml b/apps/soundcraft/Cargo.toml index cb9dab1..783c7b5 100644 --- a/apps/soundcraft/Cargo.toml +++ b/apps/soundcraft/Cargo.toml @@ -28,3 +28,5 @@ winresource = "0.1" [target.'cfg(target_os = "macos")'.dependencies] muda = { version = "0.19.2", default-features = false } +objc2 = "0.6" +objc2-app-kit = { version = "0.3", default-features = false, features = ["NSApplication", "NSResponder"] } diff --git a/apps/soundcraft/src/native_menu.rs b/apps/soundcraft/src/native_menu.rs index 9cc72de..4bd085a 100644 --- a/apps/soundcraft/src/native_menu.rs +++ b/apps/soundcraft/src/native_menu.rs @@ -1,5 +1,7 @@ //! macOS system menu bar. All actions use the same menu dispatch as the egui host. -use muda::{CheckMenuItem, Menu, MenuEvent, PredefinedMenuItem, Submenu}; +use muda::{CheckMenuItem, Menu, MenuEvent, MenuItem, PredefinedMenuItem, Submenu}; +use objc2::MainThreadMarker; +use objc2_app_kit::NSApplication; use soundcraft_ui_egui::{SoundApp, menus}; use std::sync::mpsc::{Receiver, channel}; @@ -36,8 +38,9 @@ impl NativeMenu { app_menu.append(&PredefinedMenuItem::separator())?; app_menu.append(&PredefinedMenuItem::services(None))?; app_menu.append(&PredefinedMenuItem::separator())?; - app_menu.append(&PredefinedMenuItem::hide(Some("Hide SoundCraft")))?; - app_menu.append(&PredefinedMenuItem::hide_others(None))?; + // muda's own Hide items take ⌘H and ⌥⌘H, which are Heal Separation and Copy to Send. + app_menu.append(&MenuItem::with_id("hide", "Hide SoundCraft", true, None))?; + app_menu.append(&MenuItem::with_id("hide_others", "Hide Others", true, None))?; app_menu.append(&PredefinedMenuItem::show_all(None))?; app_menu.append(&PredefinedMenuItem::separator())?; native.add_item(app, &app_menu, "Quit SoundCraft", "", Some("app.quit".into()))?; @@ -82,7 +85,12 @@ impl NativeMenu { while let Ok(event) = self.events.try_recv() { // A click changes state (and Cocoa flips the item's check mark): sync on the next pass. self.last_sync = None; - if let Some(entry) = self.entries.iter().find(|e| e.item.id() == &event.id) + if (event.id == "hide" || event.id == "hide_others") + && let Some(mtm) = MainThreadMarker::new() + { + let ns = NSApplication::sharedApplication(mtm); + if event.id == "hide" { ns.hide(None) } else { ns.hideOtherApplications(None) } + } else if let Some(entry) = self.entries.iter().find(|e| e.item.id() == &event.id) && let Some(command) = &entry.command && menus::item_state(app, &entry.path, Some(command)).0 {