diff --git a/Cargo.toml b/Cargo.toml index 963894b5910b..449056169aa0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,3 +70,5 @@ opt-level = "s" [patch.crates-io] schemars_derive = { git = 'https://github.com/tauri-apps/schemars.git', branch = 'feat/preserve-description-newlines' } tauri = { path = "./crates/tauri" } +tray-icon = { git = "https://github.com/dfaust/tray-icon", branch = "ksni" } +muda = { git = "https://github.com/dfaust/muda", branch = "ksni" } diff --git a/crates/tauri/Cargo.toml b/crates/tauri/Cargo.toml index 412d12ba2819..d8630409983c 100644 --- a/crates/tauri/Cargo.toml +++ b/crates/tauri/Cargo.toml @@ -25,6 +25,7 @@ features = [ "protocol-asset", "test", "specta", + "linux-ksni", ] rustc-args = ["--cfg", "docsrs"] rustdoc-args = ["--cfg", "docsrs"] @@ -182,7 +183,7 @@ test = [] compression = ["tauri-macros/compression", "tauri-utils/compression"] wry = ["tauri-runtime-wry"] objc-exception = ["tauri-runtime-wry/objc-exception"] -linux-libxdo = ["tray-icon/libxdo", "muda/libxdo"] +linux-libxdo = ["muda/libxdo"] isolation = ["tauri-utils/isolation", "tauri-macros/isolation", "uuid"] custom-protocol = ["tauri-macros/custom-protocol"] # TODO: Remove these flags in v3 and/or enable them by default behind a mobile flag https://github.com/tauri-apps/tauri/issues/12384 @@ -206,6 +207,7 @@ image-ico = ["image/ico"] image-png = ["image/png"] macos-proxy = ["tauri-runtime-wry/macos-proxy"] specta = ["dep:specta"] +linux-ksni = ["tray-icon?/linux-ksni"] [[example]] name = "commands" diff --git a/crates/tauri/src/lib.rs b/crates/tauri/src/lib.rs index caf81748e45e..1291ada58be4 100644 --- a/crates/tauri/src/lib.rs +++ b/crates/tauri/src/lib.rs @@ -35,6 +35,7 @@ //! - **image-png**: Adds support to parse `.png` image, see [`Image`]. //! - **macos-proxy**: Adds support for [`WebviewBuilder::proxy_url`] on macOS. Requires macOS 14+. //! - **specta**: Add support for [`specta::specta`](https://docs.rs/specta/%5E2.0.0-rc.9/specta/attr.specta.html) with Tauri arguments such as [`State`](crate::State), [`Window`](crate::Window) and [`AppHandle`](crate::AppHandle) +//! - **linux-ksni**: Enables the experimental `linux-ksni` feature of the `tray-icon` crate, which uses the xdg standard for system tray icons on Linux. //! //! ## Cargo allowlist features //! diff --git a/crates/tauri/src/tray/mod.rs b/crates/tauri/src/tray/mod.rs index 8f900ab8edb7..93839c510a03 100644 --- a/crates/tauri/src/tray/mod.rs +++ b/crates/tauri/src/tray/mod.rs @@ -218,11 +218,6 @@ pub struct TrayIconBuilder { impl TrayIconBuilder { /// Creates a new tray icon builder. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Sometimes the icon won't be visible unless a menu is set. - /// Setting an empty [`Menu`](crate::menu::Menu) is enough. pub fn new() -> Self { Self { inner: tray_icon::TrayIconBuilder::new(), @@ -232,11 +227,6 @@ impl TrayIconBuilder { } /// Creates a new tray icon builder with the specified id. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Sometimes the icon won't be visible unless a menu is set. - /// Setting an empty [`Menu`](crate::menu::Menu) is enough. pub fn with_id>(id: I) -> Self { let mut builder = Self::new(); builder.inner = builder.inner.with_id(id); @@ -259,6 +249,7 @@ impl TrayIconBuilder { /// /// - **Linux:** Sometimes the icon won't be visible unless a menu is set. /// Setting an empty [`Menu`](crate::menu::Menu) is enough. + /// Works with feature `linux-ksni`. pub fn icon(mut self, icon: Image<'_>) -> Self { let icon = icon.try_into().ok(); if let Some(icon) = icon { @@ -271,7 +262,7 @@ impl TrayIconBuilder { /// /// ## Platform-specific: /// - /// - **Linux:** Unsupported. + /// - **Linux:** Unsupported. Works with feature `linux-ksni`. pub fn tooltip>(mut self, s: S) -> Self { self.inner = self.inner.with_tooltip(s); self @@ -286,6 +277,7 @@ impl TrayIconBuilder { /// updated information. In general, it shouldn't be shown unless a /// user requests it as it can take up a significant amount of space /// on the user's panel. This may not be shown in all visualizations. + /// Works with feature `linux-ksni`. /// - **Windows:** Unsupported. pub fn title>(mut self, title: S) -> Self { self.inner = self.inner.with_title(title); @@ -294,8 +286,11 @@ impl TrayIconBuilder { /// Set tray icon temp dir path. **Linux only**. /// + /// Not availabe with feature `linux-ksni`. + /// /// On Linux, we need to write the icon to the disk and usually it will /// be `$XDG_RUNTIME_DIR/tray-icon` or `$TEMP/tray-icon`. + #[cfg(not(feature = "linux-ksni"))] pub fn temp_dir_path>(mut self, s: P) -> Self { self.inner = self.inner.with_temp_dir_path(s); self @@ -509,7 +504,7 @@ impl TrayIcon { /// /// ## Platform-specific: /// - /// - **Linux**: once a menu is set it cannot be removed so `None` has no effect + /// - **Linux**: Once a menu is set it cannot be removed so `None` has no effect. Works with feature `linux-ksni`. pub fn set_menu(&self, menu: Option) -> crate::Result<()> { run_item_main_thread!(self, |self_: Self| { self_.inner.set_menu(menu.map(|m| m.inner_context_owned())) @@ -520,7 +515,7 @@ impl TrayIcon { /// /// ## Platform-specific: /// - /// - **Linux:** Unsupported + /// - **Linux:** Unsupported. Works with feature `linux-ksni`. pub fn set_tooltip>(&self, tooltip: Option) -> crate::Result<()> { let s = tooltip.map(|s| s.as_ref().to_string()); run_item_main_thread!(self, |self_: Self| self_.inner.set_tooltip(s))?.map_err(Into::into) @@ -535,6 +530,7 @@ impl TrayIcon { /// updated information. In general, it shouldn't be shown unless a /// user requests it as it can take up a significant amount of space /// on the user's panel. This may not be shown in all visualizations. + /// Works with feature `linux-ksni`. /// - **Windows:** Unsupported pub fn set_title>(&self, title: Option) -> crate::Result<()> { let s = title.map(|s| s.as_ref().to_string()); @@ -548,8 +544,11 @@ impl TrayIcon { /// Sets the tray icon temp dir path. **Linux only**. /// + /// Not availabe with feature `linux-ksni`. + /// /// On Linux, we need to write the icon to the disk and usually it will /// be `$XDG_RUNTIME_DIR/tray-icon` or `$TEMP/tray-icon`. + #[cfg(not(feature = "linux-ksni"))] pub fn set_temp_dir_path>(&self, path: Option

) -> crate::Result<()> { #[allow(unused)] let p = path.map(|p| p.as_ref().to_path_buf()); diff --git a/crates/tauri/src/tray/plugin.rs b/crates/tauri/src/tray/plugin.rs index fcb610d53076..4d5ece9723b2 100644 --- a/crates/tauri/src/tray/plugin.rs +++ b/crates/tauri/src/tray/plugin.rs @@ -73,6 +73,7 @@ fn new( if let Some(title) = options.title { builder = builder.title(title); } + #[cfg(not(feature = "linux-ksni"))] if let Some(temp_dir_path) = options.temp_dir_path { builder = builder.temp_dir_path(temp_dir_path); } @@ -191,6 +192,7 @@ fn set_visible( tray.set_visible(visible) } +#[cfg(not(feature = "linux-ksni"))] #[command(root = "crate")] fn set_temp_dir_path( webview: Webview, @@ -235,6 +237,7 @@ pub(crate) fn init() -> TauriPlugin { set_tooltip, set_title, set_visible, + #[cfg(not(feature = "linux-ksni"))] set_temp_dir_path, set_icon_as_template, set_show_menu_on_left_click,