Browse Source

feat: expose `set_title` for MacOS tray (#5182)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
Tomáš Vojtášek 2 years ago
parent
commit
8f1ace7795

+ 5 - 0
.changes/tray-title-config.md

@@ -0,0 +1,5 @@
+---
+"tauri-utils": minor
+---
+
+Added `title` option on the system tray configuration (macOS only).

+ 7 - 0
.changes/tray-title.md

@@ -0,0 +1,7 @@
+---
+"tauri": minor
+"tauri-runtime": minor
+"tauri-runtime-wry": minor
+---
+
+Added methods to set the system tray title on macOS.

+ 8 - 0
core/tauri-runtime-wry/src/lib.rs

@@ -1079,6 +1079,8 @@ pub enum TrayMessage {
   UpdateIcon(Icon),
   #[cfg(target_os = "macos")]
   UpdateIconAsTemplate(bool),
+  #[cfg(target_os = "macos")]
+  UpdateTitle(String),
   Create(SystemTray, Sender<Result<()>>),
   Destroy,
 }
@@ -2488,6 +2490,12 @@ fn handle_user_message<T: UserEvent>(
               tray.set_icon_as_template(is_template);
             }
           }
+          #[cfg(target_os = "macos")]
+          TrayMessage::UpdateTitle(title) => {
+            if let Some(tray) = &mut *tray_context.tray.lock().unwrap() {
+              tray.set_title(&title);
+            }
+          }
           TrayMessage::Create(_tray, _tx) => {
             // already handled
           }

+ 16 - 1
core/tauri-runtime-wry/src/system_tray.rs

@@ -107,7 +107,11 @@ pub fn create_tray<T>(
   {
     builder = builder
       .with_icon_as_template(system_tray.icon_as_template)
-      .with_menu_on_left_click(system_tray.menu_on_left_click)
+      .with_menu_on_left_click(system_tray.menu_on_left_click);
+
+    if let Some(title) = system_tray.title {
+      builder = builder.with_title(&title);
+    }
   }
 
   let tray = builder
@@ -156,6 +160,17 @@ impl<T: UserEvent> TrayHandle for SystemTrayHandle<T> {
       .map_err(|_| Error::FailedToSendMessage)
   }
 
+  #[cfg(target_os = "macos")]
+  fn set_title(&self, title: &str) -> tauri_runtime::Result<()> {
+    self
+      .proxy
+      .send_event(Message::Tray(
+        self.id,
+        TrayMessage::UpdateTitle(title.to_owned()),
+      ))
+      .map_err(|_| Error::FailedToSendMessage)
+  }
+
   fn destroy(&self) -> Result<()> {
     self
       .proxy

+ 15 - 1
core/tauri-runtime/src/lib.rs

@@ -50,6 +50,8 @@ pub struct SystemTray {
   pub icon_as_template: bool,
   #[cfg(target_os = "macos")]
   pub menu_on_left_click: bool,
+  #[cfg(target_os = "macos")]
+  pub title: Option<String>,
   pub on_event: Option<Box<TrayEventHandler>>,
 }
 
@@ -63,7 +65,8 @@ impl fmt::Debug for SystemTray {
     #[cfg(target_os = "macos")]
     {
       d.field("icon_as_template", &self.icon_as_template)
-        .field("menu_on_left_click", &self.menu_on_left_click);
+        .field("menu_on_left_click", &self.menu_on_left_click)
+        .field("title", &self.title);
     }
     d.finish()
   }
@@ -81,6 +84,8 @@ impl Clone for SystemTray {
       icon_as_template: self.icon_as_template,
       #[cfg(target_os = "macos")]
       menu_on_left_click: self.menu_on_left_click,
+      #[cfg(target_os = "macos")]
+      title: self.title.clone(),
     }
   }
 }
@@ -96,6 +101,8 @@ impl Default for SystemTray {
       icon_as_template: false,
       #[cfg(target_os = "macos")]
       menu_on_left_click: false,
+      #[cfg(target_os = "macos")]
+      title: None,
       on_event: None,
     }
   }
@@ -142,6 +149,13 @@ impl SystemTray {
     self
   }
 
+  #[cfg(target_os = "macos")]
+  #[must_use]
+  pub fn with_title(mut self, title: &str) -> Self {
+    self.title = Some(title.to_owned());
+    self
+  }
+
   /// Sets the menu to show when the system tray is right clicked.
   #[must_use]
   pub fn with_menu(mut self, menu: menu::SystemTrayMenu) -> Self {

+ 2 - 0
core/tauri-runtime/src/menu.rs

@@ -152,6 +152,8 @@ pub trait TrayHandle: fmt::Debug + Clone + Send + Sync {
   fn update_item(&self, id: u16, update: MenuUpdate) -> crate::Result<()>;
   #[cfg(target_os = "macos")]
   fn set_icon_as_template(&self, is_template: bool) -> crate::Result<()>;
+  #[cfg(target_os = "macos")]
+  fn set_title(&self, title: &str) -> crate::Result<()>;
   fn destroy(&self) -> crate::Result<()>;
 }
 

+ 5 - 1
core/tauri-utils/src/config.rs

@@ -2391,6 +2391,8 @@ pub struct SystemTrayConfig {
     alias = "menu-on-left-click"
   )]
   pub menu_on_left_click: bool,
+  /// Title for MacOS tray
+  pub title: Option<String>,
 }
 
 fn default_tray_menu_on_left_click() -> bool {
@@ -3350,12 +3352,14 @@ mod build {
       let icon_as_template = self.icon_as_template;
       let menu_on_left_click = self.menu_on_left_click;
       let icon_path = path_buf_lit(&self.icon_path);
+      let title = opt_str_lit(self.title.as_ref());
       literal_struct!(
         tokens,
         SystemTrayConfig,
         icon_path,
         icon_as_template,
-        menu_on_left_click
+        menu_on_left_click,
+        title
       );
     }
   }

+ 46 - 0
core/tauri/src/app/tray.rs

@@ -62,6 +62,8 @@ pub struct SystemTray {
   menu_on_left_click_set: bool,
   #[cfg(target_os = "macos")]
   icon_as_template_set: bool,
+  #[cfg(target_os = "macos")]
+  title: Option<String>,
 }
 
 impl fmt::Debug for SystemTray {
@@ -94,6 +96,8 @@ impl Default for SystemTray {
       icon_as_template_set: false,
       #[cfg(target_os = "macos")]
       menu_on_left_click_set: false,
+      #[cfg(target_os = "macos")]
+      title: None,
     }
   }
 }
@@ -228,6 +232,31 @@ impl SystemTray {
     self
   }
 
+  /// Sets the menu title`
+  ///
+  /// # Examples
+  ///
+  /// ```
+  /// use tauri::SystemTray;
+  ///
+  /// tauri::Builder::default()
+  ///   .setup(|app| {
+  ///     let mut tray_builder = SystemTray::new();
+  ///     #[cfg(target_os = "macos")]
+  ///     {
+  ///       tray_builder = tray_builder.with_title("My App");
+  ///     }
+  ///     let tray_handle = tray_builder.build(app)?;
+  ///     Ok(())
+  ///   });
+  /// ```
+  #[cfg(target_os = "macos")]
+  #[must_use]
+  pub fn with_title(mut self, title: &str) -> Self {
+    self.title = Some(title.to_owned());
+    self
+  }
+
   /// Sets the event listener for this system tray.
   ///
   /// # Examples
@@ -342,6 +371,14 @@ impl SystemTray {
           .as_ref()
           .map_or(false, |t| t.menu_on_left_click);
       }
+      if self.title.is_none() {
+        self.title = manager
+          .config()
+          .tauri
+          .system_tray
+          .as_ref()
+          .and_then(|t| t.title.clone())
+      }
     }
 
     let tray_id = self.id.clone();
@@ -372,6 +409,9 @@ impl SystemTray {
     {
       runtime_tray = runtime_tray.with_icon_as_template(self.icon_as_template);
       runtime_tray = runtime_tray.with_menu_on_left_click(self.menu_on_left_click);
+      if let Some(title) = self.title {
+        runtime_tray = runtime_tray.with_title(&title);
+      }
     }
 
     let id = runtime_tray.id;
@@ -564,6 +604,12 @@ impl<R: Runtime> SystemTrayHandle<R> {
       .map_err(Into::into)
   }
 
+  /// Adds the title to the tray menu
+  #[cfg(target_os = "macos")]
+  pub fn set_title(&self, title: &str) -> crate::Result<()> {
+    self.inner.set_title(title).map_err(Into::into)
+  }
+
   /// Destroys this system tray.
   pub fn destroy(&self) -> crate::Result<()> {
     self.inner.destroy().map_err(Into::into)

+ 5 - 0
core/tauri/src/test/mock_runtime.rs

@@ -539,6 +539,11 @@ impl TrayHandle for MockTrayHandler {
     Ok(())
   }
 
+  #[cfg(target_os = "macos")]
+  fn set_title(&self, title: &str) -> tauri_runtime::Result<()> {
+    Ok(())
+  }
+
   fn destroy(&self) -> Result<()> {
     Ok(())
   }

+ 14 - 2
examples/api/src-tauri/src/desktop.rs

@@ -58,14 +58,22 @@ pub fn main() {
 }
 
 fn create_tray(app: &tauri::App) -> tauri::Result<()> {
-  let tray_menu1 = SystemTrayMenu::new()
+  let mut tray_menu1 = SystemTrayMenu::new()
     .add_item(CustomMenuItem::new("toggle", "Toggle"))
     .add_item(CustomMenuItem::new("new", "New window"))
     .add_item(CustomMenuItem::new("icon_1", "Tray Icon 1"))
-    .add_item(CustomMenuItem::new("icon_2", "Tray Icon 2"))
+    .add_item(CustomMenuItem::new("icon_2", "Tray Icon 2"));
+
+  #[cfg(target_os = "macos")]
+  {
+    tray_menu1 = tray_menu1.add_item(CustomMenuItem::new("set_title", "Set Title"));
+  }
+
+  tray_menu1 = tray_menu1
     .add_item(CustomMenuItem::new("switch_menu", "Switch Menu"))
     .add_item(CustomMenuItem::new("exit_app", "Quit"))
     .add_item(CustomMenuItem::new("destroy", "Destroy"));
+
   let tray_menu2 = SystemTrayMenu::new()
     .add_item(CustomMenuItem::new("toggle", "Toggle"))
     .add_item(CustomMenuItem::new("new", "New window"))
@@ -118,6 +126,10 @@ fn create_tray(app: &tauri::App) -> tauri::Result<()> {
                 .build()
                 .unwrap();
             }
+            "set_title" => {
+              #[cfg(target_os = "macos")]
+              tray_handle.set_title("Tauri").unwrap();
+            }
             "icon_1" => {
               #[cfg(target_os = "macos")]
               tray_handle.set_icon_as_template(true).unwrap();

+ 7 - 0
tooling/cli/schema.json

@@ -2470,6 +2470,13 @@
           "description": "A Boolean value that determines whether the menu should appear when the tray icon receives a left click on macOS.",
           "default": true,
           "type": "boolean"
+        },
+        "title": {
+          "description": "Title for MacOS tray",
+          "type": [
+            "string",
+            "null"
+          ]
         }
       },
       "additionalProperties": false