Skip to content

Commit

Permalink
Merge branch 'pop-os:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam-Cosner authored Feb 18, 2025
2 parents 06758e3 + 3f25af8 commit ac81f0a
Show file tree
Hide file tree
Showing 11 changed files with 223 additions and 100 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ markdown = ["iced/markdown"]
apply = "0.3.0"
ashpd = { version = "0.9.1", default-features = false, optional = true }
async-fs = { version = "2.1", optional = true }
cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "29ab323", optional = true }
cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "178eb0b", optional = true }
chrono = "0.4.35"
cosmic-config = { path = "cosmic-config" }
cosmic-settings-daemon = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true }
Expand Down
58 changes: 45 additions & 13 deletions cosmic-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub enum Error {
Io(std::io::Error),
NoConfigDirectory,
Notify(notify::Error),
NotFound,
Ron(ron::Error),
RonSpanned(ron::error::SpannedError),
GetKey(String, std::io::Error),
Expand All @@ -46,6 +47,7 @@ impl fmt::Display for Error {
Self::Io(err) => err.fmt(f),
Self::NoConfigDirectory => write!(f, "cosmic config directory not found"),
Self::Notify(err) => err.fmt(f),
Self::NotFound => write!(f, "cosmic config key not configured"),
Self::Ron(err) => err.fmt(f),
Self::RonSpanned(err) => err.fmt(f),
Self::GetKey(key, err) => write!(f, "failed to get key '{}': {}", key, err),
Expand All @@ -55,6 +57,15 @@ impl fmt::Display for Error {

impl std::error::Error for Error {}

impl Error {
/// Whether the reason for the missing config is caused by an error.
///
/// Useful for determining if it is appropriate to log as an error.
pub fn is_err(&self) -> bool {
!matches!(self, Self::NoConfigDirectory | Self::NotFound)
}
}

impl From<atomicwrites::Error<std::io::Error>> for Error {
fn from(f: atomicwrites::Error<std::io::Error>) -> Self {
Self::AtomicWrites(f)
Expand Down Expand Up @@ -87,7 +98,15 @@ impl From<ron::error::SpannedError> for Error {

pub trait ConfigGet {
/// Get a configuration value
///
/// Fallback to the system default if a local user override is not defined.
fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error>;

/// Get a locally-defined configuration value from the user's local config.
fn get_local<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error>;

/// Get the system-defined default configuration value.
fn get_system_default<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error>;
}

pub trait ConfigSet {
Expand Down Expand Up @@ -216,7 +235,7 @@ impl Config {
}

// Start a transaction (to set multiple configs at the same time)
pub fn transaction<'a>(&'a self) -> ConfigTransaction<'a> {
pub fn transaction(&self) -> ConfigTransaction {
ConfigTransaction {
config: self,
updates: Mutex::new(Vec::new()),
Expand Down Expand Up @@ -288,6 +307,7 @@ impl Config {
Ok(system_path.join(sanitize_name(key)?))
}

/// Get the path of the key in the user's local config directory.
fn key_path(&self, key: &str) -> Result<PathBuf, Error> {
let Some(user_path) = self.user_path.as_ref() else {
return Err(Error::NoConfigDirectory);
Expand All @@ -300,22 +320,34 @@ impl Config {
impl ConfigGet for Config {
//TODO: check for transaction
fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error> {
match self.get_local(key) {
Ok(value) => Ok(value),
Err(Error::NotFound) => self.get_system_default(key),
Err(why) => Err(why),
}
}

fn get_local<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error> {
// If key path exists
let key_path = self.key_path(key);
let data = match key_path {
match self.key_path(key) {
Ok(key_path) if key_path.is_file() => {
// Load user override
fs::read_to_string(key_path).map_err(|err| Error::GetKey(key.to_string(), err))?
}
_ => {
// Load system default
let default_path = self.default_path(key)?;
fs::read_to_string(default_path)
.map_err(|err| Error::GetKey(key.to_string(), err))?
let data = fs::read_to_string(key_path)
.map_err(|err| Error::GetKey(key.to_string(), err))?;

Ok(ron::from_str(&data)?)
}
};
let t = ron::from_str(&data)?;
Ok(t)

_ => Err(Error::NotFound),
}
}

fn get_system_default<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error> {
// Load system default
let default_path = self.default_path(key)?;
let data =
fs::read_to_string(default_path).map_err(|err| Error::GetKey(key.to_string(), err))?;
Ok(ron::from_str(&data)?)
}
}

Expand Down
182 changes: 107 additions & 75 deletions cosmic-theme/src/model/theme.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::{
composite::over,
steps::{color_index, get_surface_color, get_text, steps},
steps::{color_index, get_index, get_small_widget_color, get_surface_color, get_text, steps},
Component, Container, CornerRadii, CosmicPalette, CosmicPaletteInner, Spacing, ThemeMode,
DARK_PALETTE, LIGHT_PALETTE, NAME,
};
use cosmic_config::{Config, CosmicConfigEntry};
use palette::{rgb::Rgb, IntoColor, Oklcha, Srgb, Srgba};
use palette::{color_difference::Wcag21RelativeContrast, rgb::Rgb, IntoColor, Oklcha, Srgb, Srgba};
use serde::{Deserialize, Serialize};
use std::num::NonZeroUsize;

Expand Down Expand Up @@ -97,6 +97,9 @@ pub struct Theme {
pub is_frosted: bool,
/// shade color for dialogs
pub shade: Srgba,
/// accent text colors
/// If None, accent base color is the accent text color.
pub accent_text: Option<Srgba>,
}

impl Default for Theme {
Expand Down Expand Up @@ -276,7 +279,7 @@ impl Theme {
#[allow(clippy::doc_markdown)]
/// get @accent_text_color
pub fn accent_text_color(&self) -> Srgba {
self.accent.base
self.accent_text.unwrap_or(self.accent.base)
}
#[must_use]
#[allow(clippy::doc_markdown)]
Expand Down Expand Up @@ -844,9 +847,102 @@ impl ThemeBuilder {
color_index(bg_component, step_array.len()),
&step_array,
&p_ref.neutral_8,
text_steps_array.as_ref(),
text_steps_array.as_deref(),
);

let primary = {
let container_bg = if let Some(primary_container_bg_color) = primary_container_bg {
primary_container_bg_color
} else {
get_surface_color(bg_index, 5, &step_array, is_dark, &p_ref.neutral_1)
};

let base_index: usize = color_index(container_bg, step_array.len());
let component_base =
get_surface_color(base_index, 6, &step_array, is_dark, &p_ref.neutral_3);

component_hovered_overlay = if base_index < 91 {
p_ref.neutral_10
} else {
p_ref.neutral_0
};
component_hovered_overlay.alpha = 0.1;

component_pressed_overlay = component_hovered_overlay;
component_pressed_overlay.alpha = 0.2;

let container = Container::new(
Component::component(
component_base,
accent,
get_text(
color_index(component_base, step_array.len()),
&step_array,
&p_ref.neutral_8,
text_steps_array.as_deref(),
),
component_hovered_overlay,
component_pressed_overlay,
is_high_contrast,
p_ref.neutral_8,
),
container_bg,
get_text(
base_index,
&step_array,
&p_ref.neutral_8,
text_steps_array.as_deref(),
),
get_small_widget_color(base_index, 5, &neutral_steps, &p_ref.neutral_6),
);

container
};

let accent_text = if is_dark {
(primary.base.relative_contrast(accent.color) < 4.).then(|| {
let step_array = steps(accent, NonZeroUsize::new(100).unwrap());
let primary_color_index = color_index(primary.base, 100);
let steps = if is_high_contrast { 60 } else { 50 };
let accent_text = get_surface_color(
primary_color_index,
steps,
&step_array,
is_dark,
&Srgba::new(1., 1., 1., 1.),
);
if primary.base.relative_contrast(accent_text.color) < 4. {
Srgba::new(1., 1., 1., 1.)
} else {
accent_text
}
})
} else {
let darkest = if bg.relative_luminance().luma < primary.base.relative_luminance().luma {
bg
} else {
primary.base
};

(darkest.relative_contrast(accent.color) < 4.).then(|| {
let step_array = steps(accent, NonZeroUsize::new(100).unwrap());
let primary_color_index = color_index(darkest, 100);
let steps = if is_high_contrast { 60 } else { 50 };
let accent_text = get_surface_color(
primary_color_index,
steps,
&step_array,
is_dark,
&Srgba::new(1., 1., 1., 1.),
);
if darkest.relative_contrast(accent_text.color) < 4. {
Srgba::new(0., 0., 0., 1.)
} else {
accent_text
}
})
};

let mut theme: Theme = Theme {
name: palette.name().to_string(),
shade: if palette.is_dark() {
Expand All @@ -869,70 +965,11 @@ impl ThemeBuilder {
bg_index,
&step_array,
&p_ref.neutral_8,
text_steps_array.as_ref(),
),
get_surface_color(
bg_index,
5,
&neutral_steps,
bg_index <= 65,
&p_ref.neutral_6,
text_steps_array.as_deref(),
),
get_small_widget_color(bg_index, 5, &neutral_steps, &p_ref.neutral_6),
),
primary: {
let container_bg = if let Some(primary_container_bg_color) = primary_container_bg {
primary_container_bg_color
} else {
get_surface_color(bg_index, 5, &step_array, is_dark, &p_ref.neutral_1)
};

let base_index: usize = color_index(container_bg, step_array.len());
let component_base =
get_surface_color(base_index, 6, &step_array, is_dark, &p_ref.neutral_3);

component_hovered_overlay = if base_index < 91 {
p_ref.neutral_10
} else {
p_ref.neutral_0
};
component_hovered_overlay.alpha = 0.1;

component_pressed_overlay = component_hovered_overlay;
component_pressed_overlay.alpha = 0.2;

let container = Container::new(
Component::component(
component_base,
accent,
get_text(
color_index(component_base, step_array.len()),
&step_array,
&p_ref.neutral_8,
text_steps_array.as_ref(),
),
component_hovered_overlay,
component_pressed_overlay,
is_high_contrast,
p_ref.neutral_8,
),
container_bg,
get_text(
base_index,
&step_array,
&p_ref.neutral_8,
text_steps_array.as_ref(),
),
get_surface_color(
base_index,
5,
&neutral_steps,
base_index <= 65,
&p_ref.neutral_6,
),
);

container
},
primary,
secondary: {
let container_bg = if let Some(secondary_container_bg) = secondary_container_bg {
secondary_container_bg
Expand Down Expand Up @@ -962,7 +999,7 @@ impl ThemeBuilder {
color_index(secondary_component, step_array.len()),
&step_array,
&p_ref.neutral_8,
text_steps_array.as_ref(),
text_steps_array.as_deref(),
),
component_hovered_overlay,
component_pressed_overlay,
Expand All @@ -974,15 +1011,9 @@ impl ThemeBuilder {
base_index,
&step_array,
&p_ref.neutral_8,
text_steps_array.as_ref(),
),
get_surface_color(
base_index,
5,
&neutral_steps,
base_index <= 65,
&p_ref.neutral_6,
text_steps_array.as_deref(),
),
get_small_widget_color(base_index, 5, &neutral_steps, &p_ref.neutral_6),
)
},
accent: Component::colored_component(
Expand Down Expand Up @@ -1098,6 +1129,7 @@ impl ThemeBuilder {
active_hint,
window_hint,
is_frosted,
accent_text,
};
theme.spacing = spacing;
theme.corner_radii = corner_radii;
Expand Down
Loading

0 comments on commit ac81f0a

Please sign in to comment.