diff --git a/src/desktop_file.rs b/src/desktop_file.rs index 7a143ce..38ddb36 100644 --- a/src/desktop_file.rs +++ b/src/desktop_file.rs @@ -95,7 +95,7 @@ fn find_desktop_file_by_filename(app_id: &str, files: &[PathBuf]) -> Option Button image.add_class("image"); image.add_class("icon"); - match ImageProvider::parse(input, icon_theme, size) + match ImageProvider::parse(input, icon_theme, false, size) .map(|provider| provider.load_into_image(image.clone())) { Some(_) => { @@ -41,7 +41,7 @@ pub fn new_icon_label(input: &str, icon_theme: &IconTheme, size: i32) -> gtk::Bo container.add(&image); - ImageProvider::parse(input, icon_theme, size) + ImageProvider::parse(input, icon_theme, false, size) .map(|provider| provider.load_into_image(image)); } else { let label = Label::new(Some(input)); diff --git a/src/image/provider.rs b/src/image/provider.rs index 7d6e967..397ba62 100644 --- a/src/image/provider.rs +++ b/src/image/provider.rs @@ -41,30 +41,44 @@ impl<'a> ImageProvider<'a> { /// /// Note this checks that icons exist in theme, or files exist on disk /// but no other check is performed. - pub fn parse(input: &str, theme: &'a IconTheme, size: i32) -> Option { - let location = Self::get_location(input, theme, size, 0)?; + pub fn parse(input: &str, theme: &'a IconTheme, use_fallback: bool, size: i32) -> Option { + let location = Self::get_location(input, theme, size, use_fallback, 0)?; + Some(Self { location, size }) } /// Returns true if the input starts with a prefix /// that is supported by the parser /// (ie the parser would not fallback to checking the input). - #[cfg(any(feature = "music", feature = "workspaces"))] pub fn is_definitely_image_input(input: &str) -> bool { input.starts_with("icon:") || input.starts_with("file://") || input.starts_with("http://") || input.starts_with("https://") + || input.starts_with('/') } fn get_location( input: &str, theme: &'a IconTheme, size: i32, + use_fallback: bool, recurse_depth: usize, ) -> Option> { + macro_rules! fallback { + () => { + if use_fallback { + Some(Self::get_fallback_icon(theme)) + } else { + None + } + }; + } + const MAX_RECURSE_DEPTH: usize = 2; + let should_parse_desktop_file = !Self::is_definitely_image_input(input); + let (input_type, input_name) = input .split_once(':') .map_or((None, input), |(t, n)| (Some(t), n)); @@ -99,22 +113,26 @@ impl<'a> ImageProvider<'a> { Report::msg(format!("Unsupported image type: {input_type}")) .note("You may need to recompile with support if available") ); - None + fallback!() } None if PathBuf::from(input_name).is_file() => { Some(ImageLocation::Local(PathBuf::from(input_name))) } - None if recurse_depth == MAX_RECURSE_DEPTH => Some(Self::get_fallback_icon(theme)), - None => { - if let Some(location) = get_desktop_icon_name(input_name) - .map(|input| Self::get_location(&input, theme, size, recurse_depth + 1)) - { + None if recurse_depth == MAX_RECURSE_DEPTH => fallback!(), + None if should_parse_desktop_file => { + if let Some(location) = get_desktop_icon_name(input_name).map(|input| { + Self::get_location(&input, theme, size, use_fallback, recurse_depth + 1) + }) { location } else { warn!("Failed to find image: {input}"); - Some(Self::get_fallback_icon(theme)) + fallback!() } } + None => { + warn!("Failed to find image: {input}"); + fallback!() + } } } diff --git a/src/modules/custom/image.rs b/src/modules/custom/image.rs index 52d21e8..4a92e38 100644 --- a/src/modules/custom/image.rs +++ b/src/modules/custom/image.rs @@ -32,7 +32,7 @@ impl CustomWidget for ImageWidget { let icon_theme = context.icon_theme.clone(); dynamic_string(&self.src, move |src| { - ImageProvider::parse(&src, &icon_theme, self.size) + ImageProvider::parse(&src, &icon_theme, false, self.size) .map(|image| image.load_into_image(gtk_image.clone())); Continue(true) diff --git a/src/modules/focused.rs b/src/modules/focused.rs index 6e4e0b6..93b58c6 100644 --- a/src/modules/focused.rs +++ b/src/modules/focused.rs @@ -128,7 +128,7 @@ impl Module for FocusedModule { let icon_theme = icon_theme.clone(); context.widget_rx.attach(None, move |(name, id)| { if self.show_icon { - match ImageProvider::parse(&id, &icon_theme, self.icon_size) + match ImageProvider::parse(&id, &icon_theme, true, self.icon_size) .map(|image| image.load_into_image(icon.clone())) { Some(Ok(_)) => icon.show(), diff --git a/src/modules/launcher/item.rs b/src/modules/launcher/item.rs index 2a53b36..2c93071 100644 --- a/src/modules/launcher/item.rs +++ b/src/modules/launcher/item.rs @@ -191,7 +191,7 @@ impl ItemButton { if appearance.show_icons { let gtk_image = gtk::Image::new(); let image = - ImageProvider::parse(&item.app_id.clone(), icon_theme, appearance.icon_size); + ImageProvider::parse(&item.app_id.clone(), icon_theme, true, appearance.icon_size); if let Some(image) = image { button.set_image(Some(>k_image)); button.set_always_show_image(true); diff --git a/src/modules/music/mod.rs b/src/modules/music/mod.rs index fe40d54..ccf1490 100644 --- a/src/modules/music/mod.rs +++ b/src/modules/music/mod.rs @@ -408,11 +408,13 @@ impl Module