diff --git a/src/lib.rs b/src/lib.rs index 4517fdc..1098148 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,6 +51,8 @@ //! .find(); //! # } //! ``` +use theme::{Theme, BASE_PATHS}; + use crate::cache::{CacheEntry, CACHE}; use crate::theme::{try_build_icon_path, THEMES}; use std::path::PathBuf; @@ -242,15 +244,25 @@ impl<'a> LookupBuilder<'a> { }) }) .or_else(|| { - THEMES - .get("hicolor") - // Fallback to 'hicolor' - .and_then(|hicolor| { - hicolor.try_get_icon(self.name, self.size, self.scale, self.force_svg) - }) + for theme_base_dir in BASE_PATHS.iter() { + let theme = Theme::from_path(theme_base_dir.join("hicolor")); + if let Some(icon) = theme.and_then(|theme| { + theme.try_get_icon(self.name, self.size, self.scale, self.force_svg) + }) { + return Some(icon); + } + } + None }) - // Last chance, try to find the icon in "/usr/share/pixmaps" - .or_else(|| try_build_icon_path(self.name, "/usr/share/pixmaps", self.force_svg)); + .or_else(|| try_build_icon_path(self.name, "/usr/share/pixmaps", self.force_svg)) + .or_else(|| { + let p = PathBuf::from(&self.name); + if let (Some(name), Some(parent)) = (p.file_name(), p.parent()) { + try_build_icon_path(&name.to_string_lossy(), parent, self.force_svg) + } else { + None + } + }); if self.cache { self.store(self.theme, icon) diff --git a/src/theme/mod.rs b/src/theme/mod.rs index 1cbc104..7d1ca6b 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -2,7 +2,7 @@ use crate::theme::error::ThemeError; use crate::theme::paths::ThemePath; use ini::Ini; use once_cell::sync::Lazy; -use paths::BASE_PATHS; +pub(crate) use paths::BASE_PATHS; use std::collections::BTreeMap; use std::fmt::{Debug, Formatter}; use std::path::{Path, PathBuf}; @@ -96,6 +96,7 @@ pub(super) fn try_build_icon_path>( fn try_build_svg>(name: &str, path: P) -> Option { let path = path.as_ref(); let svg = path.join(format!("{name}.svg")); + if svg.exists() { Some(svg) } else { @@ -106,6 +107,7 @@ fn try_build_svg>(name: &str, path: P) -> Option { fn try_build_png>(name: &str, path: P) -> Option { let path = path.as_ref(); let png = path.join(format!("{name}.png")); + if png.exists() { Some(png) } else { @@ -139,7 +141,7 @@ pub(super) fn get_all_themes() -> Result> { } impl Theme { - fn from_path>(path: P) -> Option { + pub(crate) fn from_path>(path: P) -> Option { let path = path.as_ref(); let has_index = path.join("index.theme").exists(); diff --git a/src/theme/paths.rs b/src/theme/paths.rs index f3b78c1..b0c42c1 100644 --- a/src/theme/paths.rs +++ b/src/theme/paths.rs @@ -3,8 +3,8 @@ use crate::theme::error::ThemeError; use dirs::home_dir; use ini::Ini; use once_cell::sync::Lazy; -use xdg::BaseDirectories; use std::path::PathBuf; +use xdg::BaseDirectories; pub(crate) static BASE_PATHS: Lazy> = Lazy::new(icon_theme_base_paths); @@ -12,13 +12,16 @@ pub(crate) static BASE_PATHS: Lazy> = Lazy::new(icon_theme_base_pat /// Paths that are not found are filtered out. fn icon_theme_base_paths() -> Vec { let home_icon_dir = home_dir().expect("No $HOME directory").join(".icons"); - let mut data_dirs = BaseDirectories::new().map(|bd| bd.get_data_dirs()).unwrap_or_default(); + let mut data_dirs: Vec<_> = BaseDirectories::new() + .map(|bd| { + bd.get_data_dirs() + .into_iter() + .map(|p| p.join("icons")) + .collect() + }) + .unwrap_or_default(); data_dirs.push(home_icon_dir); - - data_dirs - .into_iter() - .filter(|p| p.exists()) - .collect() + data_dirs.into_iter().filter(|p| p.exists()).collect() } #[derive(Debug)]