From f81ebddfcc1aea0d4989706aef43538e8ea98bea Mon Sep 17 00:00:00 2001 From: "Ngo Iok Ui (Wu Yu Wei)" Date: Fri, 13 Aug 2021 21:23:32 +0800 Subject: [PATCH] feat: remove menu feature flag (#2415) Co-authored-by: Lucas Nogueira --- .changes/config.json | 2 +- .changes/remove-menu-flag.md | 7 + .github/workflows/artifacts-updater.yml | 2 +- .github/workflows/bench.yml | 2 +- .github/workflows/build-smoke-tests.yml | 2 +- .github/workflows/core-lint-fmt.yml | 4 +- .../workflows/covector-version-or-publish.yml | 2 +- .github/workflows/smoke-test-prod.yml | 2 +- .github/workflows/test-bundler.yml | 4 +- .github/workflows/test-core.yml | 4 +- .github/workflows/test-cta.yml | 4 +- .github/workflows/udeps.yml | 2 +- .github/workflows/update-docs.yml | 2 +- core/tauri-runtime-wry/Cargo.toml | 1 - core/tauri-runtime-wry/src/lib.rs | 256 +++++++++++--- core/tauri-runtime-wry/src/menu.rs | 313 ------------------ core/tauri-runtime-wry/src/system_tray.rs | 102 ++++++ core/tauri-runtime/Cargo.toml | 1 - core/tauri-runtime/src/lib.rs | 8 - core/tauri-runtime/src/webview.rs | 5 - core/tauri/Cargo.toml | 1 - core/tauri/src/app.rs | 14 - core/tauri/src/lib.rs | 11 +- core/tauri/src/manager.rs | 21 +- core/tauri/src/window.rs | 7 - core/tauri/src/window/menu.rs | 2 - docs/usage/guides/visual/menu.md | 9 - examples/api/src-tauri/Cargo.toml | 2 +- tooling/cli.rs/src/interface/rust.rs | 3 - 29 files changed, 338 insertions(+), 457 deletions(-) create mode 100644 .changes/remove-menu-flag.md delete mode 100644 core/tauri-runtime-wry/src/menu.rs create mode 100644 core/tauri-runtime-wry/src/system_tray.rs diff --git a/.changes/config.json b/.changes/config.json index 96fc2fc71..c502a5f26 100644 --- a/.changes/config.json +++ b/.changes/config.json @@ -8,7 +8,7 @@ "getPublishedVersion": "cargo search ${ pkgFile.pkg.package.name } --limit 1 | sed -nE \"s/^[^\\\"]*\\\"//; s/\\\".*//1p\"", "prepublish": [ "sudo apt-get update", - "sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev", + "sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev", "cargo install cargo-audit --features=fix", { "command": "cargo generate-lockfile", diff --git a/.changes/remove-menu-flag.md b/.changes/remove-menu-flag.md new file mode 100644 index 000000000..42563fd7c --- /dev/null +++ b/.changes/remove-menu-flag.md @@ -0,0 +1,7 @@ +--- +"tauri": minor +"tauri-runtime": minor +"tauri-runtime-wry": minor +--- + +Remove menu feature flag since there's no package dependency need to be installed on any platform anymore. diff --git a/.github/workflows/artifacts-updater.yml b/.github/workflows/artifacts-updater.yml index af4801425..3a998e51e 100644 --- a/.github/workflows/artifacts-updater.yml +++ b/.github/workflows/artifacts-updater.yml @@ -35,7 +35,7 @@ jobs: if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev - name: Get current date run: echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 88ff1e6e6..1e99cfd81 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -37,7 +37,7 @@ jobs: run: | python -m pip install --upgrade pip sudo apt-get update - sudo apt-get install -y webkit2gtk-4.0 libgtksourceview-3.0-dev libappindicator3-dev xvfb + sudo apt-get install -y webkit2gtk-4.0 libappindicator3-dev xvfb wget https://github.com/sharkdp/hyperfine/releases/download/v1.11.0/hyperfine_1.11.0_amd64.deb sudo dpkg -i hyperfine_1.11.0_amd64.deb pip install memory_profiler diff --git a/.github/workflows/build-smoke-tests.yml b/.github/workflows/build-smoke-tests.yml index 37b81b820..4810de018 100644 --- a/.github/workflows/build-smoke-tests.yml +++ b/.github/workflows/build-smoke-tests.yml @@ -69,7 +69,7 @@ jobs: if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev - name: yarn install for cli working-directory: tauri/tooling/cli.js run: yarn diff --git a/.github/workflows/core-lint-fmt.yml b/.github/workflows/core-lint-fmt.yml index ee6885d7f..036fb29b5 100644 --- a/.github/workflows/core-lint-fmt.yml +++ b/.github/workflows/core-lint-fmt.yml @@ -24,7 +24,7 @@ jobs: - name: install webkit2gtk run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev - uses: actions-rs/toolchain@v1 with: @@ -151,7 +151,7 @@ jobs: - name: install webkit2gtk run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/covector-version-or-publish.yml b/.github/workflows/covector-version-or-publish.yml index 2efc071f6..d39154211 100644 --- a/.github/workflows/covector-version-or-publish.yml +++ b/.github/workflows/covector-version-or-publish.yml @@ -76,7 +76,7 @@ jobs: - name: install webkit2gtk run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev # Rust - name: generate rust docs diff --git a/.github/workflows/smoke-test-prod.yml b/.github/workflows/smoke-test-prod.yml index b1f582bfa..e7b39d2de 100644 --- a/.github/workflows/smoke-test-prod.yml +++ b/.github/workflows/smoke-test-prod.yml @@ -37,7 +37,7 @@ jobs: if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev - name: cache rust bin id: cache_rust_bin uses: actions/cache@v1 diff --git a/.github/workflows/test-bundler.yml b/.github/workflows/test-bundler.yml index 343d30e1e..dd3249d26 100644 --- a/.github/workflows/test-bundler.yml +++ b/.github/workflows/test-bundler.yml @@ -35,7 +35,7 @@ jobs: if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev - name: Get current date run: echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV @@ -100,7 +100,7 @@ jobs: if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev - name: clippy check uses: actions-rs/clippy-check@v1 with: diff --git a/.github/workflows/test-core.yml b/.github/workflows/test-core.yml index dd8d3d455..c60320fca 100644 --- a/.github/workflows/test-core.yml +++ b/.github/workflows/test-core.yml @@ -37,7 +37,7 @@ jobs: if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev - name: Get current date run: echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV @@ -161,7 +161,7 @@ jobs: if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev - name: Get current date run: echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV diff --git a/.github/workflows/test-cta.yml b/.github/workflows/test-cta.yml index 3b2ab8dbd..2c24c5aa5 100644 --- a/.github/workflows/test-cta.yml +++ b/.github/workflows/test-cta.yml @@ -45,7 +45,7 @@ jobs: if: (github.event.inputs.platform || 'ubuntu') == 'ubuntu' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev - run: yarn working-directory: tooling/cli.js - run: yarn build @@ -86,7 +86,7 @@ jobs: # if: (github.event.inputs.platform || 'ubuntu') == 'ubuntu' # run: | # sudo apt-get update - # sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + # sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev # - run: yarn # working-directory: tooling/create-tauri-app # - run: yarn build diff --git a/.github/workflows/udeps.yml b/.github/workflows/udeps.yml index e00033c39..6be2a4890 100644 --- a/.github/workflows/udeps.yml +++ b/.github/workflows/udeps.yml @@ -90,7 +90,7 @@ jobs: - name: Install required packages run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev - uses: actions-rs/cargo@v1 with: diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml index f5bbdd62c..4fce8d5f6 100644 --- a/.github/workflows/update-docs.yml +++ b/.github/workflows/update-docs.yml @@ -43,7 +43,7 @@ jobs: - name: install webkit2gtk run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libgtksourceview-3.0-dev webkit2gtk-4.0 libappindicator3-dev + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev # Rust - name: generate rust docs diff --git a/core/tauri-runtime-wry/Cargo.toml b/core/tauri-runtime-wry/Cargo.toml index 71b2b4933..07b3d337e 100644 --- a/core/tauri-runtime-wry/Cargo.toml +++ b/core/tauri-runtime-wry/Cargo.toml @@ -29,5 +29,4 @@ gtk = { version = "0.14", features = [ "v3_20" ] } [features] dox = [ "wry/dox" ] -menu = [ "tauri-runtime/menu"] system-tray = [ "wry/tray", "tauri-runtime/system-tray" ] diff --git a/core/tauri-runtime-wry/src/lib.rs b/core/tauri-runtime-wry/src/lib.rs index 1e2d8c191..43080b4e8 100644 --- a/core/tauri-runtime-wry/src/lib.rs +++ b/core/tauri-runtime-wry/src/lib.rs @@ -5,6 +5,7 @@ //! The [`wry`] Tauri [`Runtime`]. use tauri_runtime::{ + menu::{CustomMenuItem, Menu, MenuEntry, MenuHash, MenuItem, MenuUpdate, Submenu}, monitor::Monitor, webview::{ FileDropEvent, FileDropHandler, RpcRequest, WebviewRpcHandler, WindowBuilder, WindowBuilderBase, @@ -17,7 +18,6 @@ use tauri_runtime::{ RunEvent, RunIteration, Runtime, RuntimeHandle, UserAttentionType, }; -#[cfg(feature = "menu")] use tauri_runtime::window::MenuEvent; #[cfg(feature = "system-tray")] use tauri_runtime::{SystemTray, SystemTrayEvent}; @@ -49,6 +49,10 @@ use wry::{ event::{Event, WindowEvent as WryWindowEvent}, event_loop::{ControlFlow, EventLoop, EventLoopProxy, EventLoopWindowTarget}, global_shortcut::{GlobalShortcut, ShortcutManager as WryShortcutManager}, + menu::{ + CustomMenuItem as WryCustomMenuItem, MenuBar, MenuId as WryMenuId, MenuItem as WryMenuItem, + MenuItemAttributes as WryMenuItemAttributes, MenuType, + }, monitor::MonitorHandle, window::{Fullscreen, Icon as WindowIcon, UserAttentionType as WryUserAttentionType}, }, @@ -63,6 +67,13 @@ pub use wry::application::window::{Window, WindowBuilder as WryWindowBuilder, Wi #[cfg(target_os = "windows")] use wry::webview::WebviewExtWindows; +#[cfg(target_os = "macos")] +use tauri_runtime::menu::NativeImage; +#[cfg(target_os = "macos")] +pub use wry::application::platform::macos::{ + CustomMenuItemExtMacOS, NativeImage as WryNativeImage, +}; + use std::{ collections::{ hash_map::Entry::{Occupied, Vacant}, @@ -80,19 +91,25 @@ use std::{ thread::{current as current_thread, ThreadId}, }; -#[cfg(any(feature = "menu", feature = "system-tray"))] -mod menu; -#[cfg(any(feature = "menu", feature = "system-tray"))] -use menu::*; +#[cfg(feature = "system-tray")] +mod system_tray; +#[cfg(feature = "system-tray")] +use system_tray::*; mod mime_type; use mime_type::MimeType; type WebContextStore = Mutex, WebContext>>; +// window type WindowEventHandler = Box; type WindowEventListenersMap = Arc>>; type WindowEventListeners = Arc>>; +// global shortcut type GlobalShortcutListeners = Arc>>>; +// menu +pub type MenuEventHandler = Box; +pub type MenuEventListeners = Arc>>; +pub type WindowMenuEventListeners = Arc>>; macro_rules! dispatcher_getter { ($self: ident, $message: expr) => {{ @@ -134,6 +151,124 @@ struct EventLoopContext { proxy: EventLoopProxy, } +pub struct MenuItemAttributesWrapper<'a>(pub WryMenuItemAttributes<'a>); + +impl<'a> From<&'a CustomMenuItem> for MenuItemAttributesWrapper<'a> { + fn from(item: &'a CustomMenuItem) -> Self { + let mut attributes = WryMenuItemAttributes::new(&item.title) + .with_enabled(item.enabled) + .with_selected(item.selected) + .with_id(WryMenuId(item.id)); + if let Some(accelerator) = item.keyboard_accelerator.as_ref() { + attributes = attributes.with_accelerators(&accelerator.parse().expect("invalid accelerator")); + } + Self(attributes) + } +} + +pub struct MenuItemWrapper(pub WryMenuItem); + +impl From for MenuItemWrapper { + fn from(item: MenuItem) -> Self { + match item { + MenuItem::About(v) => Self(WryMenuItem::About(v)), + MenuItem::Hide => Self(WryMenuItem::Hide), + MenuItem::Services => Self(WryMenuItem::Services), + MenuItem::HideOthers => Self(WryMenuItem::HideOthers), + MenuItem::ShowAll => Self(WryMenuItem::ShowAll), + MenuItem::CloseWindow => Self(WryMenuItem::CloseWindow), + MenuItem::Quit => Self(WryMenuItem::Quit), + MenuItem::Copy => Self(WryMenuItem::Copy), + MenuItem::Cut => Self(WryMenuItem::Cut), + MenuItem::Undo => Self(WryMenuItem::Undo), + MenuItem::Redo => Self(WryMenuItem::Redo), + MenuItem::SelectAll => Self(WryMenuItem::SelectAll), + MenuItem::Paste => Self(WryMenuItem::Paste), + MenuItem::EnterFullScreen => Self(WryMenuItem::EnterFullScreen), + MenuItem::Minimize => Self(WryMenuItem::Minimize), + MenuItem::Zoom => Self(WryMenuItem::Zoom), + MenuItem::Separator => Self(WryMenuItem::Separator), + _ => unimplemented!(), + } + } +} + +#[cfg(target_os = "macos")] +pub struct NativeImageWrapper(pub WryNativeImage); + +#[cfg(target_os = "macos")] +impl std::fmt::Debug for NativeImageWrapper { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("NativeImageWrapper").finish() + } +} + +#[cfg(target_os = "macos")] +impl From for NativeImageWrapper { + fn from(image: NativeImage) -> NativeImageWrapper { + let wry_image = match image { + NativeImage::Add => WryNativeImage::Add, + NativeImage::Advanced => WryNativeImage::Advanced, + NativeImage::Bluetooth => WryNativeImage::Bluetooth, + NativeImage::Bookmarks => WryNativeImage::Bookmarks, + NativeImage::Caution => WryNativeImage::Caution, + NativeImage::ColorPanel => WryNativeImage::ColorPanel, + NativeImage::ColumnView => WryNativeImage::ColumnView, + NativeImage::Computer => WryNativeImage::Computer, + NativeImage::EnterFullScreen => WryNativeImage::EnterFullScreen, + NativeImage::Everyone => WryNativeImage::Everyone, + NativeImage::ExitFullScreen => WryNativeImage::ExitFullScreen, + NativeImage::FlowView => WryNativeImage::FlowView, + NativeImage::Folder => WryNativeImage::Folder, + NativeImage::FolderBurnable => WryNativeImage::FolderBurnable, + NativeImage::FolderSmart => WryNativeImage::FolderSmart, + NativeImage::FollowLinkFreestanding => WryNativeImage::FollowLinkFreestanding, + NativeImage::FontPanel => WryNativeImage::FontPanel, + NativeImage::GoLeft => WryNativeImage::GoLeft, + NativeImage::GoRight => WryNativeImage::GoRight, + NativeImage::Home => WryNativeImage::Home, + NativeImage::IChatTheater => WryNativeImage::IChatTheater, + NativeImage::IconView => WryNativeImage::IconView, + NativeImage::Info => WryNativeImage::Info, + NativeImage::InvalidDataFreestanding => WryNativeImage::InvalidDataFreestanding, + NativeImage::LeftFacingTriangle => WryNativeImage::LeftFacingTriangle, + NativeImage::ListView => WryNativeImage::ListView, + NativeImage::LockLocked => WryNativeImage::LockLocked, + NativeImage::LockUnlocked => WryNativeImage::LockUnlocked, + NativeImage::MenuMixedState => WryNativeImage::MenuMixedState, + NativeImage::MenuOnState => WryNativeImage::MenuOnState, + NativeImage::MobileMe => WryNativeImage::MobileMe, + NativeImage::MultipleDocuments => WryNativeImage::MultipleDocuments, + NativeImage::Network => WryNativeImage::Network, + NativeImage::Path => WryNativeImage::Path, + NativeImage::PreferencesGeneral => WryNativeImage::PreferencesGeneral, + NativeImage::QuickLook => WryNativeImage::QuickLook, + NativeImage::RefreshFreestanding => WryNativeImage::RefreshFreestanding, + NativeImage::Refresh => WryNativeImage::Refresh, + NativeImage::Remove => WryNativeImage::Remove, + NativeImage::RevealFreestanding => WryNativeImage::RevealFreestanding, + NativeImage::RightFacingTriangle => WryNativeImage::RightFacingTriangle, + NativeImage::Share => WryNativeImage::Share, + NativeImage::Slideshow => WryNativeImage::Slideshow, + NativeImage::SmartBadge => WryNativeImage::SmartBadge, + NativeImage::StatusAvailable => WryNativeImage::StatusAvailable, + NativeImage::StatusNone => WryNativeImage::StatusNone, + NativeImage::StatusPartiallyAvailable => WryNativeImage::StatusPartiallyAvailable, + NativeImage::StatusUnavailable => WryNativeImage::StatusUnavailable, + NativeImage::StopProgressFreestanding => WryNativeImage::StopProgressFreestanding, + NativeImage::StopProgress => WryNativeImage::StopProgress, + + NativeImage::TrashEmpty => WryNativeImage::TrashEmpty, + NativeImage::TrashFull => WryNativeImage::TrashFull, + NativeImage::User => WryNativeImage::User, + NativeImage::UserAccounts => WryNativeImage::UserAccounts, + NativeImage::UserGroup => WryNativeImage::UserGroup, + NativeImage::UserGuest => WryNativeImage::UserGuest, + }; + Self(wry_image) + } +} + #[derive(Debug, Clone)] pub struct GlobalShortcutWrapper(GlobalShortcut); @@ -438,7 +573,6 @@ impl From for UserAttentionTypeWrapper { pub struct WindowBuilderWrapper { inner: WryWindowBuilder, center: bool, - #[cfg(feature = "menu")] menu: Menu, } @@ -481,7 +615,6 @@ impl WindowBuilder for WindowBuilderWrapper { window } - #[cfg(feature = "menu")] fn menu(mut self, menu: Menu) -> Self { self.menu = convert_menu_id(Menu::new(), menu); self @@ -604,7 +737,6 @@ impl WindowBuilder for WindowBuilderWrapper { self.inner.window.window_icon.is_some() } - #[cfg(feature = "menu")] fn has_menu(&self) -> bool { self.inner.window.window_menu.is_some() } @@ -675,7 +807,6 @@ pub enum WindowMessage { IsDecorated(Sender), IsResizable(Sender), IsVisible(Sender), - #[cfg(feature = "menu")] IsMenuVisible(Sender), CurrentMonitor(Sender>), PrimaryMonitor(Sender>), @@ -701,9 +832,7 @@ pub enum WindowMessage { Unmaximize, Minimize, Unminimize, - #[cfg(feature = "menu")] ShowMenu, - #[cfg(feature = "menu")] HideMenu, Show, Hide, @@ -719,8 +848,7 @@ pub enum WindowMessage { SetIcon(WindowIcon), SetSkipTaskbar(bool), DragWindow, - #[cfg(feature = "menu")] - UpdateMenuItem(u16, menu::MenuUpdate), + UpdateMenuItem(u16, MenuUpdate), } #[derive(Debug, Clone)] @@ -740,7 +868,7 @@ pub enum WebviewEvent { #[cfg(feature = "system-tray")] #[derive(Debug, Clone)] pub enum TrayMessage { - UpdateItem(u16, menu::MenuUpdate), + UpdateItem(u16, MenuUpdate), UpdateIcon(Icon), #[cfg(target_os = "macos")] UpdateIconAsTemplate(bool), @@ -786,7 +914,6 @@ struct DispatcherContext { is_event_loop_running: Arc, proxy: EventLoopProxy, window_event_listeners: WindowEventListeners, - #[cfg(feature = "menu")] menu_event_listeners: MenuEventListeners, } @@ -834,7 +961,6 @@ impl Dispatch for WryDispatcher { id } - #[cfg(feature = "menu")] fn on_menu_event(&self, f: F) -> Uuid { let id = Uuid::new_v4(); self @@ -894,7 +1020,6 @@ impl Dispatch for WryDispatcher { Ok(dispatcher_getter!(self, WindowMessage::IsVisible)) } - #[cfg(feature = "menu")] fn is_menu_visible(&self) -> Result { Ok(dispatcher_getter!(self, WindowMessage::IsMenuVisible)) } @@ -1052,7 +1177,6 @@ impl Dispatch for WryDispatcher { .map_err(|_| Error::FailedToSendMessage) } - #[cfg(feature = "menu")] fn show_menu(&self) -> Result<()> { self .context @@ -1061,7 +1185,6 @@ impl Dispatch for WryDispatcher { .map_err(|_| Error::FailedToSendMessage) } - #[cfg(feature = "menu")] fn hide_menu(&self) -> Result<()> { self .context @@ -1220,8 +1343,7 @@ impl Dispatch for WryDispatcher { .map_err(|_| Error::FailedToSendMessage) } - #[cfg(feature = "menu")] - fn update_menu_item(&self, id: u16, update: menu::MenuUpdate) -> Result<()> { + fn update_menu_item(&self, id: u16, update: MenuUpdate) -> Result<()> { self .context .proxy @@ -1258,7 +1380,6 @@ impl WindowHandle { pub struct WindowWrapper { label: String, inner: WindowHandle, - #[cfg(feature = "menu")] menu_items: HashMap, } @@ -1274,7 +1395,6 @@ pub struct Wry { windows: Arc>>, web_context: WebContextStore, window_event_listeners: WindowEventListeners, - #[cfg(feature = "menu")] menu_event_listeners: MenuEventListeners, #[cfg(feature = "system-tray")] tray_context: TrayContext, @@ -1392,7 +1512,6 @@ impl Runtime for Wry { windows: Default::default(), web_context: Default::default(), window_event_listeners: Default::default(), - #[cfg(feature = "menu")] menu_event_listeners: Default::default(), #[cfg(feature = "system-tray")] tray_context: Default::default(), @@ -1406,7 +1525,6 @@ impl Runtime for Wry { is_event_loop_running: self.is_event_loop_running.clone(), proxy: self.event_loop.create_proxy(), window_event_listeners: self.window_event_listeners.clone(), - #[cfg(feature = "menu")] menu_event_listeners: self.menu_event_listeners.clone(), }, } @@ -1431,7 +1549,6 @@ impl Runtime for Wry { is_event_loop_running: self.is_event_loop_running.clone(), proxy: proxy.clone(), window_event_listeners: self.window_event_listeners.clone(), - #[cfg(feature = "menu")] menu_event_listeners: self.menu_event_listeners.clone(), }, pending, @@ -1473,7 +1590,6 @@ impl Runtime for Wry { is_event_loop_running: self.is_event_loop_running.clone(), proxy, window_event_listeners: self.window_event_listeners.clone(), - #[cfg(feature = "menu")] menu_event_listeners: self.menu_event_listeners.clone(), }, }; @@ -1543,7 +1659,6 @@ impl Runtime for Wry { let windows = self.windows.clone(); let web_context = &self.web_context; let window_event_listeners = self.window_event_listeners.clone(); - #[cfg(feature = "menu")] let menu_event_listeners = self.menu_event_listeners.clone(); #[cfg(feature = "system-tray")] let tray_context = self.tray_context.clone(); @@ -1571,7 +1686,6 @@ impl Runtime for Wry { global_shortcut_manager: global_shortcut_manager.clone(), global_shortcut_manager_handle: &global_shortcut_manager_handle, clipboard_manager: clipboard_manager.clone(), - #[cfg(feature = "menu")] menu_event_listeners: &menu_event_listeners, #[cfg(feature = "system-tray")] tray_context: &tray_context, @@ -1589,7 +1703,6 @@ impl Runtime for Wry { let windows = self.windows.clone(); let web_context = self.web_context; let window_event_listeners = self.window_event_listeners.clone(); - #[cfg(feature = "menu")] let menu_event_listeners = self.menu_event_listeners.clone(); #[cfg(feature = "system-tray")] let tray_context = self.tray_context; @@ -1609,7 +1722,6 @@ impl Runtime for Wry { global_shortcut_manager: global_shortcut_manager.clone(), global_shortcut_manager_handle: &global_shortcut_manager_handle, clipboard_manager: clipboard_manager.clone(), - #[cfg(feature = "menu")] menu_event_listeners: &menu_event_listeners, #[cfg(feature = "system-tray")] tray_context: &tray_context, @@ -1627,7 +1739,6 @@ struct EventLoopIterationContext<'a> { global_shortcut_manager: Arc>, global_shortcut_manager_handle: &'a GlobalShortcutManagerHandle, clipboard_manager: Arc>, - #[cfg(feature = "menu")] menu_event_listeners: &'a MenuEventListeners, #[cfg(feature = "system-tray")] tray_context: &'a TrayContext, @@ -1647,7 +1758,6 @@ fn handle_event_loop( global_shortcut_manager, global_shortcut_manager_handle, clipboard_manager, - #[cfg(feature = "menu")] menu_event_listeners, #[cfg(feature = "system-tray")] tray_context, @@ -1667,7 +1777,6 @@ fn handle_event_loop( } } } - #[cfg(feature = "menu")] Event::MenuEvent { window_id, menu_id, @@ -1756,7 +1865,6 @@ fn handle_event_loop( control_flow, #[cfg(target_os = "linux")] window_event_listeners, - #[cfg(feature = "menu")] menu_event_listeners.clone(), ); } @@ -1807,7 +1915,6 @@ fn handle_event_loop( WindowMessage::IsDecorated(tx) => tx.send(window.is_decorated()).unwrap(), WindowMessage::IsResizable(tx) => tx.send(window.is_resizable()).unwrap(), WindowMessage::IsVisible(tx) => tx.send(window.is_visible()).unwrap(), - #[cfg(feature = "menu")] WindowMessage::IsMenuVisible(tx) => tx.send(window.is_menu_visible()).unwrap(), WindowMessage::CurrentMonitor(tx) => tx.send(window.current_monitor()).unwrap(), WindowMessage::PrimaryMonitor(tx) => tx.send(window.primary_monitor()).unwrap(), @@ -1841,9 +1948,7 @@ fn handle_event_loop( WindowMessage::Unmaximize => window.set_maximized(false), WindowMessage::Minimize => window.set_minimized(true), WindowMessage::Unminimize => window.set_minimized(false), - #[cfg(feature = "menu")] WindowMessage::ShowMenu => window.show_menu(), - #[cfg(feature = "menu")] WindowMessage::HideMenu => window.hide_menu(), WindowMessage::Show => window.set_visible(true), WindowMessage::Hide => window.set_visible(false), @@ -1855,7 +1960,6 @@ fn handle_event_loop( control_flow, #[cfg(target_os = "linux")] window_event_listeners, - #[cfg(feature = "menu")] menu_event_listeners.clone(), ); } @@ -1893,7 +1997,6 @@ fn handle_event_loop( WindowMessage::DragWindow => { let _ = window.drag_window(); } - #[cfg(feature = "menu")] WindowMessage::UpdateMenuItem(id, update) => { let item = webview .menu_items @@ -1962,7 +2065,6 @@ fn handle_event_loop( .unwrap() .insert(window.id(), WindowEventListenersMap::default()); - #[cfg(feature = "menu")] context .menu_event_listeners .lock() @@ -1976,7 +2078,6 @@ fn handle_event_loop( WindowWrapper { label, inner: WindowHandle::Window(w.clone()), - #[cfg(feature = "menu")] menu_items: Default::default(), }, ); @@ -2075,10 +2176,9 @@ fn on_window_close<'a>( windows: &mut MutexGuard<'a, HashMap>, control_flow: &mut ControlFlow, #[cfg(target_os = "linux")] window_event_listeners: &WindowEventListeners, - #[cfg(feature = "menu")] menu_event_listeners: MenuEventListeners, + menu_event_listeners: MenuEventListeners, ) { if let Some(webview) = windows.remove(&window_id) { - #[cfg(feature = "menu")] menu_event_listeners.lock().unwrap().remove(&window_id); callback(RunEvent::WindowClose(webview.label.clone())); @@ -2128,6 +2228,71 @@ fn center_window(window: &Window) -> Result<()> { } } +fn convert_menu_id(mut new_menu: Menu, menu: Menu) -> Menu { + for item in menu.items { + match item { + MenuEntry::CustomItem(c) => { + let mut item = CustomMenuItem::new(c.id_str, c.title); + #[cfg(target_os = "macos")] + if let Some(native_image) = c.native_image { + item = item.native_image(native_image); + } + if let Some(accelerator) = c.keyboard_accelerator { + item = item.accelerator(accelerator); + } + if !c.enabled { + item = item.disabled(); + } + if c.selected { + item = item.selected(); + } + new_menu = new_menu.add_item(item); + } + MenuEntry::NativeItem(i) => { + new_menu = new_menu.add_native_item(i); + } + MenuEntry::Submenu(submenu) => { + let new_submenu = convert_menu_id(Menu::new(), submenu.inner); + new_menu = new_menu.add_submenu(Submenu::new(submenu.title, new_submenu)); + } + } + } + new_menu +} + +fn to_wry_menu( + custom_menu_items: &mut HashMap, + menu: Menu, +) -> MenuBar { + let mut wry_menu = MenuBar::new(); + for item in menu.items { + match item { + MenuEntry::CustomItem(c) => { + let mut attributes = MenuItemAttributesWrapper::from(&c).0; + attributes = attributes.with_id(WryMenuId(c.id)); + #[allow(unused_mut)] + let mut item = wry_menu.add_item(attributes); + #[cfg(target_os = "macos")] + if let Some(native_image) = c.native_image { + item.set_native_image(NativeImageWrapper::from(native_image).0); + } + custom_menu_items.insert(c.id, item); + } + MenuEntry::NativeItem(i) => { + wry_menu.add_native_item(MenuItemWrapper::from(i).0); + } + MenuEntry::Submenu(submenu) => { + wry_menu.add_submenu( + &submenu.title, + submenu.enabled, + to_wry_menu(custom_menu_items, submenu.inner), + ); + } + } + } + wry_menu +} + fn create_webview( event_loop: &EventLoopWindowTarget, web_context: &WebContextStore, @@ -2146,7 +2311,6 @@ fn create_webview( } = pending; let is_window_transparent = window_builder.inner.window.transparent; - #[cfg(feature = "menu")] let menu_items = { let mut menu_items = HashMap::new(); let menu = to_wry_menu(&mut menu_items, window_builder.menu); @@ -2161,7 +2325,6 @@ fn create_webview( .unwrap() .insert(window.id(), WindowEventListenersMap::default()); - #[cfg(feature = "menu")] context .menu_event_listeners .lock() @@ -2224,7 +2387,6 @@ fn create_webview( Ok(WindowWrapper { label, inner: WindowHandle::Webview(webview), - #[cfg(feature = "menu")] menu_items, }) } diff --git a/core/tauri-runtime-wry/src/menu.rs b/core/tauri-runtime-wry/src/menu.rs deleted file mode 100644 index 853551870..000000000 --- a/core/tauri-runtime-wry/src/menu.rs +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright 2019-2021 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: MIT - -pub use tauri_runtime::{ - menu::{ - CustomMenuItem, Menu, MenuEntry, MenuItem, MenuUpdate, Submenu, SystemTrayMenu, - SystemTrayMenuEntry, SystemTrayMenuItem, TrayHandle, - }, - window::MenuEvent, - Icon, SystemTrayEvent, -}; -pub use wry::application::{ - event::TrayEvent, - event_loop::EventLoopProxy, - menu::{ - ContextMenu as WryContextMenu, CustomMenuItem as WryCustomMenuItem, MenuBar, - MenuId as WryMenuId, MenuItem as WryMenuItem, MenuItemAttributes as WryMenuItemAttributes, - MenuType, - }, - window::WindowId, -}; - -#[cfg(target_os = "macos")] -use tauri_runtime::menu::NativeImage; -#[cfg(target_os = "macos")] -pub use wry::application::platform::macos::{ - CustomMenuItemExtMacOS, NativeImage as WryNativeImage, -}; - -#[cfg(feature = "system-tray")] -use crate::{Error, Message, Result, TrayMessage}; - -#[cfg(any(feature = "menu", feature = "system-tray"))] -use tauri_runtime::menu::MenuHash; - -use uuid::Uuid; - -use std::{ - collections::HashMap, - sync::{Arc, Mutex}, -}; - -#[cfg(feature = "menu")] -pub type MenuEventHandler = Box; -#[cfg(feature = "menu")] -pub type MenuEventListeners = Arc>>; -#[cfg(feature = "menu")] -pub type WindowMenuEventListeners = Arc>>; - -#[cfg(feature = "system-tray")] -pub type SystemTrayEventHandler = Box; -#[cfg(feature = "system-tray")] -pub type SystemTrayEventListeners = Arc>>; -#[cfg(feature = "system-tray")] -pub type SystemTrayItems = Arc>>; - -#[cfg(feature = "system-tray")] -#[derive(Debug, Clone)] -pub struct SystemTrayHandle { - pub(crate) proxy: EventLoopProxy, -} - -#[cfg(feature = "system-tray")] -impl TrayHandle for SystemTrayHandle { - fn set_icon(&self, icon: Icon) -> Result<()> { - self - .proxy - .send_event(Message::Tray(TrayMessage::UpdateIcon(icon))) - .map_err(|_| Error::FailedToSendMessage) - } - fn update_item(&self, id: u16, update: MenuUpdate) -> Result<()> { - self - .proxy - .send_event(Message::Tray(TrayMessage::UpdateItem(id, update))) - .map_err(|_| Error::FailedToSendMessage) - } - #[cfg(target_os = "macos")] - fn set_icon_as_template(&self, is_template: bool) -> tauri_runtime::Result<()> { - self - .proxy - .send_event(Message::Tray(TrayMessage::UpdateIconAsTemplate( - is_template, - ))) - .map_err(|_| Error::FailedToSendMessage) - } -} - -#[cfg(target_os = "macos")] -pub struct NativeImageWrapper(pub WryNativeImage); - -#[cfg(target_os = "macos")] -impl std::fmt::Debug for NativeImageWrapper { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("NativeImageWrapper").finish() - } -} - -#[cfg(target_os = "macos")] -impl From for NativeImageWrapper { - fn from(image: NativeImage) -> NativeImageWrapper { - let wry_image = match image { - NativeImage::Add => WryNativeImage::Add, - NativeImage::Advanced => WryNativeImage::Advanced, - NativeImage::Bluetooth => WryNativeImage::Bluetooth, - NativeImage::Bookmarks => WryNativeImage::Bookmarks, - NativeImage::Caution => WryNativeImage::Caution, - NativeImage::ColorPanel => WryNativeImage::ColorPanel, - NativeImage::ColumnView => WryNativeImage::ColumnView, - NativeImage::Computer => WryNativeImage::Computer, - NativeImage::EnterFullScreen => WryNativeImage::EnterFullScreen, - NativeImage::Everyone => WryNativeImage::Everyone, - NativeImage::ExitFullScreen => WryNativeImage::ExitFullScreen, - NativeImage::FlowView => WryNativeImage::FlowView, - NativeImage::Folder => WryNativeImage::Folder, - NativeImage::FolderBurnable => WryNativeImage::FolderBurnable, - NativeImage::FolderSmart => WryNativeImage::FolderSmart, - NativeImage::FollowLinkFreestanding => WryNativeImage::FollowLinkFreestanding, - NativeImage::FontPanel => WryNativeImage::FontPanel, - NativeImage::GoLeft => WryNativeImage::GoLeft, - NativeImage::GoRight => WryNativeImage::GoRight, - NativeImage::Home => WryNativeImage::Home, - NativeImage::IChatTheater => WryNativeImage::IChatTheater, - NativeImage::IconView => WryNativeImage::IconView, - NativeImage::Info => WryNativeImage::Info, - NativeImage::InvalidDataFreestanding => WryNativeImage::InvalidDataFreestanding, - NativeImage::LeftFacingTriangle => WryNativeImage::LeftFacingTriangle, - NativeImage::ListView => WryNativeImage::ListView, - NativeImage::LockLocked => WryNativeImage::LockLocked, - NativeImage::LockUnlocked => WryNativeImage::LockUnlocked, - NativeImage::MenuMixedState => WryNativeImage::MenuMixedState, - NativeImage::MenuOnState => WryNativeImage::MenuOnState, - NativeImage::MobileMe => WryNativeImage::MobileMe, - NativeImage::MultipleDocuments => WryNativeImage::MultipleDocuments, - NativeImage::Network => WryNativeImage::Network, - NativeImage::Path => WryNativeImage::Path, - NativeImage::PreferencesGeneral => WryNativeImage::PreferencesGeneral, - NativeImage::QuickLook => WryNativeImage::QuickLook, - NativeImage::RefreshFreestanding => WryNativeImage::RefreshFreestanding, - NativeImage::Refresh => WryNativeImage::Refresh, - NativeImage::Remove => WryNativeImage::Remove, - NativeImage::RevealFreestanding => WryNativeImage::RevealFreestanding, - NativeImage::RightFacingTriangle => WryNativeImage::RightFacingTriangle, - NativeImage::Share => WryNativeImage::Share, - NativeImage::Slideshow => WryNativeImage::Slideshow, - NativeImage::SmartBadge => WryNativeImage::SmartBadge, - NativeImage::StatusAvailable => WryNativeImage::StatusAvailable, - NativeImage::StatusNone => WryNativeImage::StatusNone, - NativeImage::StatusPartiallyAvailable => WryNativeImage::StatusPartiallyAvailable, - NativeImage::StatusUnavailable => WryNativeImage::StatusUnavailable, - NativeImage::StopProgressFreestanding => WryNativeImage::StopProgressFreestanding, - NativeImage::StopProgress => WryNativeImage::StopProgress, - - NativeImage::TrashEmpty => WryNativeImage::TrashEmpty, - NativeImage::TrashFull => WryNativeImage::TrashFull, - NativeImage::User => WryNativeImage::User, - NativeImage::UserAccounts => WryNativeImage::UserAccounts, - NativeImage::UserGroup => WryNativeImage::UserGroup, - NativeImage::UserGuest => WryNativeImage::UserGuest, - }; - Self(wry_image) - } -} - -pub struct MenuItemAttributesWrapper<'a>(pub WryMenuItemAttributes<'a>); - -impl<'a> From<&'a CustomMenuItem> for MenuItemAttributesWrapper<'a> { - fn from(item: &'a CustomMenuItem) -> Self { - let mut attributes = WryMenuItemAttributes::new(&item.title) - .with_enabled(item.enabled) - .with_selected(item.selected) - .with_id(WryMenuId(item.id)); - if let Some(accelerator) = item.keyboard_accelerator.as_ref() { - attributes = attributes.with_accelerators(&accelerator.parse().expect("invalid accelerator")); - } - Self(attributes) - } -} - -pub struct MenuItemWrapper(pub WryMenuItem); - -impl From for MenuItemWrapper { - fn from(item: MenuItem) -> Self { - match item { - MenuItem::About(v) => Self(WryMenuItem::About(v)), - MenuItem::Hide => Self(WryMenuItem::Hide), - MenuItem::Services => Self(WryMenuItem::Services), - MenuItem::HideOthers => Self(WryMenuItem::HideOthers), - MenuItem::ShowAll => Self(WryMenuItem::ShowAll), - MenuItem::CloseWindow => Self(WryMenuItem::CloseWindow), - MenuItem::Quit => Self(WryMenuItem::Quit), - MenuItem::Copy => Self(WryMenuItem::Copy), - MenuItem::Cut => Self(WryMenuItem::Cut), - MenuItem::Undo => Self(WryMenuItem::Undo), - MenuItem::Redo => Self(WryMenuItem::Redo), - MenuItem::SelectAll => Self(WryMenuItem::SelectAll), - MenuItem::Paste => Self(WryMenuItem::Paste), - MenuItem::EnterFullScreen => Self(WryMenuItem::EnterFullScreen), - MenuItem::Minimize => Self(WryMenuItem::Minimize), - MenuItem::Zoom => Self(WryMenuItem::Zoom), - MenuItem::Separator => Self(WryMenuItem::Separator), - _ => unimplemented!(), - } - } -} - -impl From for MenuItemWrapper { - fn from(item: SystemTrayMenuItem) -> Self { - match item { - SystemTrayMenuItem::Separator => Self(WryMenuItem::Separator), - _ => unimplemented!(), - } - } -} - -#[cfg(feature = "menu")] -pub fn convert_menu_id(mut new_menu: Menu, menu: Menu) -> Menu { - for item in menu.items { - match item { - MenuEntry::CustomItem(c) => { - let mut item = CustomMenuItem::new(c.id_str, c.title); - #[cfg(target_os = "macos")] - if let Some(native_image) = c.native_image { - item = item.native_image(native_image); - } - if let Some(accelerator) = c.keyboard_accelerator { - item = item.accelerator(accelerator); - } - if !c.enabled { - item = item.disabled(); - } - if c.selected { - item = item.selected(); - } - new_menu = new_menu.add_item(item); - } - MenuEntry::NativeItem(i) => { - new_menu = new_menu.add_native_item(i); - } - MenuEntry::Submenu(submenu) => { - let new_submenu = convert_menu_id(Menu::new(), submenu.inner); - new_menu = new_menu.add_submenu(Submenu::new(submenu.title, new_submenu)); - } - } - } - new_menu -} - -#[cfg(feature = "menu")] -pub fn to_wry_menu( - custom_menu_items: &mut HashMap, - menu: Menu, -) -> MenuBar { - let mut wry_menu = MenuBar::new(); - for item in menu.items { - match item { - MenuEntry::CustomItem(c) => { - let mut attributes = MenuItemAttributesWrapper::from(&c).0; - attributes = attributes.with_id(WryMenuId(c.id)); - #[allow(unused_mut)] - let mut item = wry_menu.add_item(attributes); - #[cfg(target_os = "macos")] - if let Some(native_image) = c.native_image { - item.set_native_image(NativeImageWrapper::from(native_image).0); - } - custom_menu_items.insert(c.id, item); - } - MenuEntry::NativeItem(i) => { - wry_menu.add_native_item(MenuItemWrapper::from(i).0); - } - MenuEntry::Submenu(submenu) => { - wry_menu.add_submenu( - &submenu.title, - submenu.enabled, - to_wry_menu(custom_menu_items, submenu.inner), - ); - } - } - } - wry_menu -} - -#[cfg(feature = "system-tray")] -pub fn to_wry_context_menu( - custom_menu_items: &mut HashMap, - menu: SystemTrayMenu, -) -> WryContextMenu { - let mut tray_menu = WryContextMenu::new(); - for item in menu.items { - match item { - SystemTrayMenuEntry::CustomItem(c) => { - #[allow(unused_mut)] - let mut item = tray_menu.add_item(MenuItemAttributesWrapper::from(&c).0); - #[cfg(target_os = "macos")] - if let Some(native_image) = c.native_image { - item.set_native_image(NativeImageWrapper::from(native_image).0); - } - custom_menu_items.insert(c.id, item); - } - SystemTrayMenuEntry::NativeItem(i) => { - tray_menu.add_native_item(MenuItemWrapper::from(i).0); - } - SystemTrayMenuEntry::Submenu(submenu) => { - tray_menu.add_submenu( - &submenu.title, - submenu.enabled, - to_wry_context_menu(custom_menu_items, submenu.inner), - ); - } - } - } - tray_menu -} diff --git a/core/tauri-runtime-wry/src/system_tray.rs b/core/tauri-runtime-wry/src/system_tray.rs new file mode 100644 index 000000000..e9119d56c --- /dev/null +++ b/core/tauri-runtime-wry/src/system_tray.rs @@ -0,0 +1,102 @@ +// Copyright 2019-2021 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +pub use tauri_runtime::{ + menu::{ + Menu, MenuEntry, MenuItem, MenuUpdate, Submenu, SystemTrayMenu, SystemTrayMenuEntry, + SystemTrayMenuItem, TrayHandle, + }, + Icon, SystemTrayEvent, +}; +pub use wry::application::{ + event::TrayEvent, + event_loop::EventLoopProxy, + menu::{ + ContextMenu as WryContextMenu, CustomMenuItem as WryCustomMenuItem, MenuItem as WryMenuItem, + }, +}; + +use crate::{Error, Message, Result, TrayMessage}; + +use tauri_runtime::menu::MenuHash; + +use uuid::Uuid; + +use std::{ + collections::HashMap, + sync::{Arc, Mutex}, +}; + +pub type SystemTrayEventHandler = Box; +pub type SystemTrayEventListeners = Arc>>; +pub type SystemTrayItems = Arc>>; + +#[derive(Debug, Clone)] +pub struct SystemTrayHandle { + pub(crate) proxy: EventLoopProxy, +} + +impl TrayHandle for SystemTrayHandle { + fn set_icon(&self, icon: Icon) -> Result<()> { + self + .proxy + .send_event(Message::Tray(TrayMessage::UpdateIcon(icon))) + .map_err(|_| Error::FailedToSendMessage) + } + fn update_item(&self, id: u16, update: MenuUpdate) -> Result<()> { + self + .proxy + .send_event(Message::Tray(TrayMessage::UpdateItem(id, update))) + .map_err(|_| Error::FailedToSendMessage) + } + #[cfg(target_os = "macos")] + fn set_icon_as_template(&self, is_template: bool) -> tauri_runtime::Result<()> { + self + .proxy + .send_event(Message::Tray(TrayMessage::UpdateIconAsTemplate( + is_template, + ))) + .map_err(|_| Error::FailedToSendMessage) + } +} + +impl From for crate::MenuItemWrapper { + fn from(item: SystemTrayMenuItem) -> Self { + match item { + SystemTrayMenuItem::Separator => Self(WryMenuItem::Separator), + _ => unimplemented!(), + } + } +} + +pub fn to_wry_context_menu( + custom_menu_items: &mut HashMap, + menu: SystemTrayMenu, +) -> WryContextMenu { + let mut tray_menu = WryContextMenu::new(); + for item in menu.items { + match item { + SystemTrayMenuEntry::CustomItem(c) => { + #[allow(unused_mut)] + let mut item = tray_menu.add_item(crate::MenuItemAttributesWrapper::from(&c).0); + #[cfg(target_os = "macos")] + if let Some(native_image) = c.native_image { + item.set_native_image(crate::NativeImageWrapper::from(native_image).0); + } + custom_menu_items.insert(c.id, item); + } + SystemTrayMenuEntry::NativeItem(i) => { + tray_menu.add_native_item(crate::MenuItemWrapper::from(i).0); + } + SystemTrayMenuEntry::Submenu(submenu) => { + tray_menu.add_submenu( + &submenu.title, + submenu.enabled, + to_wry_context_menu(custom_menu_items, submenu.inner), + ); + } + } + } + tray_menu +} diff --git a/core/tauri-runtime/Cargo.toml b/core/tauri-runtime/Cargo.toml index 3f4aa943a..75c9ea795 100644 --- a/core/tauri-runtime/Cargo.toml +++ b/core/tauri-runtime/Cargo.toml @@ -35,5 +35,4 @@ winapi = "0.3" gtk = { version = "0.14", features = [ "v3_20" ] } [features] -menu = [ ] system-tray = [ ] diff --git a/core/tauri-runtime/src/lib.rs b/core/tauri-runtime/src/lib.rs index bf2fe5f05..f1207f772 100644 --- a/core/tauri-runtime/src/lib.rs +++ b/core/tauri-runtime/src/lib.rs @@ -14,8 +14,6 @@ use uuid::Uuid; use winapi::shared::windef::HWND; /// Create window and system tray menus. -#[cfg(any(feature = "menu", feature = "system-tray"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "menu", feature = "system-tray"))))] pub mod menu; /// Types useful for interacting with a user's monitors. pub mod monitor; @@ -353,8 +351,6 @@ pub trait Dispatch: Debug + Clone + Send + Sized + 'static { fn on_window_event(&self, f: F) -> Uuid; /// Registers a window event handler. - #[cfg(feature = "menu")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))] fn on_menu_event(&self, f: F) -> Uuid; // GETTERS @@ -394,7 +390,6 @@ pub trait Dispatch: Debug + Clone + Send + Sized + 'static { fn is_visible(&self) -> crate::Result; /// Gets the window menu current visibility state. - #[cfg(feature = "menu")] fn is_menu_visible(&self) -> crate::Result; /// Returns the monitor on which the window currently resides. @@ -466,11 +461,9 @@ pub trait Dispatch: Debug + Clone + Send + Sized + 'static { fn unminimize(&self) -> crate::Result<()>; /// Shows the window menu. - #[cfg(feature = "menu")] fn show_menu(&self) -> crate::Result<()>; /// Hides the window menu. - #[cfg(feature = "menu")] fn hide_menu(&self) -> crate::Result<()>; /// Shows the window. @@ -519,6 +512,5 @@ pub trait Dispatch: Debug + Clone + Send + Sized + 'static { fn eval_script>(&self, script: S) -> crate::Result<()>; /// Applies the specified `update` to the menu item associated with the given `id`. - #[cfg(feature = "menu")] fn update_menu_item(&self, id: u16, update: menu::MenuUpdate) -> crate::Result<()>; } diff --git a/core/tauri-runtime/src/webview.rs b/core/tauri-runtime/src/webview.rs index 1eed1ad93..3cb87e7af 100644 --- a/core/tauri-runtime/src/webview.rs +++ b/core/tauri-runtime/src/webview.rs @@ -6,7 +6,6 @@ use crate::{window::DetachedWindow, Icon}; -#[cfg(feature = "menu")] use crate::menu::Menu; use serde::Deserialize; @@ -118,8 +117,6 @@ pub trait WindowBuilder: WindowBuilderBase { fn with_config(config: WindowConfig) -> Self; /// Sets the menu for the window. - #[cfg(feature = "menu")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))] fn menu(self, menu: Menu) -> Self; /// Show window in the center of the screen. @@ -194,8 +191,6 @@ pub trait WindowBuilder: WindowBuilderBase { fn has_icon(&self) -> bool; /// Whether the menu was set or not. - #[cfg(feature = "menu")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))] fn has_menu(&self) -> bool; } diff --git a/core/tauri/Cargo.toml b/core/tauri/Cargo.toml index b0f5c0e3f..486a26a77 100644 --- a/core/tauri/Cargo.toml +++ b/core/tauri/Cargo.toml @@ -106,7 +106,6 @@ api-all = [ "path-all" ] updater = [ "minisign-verify", "base64" ] -menu = [ "tauri-runtime/menu", "tauri-runtime-wry/menu" ] system-tray = [ "tauri-runtime/system-tray", "tauri-runtime-wry/system-tray" ] reqwest-client = [ "reqwest", "bytes" ] fs-all = [ "fs-write-binary-file" ] diff --git a/core/tauri/src/app.rs b/core/tauri/src/app.rs index bc276f1c8..3495a948c 100644 --- a/core/tauri/src/app.rs +++ b/core/tauri/src/app.rs @@ -30,7 +30,6 @@ use std::{ sync::{mpsc::Sender, Arc}, }; -#[cfg(feature = "menu")] use crate::runtime::menu::{Menu, MenuId, MenuIdRef}; #[cfg(all(windows, feature = "system-tray"))] @@ -41,7 +40,6 @@ use crate::runtime::{Icon, SystemTrayEvent as RuntimeSystemTrayEvent}; #[cfg(feature = "updater")] use crate::updater; -#[cfg(feature = "menu")] pub(crate) type GlobalMenuEventListener = Box) + Send + Sync>; pub(crate) type GlobalWindowEventListener = Box) + Send + Sync>; #[cfg(feature = "system-tray")] @@ -97,8 +95,6 @@ pub enum Event { } /// A menu event that was triggered on a window. -#[cfg(feature = "menu")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))] #[default_runtime(crate::Wry, wry)] #[derive(Debug)] pub struct WindowMenuEvent { @@ -106,7 +102,6 @@ pub struct WindowMenuEvent { pub(crate) window: Window, } -#[cfg(feature = "menu")] impl WindowMenuEvent { /// The menu item id. pub fn menu_item_id(&self) -> MenuIdRef<'_> { @@ -543,11 +538,9 @@ pub struct Builder { state: StateManager, /// The menu set to all windows. - #[cfg(feature = "menu")] menu: Option, /// Menu event handlers that listens to all windows. - #[cfg(feature = "menu")] menu_event_listeners: Vec>, /// Window event handlers that listens to all windows. @@ -573,9 +566,7 @@ impl Builder { plugins: PluginStore::default(), uri_scheme_protocols: Default::default(), state: StateManager::new(), - #[cfg(feature = "menu")] menu: None, - #[cfg(feature = "menu")] menu_event_listeners: Vec::new(), window_event_listeners: Vec::new(), #[cfg(feature = "system-tray")] @@ -737,16 +728,12 @@ impl Builder { } /// Sets the menu to use on all windows. - #[cfg(feature = "menu")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))] pub fn menu(mut self, menu: Menu) -> Self { self.menu.replace(menu); self } /// Registers a menu event handler for all windows. - #[cfg(feature = "menu")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))] pub fn on_menu_event) + Send + Sync + 'static>( mut self, handler: F, @@ -850,7 +837,6 @@ impl Builder { self.uri_scheme_protocols, self.state, self.window_event_listeners, - #[cfg(feature = "menu")] (self.menu, self.menu_event_listeners), ); diff --git a/core/tauri/src/lib.rs b/core/tauri/src/lib.rs index 804eb021b..3a0b70f7c 100644 --- a/core/tauri/src/lib.rs +++ b/core/tauri/src/lib.rs @@ -66,15 +66,10 @@ use serde::Serialize; use std::{collections::HashMap, sync::Arc}; // Export types likely to be used by the application. -#[cfg(any(feature = "menu", feature = "system-tray"))] -#[cfg_attr(doc_cfg, doc(cfg(any(feature = "menu", feature = "system-tray"))))] pub use runtime::menu::CustomMenuItem; -#[cfg(all(target_os = "macos", any(feature = "menu", feature = "system-tray")))] -#[cfg_attr( - doc_cfg, - doc(cfg(all(target_os = "macos", any(feature = "menu", feature = "system-tray")))) -)] +#[cfg(target_os = "macos")] +#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))] pub use runtime::menu::NativeImage; pub use { @@ -108,8 +103,6 @@ pub use { SystemTray, }, }; -#[cfg(feature = "menu")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))] pub use { self::app::WindowMenuEvent, self::runtime::menu::{Menu, MenuItem, Submenu}, diff --git a/core/tauri/src/manager.rs b/core/tauri/src/manager.rs index b1d3010a2..bfc6c0203 100644 --- a/core/tauri/src/manager.rs +++ b/core/tauri/src/manager.rs @@ -26,10 +26,8 @@ use crate::{ #[cfg(target_os = "windows")] use crate::api::path::{resolve_path, BaseDirectory}; -#[cfg(feature = "menu")] use crate::app::{GlobalMenuEventListener, WindowMenuEvent}; -#[cfg(feature = "menu")] use crate::{ runtime::menu::{Menu, MenuEntry, MenuHash, MenuId}, MenuEvent, @@ -55,7 +53,6 @@ const WINDOW_DESTROYED_EVENT: &str = "tauri://destroyed"; const WINDOW_FOCUS_EVENT: &str = "tauri://focus"; const WINDOW_BLUR_EVENT: &str = "tauri://blur"; const WINDOW_SCALE_FACTOR_CHANGED_EVENT: &str = "tauri://scale-change"; -#[cfg(feature = "menu")] const MENU_EVENT: &str = "tauri://menu"; #[default_runtime(crate::Wry, wry)] @@ -81,13 +78,10 @@ pub struct InnerWindowManager { /// The webview protocols protocols available to all windows. uri_scheme_protocols: HashMap>, /// The menu set to all windows. - #[cfg(feature = "menu")] menu: Option, /// Maps runtime id to a strongly typed menu id. - #[cfg(feature = "menu")] menu_ids: HashMap, /// Menu event listeners to all windows. - #[cfg(feature = "menu")] menu_event_listeners: Arc>>, /// Window event listeners to all windows. window_event_listeners: Arc>>, @@ -104,7 +98,6 @@ impl fmt::Debug for InnerWindowManager { .field("default_window_icon", &self.default_window_icon) .field("salts", &self.salts) .field("package_info", &self.package_info); - #[cfg(feature = "menu")] { w = w .field("menu", &self.menu) @@ -130,7 +123,6 @@ impl Clone for WindowManager { } } -#[cfg(feature = "menu")] fn get_menu_ids(map: &mut HashMap, menu: &Menu) { for item in &menu.items { match item { @@ -153,10 +145,7 @@ impl WindowManager { uri_scheme_protocols: HashMap>, state: StateManager, window_event_listeners: Vec>, - #[cfg(feature = "menu")] (menu, menu_event_listeners): ( - Option, - Vec>, - ), + (menu, menu_event_listeners): (Option, Vec>), ) -> Self { Self { inner: Arc::new(InnerWindowManager { @@ -172,7 +161,6 @@ impl WindowManager { salts: Mutex::default(), package_info: context.package_info, uri_scheme_protocols, - #[cfg(feature = "menu")] menu_ids: { let mut map = HashMap::new(); if let Some(menu) = &menu { @@ -180,9 +168,7 @@ impl WindowManager { } map }, - #[cfg(feature = "menu")] menu, - #[cfg(feature = "menu")] menu_event_listeners: Arc::new(menu_event_listeners), window_event_listeners: Arc::new(window_event_listeners), }), @@ -201,7 +187,6 @@ impl WindowManager { } /// Get the menu ids mapper. - #[cfg(feature = "menu")] pub(crate) fn menu_ids(&self) -> HashMap { self.inner.menu_ids.clone() } @@ -284,7 +269,6 @@ impl WindowManager { } } - #[cfg(feature = "menu")] if !pending.window_builder.has_menu() { if let Some(menu) = &self.inner.menu { pending.window_builder = pending.window_builder.menu(menu.clone()); @@ -513,7 +497,6 @@ mod test { Default::default(), StateManager::new(), Default::default(), - #[cfg(feature = "menu")] Default::default(), ); @@ -639,7 +622,6 @@ impl WindowManager { }); } }); - #[cfg(feature = "menu")] { let window_ = window.clone(); let menu_event_listeners = self.inner.menu_event_listeners.clone(); @@ -819,7 +801,6 @@ struct ScaleFactorChanged { size: PhysicalSize, } -#[cfg(feature = "menu")] fn on_menu_event(window: &Window, event: &MenuEvent) -> crate::Result<()> { window.emit(MENU_EVENT, Some(event.menu_item_id.clone())) } diff --git a/core/tauri/src/window.rs b/core/tauri/src/window.rs index a16893f55..6ff52d61b 100644 --- a/core/tauri/src/window.rs +++ b/core/tauri/src/window.rs @@ -2,12 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -#[cfg(feature = "menu")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))] pub(crate) mod menu; -#[cfg(feature = "menu")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))] pub use menu::{MenuEvent, MenuHandle}; use crate::{ @@ -293,8 +289,6 @@ impl Window { } /// Registers a menu event listener. - #[cfg(feature = "menu")] - #[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))] pub fn on_menu_event(&self, f: F) -> uuid::Uuid { let menu_ids = self.manager.menu_ids(); self.window.dispatcher.on_menu_event(move |event| { @@ -307,7 +301,6 @@ impl Window { // Getters /// Gets a handle to the window menu. - #[cfg(feature = "menu")] pub fn menu_handle(&self) -> MenuHandle { MenuHandle { ids: self.manager.menu_ids(), diff --git a/core/tauri/src/window/menu.rs b/core/tauri/src/window/menu.rs index 5e234774c..1c776feec 100644 --- a/core/tauri/src/window/menu.rs +++ b/core/tauri/src/window/menu.rs @@ -12,13 +12,11 @@ use tauri_macros::default_runtime; use std::collections::HashMap; /// The window menu event. -#[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))] #[derive(Debug, Clone)] pub struct MenuEvent { pub(crate) menu_item_id: MenuId, } -#[cfg(feature = "menu")] impl MenuEvent { /// The menu item id. pub fn menu_item_id(&self) -> MenuIdRef<'_> { diff --git a/docs/usage/guides/visual/menu.md b/docs/usage/guides/visual/menu.md index 960036ba2..b4e6d6544 100644 --- a/docs/usage/guides/visual/menu.md +++ b/docs/usage/guides/visual/menu.md @@ -4,15 +4,6 @@ title: Window Menu Native application menus can be attached to a window. -### Setup - -Enable the `menu` feature flag on `src-tauri/Cargo.toml`: - -```toml -[dependencies] -tauri = { version = "1.0.0-beta.0", features = ["menu"] } -``` - ### Creating a menu To create a native window menu, import the `Menu`, `Submenu`, `MenuItem` and `CustomMenuItem` types. diff --git a/examples/api/src-tauri/Cargo.toml b/examples/api/src-tauri/Cargo.toml index ed63682ed..49e24b6b6 100644 --- a/examples/api/src-tauri/Cargo.toml +++ b/examples/api/src-tauri/Cargo.toml @@ -11,7 +11,7 @@ tauri-build = { path = "../../../core/tauri-build" } [dependencies] serde_json = "1.0" serde = { version = "1.0", features = [ "derive" ] } -tauri = { path = "../../../core/tauri", features = ["api-all", "cli", "menu", "system-tray", "updater"] } +tauri = { path = "../../../core/tauri", features = ["api-all", "cli", "system-tray", "updater"] } [features] default = [ "custom-protocol" ] diff --git a/tooling/cli.rs/src/interface/rust.rs b/tooling/cli.rs/src/interface/rust.rs index 2575ebbc7..74a6a1d2a 100644 --- a/tooling/cli.rs/src/interface/rust.rs +++ b/tooling/cli.rs/src/interface/rust.rs @@ -388,9 +388,6 @@ fn tauri_config_to_bundle_settings( // provides `libwebkit2gtk-4.0.so.37` and all `4.0` versions have the -37 package name depends.push("libwebkit2gtk-4.0-37".to_string()); depends.push("libgtk-3-0".to_string()); - if manifest.features.contains("menu") || system_tray_config.is_some() { - depends.push("libgtksourceview-3.0-1".to_string()); - } } let signing_identity = match std::env::var_os("APPLE_SIGNING_IDENTITY") {