Track window theme in window::State

This commit is contained in:
Héctor Ramón Jiménez 2025-09-08 06:01:36 +02:00
parent 354159bdf4
commit c1d7819c07
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
3 changed files with 41 additions and 18 deletions

View file

@ -1,3 +1,4 @@
use crate::theme;
use crate::time::Instant;
use crate::{Point, Size};
@ -71,4 +72,7 @@ pub enum Event {
///
/// - **Wayland:** Not implemented.
FilesHoveredLeft,
/// The theme mode of the window has changed.
ThemeModeChanged(theme::Mode),
}

View file

@ -5,6 +5,7 @@
use crate::core::input_method;
use crate::core::keyboard;
use crate::core::mouse;
use crate::core::theme;
use crate::core::touch;
use crate::core::window;
use crate::core::{Event, Point, Size};
@ -318,6 +319,9 @@ pub fn window_event(
Some(Event::Window(window::Event::Moved(Point::new(x, y))))
}
WindowEvent::ThemeChanged(theme) => Some(Event::Window(
window::Event::ThemeModeChanged(theme_mode(theme)),
)),
_ => None,
}
}
@ -440,6 +444,16 @@ pub fn mode(mode: Option<winit::window::Fullscreen>) -> window::Mode {
}
}
/// Converts a [`winit`] window theme to a [`theme::Mode`].
///
/// [`winit`]: https://github.com/rust-windowing/winit
pub fn theme_mode(theme: winit::window::Theme) -> theme::Mode {
match theme {
winit::window::Theme::Light => theme::Mode::Light,
winit::window::Theme::Dark => theme::Mode::Dark,
}
}
/// Converts a [`mouse::Interaction`] to a [`winit`] cursor icon.
///
/// [`winit`]: https://github.com/rust-windowing/winit

View file

@ -20,8 +20,8 @@ where
viewport_version: u64,
cursor_position: Option<winit::dpi::PhysicalPosition<f64>>,
modifiers: winit::keyboard::ModifiersState,
theme: P::Theme,
theme_mode: theme::Mode,
theme: Option<P::Theme>,
system_theme: P::Theme,
style: theme::Style,
}
@ -30,7 +30,7 @@ where
P::Theme: theme::Base,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("multi_window::State")
f.debug_struct("window::State")
.field("title", &self.title)
.field("scale_factor", &self.scale_factor)
.field("viewport", &self.viewport)
@ -53,15 +53,13 @@ where
) -> Self {
let title = program.title(window_id);
let scale_factor = program.scale_factor(window_id);
let theme_mode = match window.theme() {
None => theme::Mode::None,
Some(winit::window::Theme::Light) => theme::Mode::Light,
Some(winit::window::Theme::Dark) => theme::Mode::Dark,
};
let theme = program
.theme(window_id)
.unwrap_or_else(|| <P::Theme as theme::Base>::default(theme_mode));
let style = program.style(&theme);
let theme_mode = window
.theme()
.map(conversion::theme_mode)
.unwrap_or_default();
let theme = program.theme(window_id);
let system_theme = <P::Theme as theme::Base>::default(theme_mode);
let style = program.style(theme.as_ref().unwrap_or(&system_theme));
let viewport = {
let physical_size = window.inner_size();
@ -80,7 +78,7 @@ where
cursor_position: None,
modifiers: winit::keyboard::ModifiersState::default(),
theme,
theme_mode,
system_theme,
style,
}
}
@ -132,7 +130,7 @@ where
/// Returns the current theme of the [`State`].
pub fn theme(&self) -> &P::Theme {
&self.theme
self.theme.as_ref().unwrap_or(&self.system_theme)
}
/// Returns the current background [`Color`] of the [`State`].
@ -183,6 +181,15 @@ where
WindowEvent::ModifiersChanged(new_modifiers) => {
self.modifiers = new_modifiers.state();
}
WindowEvent::ThemeChanged(theme) => {
self.system_theme = <P::Theme as theme::Base>::default(
conversion::theme_mode(*theme),
);
if self.theme.is_none() {
window.request_redraw();
}
}
_ => {}
}
}
@ -225,9 +232,7 @@ where
}
// Update theme and appearance
self.theme = program.theme(window_id).unwrap_or_else(|| {
<P::Theme as theme::Base>::default(self.theme_mode)
});
self.style = program.style(&self.theme);
self.theme = program.theme(window_id);
self.style = program.style(self.theme());
}
}