From aef33a53d77d7933a7b16f867e013938f17de084 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Sun, 15 Mar 2026 19:58:42 +0100 Subject: [PATCH] feat(apps): use linicon for freedesktop icon theme traversal --- crates/plugins/plugin-apps/Cargo.toml | 1 + crates/plugins/plugin-apps/src/linux.rs | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/crates/plugins/plugin-apps/Cargo.toml b/crates/plugins/plugin-apps/Cargo.toml index 0c7511e..a38201b 100644 --- a/crates/plugins/plugin-apps/Cargo.toml +++ b/crates/plugins/plugin-apps/Cargo.toml @@ -16,4 +16,5 @@ tokio = { workspace = true } tracing = { workspace = true } [target.'cfg(target_os = "linux")'.dependencies] +linicon = "2.3.0" xdg = "3" diff --git a/crates/plugins/plugin-apps/src/linux.rs b/crates/plugins/plugin-apps/src/linux.rs index acbed48..2e52a9f 100644 --- a/crates/plugins/plugin-apps/src/linux.rs +++ b/crates/plugins/plugin-apps/src/linux.rs @@ -103,11 +103,21 @@ pub fn resolve_icon_path(name: &str) -> Option { if name.starts_with('/') && Path::new(name).exists() { return Some(name.to_string()); } + // Try linicon freedesktop theme traversal + let themes = ["hicolor", "Adwaita", "breeze", "Papirus"]; + for theme in &themes { + if let Some(icon_path) = linicon::lookup_icon(name) + .from_theme(theme) + .with_size(48) + .find_map(|r| r.ok()) + { + return Some(icon_path.path.to_string_lossy().into_owned()); + } + } + // Fallback to pixmaps let candidates = [ format!("/usr/share/pixmaps/{name}.png"), format!("/usr/share/pixmaps/{name}.svg"), - format!("/usr/share/icons/hicolor/48x48/apps/{name}.png"), - format!("/usr/share/icons/hicolor/scalable/apps/{name}.svg"), ]; candidates.into_iter().find(|p| Path::new(p).exists()) }