Linux: name the tray icon instead of showing the process id (#140)

tray-icon's default id is "<pid>-<n>" and the title is empty, so
StatusNotifierItem hosts showed numbers like "61965-1". On Linux and the
BSDs, give the icon the id "artcraft-launcher" and the title
"ArtCraft Launcher". Windows and macOS are unchanged.

Fixes #136

Co-authored-by: Fabio Lussi <198260595+itrycodinganditsbad@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Fabio Lussi 2026-10-12 07:53:46 +02:00 committed by GitHub
parent 7938ed90ac
commit 0358cda174
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 27 additions and 1 deletions

View File

@ -40,6 +40,15 @@ fn load_icon() -> Result<tray_icon::Icon, String> {
tray_icon::Icon::from_rgba(img.into_raw(), w, h).map_err(|e| e.to_string()) tray_icon::Icon::from_rgba(img.into_raw(), w, h).map_err(|e| e.to_string())
} }
/// Names the icon for Linux and the BSDs. tray-icon's default id is "<pid>-<n>" and the title is
/// empty, and StatusNotifierItem hosts (KDE, GNOME's AppIndicator extension) fall back to the id
/// when there is no title, so the tray showed a number like "61965-1" instead of the app name.
/// Windows and macOS keep tray-icon's defaults: there the title is drawn next to the icon (macOS)
/// or unsupported (Windows), and the id never reaches the user.
fn identity(builder: TrayIconBuilder) -> TrayIconBuilder {
if cfg!(any(target_os = "macos", target_os = "windows")) { builder } else { builder.with_id("artcraft-launcher").with_title("ArtCraft Launcher") }
}
impl Tray { impl Tray {
/// Creates the tray icon. `wake` repaints the UI so it sees the action, even when hidden. /// Creates the tray icon. `wake` repaints the UI so it sees the action, even when hidden.
/// `on_quit` runs when Quit is picked, before the UI can see it: the UI may never get to. /// `on_quit` runs when Quit is picked, before the UI can see it: the UI may never get to.
@ -55,7 +64,7 @@ impl Tray {
menu.append_items(&[&show, &check, &PredefinedMenuItem::separator(), &website, &github, &discord, &PredefinedMenuItem::separator(), &quit]) menu.append_items(&[&show, &check, &PredefinedMenuItem::separator(), &website, &github, &discord, &PredefinedMenuItem::separator(), &quit])
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
let links = [(website.id().clone(), WEBSITE_URL), (github.id().clone(), GITHUB_URL), (discord.id().clone(), DISCORD_URL)]; let links = [(website.id().clone(), WEBSITE_URL), (github.id().clone(), GITHUB_URL), (discord.id().clone(), DISCORD_URL)];
let icon = TrayIconBuilder::new() let icon = identity(TrayIconBuilder::new())
.with_menu(Box::new(menu)) .with_menu(Box::new(menu))
.with_icon(load_icon()?) .with_icon(load_icon()?)
.with_icon_as_template(cfg!(target_os = "macos")) .with_icon_as_template(cfg!(target_os = "macos"))
@ -133,3 +142,20 @@ impl Tray {
(&self.show, &self.check, &self.quit) (&self.show, &self.check, &self.quit)
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn linux_tray_has_a_stable_id_not_the_process_id() {
let id = identity(TrayIconBuilder::new()).id().clone();
let pid = std::process::id().to_string();
if cfg!(any(target_os = "macos", target_os = "windows")) {
// Left as tray-icon picks it there: "<pid>-<n>".
assert!(id.as_ref().starts_with(&pid), "{id:?}");
} else {
assert_eq!(id.as_ref(), "artcraft-launcher");
}
}
}