Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Follow the system theme in egui #4860

Merged
merged 10 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 0 additions & 62 deletions crates/eframe/src/epi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://github.com/rust-windowing/winit/issues/1549>).
///
/// 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: [`Theme::Dark`].
pub default_theme: Theme,

/// This controls what happens when you close the main eframe window.
///
/// If `true`, execution will continue after the eframe window is closed.
Expand Down Expand Up @@ -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: Theme::Dark,
run_and_return: true,

#[cfg(any(feature = "glow", feature = "wgpu"))]
Expand Down Expand Up @@ -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: `Theme::Dark`.
pub default_theme: Theme,

/// Sets the number of bits in the depth buffer.
///
/// `egui` doesn't need the depth buffer, so the default value is 0.
Expand Down Expand Up @@ -492,8 +462,6 @@ pub struct WebOptions {
impl Default for WebOptions {
fn default() -> Self {
Self {
follow_system_theme: true,
default_theme: Theme::Dark,
depth_buffer: 0,

#[cfg(feature = "glow")]
Expand All @@ -509,31 +477,6 @@ impl Default for WebOptions {

// ----------------------------------------------------------------------------

/// Dark or Light theme.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum Theme {
/// Dark mode: light text on a dark background.
Dark,

/// Light mode: dark text on a light background.
Light,
}

impl Theme {
/// Get the egui visuals corresponding to this theme.
///
/// Use with [`egui::Context::set_visuals`].
pub fn egui_visuals(self) -> egui::Visuals {
match self {
Self::Dark => egui::Visuals::dark(),
Self::Light => egui::Visuals::light(),
}
}
}

// ----------------------------------------------------------------------------

/// WebGL Context options
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
Expand Down Expand Up @@ -814,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<Theme>,

/// Seconds of cpu usage (in seconds) on the previous frame.
///
/// This includes [`App::update`] as well as rendering (except for vsync waiting).
Expand Down
22 changes: 2 additions & 20 deletions crates/eframe/src/native/epi_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use raw_window_handle::{HasDisplayHandle as _, HasWindowHandle as _};
use egui::{DeferredViewportUiCallback, NumExt as _, ViewportBuilder, ViewportId};
use egui_winit::{EventResponse, WindowSettings};

use crate::{epi, Theme};
use crate::epi;

pub fn viewport_builder(
egui_zoom_factor: f32,
Expand Down Expand Up @@ -158,7 +158,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,
Expand All @@ -169,7 +168,6 @@ impl EpiIntegration {
pub fn new(
egui_ctx: egui::Context,
window: &winit::window::Window,
system_theme: Option<Theme>,
app_name: &str,
native_options: &crate::NativeOptions,
storage: Option<Box<dyn epi::Storage>>,
Expand All @@ -180,10 +178,7 @@ impl EpiIntegration {
#[cfg(feature = "wgpu")] wgpu_render_state: Option<egui_wgpu::RenderState>,
) -> Self {
let frame = epi::Frame {
info: epi::IntegrationInfo {
system_theme,
cpu_usage: None,
},
info: epi::IntegrationInfo { cpu_usage: None },
storage,
#[cfg(feature = "glow")]
gl,
Expand Down Expand Up @@ -217,7 +212,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,
Expand Down Expand Up @@ -251,11 +245,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());
}
_ => {}
}

Expand Down Expand Up @@ -398,10 +387,3 @@ 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,
}
}
7 changes: 1 addition & 6 deletions crates/eframe/src/native/glow_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,14 +228,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,
Expand Down Expand Up @@ -281,9 +278,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
Expand Down Expand Up @@ -1120,6 +1114,7 @@ impl GlutinWindowContext {
viewport_id,
event_loop,
Some(window.scale_factor() as f32),
window.theme(),
self.max_texture_side,
)
});
Expand Down
6 changes: 2 additions & 4 deletions crates/eframe/src/native/wgpu_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,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,
Expand Down Expand Up @@ -243,6 +241,7 @@ impl WgpuWinitApp {
ViewportId::ROOT,
event_loop,
Some(window.scale_factor() as f32),
window.theme(),
painter.max_texture_side(),
);

Expand All @@ -251,8 +250,6 @@ impl WgpuWinitApp {
let event_loop_proxy = self.repaint_proxy.lock().clone();
egui_winit.init_accesskit(&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");
Expand Down Expand Up @@ -872,6 +869,7 @@ impl Viewport {
viewport_id,
event_loop,
Some(window.scale_factor() as f32),
window.theme(),
painter.max_texture_side(),
));

Expand Down
10 changes: 0 additions & 10 deletions crates/eframe/src/native/winit_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,6 @@ pub enum EventResult {
Exit,
}

pub fn system_theme(window: &Window, options: &crate::NativeOptions) -> Option<crate::Theme> {
if options.follow_system_theme {
window
.theme()
.map(super::epi_integration::theme_from_winit_theme)
} else {
None
}
}

#[cfg(feature = "accesskit")]
pub(crate) fn on_accesskit_window_event(
egui_winit: &mut egui_winit::State,
Expand Down
11 changes: 1 addition & 10 deletions crates/eframe/src/web/app_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,11 @@ impl AppRunner {
) -> Result<Self, String> {
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();
Expand All @@ -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(),
Expand Down Expand Up @@ -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)
}
Expand Down
13 changes: 7 additions & 6 deletions crates/eframe/src/web/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}

Expand Down Expand Up @@ -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();

if let Some(media_query_list) = prefers_color_scheme_dark(&window)? {
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::<web_sys::MediaQueryListEvent>(
&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();
},
)?;
Expand Down
10 changes: 4 additions & 6 deletions crates/eframe/src/web/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ use web_sys::MediaQueryList;

use input::*;

use crate::Theme;

// ----------------------------------------------------------------------------

pub(crate) fn string_from_js_value(value: &JsValue) -> String {
Expand Down Expand Up @@ -103,7 +101,7 @@ pub fn native_pixels_per_point() -> f32 {
/// Ask the browser about the preferred system theme.
///
/// `None` means unknown.
pub fn system_theme() -> Option<Theme> {
pub fn system_theme() -> Option<egui::Theme> {
let dark_mode = prefers_color_scheme_dark(&web_sys::window()?)
.ok()??
.matches();
Expand All @@ -114,11 +112,11 @@ fn prefers_color_scheme_dark(window: &web_sys::Window) -> Result<Option<MediaQue
window.match_media("(prefers-color-scheme: dark)")
}

fn theme_from_dark_mode(dark_mode: bool) -> Theme {
fn theme_from_dark_mode(dark_mode: bool) -> egui::Theme {
if dark_mode {
Theme::Dark
egui::Theme::Dark
} else {
Theme::Light
egui::Theme::Light
}
}

Expand Down
6 changes: 0 additions & 6 deletions crates/eframe/src/web/web_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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?;
Expand All @@ -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)?;
}
Expand Down
Loading
Loading