Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add set_visible #14

Merged
merged 2 commits into from
Jan 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/visible.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tray-icon": "patch"
---

Add `TrayIcon::set_visible`.
7 changes: 6 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ impl TrayIcon {
self.id
}

/// Set new tray icon. If `None` is provided, it will hide the icon.
/// Set new tray icon. If `None` is provided, it will remove the icon.
pub fn set_icon(&mut self, icon: Option<Icon>) -> Result<()> {
self.tray.set_icon(icon)
}
Expand Down Expand Up @@ -273,6 +273,11 @@ impl TrayIcon {
self.tray.set_title(title)
}

/// Show or hide this tray icon
pub fn set_visible(&mut self, visible: bool) {
self.tray.set_visible(visible)
}

/// Sets the tray icon temp dir path. **Linux only**.
///
/// On Linux, we need to write the icon to the disk and usually it will
Expand Down
10 changes: 9 additions & 1 deletion src/platform_impl/gtk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl TrayIcon {
self.indicator
.set_icon_theme_path(&parent_path.to_string_lossy());
self.indicator
.set_icon_full(&icon_path.to_string_lossy(), "icon");
.set_icon_full(&icon_path.to_string_lossy(), "tray icon");
self.path = icon_path;

Ok(())
Expand All @@ -79,6 +79,14 @@ impl TrayIcon {
.set_label(title.as_ref().map(|t| t.as_ref()).unwrap_or(""), "");
}

pub fn set_visible(&mut self, visible: bool) {
if visible {
self.indicator.set_status(AppIndicatorStatus::Passive);
} else {
self.indicator.set_status(AppIndicatorStatus::Active);
}
}

pub fn set_temp_dir_path<P: AsRef<Path>>(&mut self, path: Option<P>) {
self.temp_dir_path = path.map(|p| p.as_ref().to_path_buf());
}
Expand Down
14 changes: 12 additions & 2 deletions src/platform_impl/macos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ impl TrayIcon {
}
}

pub fn set_visible(&mut self, visible: bool) {
unsafe {
let button = self.ns_status_bar.button();
let visible = !visible as i8;
let _: () = msg_send![button, setHidden: visible];
}
}

pub fn set_icon_as_template(&mut self, is_template: bool) {
unsafe {
let button = self.ns_status_bar.button();
Expand All @@ -145,6 +153,8 @@ impl Drop for TrayIcon {
}

fn create_button_with_icon(ns_status_bar: id, icon: Option<Icon>, icon_is_template: bool) {
let button = unsafe { ns_status_bar.button() };

if let Some(icon) = icon {
// The image is to the right of the title https://developer.apple.com/documentation/appkit/nscellimageposition/nsimageleft
const NSIMAGE_LEFT: i32 = 2;
Expand All @@ -157,8 +167,6 @@ fn create_button_with_icon(ns_status_bar: id, icon: Option<Icon>, icon_is_templa
let icon_width: f64 = (width as f64) / (height as f64 / icon_height);

unsafe {
let button = ns_status_bar.button();

// build our icon
let nsdata = NSData::dataWithBytes_length_(
nil,
Expand All @@ -174,6 +182,8 @@ fn create_button_with_icon(ns_status_bar: id, icon: Option<Icon>, icon_is_templa
let _: () = msg_send![button, setImagePosition: NSIMAGE_LEFT];
let _: () = msg_send![nsimage, setTemplate: icon_is_template as i8];
}
} else {
unsafe { button.setImage_(nil) };
}
}

Expand Down
57 changes: 46 additions & 11 deletions src/platform_impl/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ const TRAY_SUBCLASS_ID: usize = 6001;
const WM_USER_TRAYICON: u32 = 6002;
const WM_USER_UPDATE_TRAYMENU: u32 = 6003;
const WM_USER_UPDATE_TRAYICON: u32 = 6004;
const WM_USER_UPDATE_TRAYTOOLTIP: u32 = 6005;
const WM_USER_SHOW_TRAYICON: u32 = 6005;
const WM_USER_HIDE_TRAYICON: u32 = 6006;
const WM_USER_UPDATE_TRAYTOOLTIP: u32 = 6007;

/// When the taskbar is created, it registers a message with the "TaskbarCreated" string and then broadcasts this message to all top-level windows
/// When the application receives this message, it should assume that any taskbar icons it added have been removed and add them again.
Expand Down Expand Up @@ -218,21 +220,27 @@ impl TrayIcon {
}

pub fn set_title<S: AsRef<str>>(&mut self, _title: Option<S>) {}

pub fn set_visible(&mut self, visible: bool) {
unsafe {
SendMessageW(
self.hwnd,
if visible {
WM_USER_SHOW_TRAYICON
} else {
WM_USER_HIDE_TRAYICON
},
0,
0,
);
}
}
}

impl Drop for TrayIcon {
fn drop(&mut self) {
unsafe {
// remove the icon from system tray
let mut nid = NOTIFYICONDATAW {
uFlags: NIF_ICON,
hWnd: self.hwnd,
uID: self.id,
..std::mem::zeroed()
};
if Shell_NotifyIconW(NIM_DELETE, &mut nid as _) == 0 {
eprintln!("Error removing system tray icon");
}
remove_tray_icon(self.hwnd, self.id);

if let Some(menu) = &self.menu {
menu.detach_menu_subclass_from_hwnd(self.hwnd);
Expand Down Expand Up @@ -267,6 +275,20 @@ unsafe extern "system" fn tray_subclass_proc(
let icon = Box::from_raw(wparam as *mut Option<Icon>);
subclass_input.icon = *icon;
}
WM_USER_SHOW_TRAYICON => {
register_tray_icon(
subclass_input.hwnd,
subclass_input.id,
&subclass_input
.icon
.as_ref()
.map(|i| i.inner.as_raw_handle()),
&subclass_input.tooltip,
);
}
WM_USER_HIDE_TRAYICON => {
remove_tray_icon(subclass_input.hwnd, subclass_input.id);
}
WM_USER_UPDATE_TRAYTOOLTIP => {
let tooltip = Box::from_raw(wparam as *mut Option<String>);
subclass_input.tooltip = *tooltip;
Expand Down Expand Up @@ -384,3 +406,16 @@ unsafe fn register_tray_icon(

Shell_NotifyIconW(NIM_ADD, &mut nid as _) == 1
}

unsafe fn remove_tray_icon(hwnd: HWND, id: u32) {
let mut nid = NOTIFYICONDATAW {
uFlags: NIF_ICON,
hWnd: hwnd,
uID: id,
..std::mem::zeroed()
};

if Shell_NotifyIconW(NIM_DELETE, &mut nid as _) == 0 {
eprintln!("Error removing system tray icon");
}
}