From 359f51676b8c63ac6e07a1e3d0af68f58d269ce5 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sat, 30 Sep 2023 08:27:15 -0300 Subject: [PATCH] fix(macos): properly set icon_as_template and menu_on_left_click --- .changes/fix-tray-attributes.md | 5 ++ src/platform/macos.rs | 10 +-- src/platform_impl/macos/system_tray.rs | 94 +++++++++++++++----------- 3 files changed, 65 insertions(+), 44 deletions(-) create mode 100644 .changes/fix-tray-attributes.md diff --git a/.changes/fix-tray-attributes.md b/.changes/fix-tray-attributes.md new file mode 100644 index 000000000..ce54c6893 --- /dev/null +++ b/.changes/fix-tray-attributes.md @@ -0,0 +1,5 @@ +--- +"tao": patch +--- + +Fixes `icon_as_template` and `menu_on_left_click` SystemTray implementation on macOS. diff --git a/src/platform/macos.rs b/src/platform/macos.rs index 04c52da94..631128200 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -616,17 +616,17 @@ pub trait SystemTrayBuilderExtMacOS { #[cfg(feature = "tray")] impl SystemTrayBuilderExtMacOS for SystemTrayBuilder { fn with_icon_as_template(mut self, is_template: bool) -> Self { - self.platform_tray_builder.system_tray.icon_is_template = is_template; + self.platform_tray_builder.icon_is_template = is_template; self } fn with_menu_on_left_click(mut self, enable: bool) -> Self { - self.platform_tray_builder.system_tray.menu_on_left_click = enable; + self.platform_tray_builder.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.platform_tray_builder.title = Some(title.to_owned()); self } } @@ -649,11 +649,11 @@ pub trait SystemTrayExtMacOS { #[cfg(feature = "tray")] impl SystemTrayExtMacOS for SystemTray { fn set_icon_as_template(&mut self, is_template: bool) { - self.0.icon_is_template = is_template + self.0.set_icon_as_template(is_template); } fn enable_menu_on_left_click(&mut self, enable: bool) { - self.0.menu_on_left_click = enable + self.0.set_show_menu_on_left_click(enable); } fn set_title(&mut self, title: &str) { diff --git a/src/platform_impl/macos/system_tray.rs b/src/platform_impl/macos/system_tray.rs index c7e35a8ac..445c977c8 100644 --- a/src/platform_impl/macos/system_tray.rs +++ b/src/platform_impl/macos/system_tray.rs @@ -40,35 +40,40 @@ enum ClickType { } pub struct SystemTrayBuilder { - pub(crate) system_tray: SystemTray, + icon: Icon, + tray_menu: Option, + pub(crate) icon_is_template: bool, + pub(crate) menu_on_left_click: bool, + pub(crate) title: Option, } impl SystemTrayBuilder { /// Creates a new SystemTray for platforms where this is appropriate. #[inline] pub fn new(icon: Icon, tray_menu: Option) -> Self { - let (ns_status_bar, tray_target) = Self::create(icon.clone()); - Self { - system_tray: SystemTray { - icon_is_template: false, - icon, - menu_on_left_click: true, - tray_menu, - ns_status_bar, - title: None, - tray_target, - }, + icon, + tray_menu, + icon_is_template: false, + menu_on_left_click: true, + title: None, } } - fn create(icon: Icon) -> (id, id) { - unsafe { + /// Builds the system tray. + #[inline] + pub fn build( + self, + _window_target: &EventLoopWindowTarget, + tray_id: TrayId, + tooltip: Option, + ) -> Result { + let tray = unsafe { let ns_status_item = NSStatusBar::systemStatusBar(nil).statusItemWithLength_(NSVariableStatusItemLength); let _: () = msg_send![ns_status_item, retain]; - set_icon_for_ns_status_item_button(ns_status_item, icon, false); + set_icon_for_ns_status_item_button(ns_status_item, &self.icon, self.icon_is_template); let button = ns_status_item.button(); let frame: NSRect = msg_send![button, frame]; @@ -77,33 +82,30 @@ impl SystemTrayBuilder { let _: () = msg_send![tray_target, retain]; let _: () = msg_send![tray_target, setWantsLayer: YES]; - (ns_status_item, tray_target) - } - } + let system_tray = SystemTray { + icon_is_template: self.icon_is_template, + icon: self.icon, + menu_on_left_click: self.menu_on_left_click, + tray_menu: self.tray_menu, + ns_status_bar: ns_status_item, + title: None, + tray_target, + }; - /// Builds the system tray. - #[inline] - pub fn build( - self, - _window_target: &EventLoopWindowTarget, - tray_id: TrayId, - tooltip: Option, - ) -> Result { - unsafe { // use our existing status bar - let ns_status_item = self.system_tray.ns_status_bar; + let ns_status_item = system_tray.ns_status_bar; + let tray_target = system_tray.tray_target; - let tray_target = self.system_tray.tray_target; (*tray_target).set_ivar(TRAY_ID, tray_id.0); (*tray_target).set_ivar(TRAY_STATUS_ITEM, ns_status_item); (*tray_target).set_ivar(TRAY_MENU, nil); - (*tray_target).set_ivar(TRAY_MENU_ON_LEFT_CLICK, self.system_tray.menu_on_left_click); + (*tray_target).set_ivar(TRAY_MENU_ON_LEFT_CLICK, system_tray.menu_on_left_click); let button: id = ns_status_item.button(); let _: () = msg_send![button, addSubview: tray_target]; // attach menu only if provided - if let Some(menu) = self.system_tray.tray_menu.clone() { + if let Some(menu) = system_tray.tray_menu.clone() { ns_status_item.setMenu_(menu.menu); (*tray_target).set_ivar(TRAY_MENU, menu.menu); @@ -112,16 +114,18 @@ impl SystemTrayBuilder { // attach tool_tip if provided if let Some(tooltip) = tooltip { - self.system_tray.set_tooltip(&tooltip); + system_tray.set_tooltip(&tooltip); } // set up title if provided - if let Some(title) = &self.system_tray.title { - self.system_tray.set_title(title); + if let Some(title) = &system_tray.title { + system_tray.set_title(title); } - } - Ok(RootSystemTray(self.system_tray)) + system_tray + }; + + Ok(RootSystemTray(tray)) } } @@ -160,17 +164,29 @@ impl SystemTray { } pub fn set_icon(&mut self, icon: Icon) { - set_icon_for_ns_status_item_button(self.ns_status_bar, icon.clone(), self.icon_is_template); + set_icon_for_ns_status_item_button(self.ns_status_bar, &icon, self.icon_is_template); unsafe { let _: () = msg_send![self.tray_target, updateDimensions]; } self.icon = icon; } - pub fn set_icon_as_template(mut self, is_template: bool) { + pub fn set_icon_as_template(&mut self, is_template: bool) { + unsafe { + let button = self.ns_status_bar.button(); + let nsimage: id = msg_send![button, image]; + let _: () = msg_send![nsimage, setTemplate: is_template as i8]; + } self.icon_is_template = is_template; } + pub fn set_show_menu_on_left_click(&mut self, enable: bool) { + unsafe { + (*self.tray_target).set_ivar(TRAY_MENU_ON_LEFT_CLICK, enable); + } + self.menu_on_left_click = enable; + } + pub fn set_menu(&mut self, tray_menu: &Menu) { unsafe { self.tray_menu = Some(tray_menu.clone()); @@ -198,7 +214,7 @@ impl SystemTray { } } -fn set_icon_for_ns_status_item_button(ns_status_item: id, icon: Icon, icon_is_template: bool) { +fn set_icon_for_ns_status_item_button(ns_status_item: id, icon: &Icon, icon_is_template: bool) { // The image is to the right of the title https://developer.apple.com/documentation/appkit/nscellimageposition/nsimageleft const NSIMAGE_LEFT: i32 = 2;