1use crate::cosmic_theme::Density;
7use cosmic_config::cosmic_config_derive::CosmicConfigEntry;
8use cosmic_config::{Config, CosmicConfigEntry};
9use serde::{Deserialize, Serialize};
10use std::collections::BTreeSet;
11use std::sync::{LazyLock, RwLock};
12
13pub const ID: &str = "com.system76.CosmicTk";
15
16const MONO_FAMILY_DEFAULT: &str = "Noto Sans Mono";
17const SANS_FAMILY_DEFAULT: &str = "Open Sans";
18
19pub static COSMIC_TK: LazyLock<RwLock<CosmicTk>> = LazyLock::new(|| {
20 RwLock::new(
21 CosmicTk::config()
22 .map(|c| {
23 CosmicTk::get_entry(&c).unwrap_or_else(|(errors, mode)| {
24 for why in errors.into_iter().filter(cosmic_config::Error::is_err) {
25 if let cosmic_config::Error::GetKey(_, err) = &why {
26 if err.kind() == std::io::ErrorKind::NotFound {
27 continue;
29 }
30 }
31 tracing::error!(?why, "CosmicTk config entry error");
32 }
33 mode
34 })
35 })
36 .unwrap_or_default(),
37 )
38});
39
40#[allow(clippy::missing_panics_doc)]
42pub fn apply_theme_global() -> bool {
43 COSMIC_TK.read().unwrap().apply_theme_global
44}
45
46#[allow(clippy::missing_panics_doc)]
48pub fn show_minimize() -> bool {
49 COSMIC_TK.read().unwrap().show_minimize
50}
51
52#[allow(clippy::missing_panics_doc)]
54pub fn show_maximize() -> bool {
55 COSMIC_TK.read().unwrap().show_maximize
56}
57
58#[allow(clippy::missing_panics_doc)]
60pub fn icon_theme() -> String {
61 COSMIC_TK.read().unwrap().icon_theme.clone()
62}
63
64#[allow(clippy::missing_panics_doc)]
66pub fn header_size() -> Density {
67 COSMIC_TK.read().unwrap().header_size
68}
69
70#[allow(clippy::missing_panics_doc)]
72pub fn interface_density() -> Density {
73 COSMIC_TK.read().unwrap().interface_density
74}
75
76#[allow(clippy::missing_panics_doc)]
77pub fn interface_font() -> FontConfig {
78 COSMIC_TK.read().unwrap().interface_font.clone()
79}
80
81#[allow(clippy::missing_panics_doc)]
82pub fn monospace_font() -> FontConfig {
83 COSMIC_TK.read().unwrap().monospace_font.clone()
84}
85
86#[derive(Clone, CosmicConfigEntry, Debug, Eq, PartialEq)]
87#[version = 1]
88pub struct CosmicTk {
89 pub apply_theme_global: bool,
91
92 pub show_minimize: bool,
94
95 pub show_maximize: bool,
97
98 pub icon_theme: String,
100
101 pub header_size: Density,
103
104 pub interface_density: Density,
106
107 pub interface_font: FontConfig,
109
110 pub monospace_font: FontConfig,
112}
113
114impl Default for CosmicTk {
115 fn default() -> Self {
116 Self {
117 apply_theme_global: false,
118 show_minimize: true,
119 show_maximize: true,
120 icon_theme: String::from("Cosmic"),
121 header_size: Density::Standard,
122 interface_density: Density::Standard,
123 interface_font: FontConfig {
124 family: SANS_FAMILY_DEFAULT.to_owned(),
125 weight: iced::font::Weight::Normal,
126 stretch: iced::font::Stretch::Normal,
127 style: iced::font::Style::Normal,
128 },
129 monospace_font: FontConfig {
130 family: MONO_FAMILY_DEFAULT.to_owned(),
131 weight: iced::font::Weight::Normal,
132 stretch: iced::font::Stretch::Normal,
133 style: iced::font::Style::Normal,
134 },
135 }
136 }
137}
138
139impl CosmicTk {
140 #[inline]
141 pub fn config() -> Result<Config, cosmic_config::Error> {
142 Config::new(ID, Self::VERSION)
143 }
144}
145
146#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
147pub struct FontConfig {
148 pub family: String,
149 pub weight: iced::font::Weight,
150 pub stretch: iced::font::Stretch,
151 pub style: iced::font::Style,
152}
153
154impl From<FontConfig> for iced::Font {
155 fn from(font: FontConfig) -> Self {
156 static FAMILY_MAP: LazyLock<RwLock<BTreeSet<&'static str>>> =
158 LazyLock::new(RwLock::default);
159
160 let read_guard = FAMILY_MAP.read().unwrap();
161 let name: Option<&'static str> = read_guard.get(font.family.as_str()).copied();
162 drop(read_guard);
163
164 let name = name.unwrap_or_else(|| {
165 let value: &'static str = font.family.clone().leak();
166 FAMILY_MAP.write().unwrap().insert(value);
167 value
168 });
169
170 Self {
171 family: iced::font::Family::Name(name),
172 weight: font.weight,
173 stretch: font.stretch,
174 style: font.style,
175 }
176 }
177}