diff --git a/.changes/macos-sytem-tray-title.md b/.changes/macos-sytem-tray-title.md new file mode 100644 index 000000000..642d6f4c4 --- /dev/null +++ b/.changes/macos-sytem-tray-title.md @@ -0,0 +1,5 @@ +--- +"tao": "minor" +--- + +Added `SystemTrayExtMacOS::set_title` to `SystemTray` and `SystemTrayBuilderExtMacOS::with_title` to set the tray icon title on MacOS diff --git a/examples/system_tray.rs b/examples/system_tray.rs index a33040f4c..aa65e1c9c 100644 --- a/examples/system_tray.rs +++ b/examples/system_tray.rs @@ -17,6 +17,9 @@ fn main() { TrayId, }; + #[cfg(target_os = "macos")] + use tao::platform::macos::{SystemTrayBuilderExtMacOS, SystemTrayExtMacOS}; + env_logger::init(); let event_loop = EventLoop::new(); @@ -31,11 +34,12 @@ fn main() { let second_tray_id = TrayId::new("2nd-tray"); let icon = load_icon(std::path::Path::new(path)); let mut tray_menu = Menu::new(); + let menu_item = tray_menu.add_item(MenuItemAttributes::new("Set tray title (macos)")); #[cfg(target_os = "macos")] { tray_menu - .add_item(MenuItemAttributes::new("Item 1")) + .add_item(MenuItemAttributes::new("Menu Item with icon")) .set_icon(icon.clone()); } @@ -48,10 +52,18 @@ fn main() { .build(&event_loop) .unwrap(); - #[cfg(not(target_os = "linux"))] + #[cfg(target_os = "windows")] + let system_tray = SystemTrayBuilder::new(icon.clone(), Some(tray_menu)) + .with_id(main_tray_id) + .with_tooltip("tao - windowing creation library") + .build(&event_loop) + .unwrap(); + + #[cfg(target_os = "macos")] let system_tray = SystemTrayBuilder::new(icon.clone(), Some(tray_menu)) .with_id(main_tray_id) .with_tooltip("tao - windowing creation library") + .with_title("Tao") .build(&event_loop) .unwrap(); @@ -86,6 +98,13 @@ fn main() { *control_flow = ControlFlow::Exit; } else if menu_id == log.clone().id() { println!("Log clicked"); + } else if menu_id == menu_item.clone().id() { + #[cfg(target_os = "macos")] + { + if let Some(tray) = system_tray.as_mut() { + tray.set_title("Tao - clicked"); + } + } } } Event::TrayEvent { diff --git a/src/platform/macos.rs b/src/platform/macos.rs index 643fe3e0b..c5b47b8bc 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -515,6 +515,9 @@ pub trait SystemTrayBuilderExtMacOS { /// Enables or disables showing the tray menu on left click, default is true. fn with_menu_on_left_click(self, enable: bool) -> Self; + + /// Sets the tray icon title + fn with_title(self, title: &str) -> Self; } #[cfg(feature = "tray")] @@ -528,6 +531,11 @@ impl SystemTrayBuilderExtMacOS for SystemTrayBuilder { self.platform_tray_builder.system_tray.menu_on_left_click = enable; self } + + fn with_title(mut self, title: &str) -> Self { + self.platform_tray_builder.system_tray.title = Some(title.to_owned()); + self + } } #[cfg(feature = "tray")] @@ -540,6 +548,9 @@ pub trait SystemTrayExtMacOS { /// Enables or disables showing the tray menu on left click, default is true. fn enable_menu_on_left_click(&mut self, enable: bool); + + /// Sets the tray icon title + fn set_title(&mut self, title: &str); } #[cfg(feature = "tray")] @@ -551,4 +562,8 @@ impl SystemTrayExtMacOS for SystemTray { fn enable_menu_on_left_click(&mut self, enable: bool) { self.0.menu_on_left_click = enable } + + fn set_title(&mut self, title: &str) { + self.0.set_title(title) + } } diff --git a/src/platform_impl/macos/system_tray.rs b/src/platform_impl/macos/system_tray.rs index 8a6694d46..c51763e0a 100644 --- a/src/platform_impl/macos/system_tray.rs +++ b/src/platform_impl/macos/system_tray.rs @@ -18,8 +18,8 @@ use crate::{ }; use cocoa::{ appkit::{ - NSButton, NSEventMask, NSEventModifierFlags, NSEventType, NSImage, NSSquareStatusItemLength, - NSStatusBar, NSStatusItem, NSWindow, + NSButton, NSEventMask, NSEventModifierFlags, NSEventType, NSImage, NSStatusBar, NSStatusItem, + NSVariableStatusItemLength, NSWindow, }, base::{id, nil, NO, YES}, foundation::{NSData, NSPoint, NSSize, NSString}, @@ -40,7 +40,7 @@ impl SystemTrayBuilder { pub fn new(icon: Icon, tray_menu: Option) -> Self { unsafe { let ns_status_bar = - NSStatusBar::systemStatusBar(nil).statusItemWithLength_(NSSquareStatusItemLength); + NSStatusBar::systemStatusBar(nil).statusItemWithLength_(NSVariableStatusItemLength); let _: () = msg_send![ns_status_bar, retain]; Self { @@ -50,6 +50,7 @@ impl SystemTrayBuilder { menu_on_left_click: true, tray_menu, ns_status_bar, + title: None, }, } } @@ -100,6 +101,11 @@ impl SystemTrayBuilder { if let Some(tooltip) = tooltip { self.system_tray.set_tooltip(&tooltip); } + + // set up title if provided + if let Some(title) = &self.system_tray.title { + self.system_tray.set_title(title); + } } Ok(RootSystemTray(self.system_tray)) @@ -114,6 +120,7 @@ pub struct SystemTray { pub(crate) menu_on_left_click: bool, pub(crate) tray_menu: Option, pub(crate) ns_status_bar: id, + pub(crate) title: Option, } impl Drop for SystemTray { @@ -149,9 +156,20 @@ impl SystemTray { } } + pub fn set_title(&self, title: &str) { + unsafe { + NSButton::setTitle_( + self.ns_status_bar.button(), + NSString::alloc(nil).init_str(title), + ); + } + } + fn create_button_with_icon(&self) { const ICON_WIDTH: f64 = 18.0; const ICON_HEIGHT: f64 = 18.0; + // The image is to the right of the title https://developer.apple.com/documentation/appkit/nscellimageposition/nsimageleft + const NSIMAGE_LEFT: i32 = 2; let icon = self.icon.inner.to_png(); @@ -171,6 +189,7 @@ impl SystemTray { button.setImage_(nsimage); let _: () = msg_send![nsimage, setSize: new_size]; + let _: () = msg_send![button, setImagePosition: NSIMAGE_LEFT]; let is_template = match self.icon_is_template { true => YES, false => NO,