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::time::Instant;
use crate::{Point, Size}; use crate::{Point, Size};
@ -71,4 +72,7 @@ pub enum Event {
/// ///
/// - **Wayland:** Not implemented. /// - **Wayland:** Not implemented.
FilesHoveredLeft, 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::input_method;
use crate::core::keyboard; use crate::core::keyboard;
use crate::core::mouse; use crate::core::mouse;
use crate::core::theme;
use crate::core::touch; use crate::core::touch;
use crate::core::window; use crate::core::window;
use crate::core::{Event, Point, Size}; use crate::core::{Event, Point, Size};
@ -318,6 +319,9 @@ pub fn window_event(
Some(Event::Window(window::Event::Moved(Point::new(x, y)))) Some(Event::Window(window::Event::Moved(Point::new(x, y))))
} }
WindowEvent::ThemeChanged(theme) => Some(Event::Window(
window::Event::ThemeModeChanged(theme_mode(theme)),
)),
_ => None, _ => 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. /// Converts a [`mouse::Interaction`] to a [`winit`] cursor icon.
/// ///
/// [`winit`]: https://github.com/rust-windowing/winit /// [`winit`]: https://github.com/rust-windowing/winit

View file

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