diff --git a/crates/eframe/src/web/events.rs b/crates/eframe/src/web/events.rs index 2bffdb78..168d6123 100644 --- a/crates/eframe/src/web/events.rs +++ b/crates/eframe/src/web/events.rs @@ -3,8 +3,8 @@ use crate::web::string_from_js_value; use super::{ AppRunner, Closure, DEBUG_RESIZE, JsCast as _, JsValue, WebRunner, button_from_mouse_event, location_hash, modifiers_from_kb_event, modifiers_from_mouse_event, modifiers_from_wheel_event, - native_pixels_per_point, pos_from_mouse_event, prefers_color_scheme_dark, primary_touch_pos, - push_touches, text_from_keyboard_event, theme_from_dark_mode, translate_key, + native_pixels_per_point, pos_from_mouse_event, prefers_color_scheme, primary_touch_pos, + push_touches, text_from_keyboard_event, translate_key, }; use web_sys::{Document, EventTarget, ShadowRoot}; @@ -469,16 +469,19 @@ 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.input.raw.system_theme = Some(theme); - runner.needs_repaint.repaint_asap(); - }, - )?; + for theme in [egui::Theme::Dark, egui::Theme::Light] { + if let Some(media_query_list) = prefers_color_scheme(window, theme)? { + runner_ref.add_event_listener::( + &media_query_list, + "change", + |_event, runner| { + if let Some(theme) = super::system_theme() { + runner.input.raw.system_theme = Some(theme); + runner.needs_repaint.repaint_asap(); + } + }, + )?; + } } Ok(()) diff --git a/crates/eframe/src/web/mod.rs b/crates/eframe/src/web/mod.rs index 2bdd3af6..fdc9d212 100644 --- a/crates/eframe/src/web/mod.rs +++ b/crates/eframe/src/web/mod.rs @@ -40,6 +40,7 @@ pub(crate) type ActiveWebPainter = web_painter_wgpu::WebPainterWgpu; pub use backend::*; +use egui::Theme; use wasm_bindgen::prelude::*; use web_sys::{Document, MediaQueryList, Node}; @@ -113,24 +114,31 @@ pub fn native_pixels_per_point() -> f32 { /// /// `None` means unknown. pub fn system_theme() -> Option { - let dark_mode = prefers_color_scheme_dark(&web_sys::window()?) - .ok()?? - .matches(); - Some(theme_from_dark_mode(dark_mode)) -} - -fn prefers_color_scheme_dark(window: &web_sys::Window) -> Result, JsValue> { - window.match_media("(prefers-color-scheme: dark)") -} - -fn theme_from_dark_mode(dark_mode: bool) -> egui::Theme { - if dark_mode { - egui::Theme::Dark + let window = web_sys::window()?; + if does_prefer_color_scheme(&window, Theme::Dark) == Some(true) { + Some(Theme::Dark) + } else if does_prefer_color_scheme(&window, Theme::Light) == Some(true) { + Some(Theme::Light) } else { - egui::Theme::Light + None } } +fn does_prefer_color_scheme(window: &web_sys::Window, theme: Theme) -> Option { + Some(prefers_color_scheme(window, theme).ok()??.matches()) +} + +fn prefers_color_scheme( + window: &web_sys::Window, + theme: Theme, +) -> Result, JsValue> { + let theme = match theme { + Theme::Dark => "dark", + Theme::Light => "light", + }; + window.match_media(format!("(prefers-color-scheme: {theme})").as_str()) +} + /// Returns the canvas in client coordinates. fn canvas_content_rect(canvas: &web_sys::HtmlCanvasElement) -> egui::Rect { let bounding_rect = canvas.get_bounding_client_rect();