wip: support desktop portal color-scheme, and accent variables
This commit is contained in:
parent
ce45af20f8
commit
c390b2614d
7 changed files with 264 additions and 25 deletions
|
|
@ -6,6 +6,7 @@ use std::collections::HashMap;
|
|||
use cosmic_config::CosmicConfigEntry;
|
||||
use cosmic_theme::ThemeMode;
|
||||
use iced_core::window::Id;
|
||||
use palette::Srgba;
|
||||
|
||||
use crate::Theme;
|
||||
|
||||
|
|
@ -59,9 +60,15 @@ pub struct Core {
|
|||
/// Last known system theme
|
||||
pub(super) system_theme: Theme,
|
||||
|
||||
/// Theme mode
|
||||
/// Configured theme mode
|
||||
pub(super) system_theme_mode: ThemeMode,
|
||||
|
||||
pub(super) portal_is_dark: Option<bool>,
|
||||
|
||||
pub(super) portal_accent: Option<Srgba>,
|
||||
|
||||
pub(super) portal_is_high_contrast: Option<bool>,
|
||||
|
||||
pub(super) title: HashMap<Id, String>,
|
||||
|
||||
pub window: Window,
|
||||
|
|
@ -121,6 +128,9 @@ impl Default for Core {
|
|||
single_instance: false,
|
||||
#[cfg(feature = "dbus-config")]
|
||||
settings_daemon: None,
|
||||
portal_is_dark: None,
|
||||
portal_accent: None,
|
||||
portal_is_high_contrast: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -260,4 +270,11 @@ impl Core {
|
|||
T::VERSION,
|
||||
)
|
||||
}
|
||||
|
||||
/// Whether the application should use a dark theme, according to the system
|
||||
#[must_use]
|
||||
pub fn system_is_dark(&self) -> bool {
|
||||
self.portal_is_dark
|
||||
.unwrap_or(self.system_theme_mode.is_dark)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ use iced_futures::event::listen_with;
|
|||
use iced_runtime::command::Action;
|
||||
#[cfg(not(feature = "wayland"))]
|
||||
use iced_runtime::window::Action as WindowAction;
|
||||
use palette::color_difference::EuclideanDistance;
|
||||
|
||||
/// A message managed internally by COSMIC.
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -72,6 +73,8 @@ pub enum Message {
|
|||
/// Activate the application
|
||||
Activate(String),
|
||||
ShowWindowMenu,
|
||||
#[cfg(feature = "xdg-portal")]
|
||||
DesktopSettings(crate::theme::portal::Desktop),
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -210,6 +213,10 @@ where
|
|||
.single_instance
|
||||
.then(|| super::single_instance_subscription::<T>())
|
||||
.unwrap_or_else(Subscription::none),
|
||||
#[cfg(feature = "xdg-portal")]
|
||||
crate::theme::portal::desktop_settings()
|
||||
.map(|e| Message::DesktopSettings(e))
|
||||
.map(super::Message::Cosmic),
|
||||
];
|
||||
|
||||
if self.app.core().keyboard_nav {
|
||||
|
|
@ -363,7 +370,15 @@ impl<T: Application> Cosmic<T> {
|
|||
// Apply last-known system theme if the system theme is preferred.
|
||||
if let ThemeType::System(_) = theme.theme_type {
|
||||
self.app.core_mut().theme_sub_counter += 1;
|
||||
|
||||
theme = self.app.core().system_theme.clone();
|
||||
let portal_accent = self.app.core().portal_accent;
|
||||
if let Some(a) = portal_accent {
|
||||
let t_inner = theme.cosmic();
|
||||
if a.distance_squared(*t_inner.accent_color()) > 0.00001 {
|
||||
theme = Theme::system(Arc::new(t_inner.with_accent(a)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
THEME.with(move |t| {
|
||||
|
|
@ -375,12 +390,23 @@ impl<T: Application> Cosmic<T> {
|
|||
Message::SystemThemeChange(theme) => {
|
||||
// Record the last-known system theme in event that the current theme is custom.
|
||||
self.app.core_mut().system_theme = theme.clone();
|
||||
let portal_accent = self.app.core().portal_accent;
|
||||
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 {
|
||||
cosmic_theme.set_theme(theme.theme_type);
|
||||
let 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)))
|
||||
} else {
|
||||
theme
|
||||
}
|
||||
} else {
|
||||
theme
|
||||
};
|
||||
cosmic_theme.set_theme(new_theme.theme_type);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -395,11 +421,29 @@ impl<T: Application> Cosmic<T> {
|
|||
}
|
||||
Message::SystemThemeModeChange(mode) => {
|
||||
let core = self.app.core_mut();
|
||||
let changed = core.system_theme_mode.is_dark != mode.is_dark;
|
||||
let prev_is_dark = core.system_is_dark();
|
||||
core.system_theme_mode = mode;
|
||||
core.theme_sub_counter += 1;
|
||||
let is_dark = core.system_is_dark();
|
||||
let changed = prev_is_dark != is_dark;
|
||||
if changed {
|
||||
let new_theme = crate::theme::system_preference();
|
||||
core.theme_sub_counter += 1;
|
||||
let mut new_theme = if is_dark {
|
||||
crate::theme::system_dark()
|
||||
} else {
|
||||
crate::theme::system_light()
|
||||
};
|
||||
|
||||
new_theme = if let Some(a) = core.portal_accent {
|
||||
let t_inner = new_theme.cosmic();
|
||||
if a.distance_squared(*t_inner.accent_color()) > 0.00001 {
|
||||
Theme::system(Arc::new(t_inner.with_accent(a)))
|
||||
} else {
|
||||
new_theme
|
||||
}
|
||||
} else {
|
||||
new_theme
|
||||
};
|
||||
|
||||
core.system_theme = new_theme.clone();
|
||||
THEME.with(move |t| {
|
||||
let mut cosmic_theme = t.borrow_mut();
|
||||
|
|
@ -428,6 +472,64 @@ impl<T: Application> Cosmic<T> {
|
|||
#[cfg(not(feature = "wayland"))]
|
||||
return window::show_window_menu(window::Id::MAIN);
|
||||
}
|
||||
#[cfg(feature = "xdg-portal")]
|
||||
Message::DesktopSettings(crate::theme::portal::Desktop::ColorScheme(s)) => {
|
||||
use ashpd::desktop::settings::ColorScheme;
|
||||
let is_dark = match s {
|
||||
ColorScheme::NoPreference => None,
|
||||
ColorScheme::PreferDark => Some(true),
|
||||
ColorScheme::PreferLight => Some(false),
|
||||
};
|
||||
let core = self.app.core_mut();
|
||||
let prev_is_dark = core.system_is_dark();
|
||||
core.portal_is_dark = is_dark;
|
||||
let is_dark = core.system_is_dark();
|
||||
let changed = prev_is_dark != is_dark;
|
||||
if changed {
|
||||
core.theme_sub_counter += 1;
|
||||
let new_theme = if is_dark {
|
||||
crate::theme::system_dark()
|
||||
} else {
|
||||
crate::theme::system_light()
|
||||
};
|
||||
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 {
|
||||
cosmic_theme.set_theme(new_theme.theme_type);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "xdg-portal")]
|
||||
Message::DesktopSettings(crate::theme::portal::Desktop::Accent(c)) => {
|
||||
use palette::{IntoColor, Oklch, Oklcha, Srgb, 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);
|
||||
let cur_accent = core.system_theme.cosmic().accent_color();
|
||||
|
||||
if cur_accent.distance_squared(*c) < 0.00001 {
|
||||
// skip calculations if we already have the same color
|
||||
return iced::Command::none();
|
||||
}
|
||||
|
||||
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(t) = cosmic_theme.theme_type.clone() {
|
||||
cosmic_theme.set_theme(ThemeType::System(Arc::new(t.with_accent(c))));
|
||||
}
|
||||
});
|
||||
}
|
||||
#[cfg(feature = "xdg-portal")]
|
||||
Message::DesktopSettings(crate::theme::portal::Desktop::Contrast(_)) => {
|
||||
// TODO when high contrast is integrated in settings and all custom themes
|
||||
}
|
||||
}
|
||||
|
||||
iced::Command::none()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue