Skip to content

Commit

Permalink
Icon theme fallback for missing themes
Browse files Browse the repository at this point in the history
Fixes: pop-os#48

This PR implements a last resort fallback to the default GTK icon theme
if COSMIC's theme is missing.

The user is warned if COSMIC's themes aren't available since a correct
installation should have them much like GTK should always have Adwaita.
  • Loading branch information
joshuamegnauth54 committed Apr 4, 2024
1 parent fb47fc7 commit 5084fc9
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut settings = Settings::default();
settings = settings.theme(config.app_theme.theme());
settings = settings.size_limits(Limits::NONE.min_width(360.0).min_height(180.0));
if let Some(fallback_theme) = crate::mime_icon::fallback_theme() {
settings = settings.default_icon_theme(fallback_theme);
}

let flags = Flags {
config_handler,
Expand Down
102 changes: 101 additions & 1 deletion src/mime_icon.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only

use cosmic::widget::icon;
use cosmic::{config::CosmicTk, cosmic_config::ConfigGet, widget::icon};
use mime_guess::Mime;
use once_cell::sync::Lazy;
use std::{collections::HashMap, path::Path, sync::Mutex};
Expand Down Expand Up @@ -69,3 +69,103 @@ pub fn mime_icon(mime: Mime, size: u16) -> icon::Handle {
None => icon::from_name(FALLBACK_MIME_ICON).size(size).handle(),
}
}

pub fn fallback_theme() -> Option<String> {
// Icon precedence
// 1. User's preferred theme (automatic via libcosmic)
// 2. COSMIC default (automatic)
// 3. GTK default
if CosmicTk::config()
.and_then(|config| config.get::<String>("icon_theme"))
.is_err()
&& icon::from_name("folder").path().is_none()
{
log::warn!("COSMIC's default theme is missing, but it should be available as part of a correct installation");

// Try GTK as a last resort.
let icon_theme = gtk_icon_theme();
if icon_theme.is_none() {
log::warn!("Could not find a valid icon theme. Install COSMIC's icon theme or set a default with cosmic-settings.");
}
icon_theme
} else {
None
}
}

fn gtk_icon_theme() -> Option<String> {
let gsettings = std::process::Command::new("gsettings")
.args(["get", "org.gnome.desktop.interface", "icon-theme"])
.output()
.ok()?;

if gsettings.status.success() {
let name = String::from_utf8(gsettings.stdout)
.ok()?
.trim()
.trim_matches('\'')
.to_owned();
Some(name)
} else {
None
}
}

#[cfg(test)]
mod tests {
use cosmic::widget;

use super::fallback_theme;

#[test]
fn basic_icon_lookup_never_fails() {
if let Some(gtk_theme) = fallback_theme() {
cosmic::icon_theme::set_default(gtk_theme);
}

// Fallback
widget::icon::from_name("text-x-generic")
.path()
.expect("`text-x-generic` should always be found");

// Trash
widget::icon::from_name("user-trash-full-symbolic")
.path()
.expect("`user-trash-full-symbolic` should always be found");
widget::icon::from_name("user-trash-symbolic")
.path()
.expect("`user-trash-symbolic` should always be found");

// Folders
widget::icon::from_name("folder")
.path()
.expect("`folder` should always be found");
widget::icon::from_name("folder-documents-symbolic")
.path()
.expect("`folder-documents-symbolic` should always be found");
widget::icon::from_name("folder-download-symbolic")
.path()
.expect("`folder-documents-symbolic` should always be found");
widget::icon::from_name("folder-music-symbolic")
.path()
.expect("`folder-music-symbolic` should always be found");
widget::icon::from_name("folder-pictures-symbolic")
.path()
.expect("`folder-pictures-symbolic` should always be found");
widget::icon::from_name("folder-publicshare-symbolic")
.path()
.expect("`folder-publicshare-symbolic` should always be found");
widget::icon::from_name("folder-templates-symbolic")
.path()
.expect("`folder-templates-symbolic` should always be found");
widget::icon::from_name("folder-videos-symbolic")
.path()
.expect("`folder-videos-symbolic` should always be found");
widget::icon::from_name("user-desktop-symbolic")
.path()
.expect("`user-desktop-symbolic` should always be found");
widget::icon::from_name("user-home-symbolic")
.path()
.expect("`user-home-symblic` should always be found");
}
}

0 comments on commit 5084fc9

Please sign in to comment.