From aeb87f88865a92fee6b96e061f618d20abe59aaa Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Fri, 13 Dec 2024 15:15:16 -0500 Subject: [PATCH] refactor: backup non-cosmic gtk css files --- cosmic-theme/src/output/gtk4_output.rs | 78 +++++++++++++++++++------- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/cosmic-theme/src/output/gtk4_output.rs b/cosmic-theme/src/output/gtk4_output.rs index 91795a706cd..d0ab0c0eff5 100644 --- a/cosmic-theme/src/output/gtk4_output.rs +++ b/cosmic-theme/src/output/gtk4_output.rs @@ -2,8 +2,9 @@ use crate::{composite::over, steps::steps, Component, Theme}; use palette::{rgb::Rgba, Darken, IntoColor, Lighten, Srgba}; use std::{ fs::{self, File}, - io::Write, + io::{self, Write}, num::NonZeroUsize, + path::Path, }; use super::{to_rgba, OutputError}; @@ -77,7 +78,7 @@ impl Theme { inverted_bg_divider.alpha = 0.5; let scrollbar_outline = to_rgba(inverted_bg_divider); - let mut css = format! {r#" + let mut css = format! {r#"/* GENERATED BY COSMIC */ @define-color window_bg_color {window_bg}; @define-color window_fg_color {window_fg}; @@ -169,6 +170,10 @@ impl Theme { } /// Apply gtk color variable settings + /// + /// # Errors + /// + /// Returns an `OutputError` if there is an error applying the CSS file. pub fn apply_gtk(is_dark: bool) -> Result<(), OutputError> { let Some(config_dir) = dirs::config_dir() else { return Err(OutputError::MissingConfigDir); @@ -180,31 +185,22 @@ impl Theme { fs::create_dir_all(>k4).map_err(OutputError::Io)?; fs::create_dir_all(>k3).map_err(OutputError::Io)?; - let cosmic_css = gtk4 - .join("cosmic") - .join(if is_dark { "dark.css" } else { "light.css" }); + let cosmic_css_dir = gtk4.join("cosmic"); + let cosmic_css = + cosmic_css_dir + .clone() + .join(if is_dark { "dark.css" } else { "light.css" }); let gtk4_dest = gtk4.join("gtk.css"); let gtk3_dest = gtk3.join("gtk.css"); #[cfg(target_family = "unix")] for gtk_dest in [>k4_dest, >k3_dest] { - use std::fs::metadata; use std::os::unix::fs::symlink; - - let mut gtk_dest_bak = gtk_dest.clone(); - gtk_dest_bak.set_extension("css.bak"); + Self::backup_non_cosmic_css(gtk_dest, &cosmic_css_dir).map_err(OutputError::Io)?; if gtk_dest.exists() { - if metadata(>k_dest) - .map_err(OutputError::Io)? - .file_type() - .is_symlink() - { - fs::remove_file(>k_dest).map_err(OutputError::Io)?; - } else { - fs::rename(>k_dest, gtk_dest_bak).map_err(OutputError::Io)?; - } + fs::remove_file(gtk_dest).map_err(OutputError::Io)?; } symlink(&cosmic_css, gtk_dest).map_err(OutputError::Io)?; @@ -213,6 +209,10 @@ impl Theme { } /// Reset the applied gtk css + /// + /// # Errors + /// + /// Returns an `OutputError` if there is an error resetting the CSS file. pub fn reset_gtk() -> Result<(), OutputError> { let Some(config_dir) = dirs::config_dir() else { return Err(OutputError::MissingConfigDir); @@ -221,11 +221,47 @@ impl Theme { let gtk4 = config_dir.join("gtk-4.0"); let gtk3 = config_dir.join("gtk-3.0"); let gtk4_dest = gtk4.join("gtk.css"); + let cosmic_css = gtk4.join("cosmic"); let gtk3_dest = gtk3.join("gtk.css"); - let res = fs::remove_file(gtk3_dest); - fs::remove_file(gtk4_dest).map_err(OutputError::Io)?; - Ok(res.map_err(OutputError::Io)?) + let res = Self::reset_cosmic_css(>k3_dest, &cosmic_css).map_err(OutputError::Io); + Self::reset_cosmic_css(>k4_dest, &cosmic_css).map_err(OutputError::Io)?; + res + } + + fn backup_non_cosmic_css(path: &Path, cosmic_css: &Path) -> io::Result<()> { + if !Self::is_cosmic_css(path, cosmic_css)?.unwrap_or(true) { + let backup_path = path.with_extension("css.bak"); + fs::rename(path, &backup_path)?; + } + Ok(()) + } + + fn reset_cosmic_css(path: &Path, cosmic_css: &Path) -> io::Result<()> { + if Self::is_cosmic_css(path, cosmic_css)?.unwrap_or_default() { + fs::remove_file(path)?; + } + Ok(()) + } + + fn is_cosmic_css(path: &Path, cosmic_css: &Path) -> io::Result> { + if !path.exists() { + return Ok(None); + } + + if let Ok(metadata) = fs::symlink_metadata(path) { + if metadata.file_type().is_symlink() { + if let Ok(actual_cosmic_css) = fs::read_link(path) { + let canonical_target = fs::canonicalize(&actual_cosmic_css)?; + let canonical_base = fs::canonicalize(cosmic_css)?; + return Ok(Some( + canonical_target == canonical_base + || canonical_target.starts_with(&canonical_base), + )); + } + } + } + Ok(Some(false)) } }