Add linux-theme-detection feature through mundy
This commit is contained in:
parent
ab7eb88951
commit
e92c87061d
8 changed files with 566 additions and 50 deletions
|
|
@ -326,7 +326,7 @@ pub fn window_event(
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a [`window::Level`] to a [`winit`] window level.
|
||||
/// Converts a [`window::Level`] into a [`winit`] window level.
|
||||
///
|
||||
/// [`winit`]: https://github.com/rust-windowing/winit
|
||||
pub fn window_level(level: window::Level) -> winit::window::WindowLevel {
|
||||
|
|
@ -339,7 +339,7 @@ pub fn window_level(level: window::Level) -> winit::window::WindowLevel {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a [`window::Position`] to a [`winit`] logical position for a given monitor.
|
||||
/// Converts a [`window::Position`] into a [`winit`] logical position for a given monitor.
|
||||
///
|
||||
/// [`winit`]: https://github.com/rust-windowing/winit
|
||||
pub fn position(
|
||||
|
|
@ -411,7 +411,7 @@ pub fn position(
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a [`window::Mode`] to a [`winit`] fullscreen mode.
|
||||
/// Converts a [`window::Mode`] into a [`winit`] fullscreen mode.
|
||||
///
|
||||
/// [`winit`]: https://github.com/rust-windowing/winit
|
||||
pub fn fullscreen(
|
||||
|
|
@ -426,7 +426,7 @@ pub fn fullscreen(
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a [`window::Mode`] to a visibility flag.
|
||||
/// Converts a [`window::Mode`] into a visibility flag.
|
||||
pub fn visible(mode: window::Mode) -> bool {
|
||||
match mode {
|
||||
window::Mode::Windowed | window::Mode::Fullscreen => true,
|
||||
|
|
@ -434,7 +434,7 @@ pub fn visible(mode: window::Mode) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a [`winit`] fullscreen mode to a [`window::Mode`].
|
||||
/// Converts a [`winit`] fullscreen mode into a [`window::Mode`].
|
||||
///
|
||||
/// [`winit`]: https://github.com/rust-windowing/winit
|
||||
pub fn mode(mode: Option<winit::window::Fullscreen>) -> window::Mode {
|
||||
|
|
@ -444,7 +444,7 @@ pub fn mode(mode: Option<winit::window::Fullscreen>) -> window::Mode {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a [`winit`] window theme to a [`theme::Mode`].
|
||||
/// Converts a [`winit`] window theme into a [`theme::Mode`].
|
||||
///
|
||||
/// [`winit`]: https://github.com/rust-windowing/winit
|
||||
pub fn theme_mode(theme: winit::window::Theme) -> theme::Mode {
|
||||
|
|
@ -454,7 +454,18 @@ pub fn theme_mode(theme: winit::window::Theme) -> theme::Mode {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a [`mouse::Interaction`] to a [`winit`] cursor icon.
|
||||
/// Converts a [`theme::Mode`] into a window theme.
|
||||
///
|
||||
/// [`winit`]: https://github.com/rust-windowing/winit
|
||||
pub fn window_theme(mode: theme::Mode) -> Option<winit::window::Theme> {
|
||||
match mode {
|
||||
theme::Mode::None => None,
|
||||
theme::Mode::Light => Some(winit::window::Theme::Light),
|
||||
theme::Mode::Dark => Some(winit::window::Theme::Dark),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a [`mouse::Interaction`] into a [`winit`] cursor icon.
|
||||
///
|
||||
/// [`winit`]: https://github.com/rust-windowing/winit
|
||||
pub fn mouse_interaction(
|
||||
|
|
@ -525,7 +536,7 @@ pub fn modifiers(
|
|||
result
|
||||
}
|
||||
|
||||
/// Converts a physical cursor position to a logical `Point`.
|
||||
/// Converts a physical cursor position into a logical `Point`.
|
||||
pub fn cursor_position(
|
||||
position: winit::dpi::PhysicalPosition<f64>,
|
||||
scale_factor: f32,
|
||||
|
|
@ -1196,7 +1207,7 @@ pub fn icon(icon: window::Icon) -> Option<winit::window::Icon> {
|
|||
winit::window::Icon::from_rgba(pixels, size.width, size.height).ok()
|
||||
}
|
||||
|
||||
/// Convertions some [`input_method::Purpose`] to its `winit` counterpart.
|
||||
/// Convertions some [`input_method::Purpose`] into its `winit` counterpart.
|
||||
pub fn ime_purpose(
|
||||
purpose: input_method::Purpose,
|
||||
) -> winit::window::ImePurpose {
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ where
|
|||
|
||||
let (_id, open) = runtime::window::open(window_settings);
|
||||
|
||||
open.then(move |_| task.take().unwrap_or(Task::none()))
|
||||
open.then(move |_| task.take().unwrap_or_else(Task::none))
|
||||
} else {
|
||||
task
|
||||
};
|
||||
|
|
@ -517,6 +517,33 @@ async fn run_instance<P>(
|
|||
let mut user_interfaces = ManuallyDrop::new(FxHashMap::default());
|
||||
let mut clipboard = Clipboard::unconnected();
|
||||
|
||||
#[cfg(all(feature = "linux-theme-detection", target_os = "linux"))]
|
||||
let system_theme = {
|
||||
let to_mode = |color_scheme| match color_scheme {
|
||||
mundy::ColorScheme::NoPreference => theme::Mode::None,
|
||||
mundy::ColorScheme::Light => theme::Mode::Light,
|
||||
mundy::ColorScheme::Dark => theme::Mode::Dark,
|
||||
};
|
||||
|
||||
runtime.run(
|
||||
mundy::Preferences::stream(mundy::Interest::ColorScheme)
|
||||
.map(move |preferences| {
|
||||
Action::ChangeTheme(to_mode(preferences.color_scheme))
|
||||
})
|
||||
.boxed(),
|
||||
);
|
||||
|
||||
mundy::Preferences::once_blocking(
|
||||
mundy::Interest::ColorScheme,
|
||||
core::time::Duration::from_millis(200),
|
||||
)
|
||||
.map(|preferences| to_mode(preferences.color_scheme))
|
||||
.unwrap_or_default()
|
||||
};
|
||||
|
||||
#[cfg(not(all(feature = "linux-theme-detection", target_os = "linux")))]
|
||||
let system_theme = theme::Mode::None;
|
||||
|
||||
loop {
|
||||
// Empty the queue if possible
|
||||
let event = if let Ok(event) = event_receiver.try_next() {
|
||||
|
|
@ -604,6 +631,7 @@ async fn run_instance<P>(
|
|||
.as_mut()
|
||||
.expect("Compositor must be initialized"),
|
||||
exit_on_close_request,
|
||||
system_theme,
|
||||
);
|
||||
|
||||
debug::theme_changed(|| {
|
||||
|
|
@ -891,7 +919,11 @@ async fn run_instance<P>(
|
|||
&mut is_window_opening,
|
||||
);
|
||||
} else {
|
||||
window.state.update(&window.raw, &window_event);
|
||||
window.state.update(
|
||||
&program,
|
||||
&window.raw,
|
||||
&window_event,
|
||||
);
|
||||
|
||||
if let Some(event) = conversion::window_event(
|
||||
window_event,
|
||||
|
|
@ -1465,6 +1497,27 @@ fn run_action<'a, P, C>(
|
|||
let _ = channel.send(Ok(()));
|
||||
}
|
||||
}
|
||||
Action::ChangeTheme(mode) => {
|
||||
let Some(theme) = conversion::window_theme(mode) else {
|
||||
return;
|
||||
};
|
||||
|
||||
for (id, window) in window_manager.iter_mut() {
|
||||
window.raw.set_theme(Some(theme));
|
||||
window.state.update(
|
||||
program,
|
||||
&window.raw,
|
||||
&winit::event::WindowEvent::ThemeChanged(theme),
|
||||
);
|
||||
|
||||
events.push((
|
||||
id,
|
||||
core::Event::Window(core::window::Event::ThemeModeChanged(
|
||||
mode,
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
Action::Reload => {
|
||||
for (id, window) in window_manager.iter_mut() {
|
||||
let Some(ui) = interfaces.remove(&id) else {
|
||||
|
|
|
|||
|
|
@ -55,8 +55,9 @@ where
|
|||
program: &program::Instance<P>,
|
||||
compositor: &mut C,
|
||||
exit_on_close_request: bool,
|
||||
system_theme: theme::Mode,
|
||||
) -> &mut Window<P, C> {
|
||||
let state = State::new(program, id, &window);
|
||||
let state = State::new(program, id, &window, system_theme);
|
||||
let viewport_version = state.viewport_version();
|
||||
let physical_size = state.physical_size();
|
||||
let surface = compositor.create_surface(
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ where
|
|||
cursor_position: Option<winit::dpi::PhysicalPosition<f64>>,
|
||||
modifiers: winit::keyboard::ModifiersState,
|
||||
theme: Option<P::Theme>,
|
||||
system_theme: P::Theme,
|
||||
default_theme: P::Theme,
|
||||
style: theme::Style,
|
||||
}
|
||||
|
||||
|
|
@ -50,16 +50,18 @@ where
|
|||
program: &program::Instance<P>,
|
||||
window_id: window::Id,
|
||||
window: &Window,
|
||||
system_theme: theme::Mode,
|
||||
) -> Self {
|
||||
let title = program.title(window_id);
|
||||
let scale_factor = program.scale_factor(window_id);
|
||||
let theme_mode = window
|
||||
.theme()
|
||||
.map(conversion::theme_mode)
|
||||
.unwrap_or_default();
|
||||
.unwrap_or(system_theme);
|
||||
|
||||
let title = program.title(window_id);
|
||||
let scale_factor = program.scale_factor(window_id);
|
||||
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 default_theme = <P::Theme as theme::Base>::default(theme_mode);
|
||||
let style = program.style(theme.as_ref().unwrap_or(&default_theme));
|
||||
|
||||
let viewport = {
|
||||
let physical_size = window.inner_size();
|
||||
|
|
@ -78,7 +80,7 @@ where
|
|||
cursor_position: None,
|
||||
modifiers: winit::keyboard::ModifiersState::default(),
|
||||
theme,
|
||||
system_theme,
|
||||
default_theme,
|
||||
style,
|
||||
}
|
||||
}
|
||||
|
|
@ -130,7 +132,7 @@ where
|
|||
|
||||
/// Returns the current theme of the [`State`].
|
||||
pub fn theme(&self) -> &P::Theme {
|
||||
self.theme.as_ref().unwrap_or(&self.system_theme)
|
||||
self.theme.as_ref().unwrap_or(&self.default_theme)
|
||||
}
|
||||
|
||||
/// Returns the current background [`Color`] of the [`State`].
|
||||
|
|
@ -144,7 +146,12 @@ where
|
|||
}
|
||||
|
||||
/// Processes the provided window event and updates the [`State`] accordingly.
|
||||
pub fn update(&mut self, window: &Window, event: &WindowEvent) {
|
||||
pub fn update(
|
||||
&mut self,
|
||||
program: &program::Instance<P>,
|
||||
window: &Window,
|
||||
event: &WindowEvent,
|
||||
) {
|
||||
match event {
|
||||
WindowEvent::Resized(new_size) => {
|
||||
let size = Size::new(new_size.width, new_size.height);
|
||||
|
|
@ -182,9 +189,10 @@ where
|
|||
self.modifiers = new_modifiers.state();
|
||||
}
|
||||
WindowEvent::ThemeChanged(theme) => {
|
||||
self.system_theme = <P::Theme as theme::Base>::default(
|
||||
self.default_theme = <P::Theme as theme::Base>::default(
|
||||
conversion::theme_mode(*theme),
|
||||
);
|
||||
self.style = program.style(self.theme());
|
||||
|
||||
if self.theme.is_none() {
|
||||
window.request_redraw();
|
||||
|
|
@ -198,7 +206,7 @@ where
|
|||
/// window.
|
||||
///
|
||||
/// Normally, a [`Program`] should be synchronized with its [`State`]
|
||||
/// and window after calling [`State::update`].
|
||||
/// and window after calling [`Program::update`].
|
||||
pub fn synchronize(
|
||||
&mut self,
|
||||
program: &program::Instance<P>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue