feat: allow preference for dark or light system theme
also converts applet to use preferred system theme
This commit is contained in:
parent
84d77281cb
commit
9292004642
3 changed files with 85 additions and 28 deletions
|
|
@ -207,11 +207,22 @@ where
|
||||||
}),
|
}),
|
||||||
self.app
|
self.app
|
||||||
.core()
|
.core()
|
||||||
.watch_config::<cosmic_theme::Theme>(if self.app.core().system_theme_mode.is_dark {
|
.watch_config::<cosmic_theme::Theme>(
|
||||||
cosmic_theme::DARK_THEME_ID
|
if THEME
|
||||||
} else {
|
.with(|t| {
|
||||||
cosmic_theme::LIGHT_THEME_ID
|
if let ThemeType::System { prefer_dark, .. } = t.borrow().theme_type {
|
||||||
})
|
prefer_dark
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| self.app.core().system_theme_mode.is_dark)
|
||||||
|
{
|
||||||
|
cosmic_theme::DARK_THEME_ID
|
||||||
|
} else {
|
||||||
|
cosmic_theme::LIGHT_THEME_ID
|
||||||
|
},
|
||||||
|
)
|
||||||
.map(|update| {
|
.map(|update| {
|
||||||
for why in update.errors {
|
for why in update.errors {
|
||||||
tracing::error!(?why, "cosmic theme config update error");
|
tracing::error!(?why, "cosmic theme config update error");
|
||||||
|
|
@ -398,7 +409,7 @@ impl<T: Application> Cosmic<T> {
|
||||||
|
|
||||||
Message::AppThemeChange(mut theme) => {
|
Message::AppThemeChange(mut theme) => {
|
||||||
// Apply last-known system theme if the system theme is preferred.
|
// Apply last-known system theme if the system theme is preferred.
|
||||||
if let ThemeType::System(_) = theme.theme_type {
|
if let ThemeType::System { theme: _, .. } = theme.theme_type {
|
||||||
self.app.core_mut().theme_sub_counter += 1;
|
self.app.core_mut().theme_sub_counter += 1;
|
||||||
|
|
||||||
theme = self.app.core().system_theme.clone();
|
theme = self.app.core().system_theme.clone();
|
||||||
|
|
@ -426,8 +437,12 @@ impl<T: Application> Cosmic<T> {
|
||||||
let mut cosmic_theme = t.borrow_mut();
|
let mut cosmic_theme = t.borrow_mut();
|
||||||
|
|
||||||
// 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 {
|
||||||
let new_theme = if let Some(a) = portal_accent {
|
theme: _,
|
||||||
|
prefer_dark,
|
||||||
|
} = cosmic_theme.theme_type
|
||||||
|
{
|
||||||
|
let mut new_theme = if let Some(a) = portal_accent {
|
||||||
let t_inner = theme.cosmic();
|
let t_inner = theme.cosmic();
|
||||||
if a.distance_squared(*t_inner.accent_color()) > 0.00001 {
|
if a.distance_squared(*t_inner.accent_color()) > 0.00001 {
|
||||||
Theme::system(Arc::new(t_inner.with_accent(a)))
|
Theme::system(Arc::new(t_inner.with_accent(a)))
|
||||||
|
|
@ -437,6 +452,8 @@ impl<T: Application> Cosmic<T> {
|
||||||
} else {
|
} else {
|
||||||
theme
|
theme
|
||||||
};
|
};
|
||||||
|
new_theme.theme_type.prefer_dark(prefer_dark);
|
||||||
|
|
||||||
cosmic_theme.set_theme(new_theme.theme_type);
|
cosmic_theme.set_theme(new_theme.theme_type);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -455,6 +472,15 @@ impl<T: Application> Cosmic<T> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Message::SystemThemeModeChange(keys, mode) => {
|
Message::SystemThemeModeChange(keys, mode) => {
|
||||||
|
if THEME.with(|t| match t.borrow().theme_type {
|
||||||
|
ThemeType::System {
|
||||||
|
theme: _,
|
||||||
|
prefer_dark,
|
||||||
|
} => prefer_dark.is_some(),
|
||||||
|
_ => false,
|
||||||
|
}) {
|
||||||
|
return iced::Command::none();
|
||||||
|
}
|
||||||
let mut cmds = vec![self.app.system_theme_mode_update(&keys, &mode)];
|
let mut cmds = vec![self.app.system_theme_mode_update(&keys, &mode)];
|
||||||
|
|
||||||
let core = self.app.core_mut();
|
let core = self.app.core_mut();
|
||||||
|
|
@ -486,9 +512,8 @@ impl<T: Application> Cosmic<T> {
|
||||||
core.system_theme = new_theme.clone();
|
core.system_theme = new_theme.clone();
|
||||||
THEME.with(move |t| {
|
THEME.with(move |t| {
|
||||||
let mut cosmic_theme = t.borrow_mut();
|
let mut cosmic_theme = t.borrow_mut();
|
||||||
|
|
||||||
// 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 { theme: _, .. } = cosmic_theme.theme_type {
|
||||||
cosmic_theme.set_theme(new_theme.theme_type);
|
cosmic_theme.set_theme(new_theme.theme_type);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -515,6 +540,15 @@ impl<T: Application> Cosmic<T> {
|
||||||
#[cfg(feature = "xdg-portal")]
|
#[cfg(feature = "xdg-portal")]
|
||||||
Message::DesktopSettings(crate::theme::portal::Desktop::ColorScheme(s)) => {
|
Message::DesktopSettings(crate::theme::portal::Desktop::ColorScheme(s)) => {
|
||||||
use ashpd::desktop::settings::ColorScheme;
|
use ashpd::desktop::settings::ColorScheme;
|
||||||
|
if THEME.with(|t| match t.borrow().theme_type {
|
||||||
|
ThemeType::System {
|
||||||
|
theme: _,
|
||||||
|
prefer_dark,
|
||||||
|
} => prefer_dark.is_some(),
|
||||||
|
_ => false,
|
||||||
|
}) {
|
||||||
|
return iced::Command::none();
|
||||||
|
}
|
||||||
let is_dark = match s {
|
let is_dark = match s {
|
||||||
ColorScheme::NoPreference => None,
|
ColorScheme::NoPreference => None,
|
||||||
ColorScheme::PreferDark => Some(true),
|
ColorScheme::PreferDark => Some(true),
|
||||||
|
|
@ -537,7 +571,7 @@ impl<T: Application> Cosmic<T> {
|
||||||
let mut cosmic_theme = t.borrow_mut();
|
let mut cosmic_theme = t.borrow_mut();
|
||||||
|
|
||||||
// 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 { theme: _, .. } = cosmic_theme.theme_type {
|
||||||
cosmic_theme.set_theme(new_theme.theme_type);
|
cosmic_theme.set_theme(new_theme.theme_type);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -546,7 +580,6 @@ impl<T: Application> Cosmic<T> {
|
||||||
#[cfg(feature = "xdg-portal")]
|
#[cfg(feature = "xdg-portal")]
|
||||||
Message::DesktopSettings(crate::theme::portal::Desktop::Accent(c)) => {
|
Message::DesktopSettings(crate::theme::portal::Desktop::Accent(c)) => {
|
||||||
use palette::Srgba;
|
use palette::Srgba;
|
||||||
|
|
||||||
let c = Srgba::new(c.red() as f32, c.green() as f32, c.blue() as f32, 1.0);
|
let c = Srgba::new(c.red() as f32, c.green() as f32, c.blue() as f32, 1.0);
|
||||||
let core = self.app.core_mut();
|
let core = self.app.core_mut();
|
||||||
core.portal_accent = Some(c);
|
core.portal_accent = Some(c);
|
||||||
|
|
@ -561,8 +594,15 @@ impl<T: Application> Cosmic<T> {
|
||||||
let mut cosmic_theme = t.borrow_mut();
|
let mut cosmic_theme = t.borrow_mut();
|
||||||
|
|
||||||
// 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(t) = cosmic_theme.theme_type.clone() {
|
if let ThemeType::System {
|
||||||
cosmic_theme.set_theme(ThemeType::System(Arc::new(t.with_accent(c))));
|
theme: t,
|
||||||
|
prefer_dark,
|
||||||
|
} = cosmic_theme.theme_type.clone()
|
||||||
|
{
|
||||||
|
cosmic_theme.set_theme(ThemeType::System {
|
||||||
|
theme: Arc::new(t.with_accent(c)),
|
||||||
|
prefer_dark,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -588,12 +628,7 @@ impl<T: Application> Cosmic<T> {
|
||||||
|
|
||||||
Message::Unfocus(id) => {
|
Message::Unfocus(id) => {
|
||||||
let core = self.app.core_mut();
|
let core = self.app.core_mut();
|
||||||
if core
|
if core.focused_window.as_ref().is_some_and(|cur| *cur == id) {
|
||||||
.focused_window
|
|
||||||
.as_ref()
|
|
||||||
.map(|cur| *cur == id)
|
|
||||||
.unwrap_or_default()
|
|
||||||
{
|
|
||||||
core.focused_window = None;
|
core.focused_window = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use crate::{
|
||||||
window, Color, Length, Limits, Rectangle,
|
window, Color, Length, Limits, Rectangle,
|
||||||
},
|
},
|
||||||
iced_style, iced_widget,
|
iced_style, iced_widget,
|
||||||
theme::{self, Button, THEME},
|
theme::{self, system_dark, system_light, Button, THEME},
|
||||||
widget, Application, Element, Renderer,
|
widget, Application, Element, Renderer,
|
||||||
};
|
};
|
||||||
pub use cosmic_panel_config;
|
pub use cosmic_panel_config;
|
||||||
|
|
@ -265,8 +265,16 @@ impl Context {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn theme(&self) -> Option<theme::Theme> {
|
pub fn theme(&self) -> Option<theme::Theme> {
|
||||||
match self.background {
|
match self.background {
|
||||||
CosmicPanelBackground::Dark => Some(theme::Theme::dark()),
|
CosmicPanelBackground::Dark => {
|
||||||
CosmicPanelBackground::Light => Some(theme::Theme::light()),
|
let mut theme = system_dark();
|
||||||
|
theme.theme_type.prefer_dark(Some(true));
|
||||||
|
Some(theme)
|
||||||
|
}
|
||||||
|
CosmicPanelBackground::Light => {
|
||||||
|
let mut theme = system_light();
|
||||||
|
theme.theme_type.prefer_dark(Some(false));
|
||||||
|
Some(theme)
|
||||||
|
}
|
||||||
_ => Some(theme::system_preference()),
|
_ => Some(theme::system_preference()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,10 @@ pub enum ThemeType {
|
||||||
HighContrastDark,
|
HighContrastDark,
|
||||||
HighContrastLight,
|
HighContrastLight,
|
||||||
Custom(Arc<CosmicTheme>),
|
Custom(Arc<CosmicTheme>),
|
||||||
System(Arc<CosmicTheme>),
|
System {
|
||||||
|
prefer_dark: Option<bool>,
|
||||||
|
theme: Arc<CosmicTheme>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ThemeType {
|
impl ThemeType {
|
||||||
|
|
@ -161,7 +164,7 @@ impl ThemeType {
|
||||||
match self {
|
match self {
|
||||||
Self::Dark | Self::HighContrastDark => true,
|
Self::Dark | Self::HighContrastDark => true,
|
||||||
Self::Light | Self::HighContrastLight => false,
|
Self::Light | Self::HighContrastLight => false,
|
||||||
Self::Custom(theme) | Self::System(theme) => theme.is_dark,
|
Self::Custom(theme) | Self::System { theme, .. } => theme.is_dark,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,7 +174,15 @@ impl ThemeType {
|
||||||
match self {
|
match self {
|
||||||
Self::Dark | Self::Light => false,
|
Self::Dark | Self::Light => false,
|
||||||
Self::HighContrastDark | Self::HighContrastLight => true,
|
Self::HighContrastDark | Self::HighContrastLight => true,
|
||||||
Self::Custom(theme) | Self::System(theme) => theme.is_high_contrast,
|
Self::Custom(theme) | Self::System { theme, .. } => theme.is_high_contrast,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prefer dark or light theme.
|
||||||
|
/// If `None`, the system preference is used.
|
||||||
|
pub fn prefer_dark(&mut self, new_prefer_dark: Option<bool>) {
|
||||||
|
if let Self::System { prefer_dark, .. } = self {
|
||||||
|
*prefer_dark = new_prefer_dark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -190,7 +201,7 @@ impl Theme {
|
||||||
ThemeType::Light => &COSMIC_LIGHT,
|
ThemeType::Light => &COSMIC_LIGHT,
|
||||||
ThemeType::HighContrastDark => &COSMIC_HC_DARK,
|
ThemeType::HighContrastDark => &COSMIC_HC_DARK,
|
||||||
ThemeType::HighContrastLight => &COSMIC_HC_LIGHT,
|
ThemeType::HighContrastLight => &COSMIC_HC_LIGHT,
|
||||||
ThemeType::Custom(ref t) | ThemeType::System(ref t) => t.as_ref(),
|
ThemeType::Custom(ref t) | ThemeType::System { theme: ref t, .. } => t.as_ref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,7 +242,10 @@ impl Theme {
|
||||||
|
|
||||||
pub fn system(theme: Arc<CosmicTheme>) -> Self {
|
pub fn system(theme: Arc<CosmicTheme>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
theme_type: ThemeType::System(theme),
|
theme_type: ThemeType::System {
|
||||||
|
theme,
|
||||||
|
prefer_dark: None,
|
||||||
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue