From 92920046425515645d7715310ce3648a34b47b2c Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Mon, 13 May 2024 22:11:59 -0400 Subject: [PATCH] feat: allow preference for dark or light system theme also converts applet to use preferred system theme --- src/app/cosmic.rs | 75 ++++++++++++++++++++++++++++++++++------------- src/applet/mod.rs | 14 +++++++-- src/theme/mod.rs | 24 +++++++++++---- 3 files changed, 85 insertions(+), 28 deletions(-) diff --git a/src/app/cosmic.rs b/src/app/cosmic.rs index 559eb463..1560c56f 100644 --- a/src/app/cosmic.rs +++ b/src/app/cosmic.rs @@ -207,11 +207,22 @@ where }), self.app .core() - .watch_config::(if self.app.core().system_theme_mode.is_dark { - cosmic_theme::DARK_THEME_ID - } else { - cosmic_theme::LIGHT_THEME_ID - }) + .watch_config::( + if THEME + .with(|t| { + 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| { for why in update.errors { tracing::error!(?why, "cosmic theme config update error"); @@ -398,7 +409,7 @@ impl Cosmic { Message::AppThemeChange(mut theme) => { // 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; theme = self.app.core().system_theme.clone(); @@ -426,8 +437,12 @@ impl Cosmic { let mut cosmic_theme = t.borrow_mut(); // Only apply update if the theme is set to load a system theme - if let ThemeType::System(_) = cosmic_theme.theme_type { - let new_theme = if let Some(a) = portal_accent { + if let ThemeType::System { + theme: _, + prefer_dark, + } = cosmic_theme.theme_type + { + let mut new_theme = if let Some(a) = portal_accent { let t_inner = theme.cosmic(); if a.distance_squared(*t_inner.accent_color()) > 0.00001 { Theme::system(Arc::new(t_inner.with_accent(a))) @@ -437,6 +452,8 @@ impl Cosmic { } else { theme }; + new_theme.theme_type.prefer_dark(prefer_dark); + cosmic_theme.set_theme(new_theme.theme_type); } }); @@ -455,6 +472,15 @@ impl Cosmic { }; } 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 core = self.app.core_mut(); @@ -486,9 +512,8 @@ impl Cosmic { core.system_theme = new_theme.clone(); THEME.with(move |t| { let mut cosmic_theme = t.borrow_mut(); - // 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); } }); @@ -515,6 +540,15 @@ impl Cosmic { #[cfg(feature = "xdg-portal")] Message::DesktopSettings(crate::theme::portal::Desktop::ColorScheme(s)) => { 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 { ColorScheme::NoPreference => None, ColorScheme::PreferDark => Some(true), @@ -537,7 +571,7 @@ impl Cosmic { let mut cosmic_theme = t.borrow_mut(); // 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); } }); @@ -546,7 +580,6 @@ impl Cosmic { #[cfg(feature = "xdg-portal")] Message::DesktopSettings(crate::theme::portal::Desktop::Accent(c)) => { use palette::Srgba; - let c = Srgba::new(c.red() as f32, c.green() as f32, c.blue() as f32, 1.0); let core = self.app.core_mut(); core.portal_accent = Some(c); @@ -561,8 +594,15 @@ impl Cosmic { let mut cosmic_theme = t.borrow_mut(); // Only apply update if the theme is set to load a system theme - if let ThemeType::System(t) = cosmic_theme.theme_type.clone() { - cosmic_theme.set_theme(ThemeType::System(Arc::new(t.with_accent(c)))); + if let ThemeType::System { + 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 Cosmic { Message::Unfocus(id) => { let core = self.app.core_mut(); - if core - .focused_window - .as_ref() - .map(|cur| *cur == id) - .unwrap_or_default() - { + if core.focused_window.as_ref().is_some_and(|cur| *cur == id) { core.focused_window = None; } } diff --git a/src/applet/mod.rs b/src/applet/mod.rs index 61e9cef9..0dbce82e 100644 --- a/src/applet/mod.rs +++ b/src/applet/mod.rs @@ -11,7 +11,7 @@ use crate::{ window, Color, Length, Limits, Rectangle, }, iced_style, iced_widget, - theme::{self, Button, THEME}, + theme::{self, system_dark, system_light, Button, THEME}, widget, Application, Element, Renderer, }; pub use cosmic_panel_config; @@ -265,8 +265,16 @@ impl Context { #[must_use] pub fn theme(&self) -> Option { match self.background { - CosmicPanelBackground::Dark => Some(theme::Theme::dark()), - CosmicPanelBackground::Light => Some(theme::Theme::light()), + CosmicPanelBackground::Dark => { + 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()), } } diff --git a/src/theme/mod.rs b/src/theme/mod.rs index 0f72efb1..72a2c218 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -151,7 +151,10 @@ pub enum ThemeType { HighContrastDark, HighContrastLight, Custom(Arc), - System(Arc), + System { + prefer_dark: Option, + theme: Arc, + }, } impl ThemeType { @@ -161,7 +164,7 @@ impl ThemeType { match self { Self::Dark | Self::HighContrastDark => true, 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 { Self::Dark | Self::Light => false, 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) { + if let Self::System { prefer_dark, .. } = self { + *prefer_dark = new_prefer_dark; } } } @@ -190,7 +201,7 @@ impl Theme { ThemeType::Light => &COSMIC_LIGHT, ThemeType::HighContrastDark => &COSMIC_HC_DARK, 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) -> Self { Self { - theme_type: ThemeType::System(theme), + theme_type: ThemeType::System { + theme, + prefer_dark: None, + }, ..Default::default() } }