diff --git a/crates/eframe/src/epi.rs b/crates/eframe/src/epi.rs index b2ab199aefb..a32de0d989b 100644 --- a/crates/eframe/src/epi.rs +++ b/crates/eframe/src/epi.rs @@ -297,21 +297,6 @@ pub struct NativeOptions { #[cfg(any(feature = "glow", feature = "wgpu"))] pub renderer: Renderer, - /// Try to detect and follow the system preferred setting for dark vs light mode. - /// - /// The theme will automatically change when the dark vs light mode preference is changed. - /// - /// Does not work on Linux (see ). - /// - /// See also [`Self::default_theme`]. - pub follow_system_theme: bool, - - /// Which theme to use in case [`Self::follow_system_theme`] is `false` - /// or eframe fails to detect the system theme. - /// - /// Default: [`egui::Theme::Dark`]. - pub default_theme: egui::Theme, - /// This controls what happens when you close the main eframe window. /// /// If `true`, execution will continue after the eframe window is closed. @@ -417,8 +402,6 @@ impl Default for NativeOptions { #[cfg(any(feature = "glow", feature = "wgpu"))] renderer: Renderer::default(), - follow_system_theme: cfg!(target_os = "macos") || cfg!(target_os = "windows"), - default_theme: egui::Theme::Dark, run_and_return: true, #[cfg(any(feature = "glow", feature = "wgpu"))] @@ -449,19 +432,6 @@ impl Default for NativeOptions { /// Options when using `eframe` in a web page. #[cfg(target_arch = "wasm32")] pub struct WebOptions { - /// Try to detect and follow the system preferred setting for dark vs light mode. - /// - /// See also [`Self::default_theme`]. - /// - /// Default: `true`. - pub follow_system_theme: bool, - - /// Which theme to use in case [`Self::follow_system_theme`] is `false` - /// or system theme detection fails. - /// - /// Default: `egui::Theme::Dark`. - pub default_theme: egui::Theme, - /// Sets the number of bits in the depth buffer. /// /// `egui` doesn't need the depth buffer, so the default value is 0. @@ -492,8 +462,6 @@ pub struct WebOptions { impl Default for WebOptions { fn default() -> Self { Self { - follow_system_theme: true, - default_theme: egui::Theme::Dark, depth_buffer: 0, #[cfg(feature = "glow")] @@ -789,11 +757,6 @@ pub struct IntegrationInfo { #[cfg(target_arch = "wasm32")] pub web_info: WebInfo, - /// Does the OS use dark or light mode? - /// - /// `None` means "don't know". - pub system_theme: Option, - /// Seconds of cpu usage (in seconds) on the previous frame. /// /// This includes [`App::update`] as well as rendering (except for vsync waiting). diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index cee3d981b8c..e1e0a8a6d91 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -7,7 +7,7 @@ use winit::event_loop::EventLoopWindowTarget; use raw_window_handle::{HasDisplayHandle as _, HasWindowHandle as _}; -use egui::{DeferredViewportUiCallback, NumExt as _, Theme, ViewportBuilder, ViewportId}; +use egui::{DeferredViewportUiCallback, NumExt as _, ViewportBuilder, ViewportId}; use egui_winit::{EventResponse, WindowSettings}; use crate::epi; @@ -161,7 +161,6 @@ pub struct EpiIntegration { close: bool, can_drag_window: bool, - follow_system_theme: bool, #[cfg(feature = "persistence")] persist_window: bool, app_icon_setter: super::app_icon::AppTitleIconSetter, @@ -172,7 +171,6 @@ impl EpiIntegration { pub fn new( egui_ctx: egui::Context, window: &winit::window::Window, - system_theme: Option, app_name: &str, native_options: &crate::NativeOptions, storage: Option>, @@ -183,10 +181,7 @@ impl EpiIntegration { #[cfg(feature = "wgpu")] wgpu_render_state: Option, ) -> Self { let frame = epi::Frame { - info: epi::IntegrationInfo { - system_theme, - cpu_usage: None, - }, + info: epi::IntegrationInfo { cpu_usage: None }, storage, #[cfg(feature = "glow")] gl, @@ -220,7 +215,6 @@ impl EpiIntegration { pending_full_output: Default::default(), close: false, can_drag_window: false, - follow_system_theme: native_options.follow_system_theme, #[cfg(feature = "persistence")] persist_window: native_options.persist_window, app_icon_setter, @@ -275,11 +269,6 @@ impl EpiIntegration { state: ElementState::Pressed, .. } => self.can_drag_window = true, - 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()); - } _ => {} } @@ -422,10 +411,3 @@ pub fn load_egui_memory(_storage: Option<&dyn epi::Storage>) -> Option Theme { - match theme { - winit::window::Theme::Dark => Theme::Dark, - winit::window::Theme::Light => Theme::Light, - } -} diff --git a/crates/eframe/src/native/glow_integration.rs b/crates/eframe/src/native/glow_integration.rs index fd19f633fde..4977030df30 100644 --- a/crates/eframe/src/native/glow_integration.rs +++ b/crates/eframe/src/native/glow_integration.rs @@ -230,14 +230,11 @@ impl GlowWinitApp { } } - let system_theme = - winit_integration::system_theme(&glutin.window(ViewportId::ROOT), &self.native_options); let painter = Rc::new(RefCell::new(painter)); let integration = EpiIntegration::new( egui_ctx, &glutin.window(ViewportId::ROOT), - system_theme, &self.app_name, &self.native_options, storage, @@ -283,9 +280,6 @@ impl GlowWinitApp { } } - let theme = system_theme.unwrap_or(self.native_options.default_theme); - integration.egui_ctx.set_visuals(theme.egui_visuals()); - if self .native_options .viewport @@ -1138,6 +1132,7 @@ impl GlutinWindowContext { viewport_id, event_loop, Some(window.scale_factor() as f32), + window.theme(), self.max_texture_side, ) }); diff --git a/crates/eframe/src/native/wgpu_integration.rs b/crates/eframe/src/native/wgpu_integration.rs index fc3f6e9e134..f0633af6b54 100644 --- a/crates/eframe/src/native/wgpu_integration.rs +++ b/crates/eframe/src/native/wgpu_integration.rs @@ -206,11 +206,9 @@ impl WgpuWinitApp { let wgpu_render_state = painter.render_state(); - let system_theme = winit_integration::system_theme(&window, &self.native_options); let integration = EpiIntegration::new( egui_ctx.clone(), &window, - system_theme, &self.app_name, &self.native_options, storage, @@ -246,6 +244,7 @@ impl WgpuWinitApp { ViewportId::ROOT, event_loop, Some(window.scale_factor() as f32), + window.theme(), painter.max_texture_side(), ); @@ -254,8 +253,6 @@ impl WgpuWinitApp { let event_loop_proxy = self.repaint_proxy.lock().clone(); integration.init_accesskit(&mut egui_winit, &window, event_loop_proxy); } - let theme = system_theme.unwrap_or(self.native_options.default_theme); - egui_ctx.set_visuals(theme.egui_visuals()); let app_creator = std::mem::take(&mut self.app_creator) .expect("Single-use AppCreator has unexpectedly already been taken"); @@ -895,6 +892,7 @@ impl Viewport { viewport_id, event_loop, Some(window.scale_factor() as f32), + window.theme(), painter.max_texture_side(), )); diff --git a/crates/eframe/src/native/winit_integration.rs b/crates/eframe/src/native/winit_integration.rs index a4d178bce35..3399467a428 100644 --- a/crates/eframe/src/native/winit_integration.rs +++ b/crates/eframe/src/native/winit_integration.rs @@ -103,16 +103,6 @@ pub enum EventResult { Exit, } -pub fn system_theme(window: &Window, options: &crate::NativeOptions) -> Option { - if options.follow_system_theme { - window - .theme() - .map(super::epi_integration::theme_from_winit_theme) - } else { - None - } -} - /// Short and fast description of an event. /// Useful for logging and profiling. pub fn short_event_description(event: &winit::event::Event) -> &'static str { diff --git a/crates/eframe/src/web/app_runner.rs b/crates/eframe/src/web/app_runner.rs index 1a0c3f44c53..216fa16ecce 100644 --- a/crates/eframe/src/web/app_runner.rs +++ b/crates/eframe/src/web/app_runner.rs @@ -38,18 +38,11 @@ impl AppRunner { ) -> Result { let painter = super::ActiveWebPainter::new(canvas, &web_options).await?; - let system_theme = if web_options.follow_system_theme { - super::system_theme() - } else { - None - }; - let info = epi::IntegrationInfo { web_info: epi::WebInfo { user_agent: super::user_agent().unwrap_or_default(), location: super::web_location(), }, - system_theme, cpu_usage: None, }; let storage = LocalStorage::default(); @@ -68,9 +61,6 @@ impl AppRunner { o.zoom_factor = 1.0; }); - let theme = system_theme.unwrap_or(web_options.default_theme); - egui_ctx.set_visuals(theme.egui_visuals()); - let cc = epi::CreationContext { egui_ctx: egui_ctx.clone(), integration_info: info.clone(), @@ -132,6 +122,7 @@ impl AppRunner { .entry(egui::ViewportId::ROOT) .or_default() .native_pixels_per_point = Some(super::native_pixels_per_point()); + runner.input.raw.system_theme = super::system_theme(); Ok(runner) } diff --git a/crates/eframe/src/web/events.rs b/crates/eframe/src/web/events.rs index 1b30a74ef15..987b0cde7a3 100644 --- a/crates/eframe/src/web/events.rs +++ b/crates/eframe/src/web/events.rs @@ -94,6 +94,7 @@ pub(crate) fn install_event_handlers(runner_ref: &WebRunner) -> Result<(), JsVal install_wheel(runner_ref, &canvas)?; install_drag_and_drop(runner_ref, &canvas)?; install_window_events(runner_ref, &window)?; + install_color_scheme_change_event(runner_ref, &window)?; Ok(()) } @@ -353,17 +354,17 @@ fn install_window_events(runner_ref: &WebRunner, window: &EventTarget) -> Result Ok(()) } -pub(crate) fn install_color_scheme_change_event(runner_ref: &WebRunner) -> Result<(), JsValue> { - let window = web_sys::window().unwrap(); - +fn install_color_scheme_change_event( + runner_ref: &WebRunner, + window: &web_sys::Window, +) -> Result<(), JsValue> { if let Some(media_query_list) = prefers_color_scheme_dark(&window)? { runner_ref.add_event_listener::( &media_query_list, "change", |event, runner| { let theme = theme_from_dark_mode(event.matches()); - runner.frame.info.system_theme = Some(theme); - runner.egui_ctx().set_visuals(theme.egui_visuals()); + runner.input.raw.system_theme = Some(theme); runner.needs_repaint.repaint_asap(); }, )?; diff --git a/crates/eframe/src/web/web_runner.rs b/crates/eframe/src/web/web_runner.rs index 12034089305..0e10a10826e 100644 --- a/crates/eframe/src/web/web_runner.rs +++ b/crates/eframe/src/web/web_runner.rs @@ -63,8 +63,6 @@ impl WebRunner { ) -> Result<(), JsValue> { self.destroy(); - let follow_system_theme = web_options.follow_system_theme; - let text_agent = TextAgent::attach(self)?; let runner = AppRunner::new(canvas, web_options, app_creator, text_agent).await?; @@ -83,10 +81,6 @@ impl WebRunner { { events::install_event_handlers(self)?; - if follow_system_theme { - events::install_color_scheme_change_event(self)?; - } - // The resize observer handles calling `request_animation_frame` to start the render loop. events::install_resize_observer(self)?; } diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 4854cd2fd68..1af52197451 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -14,7 +14,7 @@ pub use accesskit_winit; pub use egui; #[cfg(feature = "accesskit")] use egui::accesskit; -use egui::{Pos2, Rect, Vec2, ViewportBuilder, ViewportCommand, ViewportId, ViewportInfo}; +use egui::{Pos2, Rect, Theme, Vec2, ViewportBuilder, ViewportCommand, ViewportId, ViewportInfo}; pub use winit; pub mod clipboard; @@ -111,6 +111,7 @@ impl State { viewport_id: ViewportId, display_target: &dyn HasDisplayHandle, native_pixels_per_point: Option, + theme: Option, max_texture_side: Option, ) -> Self { crate::profile_function!(); @@ -150,6 +151,7 @@ impl State { .entry(ViewportId::ROOT) .or_default() .native_pixels_per_point = native_pixels_per_point; + slf.egui_input.system_theme = theme.map(to_egui_theme); if let Some(max_texture_side) = max_texture_side { slf.set_max_texture_side(max_texture_side); @@ -405,6 +407,13 @@ impl State { consumed: false, } } + WindowEvent::ThemeChanged(winit_theme) => { + self.egui_input.system_theme = Some(to_egui_theme(*winit_theme)); + EventResponse { + repaint: true, + consumed: false, + } + } WindowEvent::HoveredFile(path) => { self.egui_input.hovered_files.push(egui::HoveredFile { path: Some(path.clone()), @@ -464,7 +473,6 @@ impl State { | WindowEvent::Occluded(_) | WindowEvent::Resized(_) | WindowEvent::Moved(_) - | WindowEvent::ThemeChanged(_) | WindowEvent::TouchpadPressure { .. } | WindowEvent::CloseRequested => EventResponse { repaint: true, @@ -891,6 +899,13 @@ impl State { } } +fn to_egui_theme(theme: winit::window::Theme) -> Theme { + match theme { + winit::window::Theme::Dark => Theme::Dark, + winit::window::Theme::Light => Theme::Light, + } +} + pub fn inner_rect_in_points(window: &Window, pixels_per_point: f32) -> Option { let inner_pos_px = window.inner_position().ok()?; let inner_pos_px = egui::pos2(inner_pos_px.x as f32, inner_pos_px.y as f32); diff --git a/crates/egui_glow/examples/pure_glow.rs b/crates/egui_glow/examples/pure_glow.rs index 0066b2ea815..0f0676568d0 100644 --- a/crates/egui_glow/examples/pure_glow.rs +++ b/crates/egui_glow/examples/pure_glow.rs @@ -161,7 +161,8 @@ fn main() { let (gl_window, gl) = create_display(&event_loop); let gl = std::sync::Arc::new(gl); - let mut egui_glow = egui_glow::EguiGlow::new(&event_loop, gl.clone(), None, None, true); + let mut egui_glow = + egui_glow::EguiGlow::new(&event_loop, &gl_window.window, gl.clone(), None, None, true); let event_loop_proxy = egui::mutex::Mutex::new(event_loop.create_proxy()); egui_glow diff --git a/crates/egui_glow/src/winit.rs b/crates/egui_glow/src/winit.rs index c3bcfe386b5..48cca62d868 100644 --- a/crates/egui_glow/src/winit.rs +++ b/crates/egui_glow/src/winit.rs @@ -24,6 +24,7 @@ impl EguiGlow { /// For automatic shader version detection set `shader_version` to `None`. pub fn new( event_loop: &winit::event_loop::EventLoopWindowTarget, + window: &winit::window::Window, gl: std::sync::Arc, shader_version: Option, native_pixels_per_point: Option, @@ -42,6 +43,7 @@ impl EguiGlow { ViewportId::ROOT, event_loop, native_pixels_per_point, + window.theme(), Some(painter.max_texture_side()), );