refactor(config): improve safety and efficiency of CosmicTk config

This commit is contained in:
KushalMeghani1644 2025-09-04 15:51:57 +05:30
parent ea349aca82
commit 11bc549b08
No known key found for this signature in database
GPG key ID: B9A1B0C1FEB66685

View file

@ -8,7 +8,25 @@ use cosmic_config::cosmic_config_derive::CosmicConfigEntry;
use cosmic_config::{Config, CosmicConfigEntry}; use cosmic_config::{Config, CosmicConfigEntry};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::sync::{LazyLock, Mutex, RwLock}; use std::sync::{Arc, LazyLock, Mutex, PoisonError, RwLock, RwLockReadGuard};
/// ID for the `CosmicTk` config.
pub const ID: &str = "com.system76.CosmicTk";
const MONO_FAMILY_DEFAULT: &str = "Noto Sans Mono";
const SANS_FAMILY_DEFAULT: &str = "Open Sans";
// Copyright 2024 System76 <info@system76.com>
// SPDX-License-Identifier: MPL-2.0
//! Configurations available to libcosmic applications.
use crate::cosmic_theme::Density;
use cosmic_config::cosmic_config_derive::CosmicConfigEntry;
use cosmic_config::{Config, CosmicConfigEntry};
use serde::{Deserialize, Serialize};
use std::collections::BTreeSet;
use std::sync::{LazyLock, Mutex, RwLock, RwLockReadGuard, Arc, PoisonError};
/// ID for the `CosmicTk` config. /// ID for the `CosmicTk` config.
pub const ID: &str = "com.system76.CosmicTk"; pub const ID: &str = "com.system76.CosmicTk";
@ -17,18 +35,17 @@ const MONO_FAMILY_DEFAULT: &str = "Noto Sans Mono";
const SANS_FAMILY_DEFAULT: &str = "Open Sans"; const SANS_FAMILY_DEFAULT: &str = "Open Sans";
/// Stores static strings of the family names for `iced::Font` compatibility. /// Stores static strings of the family names for `iced::Font` compatibility.
pub static FAMILY_MAP: LazyLock<Mutex<BTreeSet<&'static str>>> = LazyLock::new(Mutex::default); pub static FAMILY_MAP: LazyLock<Mutex<BTreeSet<Arc<str>>>> =
LazyLock::new(|| Mutex::new(BTreeSet::new()));
pub static COSMIC_TK: LazyLock<RwLock<CosmicTk>> = LazyLock::new(|| { pub static COSMIC_TK: LazyLock<RwLock<CosmicTk>> = LazyLock::new(|| {
RwLock::new( RwLock::new(
CosmicTk::config() CosmicTk::config().map(|c| {
.map(|c| {
CosmicTk::get_entry(&c).unwrap_or_else(|(errors, mode)| { CosmicTk::get_entry(&c).unwrap_or_else(|(errors, mode)| {
for why in errors.into_iter().filter(cosmic_config::Error::is_err) { for why in errors.into_iter().filter(cosmic_config::Error::is_err) {
if let cosmic_config::Error::GetKey(_, err) = &why { if let cosmic_config::Error::GetKey(_, err) = &why {
if err.kind() == std::io::ErrorKind::NotFound { if err.kind() == std::io::ErrorKind::NotFound {
// No system default config installed; don't error continue; // No system default config installed
continue;
} }
} }
tracing::error!(?why, "CosmicTk config entry error"); tracing::error!(?why, "CosmicTk config entry error");
@ -38,79 +55,63 @@ pub static COSMIC_TK: LazyLock<RwLock<CosmicTk>> = LazyLock::new(|| {
}) })
.unwrap_or_default(), .unwrap_or_default(),
) )
}); });
/// Helper to handle poisoned locks and reduce repetitive `.read().unwrap()`.
fn cosmic() -> RwLockReadGuard<'static, CosmicTk> {
COSMIC_TK.read().unwrap_or_else(|e| e.into_inner())
}
/// Apply the theme to other toolkits. /// Apply the theme to other toolkits.
#[allow(clippy::missing_panics_doc)]
pub fn apply_theme_global() -> bool { pub fn apply_theme_global() -> bool {
COSMIC_TK.read().unwrap().apply_theme_global cosmic().apply_theme_global
} }
/// Show minimize button in window header. /// Show minimize button in window header.
#[allow(clippy::missing_panics_doc)]
pub fn show_minimize() -> bool { pub fn show_minimize() -> bool {
COSMIC_TK.read().unwrap().show_minimize cosmic().show_minimize
} }
/// Show maximize button in window header. /// Show maximize button in window header.
#[allow(clippy::missing_panics_doc)]
pub fn show_maximize() -> bool { pub fn show_maximize() -> bool {
COSMIC_TK.read().unwrap().show_maximize cosmic().show_maximize
} }
/// Preferred icon theme. /// Preferred icon theme.
#[allow(clippy::missing_panics_doc)] pub fn icon_theme() -> &str {
pub fn icon_theme() -> String { &cosmic().icon_theme
COSMIC_TK.read().unwrap().icon_theme.clone()
} }
/// Density of CSD/SSD header bars. /// Density of CSD/SSD header bars.
#[allow(clippy::missing_panics_doc)]
pub fn header_size() -> Density { pub fn header_size() -> Density {
COSMIC_TK.read().unwrap().header_size cosmic().header_size
} }
/// Interface density. /// Interface density.
#[allow(clippy::missing_panics_doc)]
pub fn interface_density() -> Density { pub fn interface_density() -> Density {
COSMIC_TK.read().unwrap().interface_density cosmic().interface_density
} }
#[allow(clippy::missing_panics_doc)] /// Interface font.
pub fn interface_font() -> FontConfig { pub fn interface_font() -> &FontConfig {
COSMIC_TK.read().unwrap().interface_font.clone() &cosmic().interface_font
} }
#[allow(clippy::missing_panics_doc)] /// Monospace font.
pub fn monospace_font() -> FontConfig { pub fn monospace_font() -> &FontConfig {
COSMIC_TK.read().unwrap().monospace_font.clone() &cosmic().monospace_font
} }
#[derive(Clone, CosmicConfigEntry, Debug, Eq, PartialEq)] #[derive(Clone, CosmicConfigEntry, Debug, Eq, PartialEq)]
#[version = 1] #[version = 1]
pub struct CosmicTk { pub struct CosmicTk {
/// Apply the theme to other toolkits.
pub apply_theme_global: bool, pub apply_theme_global: bool,
/// Show minimize button in window header.
pub show_minimize: bool, pub show_minimize: bool,
/// Show maximize button in window header.
pub show_maximize: bool, pub show_maximize: bool,
/// Preferred icon theme.
pub icon_theme: String, pub icon_theme: String,
/// Density of CSD/SSD header bars.
pub header_size: Density, pub header_size: Density,
/// Interface density.
pub interface_density: Density, pub interface_density: Density,
/// Interface font family
pub interface_font: FontConfig, pub interface_font: FontConfig,
/// Mono font family
pub monospace_font: FontConfig, pub monospace_font: FontConfig,
} }
@ -156,19 +157,19 @@ pub struct FontConfig {
impl From<FontConfig> for iced::Font { impl From<FontConfig> for iced::Font {
fn from(font: FontConfig) -> Self { fn from(font: FontConfig) -> Self {
let mut family_map = FAMILY_MAP.lock().unwrap(); let mut family_map = FAMILY_MAP.lock().unwrap_or_else(|e| e.into_inner());
let name: &'static str = family_map let name: Arc<str> = family_map
.get(font.family.as_str()) .get(&font.family.as_str().into())
.copied() .cloned()
.unwrap_or_else(|| { .unwrap_or_else(|| {
let value = font.family.clone().leak(); let value: Arc<str> = Arc::from(font.family.clone());
family_map.insert(value); family_map.insert(Arc::clone(&value));
value value
}); });
Self { Self {
family: iced::font::Family::Name(name), family: iced::font::Family::Name(Box::leak(name.clone().into_boxed_str())),
weight: font.weight, weight: font.weight,
stretch: font.stretch, stretch: font.stretch,
style: font.style, style: font.style,