native/desktop-macos/src/macos/application_menu_api.rs (118 lines of code) (raw):
use desktop_common::ffi_utils::{ArraySize, BorrowedStrPtr};
use desktop_common::logger::ffi_boundary;
use objc2_foundation::MainThreadMarker;
use super::keyboard::KeyModifiersSet;
use super::{application_api::MyNSApplication, application_menu::main_menu_update_impl};
// This file contains C API of the library
// The symbols listed here will be exported into .h file
// Application Menu:
#[repr(C)]
#[derive(Debug)]
pub struct AppMenuKeystroke<'a> {
pub key: BorrowedStrPtr<'a>,
pub modifiers: KeyModifiersSet,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SubMenuItemSpecialTag {
None,
AppNameMenu,
Window,
Services,
Help,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ActionMenuItemSpecialTag {
None,
Undo,
Redo,
Cut,
Copy,
Paste,
SelectAll,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ActionItemState {
On,
Off,
Mixed,
}
#[repr(C)]
pub enum AppMenuTrigger {
Keystroke,
Other,
}
pub type ItemId = i64;
pub type AppMenuItemCallback = extern "C" fn(item_id: ItemId, trigger: AppMenuTrigger);
#[repr(C)]
#[derive(Debug)]
pub enum AppMenuItem<'a> {
ActionItem {
enabled: bool,
state: ActionItemState,
title: BorrowedStrPtr<'a>,
special_tag: ActionMenuItemSpecialTag,
keystroke: Option<&'a AppMenuKeystroke<'a>>,
item_id: ItemId,
},
SeparatorItem,
SubMenuItem {
title: BorrowedStrPtr<'a>,
special_tag: SubMenuItemSpecialTag,
items: *const AppMenuItem<'a>,
items_count: ArraySize,
},
}
#[repr(C)]
#[derive(Debug)]
pub struct AppMenuStructure<'a> {
pub items: *const AppMenuItem<'a>,
pub items_count: ArraySize,
}
#[unsafe(no_mangle)]
pub extern "C" fn main_menu_update(menu: AppMenuStructure) {
ffi_boundary("main_menu_update", || {
let menu = crate::macos::application_menu::AppMenuStructureSafe::from_unsafe(&menu)?;
main_menu_update_impl(&menu);
Ok(())
});
}
#[unsafe(no_mangle)]
pub extern "C" fn main_menu_set_none() {
ffi_boundary("main_menu_set_none", || {
let mtm: MainThreadMarker = MainThreadMarker::new().unwrap();
let app = MyNSApplication::sharedApplication(mtm);
app.setMainMenu(None);
Ok(())
});
}
#[unsafe(no_mangle)]
pub extern "C" fn main_menu_offer_current_event() -> bool {
ffi_boundary("main_menu_offer_current_event", || {
let mtm: MainThreadMarker = MainThreadMarker::new().unwrap();
let app = MyNSApplication::sharedApplication(mtm);
let result = match (app.currentEvent(), app.mainMenu()) {
(Some(event), Some(menu)) => menu.performKeyEquivalent(&event),
_ => false,
};
Ok(result)
})
}
#[repr(C)]
#[derive(Debug)]
pub struct AppMenuCallbacks {
pub on_menu_action: AppMenuItemCallback,
}
#[unsafe(no_mangle)]
pub extern "C" fn app_menu_init(callbacks: AppMenuCallbacks) -> bool {
ffi_boundary("app_menu_init", || {
super::application_menu::app_menu_init_impl(callbacks);
Ok(true)
})
}
#[unsafe(no_mangle)]
pub extern "C" fn app_menu_deinit() {
ffi_boundary("app_menu_deinit", || {
super::application_menu::app_menu_deinit_impl();
Ok(())
});
}