Set window theme to match color scheme of active theme

This commit is contained in:
Héctor Ramón Jiménez 2025-09-08 10:12:04 +02:00
parent e92c87061d
commit 74425d5cb1
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
4 changed files with 40 additions and 6 deletions

View file

@ -258,7 +258,10 @@ pub trait Base {
/// Returns the default theme for the preferred [`Mode`]. /// Returns the default theme for the preferred [`Mode`].
fn default(preference: Mode) -> Self; fn default(preference: Mode) -> Self;
/// Returns the default base [`Style`] of a theme. /// Returns the [`Mode`] of the theme.
fn mode(&self) -> Mode;
/// Returns the default base [`Style`] of the theme.
fn base(&self) -> Style; fn base(&self) -> Style;
/// Returns the color [`Palette`] of the theme. /// Returns the color [`Palette`] of the theme.
@ -295,6 +298,14 @@ impl Base for Theme {
} }
} }
fn mode(&self) -> Mode {
if self.extended_palette().is_dark {
Mode::Dark
} else {
Mode::Light
}
}
fn base(&self) -> Style { fn base(&self) -> Style {
default(self) default(self)
} }

View file

@ -1207,7 +1207,7 @@ pub fn icon(icon: window::Icon) -> Option<winit::window::Icon> {
winit::window::Icon::from_rgba(pixels, size.width, size.height).ok() winit::window::Icon::from_rgba(pixels, size.width, size.height).ok()
} }
/// Convertions some [`input_method::Purpose`] into its `winit` counterpart. /// Converts some [`input_method::Purpose`] into its `winit` counterpart.
pub fn ime_purpose( pub fn ime_purpose(
purpose: input_method::Purpose, purpose: input_method::Purpose,
) -> winit::window::ImePurpose { ) -> winit::window::ImePurpose {

View file

@ -634,6 +634,10 @@ async fn run_instance<P>(
system_theme, system_theme,
); );
window.raw.set_theme(conversion::window_theme(
window.state.theme_mode(),
));
debug::theme_changed(|| { debug::theme_changed(|| {
if is_first { if is_first {
theme::Base::palette(window.state.theme()) theme::Base::palette(window.state.theme())

View file

@ -9,7 +9,7 @@ use winit::window::Window;
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
/// The state of a multi-windowed [`Program`]. /// The state of the window of a [`Program`].
pub struct State<P: Program> pub struct State<P: Program>
where where
P::Theme: theme::Base, P::Theme: theme::Base,
@ -21,6 +21,7 @@ where
cursor_position: Option<winit::dpi::PhysicalPosition<f64>>, cursor_position: Option<winit::dpi::PhysicalPosition<f64>>,
modifiers: winit::keyboard::ModifiersState, modifiers: winit::keyboard::ModifiersState,
theme: Option<P::Theme>, theme: Option<P::Theme>,
theme_mode: theme::Mode,
default_theme: P::Theme, default_theme: P::Theme,
style: theme::Style, style: theme::Style,
} }
@ -52,7 +53,7 @@ where
window: &Window, window: &Window,
system_theme: theme::Mode, system_theme: theme::Mode,
) -> Self { ) -> Self {
let theme_mode = window let system_theme = window
.theme() .theme()
.map(conversion::theme_mode) .map(conversion::theme_mode)
.unwrap_or(system_theme); .unwrap_or(system_theme);
@ -60,7 +61,9 @@ where
let title = program.title(window_id); let title = program.title(window_id);
let scale_factor = program.scale_factor(window_id); let scale_factor = program.scale_factor(window_id);
let theme = program.theme(window_id); let theme = program.theme(window_id);
let default_theme = <P::Theme as theme::Base>::default(theme_mode); let theme_mode =
theme.as_ref().map(theme::Base::mode).unwrap_or_default();
let default_theme = <P::Theme as theme::Base>::default(system_theme);
let style = program.style(theme.as_ref().unwrap_or(&default_theme)); let style = program.style(theme.as_ref().unwrap_or(&default_theme));
let viewport = { let viewport = {
@ -80,6 +83,7 @@ where
cursor_position: None, cursor_position: None,
modifiers: winit::keyboard::ModifiersState::default(), modifiers: winit::keyboard::ModifiersState::default(),
theme, theme,
theme_mode,
default_theme, default_theme,
style, style,
} }
@ -135,6 +139,11 @@ where
self.theme.as_ref().unwrap_or(&self.default_theme) self.theme.as_ref().unwrap_or(&self.default_theme)
} }
/// Returns the current [`theme::Mode`] of the [`State`].
pub fn theme_mode(&self) -> theme::Mode {
self.theme_mode
}
/// Returns the current background [`Color`] of the [`State`]. /// Returns the current background [`Color`] of the [`State`].
pub fn background_color(&self) -> Color { pub fn background_color(&self) -> Color {
self.style.background_color self.style.background_color
@ -192,9 +201,9 @@ where
self.default_theme = <P::Theme as theme::Base>::default( self.default_theme = <P::Theme as theme::Base>::default(
conversion::theme_mode(*theme), conversion::theme_mode(*theme),
); );
self.style = program.style(self.theme());
if self.theme.is_none() { if self.theme.is_none() {
self.style = program.style(&self.default_theme);
window.request_redraw(); window.request_redraw();
} }
} }
@ -242,5 +251,15 @@ where
// Update theme and appearance // Update theme and appearance
self.theme = program.theme(window_id); self.theme = program.theme(window_id);
self.style = program.style(self.theme()); self.style = program.style(self.theme());
if let Some(theme) = &self.theme {
let new_mode = theme::Base::mode(theme);
if self.theme_mode != new_mode {
window.set_theme(conversion::window_theme(new_mode));
self.theme_mode = new_mode;
}
}
} }
} }