Ver código fonte

feat: remove menu feature flag (#2415)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
Ngo Iok Ui (Wu Yu Wei) 4 anos atrás
pai
commit
f81ebddfcc

+ 1 - 1
.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",

+ 7 - 0
.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.

+ 1 - 1
.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

+ 1 - 1
.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

+ 1 - 1
.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

+ 2 - 2
.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:

+ 1 - 1
.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

+ 1 - 1
.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

+ 2 - 2
.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:

+ 2 - 2
.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

+ 2 - 2
.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

+ 1 - 1
.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:

+ 1 - 1
.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

+ 0 - 1
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" ]

+ 209 - 47
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<HashMap<Option<PathBuf>, WebContext>>;
+// window
 type WindowEventHandler = Box<dyn Fn(&WindowEvent) + Send>;
 type WindowEventListenersMap = Arc<Mutex<HashMap<Uuid, WindowEventHandler>>>;
 type WindowEventListeners = Arc<Mutex<HashMap<WindowId, WindowEventListenersMap>>>;
+// global shortcut
 type GlobalShortcutListeners = Arc<Mutex<HashMap<AcceleratorId, Box<dyn Fn() + Send>>>>;
+// menu
+pub type MenuEventHandler = Box<dyn Fn(&MenuEvent) + Send>;
+pub type MenuEventListeners = Arc<Mutex<HashMap<WindowId, WindowMenuEventListeners>>>;
+pub type WindowMenuEventListeners = Arc<Mutex<HashMap<Uuid, MenuEventHandler>>>;
 
 macro_rules! dispatcher_getter {
   ($self: ident, $message: expr) => {{
@@ -134,6 +151,124 @@ struct EventLoopContext {
   proxy: EventLoopProxy<Message>,
 }
 
+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<MenuItem> 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<NativeImage> 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<UserAttentionType> 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<bool>),
   IsResizable(Sender<bool>),
   IsVisible(Sender<bool>),
-  #[cfg(feature = "menu")]
   IsMenuVisible(Sender<bool>),
   CurrentMonitor(Sender<Option<MonitorHandle>>),
   PrimaryMonitor(Sender<Option<MonitorHandle>>),
@@ -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<AtomicBool>,
   proxy: EventLoopProxy<Message>,
   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<F: Fn(&MenuEvent) + Send + 'static>(&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<bool> {
     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<u16, WryCustomMenuItem>,
 }
 
@@ -1274,7 +1395,6 @@ pub struct Wry {
   windows: Arc<Mutex<HashMap<WindowId, WindowWrapper>>>,
   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<Mutex<WryShortcutManager>>,
   global_shortcut_manager_handle: &'a GlobalShortcutManagerHandle,
   clipboard_manager: Arc<Mutex<Clipboard>>,
-  #[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<WindowId, WindowWrapper>>,
   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<MenuHash, WryCustomMenuItem>,
+  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<Message>,
   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,
   })
 }

+ 0 - 313
core/tauri-runtime-wry/src/menu.rs

@@ -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<dyn Fn(&MenuEvent) + Send>;
-#[cfg(feature = "menu")]
-pub type MenuEventListeners = Arc<Mutex<HashMap<WindowId, WindowMenuEventListeners>>>;
-#[cfg(feature = "menu")]
-pub type WindowMenuEventListeners = Arc<Mutex<HashMap<Uuid, MenuEventHandler>>>;
-
-#[cfg(feature = "system-tray")]
-pub type SystemTrayEventHandler = Box<dyn Fn(&SystemTrayEvent) + Send>;
-#[cfg(feature = "system-tray")]
-pub type SystemTrayEventListeners = Arc<Mutex<HashMap<Uuid, SystemTrayEventHandler>>>;
-#[cfg(feature = "system-tray")]
-pub type SystemTrayItems = Arc<Mutex<HashMap<u16, WryCustomMenuItem>>>;
-
-#[cfg(feature = "system-tray")]
-#[derive(Debug, Clone)]
-pub struct SystemTrayHandle {
-  pub(crate) proxy: EventLoopProxy<super::Message>,
-}
-
-#[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<NativeImage> 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<MenuItem> 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<SystemTrayMenuItem> 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<MenuHash, WryCustomMenuItem>,
-  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<MenuHash, WryCustomMenuItem>,
-  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
-}

+ 102 - 0
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<dyn Fn(&SystemTrayEvent) + Send>;
+pub type SystemTrayEventListeners = Arc<Mutex<HashMap<Uuid, SystemTrayEventHandler>>>;
+pub type SystemTrayItems = Arc<Mutex<HashMap<u16, WryCustomMenuItem>>>;
+
+#[derive(Debug, Clone)]
+pub struct SystemTrayHandle {
+  pub(crate) proxy: EventLoopProxy<super::Message>,
+}
+
+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<SystemTrayMenuItem> 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<MenuHash, WryCustomMenuItem>,
+  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
+}

+ 0 - 1
core/tauri-runtime/Cargo.toml

@@ -35,5 +35,4 @@ winapi = "0.3"
 gtk = { version = "0.14", features = [ "v3_20" ] }
 
 [features]
-menu = [ ]
 system-tray = [ ]

+ 0 - 8
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<F: Fn(&WindowEvent) + Send + 'static>(&self, f: F) -> Uuid;
 
   /// Registers a window event handler.
-  #[cfg(feature = "menu")]
-  #[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))]
   fn on_menu_event<F: Fn(&window::MenuEvent) + Send + 'static>(&self, f: F) -> Uuid;
 
   // GETTERS
@@ -394,7 +390,6 @@ pub trait Dispatch: Debug + Clone + Send + Sized + 'static {
   fn is_visible(&self) -> crate::Result<bool>;
 
   /// Gets the window menu current visibility state.
-  #[cfg(feature = "menu")]
   fn is_menu_visible(&self) -> crate::Result<bool>;
 
   /// 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<S: Into<String>>(&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<()>;
 }

+ 0 - 5
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;
 }
 

+ 0 - 1
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" ]

+ 0 - 14
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<R> = Box<dyn Fn(WindowMenuEvent<R>) + Send + Sync>;
 pub(crate) type GlobalWindowEventListener<R> = Box<dyn Fn(GlobalWindowEvent<R>) + 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<R: Runtime> {
@@ -106,7 +102,6 @@ pub struct WindowMenuEvent<R: Runtime> {
   pub(crate) window: Window<R>,
 }
 
-#[cfg(feature = "menu")]
 impl<R: Runtime> WindowMenuEvent<R> {
   /// The menu item id.
   pub fn menu_item_id(&self) -> MenuIdRef<'_> {
@@ -543,11 +538,9 @@ pub struct Builder<R: Runtime> {
   state: StateManager,
 
   /// The menu set to all windows.
-  #[cfg(feature = "menu")]
   menu: Option<Menu>,
 
   /// Menu event handlers that listens to all windows.
-  #[cfg(feature = "menu")]
   menu_event_listeners: Vec<GlobalMenuEventListener<R>>,
 
   /// Window event handlers that listens to all windows.
@@ -573,9 +566,7 @@ impl<R: Runtime> Builder<R> {
       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<R: Runtime> Builder<R> {
   }
 
   /// 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<F: Fn(WindowMenuEvent<R>) + Send + Sync + 'static>(
     mut self,
     handler: F,
@@ -850,7 +837,6 @@ impl<R: Runtime> Builder<R> {
       self.uri_scheme_protocols,
       self.state,
       self.window_event_listeners,
-      #[cfg(feature = "menu")]
       (self.menu, self.menu_event_listeners),
     );
 

+ 2 - 9
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},

+ 1 - 20
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<R: Runtime> {
   /// The webview protocols protocols available to all windows.
   uri_scheme_protocols: HashMap<String, Arc<CustomProtocol>>,
   /// The menu set to all windows.
-  #[cfg(feature = "menu")]
   menu: Option<Menu>,
   /// Maps runtime id to a strongly typed menu id.
-  #[cfg(feature = "menu")]
   menu_ids: HashMap<MenuHash, MenuId>,
   /// Menu event listeners to all windows.
-  #[cfg(feature = "menu")]
   menu_event_listeners: Arc<Vec<GlobalMenuEventListener<R>>>,
   /// Window event listeners to all windows.
   window_event_listeners: Arc<Vec<GlobalWindowEventListener<R>>>,
@@ -104,7 +98,6 @@ impl<R: Runtime> fmt::Debug for InnerWindowManager<R> {
       .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<R: Runtime> Clone for WindowManager<R> {
   }
 }
 
-#[cfg(feature = "menu")]
 fn get_menu_ids(map: &mut HashMap<MenuHash, MenuId>, menu: &Menu) {
   for item in &menu.items {
     match item {
@@ -153,10 +145,7 @@ impl<R: Runtime> WindowManager<R> {
     uri_scheme_protocols: HashMap<String, Arc<CustomProtocol>>,
     state: StateManager,
     window_event_listeners: Vec<GlobalWindowEventListener<R>>,
-    #[cfg(feature = "menu")] (menu, menu_event_listeners): (
-      Option<Menu>,
-      Vec<GlobalMenuEventListener<R>>,
-    ),
+    (menu, menu_event_listeners): (Option<Menu>, Vec<GlobalMenuEventListener<R>>),
   ) -> Self {
     Self {
       inner: Arc::new(InnerWindowManager {
@@ -172,7 +161,6 @@ impl<R: Runtime> WindowManager<R> {
         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<R: Runtime> WindowManager<R> {
           }
           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<R: Runtime> WindowManager<R> {
   }
 
   /// Get the menu ids mapper.
-  #[cfg(feature = "menu")]
   pub(crate) fn menu_ids(&self) -> HashMap<MenuHash, MenuId> {
     self.inner.menu_ids.clone()
   }
@@ -284,7 +269,6 @@ impl<R: Runtime> WindowManager<R> {
       }
     }
 
-    #[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<R: Runtime> WindowManager<R> {
         });
       }
     });
-    #[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<u32>,
 }
 
-#[cfg(feature = "menu")]
 fn on_menu_event<R: Runtime>(window: &Window<R>, event: &MenuEvent) -> crate::Result<()> {
   window.emit(MENU_EVENT, Some(event.menu_item_id.clone()))
 }

+ 0 - 7
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<R: Runtime> Window<R> {
   }
 
   /// Registers a menu event listener.
-  #[cfg(feature = "menu")]
-  #[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))]
   pub fn on_menu_event<F: Fn(MenuEvent) + Send + 'static>(&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<R: Runtime> Window<R> {
   // Getters
 
   /// Gets a handle to the window menu.
-  #[cfg(feature = "menu")]
   pub fn menu_handle(&self) -> MenuHandle<R> {
     MenuHandle {
       ids: self.manager.menu_ids(),

+ 0 - 2
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<'_> {

+ 0 - 9
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.

+ 1 - 1
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" ]

+ 0 - 3
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") {