Menu Utilities library for Desktop Applications.
- Windows
- macOS
- Linux/BSD with GTK 3
- Linux/BSD with GTK 4
- On Windows, accelerators don't work unless the win32 message loop calls
TranslateAcceleratorW. SeeMenu::init_for_hwndfor more details
common-controls-v6: UseTaskDialogIndirectAPI fromComCtl32.dllv6 on Windows for showing the predefinedAboutmenu item dialog.libxdo: Enables linking tolibxdofor the GTK 3 backend. This is used by the predefinedCopy,Cut,PasteandSelectAllmenu items, and is enabled by default. It is not used by GTK 4.serde: Enables de/serializing the dpi types.gtk: Enables the GTK 3 backend on Linux or BSD platforms. This is enabled by default.gtk4: Enables the GTK 4 backend on Linux or BSD platforms. Usedefault-features = falsewhen enabling this feature because the default features includegtk.
The gtk and gtk4 features are mutually exclusive.
The gtk feature uses GTK 3 for menus. The gtk4 feature uses GTK 4 for menus. libxdo is only used by the GTK 3 backend to make the predefined Copy, Cut, Paste and SelectAll menu items work when the libxdo feature is enabled.
Be sure to install the packages for the GTK backend you enabled before building:
# GTK 3 backend
pacman -S gtk3 xdotool
# GTK 4 backend
pacman -S gtk4# GTK 3 backend
sudo apt install libgtk-3-dev libxdo-dev
# GTK 4 backend
sudo apt install libgtk-4-devInstall these dependencies in order to compile muda. Instructions using pkg:
# GTK 3 backend
pkg install -y rust glib pkgconf gtk3 xdotool
# GTK 4 backend
pkg install -y rust glib pkgconf gtk4Create the menu and add your items
let menu = Menu::new();
let menu_item2 = MenuItem::new("Menu item #2", false, None);
let submenu = Submenu::with_items("Submenu Outer", true,&[
&MenuItem::new("Menu item #1", true, Some(Accelerator::new(Modifiers::ALT, Code::KeyD))),
&PredefinedMenuItem::separator(),
&menu_item2,
&MenuItem::new("Menu item #3", true, None),
&PredefinedMenuItem::separator(),
&Submenu::with_items("Submenu Inner", true,&[
&MenuItem::new("Submenu item #1", true, None),
&PredefinedMenuItem::separator(),
&menu_item2,
])
]);Then add your root menu to a window on Windows, GTK 3, or GTK 4 or use it as your global app menu on macOS
// --snip--
#[cfg(target_os = "windows")]
unsafe { menu.init_for_hwnd(window.hwnd() as isize) };
#[cfg(target_os = "linux")]
menu.init_for_gtk_window(>k_window, Some(&vertical_gtk_box));
#[cfg(target_os = "macos")]
menu.init_for_nsapp();You can also use a [Menu] or a [Submenu] to show a context menu.
// --snip--
let position = muda::dpi::PhysicalPosition { x: 100., y: 120. };
#[cfg(target_os = "windows")]
unsafe { menu.show_context_menu_for_hwnd(window.hwnd() as isize, Some(position.into())) };
#[cfg(target_os = "linux")]
menu.show_context_menu_for_gtk_window(>k_window, Some(position.into()));
#[cfg(target_os = "macos")]
unsafe { menu.show_context_menu_for_nsview(nsview, Some(position.into())) };You can use MenuEvent::receiver to get a reference to the MenuEventReceiver
which you can use to listen to events when a menu item is activated
if let Ok(event) = MenuEvent::receiver().try_recv() {
match event.id {
_ if event.id == save_item.id() => {
println!("Save menu item activated");
},
_ => {}
}
}You should use [MenuEvent::set_event_handler] and forward
the menu events to the event loop by using EventLoopProxy
so that the event loop is awakened on each menu event.
enum UserEvent {
MenuEvent(muda::MenuEvent)
}
let event_loop = EventLoop::<UserEvent>::with_user_event().build().unwrap();
let proxy = event_loop.create_proxy();
muda::MenuEvent::set_event_handler(Some(move |event| {
proxy.send_event(UserEvent::MenuEvent(event));
}));Apache-2.0/MIT