Compare commits
6 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b74c6f999 | ||
|
|
ded784a4e3 | ||
|
|
99e196cc79 | ||
|
|
141bbd23ec | ||
|
|
6653157def | ||
|
|
bec679efc9 |
16 changed files with 597 additions and 64 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{self};
|
use syn;
|
||||||
|
|
||||||
#[proc_macro_derive(CosmicConfigEntry, attributes(version, id))]
|
#[proc_macro_derive(CosmicConfigEntry, attributes(version, id, cosmic_config_entry))]
|
||||||
pub fn cosmic_config_entry_derive(input: TokenStream) -> TokenStream {
|
pub fn cosmic_config_entry_derive(input: TokenStream) -> TokenStream {
|
||||||
// Construct a representation of Rust code as a syntax tree
|
// Construct a representation of Rust code as a syntax tree
|
||||||
// that we can manipulate
|
// that we can manipulate
|
||||||
|
|
@ -12,6 +12,25 @@ pub fn cosmic_config_entry_derive(input: TokenStream) -> TokenStream {
|
||||||
impl_cosmic_config_entry_macro(&ast)
|
impl_cosmic_config_entry_macro(&ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_cosmic_config_attrs(field: &syn::Field) -> Result<Option<syn::Type>, syn::Error> {
|
||||||
|
let mut with = None;
|
||||||
|
|
||||||
|
for attr in &field.attrs {
|
||||||
|
if !attr.path().is_ident("cosmic_config_entry") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
attr.parse_nested_meta(|meta| {
|
||||||
|
if meta.path.is_ident("with") {
|
||||||
|
let value = meta.value()?;
|
||||||
|
with = Some(value.parse()?);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(with)
|
||||||
|
}
|
||||||
|
|
||||||
fn impl_cosmic_config_entry_macro(ast: &syn::DeriveInput) -> TokenStream {
|
fn impl_cosmic_config_entry_macro(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
let attributes = &ast.attrs;
|
let attributes = &ast.attrs;
|
||||||
let version = attributes
|
let version = attributes
|
||||||
|
|
@ -48,14 +67,48 @@ fn impl_cosmic_config_entry_macro(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
|
|
||||||
let write_each_config_field = fields.iter().map(|field| {
|
let write_each_config_field = fields.iter().map(|field| {
|
||||||
let field_name = &field.ident;
|
let field_name = &field.ident;
|
||||||
|
let with = match get_cosmic_config_attrs(field) {
|
||||||
|
Ok(attrs) => attrs,
|
||||||
|
Err(e) => {
|
||||||
|
return e.to_compile_error();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(with) = with {
|
||||||
|
quote! {
|
||||||
|
{
|
||||||
|
let conv = self.#field_name.clone().into();
|
||||||
|
cosmic_config::ConfigSet::set::<#with>(&tx, stringify!(#field_name), conv)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
cosmic_config::ConfigSet::set(&tx, stringify!(#field_name), &self.#field_name)?;
|
cosmic_config::ConfigSet::set(&tx, stringify!(#field_name), &self.#field_name)?;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let get_each_config_field = fields.iter().map(|field| {
|
let get_each_config_field = fields.iter().map(|field| {
|
||||||
let field_name = &field.ident;
|
let field_name = &field.ident;
|
||||||
let field_type = &field.ty;
|
let field_type = &field.ty;
|
||||||
|
let with = match get_cosmic_config_attrs(field) {
|
||||||
|
Ok(attrs) => attrs,
|
||||||
|
Err(e) => {
|
||||||
|
return e.to_compile_error();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(with) = with {
|
||||||
|
quote! {
|
||||||
|
match cosmic_config::ConfigGet::get::<#with>(config, stringify!(#field_name)) {
|
||||||
|
Ok(value) => {
|
||||||
|
default.#field_name = value.into();
|
||||||
|
}
|
||||||
|
Err(why) if matches!(why, cosmic_config::Error::NoConfigDirectory) => (),
|
||||||
|
Err(e) => errors.push(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
match cosmic_config::ConfigGet::get::<#field_type>(config, stringify!(#field_name)) {
|
match cosmic_config::ConfigGet::get::<#field_type>(config, stringify!(#field_name)) {
|
||||||
Ok(#field_name) => default.#field_name = #field_name,
|
Ok(#field_name) => default.#field_name = #field_name,
|
||||||
|
|
@ -63,11 +116,35 @@ fn impl_cosmic_config_entry_macro(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
Err(e) => errors.push(e),
|
Err(e) => errors.push(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let update_each_config_field = fields.iter().map(|field| {
|
let update_each_config_field = fields.iter().map(|field| {
|
||||||
let field_name = &field.ident;
|
let field_name = &field.ident;
|
||||||
let field_type = &field.ty;
|
let field_type = &field.ty;
|
||||||
|
let with = match get_cosmic_config_attrs(field) {
|
||||||
|
Ok(attrs) => attrs,
|
||||||
|
Err(e) => {
|
||||||
|
return e.to_compile_error();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(with) = with {
|
||||||
|
quote! {
|
||||||
|
stringify!(#field_name) => {
|
||||||
|
match cosmic_config::ConfigGet::get::<#with>(config, stringify!(#field_name)) {
|
||||||
|
Ok(value) => {
|
||||||
|
let value = value.into();
|
||||||
|
if self.#field_name != value {
|
||||||
|
keys.push(stringify!(#field_name));
|
||||||
|
}
|
||||||
|
self.#field_name = value;
|
||||||
|
},
|
||||||
|
Err(e) => errors.push(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
stringify!(#field_name) => {
|
stringify!(#field_name) => {
|
||||||
match cosmic_config::ConfigGet::get::<#field_type>(config, stringify!(#field_name)) {
|
match cosmic_config::ConfigGet::get::<#field_type>(config, stringify!(#field_name)) {
|
||||||
|
|
@ -77,8 +154,7 @@ fn impl_cosmic_config_entry_macro(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
}
|
}
|
||||||
self.#field_name = value;
|
self.#field_name = value;
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => errors.push(e),
|
||||||
errors.push(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@ pub trait ConfigSet {
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
system_path: Option<PathBuf>,
|
system_path: Option<PathBuf>,
|
||||||
user_path: Option<PathBuf>,
|
user_path: Option<PathBuf>,
|
||||||
|
previous: Option<Box<Config>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that the name is relative and doesn't contain . or ..
|
/// Check that the name is relative and doesn't contain . or ..
|
||||||
|
|
@ -180,9 +181,13 @@ fn sanitize_name(name: &str) -> Result<&Path, Error> {
|
||||||
impl Config {
|
impl Config {
|
||||||
/// Get a system config for the given name and config version
|
/// Get a system config for the given name and config version
|
||||||
pub fn system(name: &str, version: u64) -> Result<Self, Error> {
|
pub fn system(name: &str, version: u64) -> Result<Self, Error> {
|
||||||
|
Self::system_inner(name, version, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn system_inner(name: &str, version: u64, look_for_previous: bool) -> Result<Self, Error> {
|
||||||
let path = sanitize_name(name)?.join(format!("v{version}"));
|
let path = sanitize_name(name)?.join(format!("v{version}"));
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let system_path = xdg::BaseDirectories::with_prefix("cosmic").find_data_file(path);
|
let system_path = xdg::BaseDirectories::with_prefix("cosmic").find_data_file(&path);
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let system_path =
|
let system_path =
|
||||||
|
|
@ -192,6 +197,13 @@ impl Config {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
system_path,
|
system_path,
|
||||||
user_path: None,
|
user_path: None,
|
||||||
|
previous: if version > 1 && look_for_previous {
|
||||||
|
Self::system_inner(name, version - 1, false)
|
||||||
|
.ok()
|
||||||
|
.map(Box::new)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,6 +211,10 @@ impl Config {
|
||||||
// Use folder at XDG config/name for config storage, return Config if successful
|
// Use folder at XDG config/name for config storage, return Config if successful
|
||||||
//TODO: fallbacks for flatpak (HOST_XDG_CONFIG_HOME, xdg-desktop settings proxy)
|
//TODO: fallbacks for flatpak (HOST_XDG_CONFIG_HOME, xdg-desktop settings proxy)
|
||||||
pub fn new(name: &str, version: u64) -> Result<Self, Error> {
|
pub fn new(name: &str, version: u64) -> Result<Self, Error> {
|
||||||
|
Self::new_inner(name, version, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_inner(name: &str, version: u64, look_for_previous: bool) -> Result<Self, Error> {
|
||||||
// Look for [name]/v[version]
|
// Look for [name]/v[version]
|
||||||
let path = sanitize_name(name)?.join(format!("v{}", version));
|
let path = sanitize_name(name)?.join(format!("v{}", version));
|
||||||
|
|
||||||
|
|
@ -223,15 +239,29 @@ impl Config {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
system_path,
|
system_path,
|
||||||
user_path: Some(user_path),
|
user_path: Some(user_path),
|
||||||
|
previous: if version > 1 && look_for_previous {
|
||||||
|
Self::new_inner(name, version - 1, false).ok().map(Box::new)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get config for the given application name and config version and custom path.
|
/// Get config for the given application name and config version and custom path.
|
||||||
pub fn with_custom_path(name: &str, version: u64, custom_path: PathBuf) -> Result<Self, Error> {
|
pub fn with_custom_path(name: &str, version: u64, custom_path: PathBuf) -> Result<Self, Error> {
|
||||||
|
Self::with_custom_path_inner(name, version, custom_path, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_custom_path_inner(
|
||||||
|
name: &str,
|
||||||
|
version: u64,
|
||||||
|
custom_path: PathBuf,
|
||||||
|
look_for_previous: bool,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
// Look for [name]/v[version]
|
// Look for [name]/v[version]
|
||||||
let path = sanitize_name(name)?.join(format!("v{version}"));
|
let path = sanitize_name(name)?.join(format!("v{version}"));
|
||||||
|
|
||||||
let mut user_path = custom_path;
|
let mut user_path = custom_path.clone();
|
||||||
user_path.push("cosmic");
|
user_path.push("cosmic");
|
||||||
user_path.push(path);
|
user_path.push(path);
|
||||||
// Create new configuration directory if not found.
|
// Create new configuration directory if not found.
|
||||||
|
|
@ -241,6 +271,13 @@ impl Config {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
system_path: None,
|
system_path: None,
|
||||||
user_path: Some(user_path),
|
user_path: Some(user_path),
|
||||||
|
previous: if version > 1 && look_for_previous {
|
||||||
|
Self::with_custom_path_inner(name, version - 1, custom_path.clone(), false)
|
||||||
|
.ok()
|
||||||
|
.map(Box::new)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,6 +287,10 @@ impl Config {
|
||||||
// Use folder at XDG config/name for config storage, return Config if successful
|
// Use folder at XDG config/name for config storage, return Config if successful
|
||||||
//TODO: fallbacks for flatpak (HOST_XDG_CONFIG_HOME, xdg-desktop settings proxy)
|
//TODO: fallbacks for flatpak (HOST_XDG_CONFIG_HOME, xdg-desktop settings proxy)
|
||||||
pub fn new_state(name: &str, version: u64) -> Result<Self, Error> {
|
pub fn new_state(name: &str, version: u64) -> Result<Self, Error> {
|
||||||
|
Self::new_state_inner(name, version, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_state_inner(name: &str, version: u64, look_for_previous: bool) -> Result<Self, Error> {
|
||||||
// Look for [name]/v[version]
|
// Look for [name]/v[version]
|
||||||
let path = sanitize_name(name)?.join(format!("v{}", version));
|
let path = sanitize_name(name)?.join(format!("v{}", version));
|
||||||
|
|
||||||
|
|
@ -263,6 +304,13 @@ impl Config {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
system_path: None,
|
system_path: None,
|
||||||
user_path: Some(user_path),
|
user_path: Some(user_path),
|
||||||
|
previous: if version > 1 && look_for_previous {
|
||||||
|
Self::new_state_inner(name, version - 1, false)
|
||||||
|
.ok()
|
||||||
|
.map(Box::new)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -373,7 +421,13 @@ impl ConfigGet for Config {
|
||||||
Ok(ron::from_str(&data)?)
|
Ok(ron::from_str(&data)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => Err(Error::NotFound),
|
_ => {
|
||||||
|
if let Some(previous) = self.previous.as_ref() {
|
||||||
|
previous.get_local(key)
|
||||||
|
} else {
|
||||||
|
Err(Error::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ export = ["serde_json"]
|
||||||
no-default = []
|
no-default = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
hex_color = { version = "3", features = ["serde"] }
|
||||||
palette = { version = "0.7.6", features = ["serializing"] }
|
palette = { version = "0.7.6", features = ["serializing"] }
|
||||||
almost = "0.2"
|
almost = "0.2"
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
|
|
|
||||||
173
cosmic-theme/src/model/color.rs
Normal file
173
cosmic-theme/src/model/color.rs
Normal file
|
|
@ -0,0 +1,173 @@
|
||||||
|
//! Color representation and serde helpers for the Cosmic theme
|
||||||
|
|
||||||
|
use hex_color::HexColor;
|
||||||
|
use palette::{Srgb, Srgba};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// A color in the Cosmic theme for serialization and deserialization
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum ColorRepr {
|
||||||
|
/// A color represented as a hex string
|
||||||
|
#[serde(with = "hex_color::rgba")]
|
||||||
|
Hex(HexColor),
|
||||||
|
/// A color represented as an RGBA value
|
||||||
|
Rgba(Srgba),
|
||||||
|
/// A color represented as an RGB value
|
||||||
|
Rgb(Srgb),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An optional color in the Cosmic theme for serialization and deserialization
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
pub struct ColorReprOption(Option<ColorRepr>);
|
||||||
|
|
||||||
|
impl From<Srgb> for ColorRepr {
|
||||||
|
fn from(color: Srgb) -> Self {
|
||||||
|
let rgb_u8: Srgb<u8> = color.into_format();
|
||||||
|
ColorRepr::Hex(HexColor {
|
||||||
|
r: rgb_u8.red,
|
||||||
|
g: rgb_u8.green,
|
||||||
|
b: rgb_u8.blue,
|
||||||
|
a: 255,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Srgba> for ColorRepr {
|
||||||
|
fn from(color: Srgba) -> Self {
|
||||||
|
let rgba_u8: Srgba<u8> = color.into_format();
|
||||||
|
ColorRepr::Hex(HexColor {
|
||||||
|
r: rgba_u8.red,
|
||||||
|
g: rgba_u8.green,
|
||||||
|
b: rgba_u8.blue,
|
||||||
|
a: rgba_u8.alpha,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ColorRepr> for Srgb {
|
||||||
|
fn from(value: ColorRepr) -> Self {
|
||||||
|
match value {
|
||||||
|
ColorRepr::Hex(hex) => Srgb::<u8>::new(hex.r, hex.g, hex.b).into_format(),
|
||||||
|
ColorRepr::Rgb(rgb) => rgb,
|
||||||
|
ColorRepr::Rgba(rgba) => Srgb::new(rgba.red, rgba.green, rgba.blue),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ColorRepr> for Srgba {
|
||||||
|
fn from(value: ColorRepr) -> Self {
|
||||||
|
match value {
|
||||||
|
ColorRepr::Hex(hex) => Srgba::<u8>::new(hex.r, hex.g, hex.b, hex.a).into_format(),
|
||||||
|
ColorRepr::Rgb(rgb) => Srgba::new(rgb.red, rgb.green, rgb.blue, 1.0),
|
||||||
|
ColorRepr::Rgba(rgba) => rgba,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ColorReprOption> for Option<Srgb> {
|
||||||
|
fn from(value: ColorReprOption) -> Self {
|
||||||
|
value.0.map(std::convert::Into::into)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ColorReprOption> for Option<Srgba> {
|
||||||
|
fn from(value: ColorReprOption) -> Self {
|
||||||
|
value.0.map(std::convert::Into::into)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Option<Srgb>> for ColorReprOption {
|
||||||
|
fn from(value: Option<Srgb>) -> Self {
|
||||||
|
ColorReprOption(value.map(std::convert::Into::into))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Option<Srgba>> for ColorReprOption {
|
||||||
|
fn from(value: Option<Srgba>) -> Self {
|
||||||
|
ColorReprOption(value.map(std::convert::Into::into))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A trait for converting between a color type and its representation for serialization and deserialization
|
||||||
|
pub trait ConvColorRepr: Sized {
|
||||||
|
/// Convert from a color representation to the color type
|
||||||
|
fn from_repr(repr: ColorRepr) -> Self;
|
||||||
|
/// Convert from the color type to its representation for serialization
|
||||||
|
fn to_repr(&self) -> ColorRepr;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConvColorRepr for Srgba {
|
||||||
|
fn from_repr(repr: ColorRepr) -> Self {
|
||||||
|
repr.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_repr(&self) -> ColorRepr {
|
||||||
|
(*self).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConvColorRepr for Srgb {
|
||||||
|
fn from_repr(repr: ColorRepr) -> Self {
|
||||||
|
repr.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_repr(&self) -> ColorRepr {
|
||||||
|
(*self).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serde helpers for serializing and deserializing colors in the Cosmic theme
|
||||||
|
pub mod color_serde {
|
||||||
|
use super::*;
|
||||||
|
use serde::{Deserialize, Deserializer, Serializer};
|
||||||
|
|
||||||
|
/// Serialize a color to a hex string
|
||||||
|
pub fn serialize<T, S>(color: &T, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
T: ConvColorRepr,
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let repr = color.to_repr();
|
||||||
|
repr.serialize(serializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize a color from a hex string or RGB/RGBA
|
||||||
|
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
|
||||||
|
where
|
||||||
|
T: ConvColorRepr,
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let repr = ColorRepr::deserialize(deserializer)?;
|
||||||
|
Ok(T::from_repr(repr))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serde helpers for serializing and deserializing optional colors in the Cosmic theme
|
||||||
|
pub mod option {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// Serialize an optional color
|
||||||
|
pub fn serialize<T, S>(value: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
T: ConvColorRepr,
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
match value {
|
||||||
|
Some(v) => super::serialize(v, serializer),
|
||||||
|
None => serializer.serialize_none(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize an optional color
|
||||||
|
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
|
||||||
|
where
|
||||||
|
T: ConvColorRepr,
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let opt = Option::<ColorRepr>::deserialize(deserializer)?;
|
||||||
|
Ok(opt.map(T::from_repr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::color::color_serde;
|
||||||
use palette::Srgba;
|
use palette::Srgba;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
|
|
@ -95,75 +96,107 @@ pub struct CosmicPaletteInner {
|
||||||
|
|
||||||
/// Utility Colors
|
/// Utility Colors
|
||||||
/// Colors used for various points of emphasis in the UI.
|
/// Colors used for various points of emphasis in the UI.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub bright_red: Srgba,
|
pub bright_red: Srgba,
|
||||||
/// Colors used for various points of emphasis in the UI.
|
/// Colors used for various points of emphasis in the UI.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub bright_green: Srgba,
|
pub bright_green: Srgba,
|
||||||
/// Colors used for various points of emphasis in the UI.
|
/// Colors used for various points of emphasis in the UI.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub bright_orange: Srgba,
|
pub bright_orange: Srgba,
|
||||||
|
|
||||||
/// Surface Grays
|
/// Surface Grays
|
||||||
/// Colors used for three levels of surfaces in the UI.
|
/// Colors used for three levels of surfaces in the UI.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub gray_1: Srgba,
|
pub gray_1: Srgba,
|
||||||
/// Colors used for three levels of surfaces in the UI.
|
/// Colors used for three levels of surfaces in the UI.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub gray_2: Srgba,
|
pub gray_2: Srgba,
|
||||||
|
|
||||||
/// System Neutrals
|
/// System Neutrals
|
||||||
/// A wider spread of dark colors for more general use.
|
/// A wider spread of dark colors for more general use.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub neutral_0: Srgba,
|
pub neutral_0: Srgba,
|
||||||
/// A wider spread of dark colors for more general use.
|
/// A wider spread of dark colors for more general use.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub neutral_1: Srgba,
|
pub neutral_1: Srgba,
|
||||||
/// A wider spread of dark colors for more general use.
|
/// A wider spread of dark colors for more general use.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub neutral_2: Srgba,
|
pub neutral_2: Srgba,
|
||||||
/// A wider spread of dark colors for more general use.
|
/// A wider spread of dark colors for more general use.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub neutral_3: Srgba,
|
pub neutral_3: Srgba,
|
||||||
/// A wider spread of dark colors for more general use.
|
/// A wider spread of dark colors for more general use.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub neutral_4: Srgba,
|
pub neutral_4: Srgba,
|
||||||
/// A wider spread of dark colors for more general use.
|
/// A wider spread of dark colors for more general use.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub neutral_5: Srgba,
|
pub neutral_5: Srgba,
|
||||||
/// A wider spread of dark colors for more general use.
|
/// A wider spread of dark colors for more general use.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub neutral_6: Srgba,
|
pub neutral_6: Srgba,
|
||||||
/// A wider spread of dark colors for more general use.
|
/// A wider spread of dark colors for more general use.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub neutral_7: Srgba,
|
pub neutral_7: Srgba,
|
||||||
/// A wider spread of dark colors for more general use.
|
/// A wider spread of dark colors for more general use.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub neutral_8: Srgba,
|
pub neutral_8: Srgba,
|
||||||
/// A wider spread of dark colors for more general use.
|
/// A wider spread of dark colors for more general use.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub neutral_9: Srgba,
|
pub neutral_9: Srgba,
|
||||||
/// A wider spread of dark colors for more general use.
|
/// A wider spread of dark colors for more general use.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub neutral_10: Srgba,
|
pub neutral_10: Srgba,
|
||||||
|
|
||||||
/// Potential Accent Color Combos
|
/// Potential Accent Color Combos
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub accent_blue: Srgba,
|
pub accent_blue: Srgba,
|
||||||
/// Potential Accent Color Combos
|
/// Potential Accent Color Combos
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub accent_indigo: Srgba,
|
pub accent_indigo: Srgba,
|
||||||
/// Potential Accent Color Combos
|
/// Potential Accent Color Combos
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub accent_purple: Srgba,
|
pub accent_purple: Srgba,
|
||||||
/// Potential Accent Color Combos
|
/// Potential Accent Color Combos
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub accent_pink: Srgba,
|
pub accent_pink: Srgba,
|
||||||
/// Potential Accent Color Combos
|
/// Potential Accent Color Combos
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub accent_red: Srgba,
|
pub accent_red: Srgba,
|
||||||
/// Potential Accent Color Combos
|
/// Potential Accent Color Combos
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub accent_orange: Srgba,
|
pub accent_orange: Srgba,
|
||||||
/// Potential Accent Color Combos
|
/// Potential Accent Color Combos
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub accent_yellow: Srgba,
|
pub accent_yellow: Srgba,
|
||||||
/// Potential Accent Color Combos
|
/// Potential Accent Color Combos
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub accent_green: Srgba,
|
pub accent_green: Srgba,
|
||||||
/// Potential Accent Color Combos
|
/// Potential Accent Color Combos
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub accent_warm_grey: Srgba,
|
pub accent_warm_grey: Srgba,
|
||||||
|
|
||||||
/// Extended Color Palette
|
/// Extended Color Palette
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub ext_warm_grey: Srgba,
|
pub ext_warm_grey: Srgba,
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub ext_orange: Srgba,
|
pub ext_orange: Srgba,
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub ext_yellow: Srgba,
|
pub ext_yellow: Srgba,
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub ext_blue: Srgba,
|
pub ext_blue: Srgba,
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub ext_purple: Srgba,
|
pub ext_purple: Srgba,
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub ext_pink: Srgba,
|
pub ext_pink: Srgba,
|
||||||
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
/// Colors used for themes, app icons, illustrations, and other brand purposes.
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub ext_indigo: Srgba,
|
pub ext_indigo: Srgba,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Dark((name:"cosmic-dark",bright_red:(red:1.0,green:0.62745098,blue:0.60392157,alpha:1.0),bright_green:(red:0.36862745,green:0.85882352,blue:0.54901960,alpha:1.0),bright_orange:(red:1.0,green:0.63921569,blue:0.49019608,alpha:1.0),gray_1:(red:0.10588235,green:0.10588235,blue:0.10588235,alpha:1.0),gray_2:(red:0.14901961,green:0.14901961,blue:0.14901961,alpha:1.0),neutral_0:(red:0.0,green:0.0,blue:0.0,alpha:1.0),neutral_1:(red:0.01176471,green:0.01176471,blue:0.01176471,alpha:1.0),neutral_2:(red:0.08627451,green:0.08627451,blue:0.08627451,alpha:1.0),neutral_3:(red:0.18039216,green:0.18039216,blue:0.18039216,alpha:1.0),neutral_4:(red:0.28235294,green:0.28235294,blue:0.28235294,alpha:1.0),neutral_5:(red:0.38823529,green:0.38823529,blue:0.38823529,alpha:1.0),neutral_6:(red:0.50196078,green:0.50196078,blue:0.50196078,alpha:1.0),neutral_7:(red:0.61960784,green:0.61960784,blue:0.61960784,alpha:1.0),neutral_8:(red:0.74509804,green:0.74509804,blue:0.74509804,alpha:1.0),neutral_9:(red:0.87058824,green:0.87058824,blue:0.87058824,alpha:1.0),neutral_10:(red:1.0,green:1.0,blue:1.0,alpha:1.0),accent_blue:(red:0.3882353,green:0.81568627,blue:0.87450981,alpha:1.0),accent_indigo:(red:0.63137255,green:0.75294118,blue:0.92156863,alpha:1.0),accent_purple:(red:0.90588235,green:0.61176471,blue:0.99607843,alpha:1.0),accent_pink:(red:1.0,green:0.61176471,blue:0.69411765,alpha:1.0),accent_red:(red:0.99215686,green:0.63137255,blue:0.62745098,alpha:1.0),accent_orange:(red:1.0,green:0.67843137,blue:0.0,alpha:1.0),accent_yellow:(red:0.96862745,green:0.87843137,blue:0.38431373,alpha:1.0),accent_green:(red:0.57254902,green:0.81176471,blue:0.61176471,alpha:1.0),accent_warm_grey:(red:0.79215686,green:0.72941176,blue:0.70588235,alpha:1.0),ext_warm_grey:(red:0.60784314,green:0.55686275,blue:0.54117647,alpha:1.0),ext_orange:(red:1.0,green:0.67843137,blue:0.0,alpha:1.0),ext_yellow:(red:0.99607843,green:0.85882353,blue:0.25098039,alpha:1.0),ext_blue:(red:0.28235294,green:0.72549020,blue:0.78039216,alpha:1.0),ext_purple:(red:0.81176471,green:0.49019608,blue:1.0,alpha:1.0),ext_pink:(red:0.97647059,green:0.22745098,blue:0.51372549,alpha:1.0),ext_indigo:(red:0.24313725,green:0.53333333,blue:1.0,alpha:1.0)))
|
Dark((name: "cosmic-dark",bright_red: "#FFA09AFF",bright_green: "#5EDB8CFF",bright_orange: "#FFA37DFF",gray_1: "#1B1B1BFF",gray_2: "#262626FF",neutral_0: "#000000FF",neutral_1: "#030303FF",neutral_2: "#161616FF",neutral_3: "#2E2E2EFF",neutral_4: "#484848FF",neutral_5: "#636363FF",neutral_6: "#808080FF",neutral_7: "#9E9E9EFF",neutral_8: "#BEBEBEFF",neutral_9: "#DEDEDEFF",neutral_10: "#FFFFFFFF",accent_blue: "#63D0DFFF",accent_indigo: "#A1C0EBFF",accent_purple: "#E79CFEFF",accent_pink: "#FF9CB1FF",accent_red: "#FDA1A0FF",accent_orange: "#FFAD00FF",accent_yellow: "#F7E062FF",accent_green: "#92CF9CFF",accent_warm_grey: "#CABAB4FF",ext_warm_grey: "#9B8E8AFF",ext_orange: "#FFAD00FF",ext_yellow: "#FEDB40FF",ext_blue: "#48B9C7FF",ext_purple: "#CF7DFFFF",ext_pink: "#F93A83FF",ext_indigo: "#3E88FFFF",))
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::color::color_serde;
|
||||||
use palette::{Srgba, WithAlpha};
|
use palette::{Srgba, WithAlpha};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|
@ -8,14 +9,18 @@ use crate::composite::over;
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct Container {
|
pub struct Container {
|
||||||
/// the color of the container
|
/// the color of the container
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub base: Srgba,
|
pub base: Srgba,
|
||||||
/// the color of components in the container
|
/// the color of components in the container
|
||||||
pub component: Component,
|
pub component: Component,
|
||||||
/// the color of dividers in the container
|
/// the color of dividers in the container
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub divider: Srgba,
|
pub divider: Srgba,
|
||||||
/// the color of text in the container
|
/// the color of text in the container
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub on: Srgba,
|
pub on: Srgba,
|
||||||
/// the color of @small_widget_container
|
/// the color of @small_widget_container
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub small_widget: Srgba,
|
pub small_widget: Srgba,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,30 +50,42 @@ impl Container {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct Component {
|
pub struct Component {
|
||||||
/// The base color of the widget
|
/// The base color of the widget
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub base: Srgba,
|
pub base: Srgba,
|
||||||
/// The color of the widget when it is hovered
|
/// The color of the widget when it is hovered
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub hover: Srgba,
|
pub hover: Srgba,
|
||||||
/// the color of the widget when it is pressed
|
/// the color of the widget when it is pressed
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub pressed: Srgba,
|
pub pressed: Srgba,
|
||||||
/// the color of the widget when it is selected
|
/// the color of the widget when it is selected
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub selected: Srgba,
|
pub selected: Srgba,
|
||||||
/// the color of the widget when it is selected
|
/// the color of the widget when it is selected
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub selected_text: Srgba,
|
pub selected_text: Srgba,
|
||||||
/// the color of the widget when it is focused
|
/// the color of the widget when it is focused
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub focus: Srgba,
|
pub focus: Srgba,
|
||||||
/// the color of dividers for this widget
|
/// the color of dividers for this widget
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub divider: Srgba,
|
pub divider: Srgba,
|
||||||
/// the color of text for this widget
|
/// the color of text for this widget
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub on: Srgba,
|
pub on: Srgba,
|
||||||
// the color of text with opacity 80 for this widget
|
// the color of text with opacity 80 for this widget
|
||||||
// pub text_opacity_80: Srgba,
|
// pub text_opacity_80: Srgba,
|
||||||
/// the color of the widget when it is disabled
|
/// the color of the widget when it is disabled
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub disabled: Srgba,
|
pub disabled: Srgba,
|
||||||
/// the color of text in the widget when it is disabled
|
/// the color of text in the widget when it is disabled
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub on_disabled: Srgba,
|
pub on_disabled: Srgba,
|
||||||
/// the color of the border for the widget
|
/// the color of the border for the widget
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub border: Srgba,
|
pub border: Srgba,
|
||||||
/// the color of the border for the widget when it is disabled
|
/// the color of the border for the widget when it is disabled
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
pub disabled_border: Srgba,
|
pub disabled_border: Srgba,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Light((name:"cosmic-light",bright_red:(red:0.53725490,green:0.01568627,blue:0.09411765,alpha:1.0),bright_green:(red:0.0,green:0.34117647,blue:0.17254901,alpha:1.0),bright_orange:(red:0.47450980,green:0.17254902,blue:0.0,alpha:1.0),gray_1:(red:0.84313725,green:0.84313725,blue:0.84313725,alpha:1.0),gray_2:(red:0.89411765,green:0.89411765,blue:0.89411765,alpha:1.0),neutral_0:(red:1.0,green:1.0,blue:1.0,alpha:1.0),neutral_1:(red:0.87058824,green:0.87058824,blue:0.87058824,alpha:1.0),neutral_2:(red:0.74509804,green:0.74509804,blue:0.74509804,alpha:1.0),neutral_3:(red:0.61960784,green:0.61960784,blue:0.61960784,alpha:1.0),neutral_4:(red:0.50196078,green:0.50196078,blue:0.50196078,alpha:1.0),neutral_5:(red:0.38823529,green:0.38823529,blue:0.38823529,alpha:1.0),neutral_6:(red:0.28235294,green:0.28235294,blue:0.28235294,alpha:1.0),neutral_7:(red:0.18039216,green:0.18039216,blue:0.18039216,alpha:1.0),neutral_8:(red:0.08627451,green:0.08627451,blue:0.08627451,alpha:1.0),neutral_9:(red:0.01176471,green:0.01176471,blue:0.01176471,alpha:1.0),neutral_10:(red:0.0,green:0.0,blue:0.0,alpha:1.0),accent_blue:(red:0.0,green:0.32156863,blue:0.35294118,alpha:1.0),accent_indigo:(red:0.18039216,green:0.28627451,blue:0.42745098,alpha:1.0),accent_purple:(red:0.40784314,green:0.12941176,blue:0.48627451,alpha:1.0),accent_pink:(red:0.52549020,green:0.01568627,blue:0.22745098,alpha:1.0),accent_red:(red:0.47058824,green:0.16078431,blue:0.18039216,alpha:1.0),accent_orange:(red:0.38431373,green:0.25098039,blue:0.0,alpha:1.0),accent_yellow:(red:0.32549020,green:0.28235294,blue:0.0,alpha:1.0),accent_green:(red:0.09411765,green:0.33333333,blue:0.16078431,alpha:1.0),accent_warm_grey:(red:0.33333333,green:0.27843137,blue:0.25882353,alpha:1.0),ext_warm_grey:(red:0.60784314,green:0.55686275,blue:0.54117647,alpha:1.0),ext_orange:(red:0.98431373,green:0.72156863,blue:0.42352941,alpha:1.0),ext_yellow:(red:0.96862745,green:0.87843137,blue:0.38431373,alpha:1.0),ext_blue:(red:0.41568627,green:0.79215686,blue:0.84705882,alpha:1.0),ext_purple:(red:0.83529412,green:0.54901961,blue:1.0,alpha:1.0),ext_pink:(red:1.0,green:0.61176471,blue:0.86666667,alpha:1.0),ext_indigo:(red:0.58431373,green:0.76862745,blue:0.98823529,alpha:1.0)))
|
Light((name: "cosmic-light",bright_red: "#890418FF",bright_green: "#00572CFF",bright_orange: "#792C00FF",gray_1: "#D7D7D7FF",gray_2: "#E4E4E4FF",neutral_0: "#FFFFFFFF",neutral_1: "#DEDEDEFF",neutral_2: "#BEBEBEFF",neutral_3: "#9E9E9EFF",neutral_4: "#808080FF",neutral_5: "#636363FF",neutral_6: "#484848FF",neutral_7: "#2E2E2EFF",neutral_8: "#161616FF",neutral_9: "#030303FF",neutral_10: "#000000FF",accent_blue: "#00525AFF",accent_indigo: "#2E496DFF",accent_purple: "#68217CFF",accent_pink: "#86043AFF",accent_red: "#78292EFF",accent_orange: "#624000FF",accent_yellow: "#534800FF",accent_green: "#185529FF",accent_warm_grey: "#554742FF",ext_warm_grey: "#9B8E8AFF",ext_orange: "#FBB86CFF",ext_yellow: "#F7E062FF",ext_blue: "#6ACAD8FF",ext_purple: "#D58CFFFF",ext_pink: "#FF9CDDFF",ext_indigo: "#95C4FCFF",))
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ pub use mode::*;
|
||||||
pub use spacing::*;
|
pub use spacing::*;
|
||||||
pub use theme::*;
|
pub use theme::*;
|
||||||
|
|
||||||
|
pub mod color;
|
||||||
mod corner;
|
mod corner;
|
||||||
mod cosmic_palette;
|
mod cosmic_palette;
|
||||||
mod density;
|
mod density;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
Component, Container, CornerRadii, CosmicPalette, CosmicPaletteInner, DARK_PALETTE,
|
Component, Container, CornerRadii, CosmicPalette, CosmicPaletteInner, DARK_PALETTE,
|
||||||
LIGHT_PALETTE, NAME, Spacing, ThemeMode,
|
LIGHT_PALETTE, NAME, Spacing, ThemeMode,
|
||||||
|
color::{ColorRepr, ColorReprOption, color_serde, color_serde::option as color_serde_option},
|
||||||
composite::over,
|
composite::over,
|
||||||
steps::{color_index, get_small_widget_color, get_surface_color, get_text, steps},
|
steps::{color_index, get_small_widget_color, get_surface_color, get_text, steps},
|
||||||
};
|
};
|
||||||
use cosmic_config::{Config, CosmicConfigEntry};
|
use cosmic_config::{Config, CosmicConfigEntry, cosmic_config_derive::CosmicConfigEntry};
|
||||||
use palette::{
|
use palette::{
|
||||||
IntoColor, Oklcha, Srgb, Srgba, WithAlpha, color_difference::Wcag21RelativeContrast, rgb::Rgb,
|
IntoColor, Oklcha, Srgb, Srgba, WithAlpha, color_difference::Wcag21RelativeContrast, rgb::Rgb,
|
||||||
};
|
};
|
||||||
|
|
@ -37,15 +38,8 @@ pub enum Layer {
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
/// Cosmic Theme data structure with all colors and its name
|
/// Cosmic Theme data structure with all colors and its name
|
||||||
#[derive(
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, CosmicConfigEntry)]
|
||||||
Clone,
|
#[version = 2]
|
||||||
Debug,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
PartialEq,
|
|
||||||
cosmic_config::cosmic_config_derive::CosmicConfigEntry,
|
|
||||||
)]
|
|
||||||
#[version = 1]
|
|
||||||
pub struct Theme {
|
pub struct Theme {
|
||||||
/// name of the theme
|
/// name of the theme
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
@ -96,15 +90,24 @@ pub struct Theme {
|
||||||
/// cosmic-comp custom window hint color
|
/// cosmic-comp custom window hint color
|
||||||
pub window_hint: Option<Srgb>,
|
pub window_hint: Option<Srgb>,
|
||||||
/// enables blurred transparency
|
/// enables blurred transparency
|
||||||
pub is_frosted: bool,
|
/// If None, frosted effect is disabled.
|
||||||
|
pub frosted: Option<BlurStrength>,
|
||||||
/// shade color for dialogs
|
/// shade color for dialogs
|
||||||
|
#[serde(with = "color_serde")]
|
||||||
|
#[cosmic_config_entry(with = ColorRepr)]
|
||||||
pub shade: Srgba,
|
pub shade: Srgba,
|
||||||
/// accent text colors
|
/// accent text colors
|
||||||
/// If None, accent base color is the accent text color.
|
/// If None, accent base color is the accent text color.
|
||||||
|
#[serde(with = "color_serde_option")]
|
||||||
|
#[cosmic_config_entry(with = ColorReprOption)]
|
||||||
pub accent_text: Option<Srgba>,
|
pub accent_text: Option<Srgba>,
|
||||||
/// control tint color
|
/// control tint color
|
||||||
|
#[serde(with = "color_serde_option")]
|
||||||
|
#[cosmic_config_entry(with = ColorReprOption)]
|
||||||
pub control_tint: Option<Srgb>,
|
pub control_tint: Option<Srgb>,
|
||||||
/// text tint color
|
/// text tint color
|
||||||
|
#[serde(with = "color_serde_option")]
|
||||||
|
#[cosmic_config_entry(with = ColorReprOption)]
|
||||||
pub text_tint: Option<Srgb>,
|
pub text_tint: Option<Srgb>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -739,7 +742,7 @@ impl Theme {
|
||||||
if color_scheme.trim().contains("default") || color_scheme.trim().contains("light") {
|
if color_scheme.trim().contains("default") || color_scheme.trim().contains("light") {
|
||||||
return Self::light_default();
|
return Self::light_default();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
Self::dark_default()
|
Self::dark_default()
|
||||||
}
|
}
|
||||||
|
|
@ -748,11 +751,11 @@ impl Theme {
|
||||||
pub fn preferred_theme() -> Self {
|
pub fn preferred_theme() -> Self {
|
||||||
let current_desktop = std::env::var("XDG_CURRENT_DESKTOP");
|
let current_desktop = std::env::var("XDG_CURRENT_DESKTOP");
|
||||||
|
|
||||||
if let Ok(desktop) = current_desktop {
|
if let Ok(desktop) = current_desktop
|
||||||
if desktop.trim().to_lowercase().contains("gnome") {
|
&& desktop.trim().to_lowercase().contains("gnome")
|
||||||
|
{
|
||||||
return Self::gtk_prefer_colorscheme();
|
return Self::gtk_prefer_colorscheme();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Self::dark_default()
|
Self::dark_default()
|
||||||
}
|
}
|
||||||
|
|
@ -766,15 +769,8 @@ impl From<CosmicPalette> for Theme {
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
/// Helper for building customized themes
|
/// Helper for building customized themes
|
||||||
#[derive(
|
#[derive(Clone, Debug, Serialize, Deserialize, CosmicConfigEntry, PartialEq)]
|
||||||
Clone,
|
#[version = 2]
|
||||||
Debug,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
cosmic_config::cosmic_config_derive::CosmicConfigEntry,
|
|
||||||
PartialEq,
|
|
||||||
)]
|
|
||||||
#[version = 1]
|
|
||||||
pub struct ThemeBuilder {
|
pub struct ThemeBuilder {
|
||||||
/// override the palette for the builder
|
/// override the palette for the builder
|
||||||
pub palette: CosmicPalette,
|
pub palette: CosmicPalette,
|
||||||
|
|
@ -783,30 +779,50 @@ pub struct ThemeBuilder {
|
||||||
/// override corner radii for the builder
|
/// override corner radii for the builder
|
||||||
pub corner_radii: CornerRadii,
|
pub corner_radii: CornerRadii,
|
||||||
/// override neutral_tint for the builder
|
/// override neutral_tint for the builder
|
||||||
|
#[serde(with = "color_serde_option")]
|
||||||
|
#[cosmic_config_entry(with = ColorReprOption)]
|
||||||
pub neutral_tint: Option<Srgb>,
|
pub neutral_tint: Option<Srgb>,
|
||||||
/// override bg_color for the builder
|
/// override bg_color for the builder
|
||||||
|
#[serde(with = "color_serde_option")]
|
||||||
|
#[cosmic_config_entry(with = ColorReprOption)]
|
||||||
pub bg_color: Option<Srgba>,
|
pub bg_color: Option<Srgba>,
|
||||||
/// override the primary container bg color for the builder
|
/// override the primary container bg color for the builder
|
||||||
|
#[serde(with = "color_serde_option")]
|
||||||
|
#[cosmic_config_entry(with = ColorReprOption)]
|
||||||
pub primary_container_bg: Option<Srgba>,
|
pub primary_container_bg: Option<Srgba>,
|
||||||
/// override the secontary container bg color for the builder
|
/// override the secontary container bg color for the builder
|
||||||
|
#[serde(with = "color_serde_option")]
|
||||||
|
#[cosmic_config_entry(with = ColorReprOption)]
|
||||||
pub secondary_container_bg: Option<Srgba>,
|
pub secondary_container_bg: Option<Srgba>,
|
||||||
/// override the text tint for the builder
|
/// override the text tint for the builder
|
||||||
|
#[serde(with = "color_serde_option")]
|
||||||
|
#[cosmic_config_entry(with = ColorReprOption)]
|
||||||
pub text_tint: Option<Srgb>,
|
pub text_tint: Option<Srgb>,
|
||||||
/// override the accent color for the builder
|
/// override the accent color for the builder
|
||||||
|
#[serde(with = "color_serde_option")]
|
||||||
|
#[cosmic_config_entry(with = ColorReprOption)]
|
||||||
pub accent: Option<Srgb>,
|
pub accent: Option<Srgb>,
|
||||||
/// override the success color for the builder
|
/// override the success color for the builder
|
||||||
|
#[serde(with = "color_serde_option")]
|
||||||
|
#[cosmic_config_entry(with = ColorReprOption)]
|
||||||
pub success: Option<Srgb>,
|
pub success: Option<Srgb>,
|
||||||
/// override the warning color for the builder
|
/// override the warning color for the builder
|
||||||
|
#[serde(with = "color_serde_option")]
|
||||||
|
#[cosmic_config_entry(with = ColorReprOption)]
|
||||||
pub warning: Option<Srgb>,
|
pub warning: Option<Srgb>,
|
||||||
/// override the destructive color for the builder
|
/// override the destructive color for the builder
|
||||||
|
#[serde(with = "color_serde_option")]
|
||||||
|
#[cosmic_config_entry(with = ColorReprOption)]
|
||||||
pub destructive: Option<Srgb>,
|
pub destructive: Option<Srgb>,
|
||||||
/// enabled blurred transparency
|
/// enabled blurred transparency
|
||||||
pub is_frosted: bool, // TODO handle
|
pub frosted: Option<BlurStrength>,
|
||||||
/// cosmic-comp window gaps size (outer, inner)
|
/// cosmic-comp window gaps size (outer, inner)
|
||||||
pub gaps: (u32, u32),
|
pub gaps: (u32, u32),
|
||||||
/// cosmic-comp active hint window outline width
|
/// cosmic-comp active hint window outline width
|
||||||
pub active_hint: u32,
|
pub active_hint: u32,
|
||||||
/// cosmic-comp custom window hint color
|
/// cosmic-comp custom window hint color
|
||||||
|
#[serde(with = "color_serde_option")]
|
||||||
|
#[cosmic_config_entry(with = ColorReprOption)]
|
||||||
pub window_hint: Option<Srgb>,
|
pub window_hint: Option<Srgb>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -825,7 +841,7 @@ impl Default for ThemeBuilder {
|
||||||
success: Default::default(),
|
success: Default::default(),
|
||||||
warning: Default::default(),
|
warning: Default::default(),
|
||||||
destructive: Default::default(),
|
destructive: Default::default(),
|
||||||
is_frosted: false,
|
frosted: None,
|
||||||
// cosmic-comp theme settings
|
// cosmic-comp theme settings
|
||||||
gaps: (0, 8),
|
gaps: (0, 8),
|
||||||
active_hint: 3,
|
active_hint: 3,
|
||||||
|
|
@ -971,9 +987,11 @@ impl ThemeBuilder {
|
||||||
gaps,
|
gaps,
|
||||||
active_hint,
|
active_hint,
|
||||||
window_hint,
|
window_hint,
|
||||||
is_frosted,
|
frosted,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
|
let container_alpha = frosted.map_or(1.0, |f| f.alpha());
|
||||||
|
|
||||||
let is_dark = palette.is_dark();
|
let is_dark = palette.is_dark();
|
||||||
let is_high_contrast = palette.is_high_contrast();
|
let is_high_contrast = palette.is_high_contrast();
|
||||||
|
|
||||||
|
|
@ -1019,12 +1037,14 @@ impl ThemeBuilder {
|
||||||
NonZeroUsize::new(100).unwrap(),
|
NonZeroUsize::new(100).unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let bg = if let Some(bg_color) = bg_color {
|
let mut bg = if let Some(bg_color) = bg_color {
|
||||||
bg_color
|
bg_color
|
||||||
} else {
|
} else {
|
||||||
p_ref.gray_1
|
p_ref.gray_1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bg.alpha = container_alpha;
|
||||||
|
|
||||||
let step_array = steps(bg, NonZeroUsize::new(100).unwrap());
|
let step_array = steps(bg, NonZeroUsize::new(100).unwrap());
|
||||||
let bg_index = color_index(bg, step_array.len());
|
let bg_index = color_index(bg, step_array.len());
|
||||||
|
|
||||||
|
|
@ -1055,11 +1075,12 @@ impl ThemeBuilder {
|
||||||
);
|
);
|
||||||
|
|
||||||
let primary = {
|
let primary = {
|
||||||
let container_bg = if let Some(primary_container_bg_color) = primary_container_bg {
|
let mut container_bg = if let Some(primary_container_bg_color) = primary_container_bg {
|
||||||
primary_container_bg_color
|
primary_container_bg_color
|
||||||
} else {
|
} else {
|
||||||
get_surface_color(bg_index, 5, &step_array, is_dark, &control_steps_array[1])
|
get_surface_color(bg_index, 5, &step_array, is_dark, &control_steps_array[1])
|
||||||
};
|
};
|
||||||
|
container_bg.alpha = container_alpha;
|
||||||
|
|
||||||
let step_array = steps(container_bg, NonZeroUsize::new(100).unwrap());
|
let step_array = steps(container_bg, NonZeroUsize::new(100).unwrap());
|
||||||
let base_index: usize = color_index(container_bg, step_array.len());
|
let base_index: usize = color_index(container_bg, step_array.len());
|
||||||
|
|
@ -1176,11 +1197,13 @@ impl ThemeBuilder {
|
||||||
),
|
),
|
||||||
primary,
|
primary,
|
||||||
secondary: {
|
secondary: {
|
||||||
let container_bg = if let Some(secondary_container_bg) = secondary_container_bg {
|
let mut container_bg = if let Some(secondary_container_bg) = secondary_container_bg
|
||||||
|
{
|
||||||
secondary_container_bg
|
secondary_container_bg
|
||||||
} else {
|
} else {
|
||||||
get_surface_color(bg_index, 10, &step_array, is_dark, &control_steps_array[2])
|
get_surface_color(bg_index, 10, &step_array, is_dark, &control_steps_array[2])
|
||||||
};
|
};
|
||||||
|
container_bg.alpha = container_alpha;
|
||||||
|
|
||||||
let step_array = steps(container_bg, NonZeroUsize::new(100).unwrap());
|
let step_array = steps(container_bg, NonZeroUsize::new(100).unwrap());
|
||||||
let base_index = color_index(container_bg, step_array.len());
|
let base_index = color_index(container_bg, step_array.len());
|
||||||
|
|
@ -1332,7 +1355,7 @@ impl ThemeBuilder {
|
||||||
gaps,
|
gaps,
|
||||||
active_hint,
|
active_hint,
|
||||||
window_hint,
|
window_hint,
|
||||||
is_frosted,
|
frosted,
|
||||||
accent_text,
|
accent_text,
|
||||||
control_tint: neutral_tint,
|
control_tint: neutral_tint,
|
||||||
text_tint,
|
text_tint,
|
||||||
|
|
@ -1354,3 +1377,69 @@ impl ThemeBuilder {
|
||||||
Config::new(LIGHT_THEME_BUILDER_ID, Self::VERSION)
|
Config::new(LIGHT_THEME_BUILDER_ID, Self::VERSION)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
pub enum BlurStrength {
|
||||||
|
ExtremelyLow = 1,
|
||||||
|
ExtremelyLow2,
|
||||||
|
VeryLow,
|
||||||
|
VeryLow2,
|
||||||
|
Low,
|
||||||
|
Low2,
|
||||||
|
Medium,
|
||||||
|
Medium2,
|
||||||
|
High,
|
||||||
|
High2,
|
||||||
|
VeryHigh,
|
||||||
|
VeryHigh2,
|
||||||
|
ExtremelyHigh,
|
||||||
|
ExtremelyHigh2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlurStrength {
|
||||||
|
/// Get the alpha value corresponding to the blur strength
|
||||||
|
/// Lower alpha values correspond to stronger blur effects, and higher alpha values correspond to weaker blur effects. The mapping is as follows:
|
||||||
|
pub fn alpha(&self) -> f32 {
|
||||||
|
match self {
|
||||||
|
Self::ExtremelyLow => 0.95,
|
||||||
|
Self::ExtremelyLow2 => 0.85,
|
||||||
|
Self::VeryLow => 0.8,
|
||||||
|
Self::VeryLow2 => 0.75,
|
||||||
|
Self::Low => 0.7,
|
||||||
|
Self::Low2 => 0.65,
|
||||||
|
Self::Medium => 0.6,
|
||||||
|
Self::Medium2 => 0.55,
|
||||||
|
Self::High => 0.5,
|
||||||
|
Self::High2 => 0.45,
|
||||||
|
Self::VeryHigh => 0.4,
|
||||||
|
Self::VeryHigh2 => 0.35,
|
||||||
|
Self::ExtremelyHigh => 0.2,
|
||||||
|
Self::ExtremelyHigh2 => 0.05,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for BlurStrength {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
1 => Ok(BlurStrength::ExtremelyLow),
|
||||||
|
2 => Ok(BlurStrength::ExtremelyLow2),
|
||||||
|
3 => Ok(BlurStrength::VeryLow),
|
||||||
|
4 => Ok(BlurStrength::VeryLow2),
|
||||||
|
5 => Ok(BlurStrength::Low),
|
||||||
|
6 => Ok(BlurStrength::Low2),
|
||||||
|
7 => Ok(BlurStrength::Medium),
|
||||||
|
8 => Ok(BlurStrength::Medium2),
|
||||||
|
9 => Ok(BlurStrength::High),
|
||||||
|
10 => Ok(BlurStrength::High2),
|
||||||
|
11 => Ok(BlurStrength::VeryHigh),
|
||||||
|
12 => Ok(BlurStrength::VeryHigh2),
|
||||||
|
13 => Ok(BlurStrength::ExtremelyHigh),
|
||||||
|
14 => Ok(BlurStrength::ExtremelyHigh2),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ ForegroundPositive=0,87,44
|
||||||
ForegroundVisited=0,82,90
|
ForegroundVisited=0,82,90
|
||||||
|
|
||||||
[Colors:Selection]
|
[Colors:Selection]
|
||||||
BackgroundAlternate=108,149,152
|
BackgroundAlternate=108,149,153
|
||||||
BackgroundNormal=0,82,90
|
BackgroundNormal=0,82,90
|
||||||
DecorationFocus=0,82,90
|
DecorationFocus=0,82,90
|
||||||
DecorationHover=0,82,90
|
DecorationHover=0,82,90
|
||||||
|
|
|
||||||
2
iced
2
iced
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7fd263d99e6ae1b07e51f25bda3367f7463806b1
|
Subproject commit 46b65a3c3e2fb6f1627d117ca061743417806aaf
|
||||||
|
|
@ -773,10 +773,31 @@ impl<T: Application> Cosmic<T> {
|
||||||
if a.distance_squared(*t_inner.accent_color()) > 0.00001 {
|
if a.distance_squared(*t_inner.accent_color()) > 0.00001 {
|
||||||
theme = Theme::system(Arc::new(t_inner.with_accent(a)));
|
theme = Theme::system(Arc::new(t_inner.with_accent(a)));
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let new_blur = theme.cosmic().frosted.is_some();
|
||||||
THEME.lock().unwrap().set_theme(theme.theme_type);
|
THEME.lock().unwrap().set_theme(theme.theme_type);
|
||||||
|
|
||||||
|
let core = self.app.core();
|
||||||
|
if core.auto_blur {
|
||||||
|
let mut cmds = Vec::with_capacity(1 + self.tracked_windows.len());
|
||||||
|
let blur = if new_blur {
|
||||||
|
iced::window::enable_blur
|
||||||
|
} else {
|
||||||
|
iced::window::disable_blur
|
||||||
|
};
|
||||||
|
cmds.push(blur(
|
||||||
|
self.app
|
||||||
|
.core()
|
||||||
|
.main_window_id()
|
||||||
|
.unwrap_or(window::Id::RESERVED),
|
||||||
|
));
|
||||||
|
for id in &self.tracked_windows {
|
||||||
|
cmds.push(blur(*id));
|
||||||
|
}
|
||||||
|
return Task::batch(cmds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::SystemThemeChange(keys, theme) => {
|
Action::SystemThemeChange(keys, theme) => {
|
||||||
|
|
@ -809,6 +830,8 @@ impl<T: Application> Cosmic<T> {
|
||||||
theme
|
theme
|
||||||
};
|
};
|
||||||
new_theme.theme_type.prefer_dark(prefer_dark);
|
new_theme.theme_type.prefer_dark(prefer_dark);
|
||||||
|
// TODO adjust theme container alphas to remove transparency?
|
||||||
|
// if auto-blur is disabled & theme is frosted, should we make container colors in theme opaque?
|
||||||
|
|
||||||
cosmic_theme.set_theme(new_theme.theme_type);
|
cosmic_theme.set_theme(new_theme.theme_type);
|
||||||
#[cfg(all(feature = "wayland", target_os = "linux"))]
|
#[cfg(all(feature = "wayland", target_os = "linux"))]
|
||||||
|
|
@ -873,7 +896,7 @@ impl<T: Application> Cosmic<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Update radius for all tracked windows
|
// Update radius for all tracked windows
|
||||||
for id in self.tracked_windows.iter() {
|
for id in &self.tracked_windows {
|
||||||
cmds.push(
|
cmds.push(
|
||||||
corner_radius(
|
corner_radius(
|
||||||
*id,
|
*id,
|
||||||
|
|
@ -956,6 +979,9 @@ impl<T: Application> Cosmic<T> {
|
||||||
|
|
||||||
// Only apply update if the theme is set to load a system theme
|
// Only apply update if the theme is set to load a system theme
|
||||||
if let ThemeType::System { .. } = cosmic_theme.theme_type {
|
if let ThemeType::System { .. } = cosmic_theme.theme_type {
|
||||||
|
// TODO adjust theme container alphas to remove transparency?
|
||||||
|
// if auto-blur is disabled & theme is frosted, should we make container colors in theme opaque?
|
||||||
|
let new_blur = new_theme.cosmic().frosted.is_some();
|
||||||
cosmic_theme.set_theme(new_theme.theme_type);
|
cosmic_theme.set_theme(new_theme.theme_type);
|
||||||
#[cfg(all(feature = "wayland", target_os = "linux"))]
|
#[cfg(all(feature = "wayland", target_os = "linux"))]
|
||||||
if self.app.core().sync_window_border_radii_to_theme() {
|
if self.app.core().sync_window_border_radii_to_theme() {
|
||||||
|
|
@ -1019,7 +1045,7 @@ impl<T: Application> Cosmic<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Update radius for all tracked windows
|
// Update radius for all tracked windows
|
||||||
for id in self.tracked_windows.iter() {
|
for id in &self.tracked_windows {
|
||||||
cmds.push(
|
cmds.push(
|
||||||
corner_radius(
|
corner_radius(
|
||||||
*id,
|
*id,
|
||||||
|
|
@ -1039,6 +1065,25 @@ impl<T: Application> Cosmic<T> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let core = self.app.core();
|
||||||
|
if core.auto_blur {
|
||||||
|
let blur = if new_blur {
|
||||||
|
iced::window::enable_blur
|
||||||
|
} else {
|
||||||
|
iced::window::disable_blur
|
||||||
|
};
|
||||||
|
|
||||||
|
cmds.push(blur(
|
||||||
|
self.app
|
||||||
|
.core()
|
||||||
|
.main_window_id()
|
||||||
|
.unwrap_or(window::Id::RESERVED),
|
||||||
|
));
|
||||||
|
for id in &self.tracked_windows {
|
||||||
|
cmds.push(blur(*id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Task::batch(cmds);
|
return Task::batch(cmds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1147,7 +1192,26 @@ impl<T: Application> Cosmic<T> {
|
||||||
|
|
||||||
// Only apply update if the theme is set to load a system theme
|
// Only apply update if the theme is set to load a system theme
|
||||||
if let ThemeType::System { theme: _, .. } = cosmic_theme.theme_type {
|
if let ThemeType::System { theme: _, .. } = cosmic_theme.theme_type {
|
||||||
|
let mut cmds = Vec::with_capacity(1 + self.tracked_windows.len());
|
||||||
|
|
||||||
|
if core.auto_blur {
|
||||||
|
let blur = if new_theme.cosmic().frosted.is_some() {
|
||||||
|
iced::window::enable_blur
|
||||||
|
} else {
|
||||||
|
iced::window::disable_blur
|
||||||
|
};
|
||||||
|
cmds.push(blur(
|
||||||
|
self.app
|
||||||
|
.core()
|
||||||
|
.main_window_id()
|
||||||
|
.unwrap_or(window::Id::RESERVED),
|
||||||
|
));
|
||||||
|
for id in &self.tracked_windows {
|
||||||
|
cmds.push(blur(*id));
|
||||||
|
}
|
||||||
|
}
|
||||||
cosmic_theme.set_theme(new_theme.theme_type);
|
cosmic_theme.set_theme(new_theme.theme_type);
|
||||||
|
return Task::batch(cmds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1263,8 +1327,24 @@ impl<T: Application> Cosmic<T> {
|
||||||
};
|
};
|
||||||
// TODO do we need per window sharp corners?
|
// TODO do we need per window sharp corners?
|
||||||
let rounded = !self.app.core().window.sharp_corners;
|
let rounded = !self.app.core().window.sharp_corners;
|
||||||
|
let core = self.app.core();
|
||||||
|
let blur_cmd = if core.auto_blur {
|
||||||
|
let blur = if t.frosted.is_some() {
|
||||||
|
iced::window::enable_blur
|
||||||
|
} else {
|
||||||
|
iced::window::disable_blur
|
||||||
|
};
|
||||||
|
let mut cmds = Vec::with_capacity(1 + self.tracked_windows.len());
|
||||||
|
cmds.push(blur(id));
|
||||||
|
for id in &self.tracked_windows {
|
||||||
|
cmds.push(blur(*id));
|
||||||
|
}
|
||||||
|
Task::batch(cmds)
|
||||||
|
} else {
|
||||||
|
Task::none()
|
||||||
|
};
|
||||||
return Task::batch([
|
return Task::batch([
|
||||||
|
blur_cmd,
|
||||||
corner_radius(
|
corner_radius(
|
||||||
id,
|
id,
|
||||||
if rounded {
|
if rounded {
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,6 @@ pub fn file_transfer_send(
|
||||||
/// Returns a list of file paths.
|
/// Returns a list of file paths.
|
||||||
#[cfg(feature = "xdg-portal")]
|
#[cfg(feature = "xdg-portal")]
|
||||||
pub fn file_transfer_receive(key: String) -> iced::Task<ashpd::Result<Vec<String>>> {
|
pub fn file_transfer_receive(key: String) -> iced::Task<ashpd::Result<Vec<String>>> {
|
||||||
dbg!(&key);
|
|
||||||
iced::Task::future(async move {
|
iced::Task::future(async move {
|
||||||
let file_transfer = ashpd::documents::FileTransfer::new().await?;
|
let file_transfer = ashpd::documents::FileTransfer::new().await?;
|
||||||
file_transfer.retrieve_files(&key).await
|
file_transfer.retrieve_files(&key).await
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,8 @@ pub struct Core {
|
||||||
|
|
||||||
#[cfg(all(feature = "wayland", target_os = "linux"))]
|
#[cfg(all(feature = "wayland", target_os = "linux"))]
|
||||||
pub(crate) sync_window_border_radii_to_theme: bool,
|
pub(crate) sync_window_border_radii_to_theme: bool,
|
||||||
|
|
||||||
|
pub(crate) auto_blur: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Core {
|
impl Default for Core {
|
||||||
|
|
@ -161,6 +163,7 @@ impl Default for Core {
|
||||||
menu_bars: HashMap::new(),
|
menu_bars: HashMap::new(),
|
||||||
#[cfg(all(feature = "wayland", target_os = "linux"))]
|
#[cfg(all(feature = "wayland", target_os = "linux"))]
|
||||||
sync_window_border_radii_to_theme: true,
|
sync_window_border_radii_to_theme: true,
|
||||||
|
auto_blur: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -502,4 +505,8 @@ impl Core {
|
||||||
pub fn sync_window_border_radii_to_theme(&self) -> bool {
|
pub fn sync_window_border_radii_to_theme(&self) -> bool {
|
||||||
self.sync_window_border_radii_to_theme
|
self.sync_window_border_radii_to_theme
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_auto_blur(&mut self, auto_blur: bool) {
|
||||||
|
self.auto_blur = auto_blur;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -565,6 +565,9 @@ impl iced_container::Catalog for Theme {
|
||||||
|
|
||||||
Container::ContextDrawer => {
|
Container::ContextDrawer => {
|
||||||
let mut a = Container::primary(cosmic);
|
let mut a = Container::primary(cosmic);
|
||||||
|
if let Some(Background::Color(ref mut color)) = a.background {
|
||||||
|
color.a = 1.;
|
||||||
|
}
|
||||||
|
|
||||||
if cosmic.is_high_contrast {
|
if cosmic.is_high_contrast {
|
||||||
a.border.width = 1.;
|
a.border.width = 1.;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue