diff --git a/core/src/window/event.rs b/core/src/window/event.rs index 45d29179..48622b70 100644 --- a/core/src/window/event.rs +++ b/core/src/window/event.rs @@ -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), } diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs index 6f22405d..8668d6a3 100644 --- a/winit/src/conversion.rs +++ b/winit/src/conversion.rs @@ -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) -> 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 diff --git a/winit/src/window/state.rs b/winit/src/window/state.rs index 6adc2205..65f08d21 100644 --- a/winit/src/window/state.rs +++ b/winit/src/window/state.rs @@ -20,8 +20,8 @@ where viewport_version: u64, cursor_position: Option>, modifiers: winit::keyboard::ModifiersState, - theme: P::Theme, - theme_mode: theme::Mode, + theme: Option, + 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(|| ::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 = ::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 = ::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(|| { - ::default(self.theme_mode) - }); - self.style = program.style(&self.theme); + self.theme = program.theme(window_id); + self.style = program.style(self.theme()); } }