1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-30 05:10:03 -04:00

eframe: Automatically change theme when system dark/light mode changes (#2750)

* React to ThemeChanged event from winit

* React to theme change using media query change event in WASM

* Share conversion from bool -> Theme

* Suppress too_many_arguments warning

* Document limitations of automatically following the dark vs light mode preference

* Simplify expression

* Conditionally compile code to prevent unused item warnings

* Remove needless borrow

* Remove another needless borrow

* Make associated functions to standalone

* Request repaint after theme has changed

* Only install event listener when `follow_system_theme` is enabled

* Remove dark-light feature gate

* Detect system theme using winit

* Update documentation

* Fix typos

* fix warning about unused argument

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
Ruben
2023-03-29 16:39:30 +02:00
committed by GitHub
parent 870264b005
commit 977749b0e0
7 changed files with 87 additions and 10 deletions

View File

@@ -310,14 +310,17 @@ pub struct EpiIntegration {
close: bool,
can_drag_window: bool,
window_state: WindowState,
follow_system_theme: bool,
}
impl EpiIntegration {
#[allow(clippy::too_many_arguments)]
pub fn new<E>(
event_loop: &EventLoopWindowTarget<E>,
max_texture_side: usize,
window: &winit::window::Window,
system_theme: Option<Theme>,
follow_system_theme: bool,
storage: Option<Box<dyn epi::Storage>>,
#[cfg(feature = "glow")] gl: Option<std::sync::Arc<glow::Context>>,
#[cfg(feature = "wgpu")] wgpu_render_state: Option<egui_wgpu::RenderState>,
@@ -366,6 +369,7 @@ impl EpiIntegration {
close: false,
can_drag_window: false,
window_state,
follow_system_theme,
}
}
@@ -429,6 +433,11 @@ impl EpiIntegration {
WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
self.frame.info.native_pixels_per_point = Some(*scale_factor as _);
}
WindowEvent::ThemeChanged(winit_theme) if self.follow_system_theme => {
let theme = theme_from_winit_theme(*winit_theme);
self.frame.info.system_theme = Some(theme);
self.egui_ctx.set_visuals(theme.egui_visuals());
}
_ => {}
}
@@ -569,3 +578,10 @@ pub fn load_egui_memory(_storage: Option<&dyn epi::Storage>) -> Option<egui::Mem
#[cfg(not(feature = "persistence"))]
None
}
pub(crate) fn theme_from_winit_theme(theme: winit::window::Theme) -> Theme {
match theme {
winit::window::Theme::Dark => Theme::Dark,
winit::window::Theme::Light => Theme::Light,
}
}

View File

@@ -675,12 +675,13 @@ mod glow_integration {
egui_glow::Painter::new(gl.clone(), "", self.native_options.shader_version)
.unwrap_or_else(|error| panic!("some OpenGL error occurred {}\n", error));
let system_theme = self.native_options.system_theme();
let system_theme = system_theme(gl_window.window(), &self.native_options);
let mut integration = epi_integration::EpiIntegration::new(
event_loop,
painter.max_texture_side(),
gl_window.window(),
system_theme,
self.native_options.follow_system_theme,
storage,
Some(gl.clone()),
#[cfg(feature = "wgpu")]
@@ -1129,12 +1130,13 @@ mod wgpu_integration {
let wgpu_render_state = painter.render_state();
let system_theme = self.native_options.system_theme();
let system_theme = system_theme(&window, &self.native_options);
let mut integration = epi_integration::EpiIntegration::new(
event_loop,
painter.max_texture_side().unwrap_or(2048),
&window,
system_theme,
self.native_options.follow_system_theme,
storage,
#[cfg(feature = "glow")]
None,
@@ -1438,3 +1440,22 @@ mod wgpu_integration {
#[cfg(feature = "wgpu")]
pub use wgpu_integration::run_wgpu;
#[cfg(any(target_os = "windows", target_os = "macos"))]
fn system_theme(window: &winit::window::Window, options: &NativeOptions) -> Option<crate::Theme> {
if options.follow_system_theme {
window
.theme()
.map(super::epi_integration::theme_from_winit_theme)
} else {
None
}
}
// Winit only reads the system theme on macOS and Windows.
// On Linux we have to fall back on dark-light (if enabled).
// See: https://github.com/rust-windowing/winit/issues/1549
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
fn system_theme(_window: &winit::window::Window, options: &NativeOptions) -> Option<crate::Theme> {
options.system_theme()
}