Desktop: Mac menu workaround (#3398)

This commit is contained in:
Timon
2025-11-19 17:13:35 +00:00
committed by GitHub
parent 788e82a7d0
commit 548e0df1a1
13 changed files with 139 additions and 122 deletions
+27
View File
@@ -0,0 +1,27 @@
use objc2::{ClassType, define_class, msg_send};
use objc2_app_kit::{NSApplication, NSEvent, NSEventType, NSResponder};
use objc2_foundation::NSObject;
pub(super) fn init() {
unsafe {
let _: &NSApplication = msg_send![GraphiteApplication::class(), sharedApplication];
}
}
define_class!(
#[unsafe(super(NSApplication, NSResponder, NSObject))]
#[name = "GraphiteApplication"]
pub(super) struct GraphiteApplication;
impl GraphiteApplication {
#[unsafe(method(sendEvent:))]
fn send_event(&self, event: &NSEvent) {
// Route keyDown events straight to the key window to skip native menu shortcut handling.
if event.r#type() == NSEventType::KeyDown && let Some(key_window) = self.keyWindow() {
unsafe { msg_send![&key_window, sendEvent: event] }
} else {
unsafe { msg_send![super(self), sendEvent: event] }
}
}
}
);
+14 -13
View File
@@ -1,6 +1,6 @@
use muda::Menu as MudaMenu;
use muda::accelerator::Accelerator;
use muda::{AboutMetadataBuilder, CheckMenuItem, IsMenuItem, MenuEvent, MenuId, MenuItem, MenuItemKind, PredefinedMenuItem, Result, Submenu};
use muda::{CheckMenuItem, IsMenuItem, MenuEvent, MenuId, MenuItem, MenuItemKind, PredefinedMenuItem, Result, Submenu};
use crate::event::{AppEvent, AppEventScheduler};
use crate::wrapper::messages::MenuItem as WrapperMenuItem;
@@ -10,18 +10,9 @@ pub(super) struct Menu {
}
impl Menu {
pub(super) fn new(event_scheduler: AppEventScheduler, app_name: &str) -> Self {
let about = PredefinedMenuItem::about(None, Some(AboutMetadataBuilder::new().name(Some(app_name)).build()));
let hide = PredefinedMenuItem::hide(None);
let hide_others = PredefinedMenuItem::hide_others(None);
let show_all = PredefinedMenuItem::show_all(None);
let quit = PredefinedMenuItem::quit(None);
let app_submenu = Submenu::with_items(
"",
true,
&[&about, &PredefinedMenuItem::separator(), &hide, &hide_others, &show_all, &PredefinedMenuItem::separator(), &quit],
)
.unwrap();
pub(super) fn new(event_scheduler: AppEventScheduler) -> Self {
// TODO: Remove as much app submenu special handling as possible
let app_submenu = Submenu::with_items("", true, &[]).unwrap();
let menu = MudaMenu::new();
menu.prepend(&app_submenu).unwrap();
@@ -29,6 +20,16 @@ impl Menu {
menu.init_for_nsapp();
MenuEvent::set_event_handler(Some(move |event: MenuEvent| {
let mtm = objc2::MainThreadMarker::new().expect("only ever called from main thread");
let is_shortcut_triggered = objc2_app_kit::NSApplication::sharedApplication(mtm)
.mainMenu()
.map(|m| m.highlightedItem().is_some())
.unwrap_or_default();
if is_shortcut_triggered {
tracing::error!("A keyboard input triggered a menu event. This is most likely a bug. Please report!");
return;
}
if let Some(id) = menu_id_to_u64(event.id()) {
event_scheduler.schedule(AppEvent::MenuEvent { id });
}