diff --git a/packages/desktop/src/cfg.rs b/packages/desktop/src/cfg.rs index 07281e364..3b0409ae8 100644 --- a/packages/desktop/src/cfg.rs +++ b/packages/desktop/src/cfg.rs @@ -36,6 +36,7 @@ pub struct Config { pub(crate) root_name: String, pub(crate) background_color: Option<(u8, u8, u8, u8)>, pub(crate) last_window_close_behaviour: WindowCloseBehaviour, + pub(crate) enable_default_menu_bar: bool, } type DropHandler = Box bool>; @@ -65,9 +66,18 @@ impl Config { root_name: "main".to_string(), background_color: None, last_window_close_behaviour: WindowCloseBehaviour::LastWindowExitsApp, + enable_default_menu_bar: true, } } + /// Set whether the default menu bar should be enabled. + /// + /// > Note: `enable` is `true` by default. To disable the default menu bar pass `false`. + pub fn with_default_menu_bar(mut self, enable: bool) -> Self { + self.enable_default_menu_bar = enable; + self + } + /// set the directory from which assets will be searched in release mode pub fn with_resource_directory(mut self, path: impl Into) -> Self { self.resource_dir = Some(path.into()); diff --git a/packages/desktop/src/lib.rs b/packages/desktop/src/lib.rs index f41b3cb1e..105bf0019 100644 --- a/packages/desktop/src/lib.rs +++ b/packages/desktop/src/lib.rs @@ -46,6 +46,7 @@ use tao::{ event::{Event, StartCause, WindowEvent}, event_loop::ControlFlow, }; +pub use webview::build_default_menu_bar; pub use wry; pub use wry::application as tao; use wry::application::event_loop::EventLoopBuilder; diff --git a/packages/desktop/src/webview.rs b/packages/desktop/src/webview.rs index 0294d3460..5f66a07c3 100644 --- a/packages/desktop/src/webview.rs +++ b/packages/desktop/src/webview.rs @@ -4,6 +4,7 @@ use crate::{desktop_context::UserWindowEvent, Config}; use tao::event_loop::{EventLoopProxy, EventLoopWindowTarget}; pub use wry; pub use wry::application as tao; +use wry::application::menu::{MenuBar, MenuItem}; use wry::application::window::Window; use wry::http::Response; use wry::webview::{WebContext, WebView, WebViewBuilder}; @@ -13,13 +14,18 @@ pub fn build( event_loop: &EventLoopWindowTarget, proxy: EventLoopProxy, ) -> (WebView, WebContext, AssetHandlerRegistry) { - let builder = cfg.window.clone(); let window = builder.with_visible(false).build(event_loop).unwrap(); let file_handler = cfg.file_drop_handler.take(); let custom_head = cfg.custom_head.clone(); let index_file = cfg.custom_index.clone(); let root_name = cfg.root_name.clone(); + if cfg.enable_default_menu_bar { + builder = builder.with_menu(build_default_menu_bar()); + } + + let window = builder.with_visible(false).build(event_loop).unwrap(); + // We assume that if the icon is None in cfg, then the user just didnt set it if cfg.window.window.window_icon.is_none() { window.set_window_icon(Some( @@ -129,3 +135,61 @@ pub fn build( (webview.build().unwrap(), web_context, asset_handlers) } + +/// Builds a standard menu bar depending on the users platform. It may be used as a starting point +/// to further customize the menu bar and pass it to a [`WindowBuilder`](tao::window::WindowBuilder). +/// > Note: The default menu bar enables macOS shortcuts like cut/copy/paste. +/// > The menu bar differs per platform because of constraints introduced +/// > by [`MenuItem`](tao::menu::MenuItem). +pub fn build_default_menu_bar() -> MenuBar { + let mut menu_bar = MenuBar::new(); + + // since it is uncommon on windows to have an "application menu" + // we add a "window" menu to be more consistent across platforms with the standard menu + let mut window_menu = MenuBar::new(); + #[cfg(target_os = "macos")] + { + window_menu.add_native_item(MenuItem::EnterFullScreen); + window_menu.add_native_item(MenuItem::Zoom); + window_menu.add_native_item(MenuItem::Separator); + } + + window_menu.add_native_item(MenuItem::Hide); + + #[cfg(target_os = "macos")] + { + window_menu.add_native_item(MenuItem::HideOthers); + window_menu.add_native_item(MenuItem::ShowAll); + } + + window_menu.add_native_item(MenuItem::Minimize); + window_menu.add_native_item(MenuItem::CloseWindow); + window_menu.add_native_item(MenuItem::Separator); + window_menu.add_native_item(MenuItem::Quit); + menu_bar.add_submenu("Window", true, window_menu); + + // since tao supports none of the below items on linux we should only add them on macos/windows + #[cfg(not(target_os = "linux"))] + { + let mut edit_menu = MenuBar::new(); + #[cfg(target_os = "macos")] + { + edit_menu.add_native_item(MenuItem::Undo); + edit_menu.add_native_item(MenuItem::Redo); + edit_menu.add_native_item(MenuItem::Separator); + } + + edit_menu.add_native_item(MenuItem::Cut); + edit_menu.add_native_item(MenuItem::Copy); + edit_menu.add_native_item(MenuItem::Paste); + + #[cfg(target_os = "macos")] + { + edit_menu.add_native_item(MenuItem::Separator); + edit_menu.add_native_item(MenuItem::SelectAll); + } + menu_bar.add_submenu("Edit", true, edit_menu); + } + + menu_bar +}