Skip to content

Commit 9cbe0a0

Browse files
committed
Use dark-light on Mac and Windows
dark-light has a nasty problem on Linux: rust-dark-light/dark-light#17 So we made dark-light opt-in in #1437 This PR makes dark-light a default dependency again, but only use it on Max and Windows. This is controlled with the new NativeOptions::follow_system_theme. If this isn't enabled, then NativeOptions::default_theme is used.
1 parent 4525cad commit 9cbe0a0

File tree

5 files changed

+84
-38
lines changed

5 files changed

+84
-38
lines changed

eframe/Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ all-features = true
2020

2121

2222
[features]
23-
default = ["default_fonts", "glow"]
23+
default = ["dark-light", "default_fonts", "glow"]
2424

2525
## Detect dark mode system preference using [`dark-light`](https://docs.rs/dark-light).
26+
##
27+
## See also [`NativeOptions::follow_system_theme`] and [`NativeOptions::default_theme`].
2628
dark-light = ["dep:dark-light"]
2729

2830
## If set, egui will use `include_bytes!` to bundle some fonts.

eframe/src/epi.rs

+63-2
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,23 @@ pub struct NativeOptions {
243243

244244
/// What rendering backend to use.
245245
pub renderer: Renderer,
246+
247+
/// If the `dark-light` feature is enabled:
248+
///
249+
/// Try to detect and follow the system preferred setting for dark vs light mode.
250+
///
251+
/// By default, this is `true` on Mac and Windows, but `false` on Linux
252+
/// due to <https://github.com/frewsxcv/rust-dark-light/issues/17>.
253+
///
254+
/// See also [`Self::default_theme`].
255+
pub follow_system_theme: bool,
256+
257+
/// Use the dark mode theme if:
258+
/// * the `dark-light` feature is disabled
259+
/// * OR [`Self::follow_system_theme`] is `false`.
260+
///
261+
/// Default: `Theme::Dark` (default to dark theme).
262+
pub default_theme: Theme,
246263
}
247264

248265
impl Default for NativeOptions {
@@ -265,6 +282,49 @@ impl Default for NativeOptions {
265282
stencil_buffer: 0,
266283
hardware_acceleration: HardwareAcceleration::Preferred,
267284
renderer: Renderer::default(),
285+
follow_system_theme: cfg!(target_os = "macos") || cfg!(target_os = "windows"),
286+
default_theme: Theme::Dark,
287+
}
288+
}
289+
}
290+
291+
impl NativeOptions {
292+
/// The theme used by the system.
293+
#[cfg(feature = "dark-light")]
294+
pub fn system_theme(&self) -> Option<Theme> {
295+
if self.follow_system_theme {
296+
crate::profile_scope!("dark_light::detect");
297+
match dark_light::detect() {
298+
dark_light::Mode::Dark => Some(Theme::Dark),
299+
dark_light::Mode::Light => Some(Theme::Light),
300+
}
301+
} else {
302+
None
303+
}
304+
}
305+
306+
/// The theme used by the system.
307+
#[cfg(not(feature = "dark-light"))]
308+
pub fn system_theme(&self) -> Option<Theme> {
309+
None
310+
}
311+
}
312+
313+
/// Dark or Light theme.
314+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
315+
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
316+
pub enum Theme {
317+
/// Dark mode: light text on a dark background.
318+
Dark,
319+
/// Light mode: dark text on a light background.
320+
Light,
321+
}
322+
323+
impl Theme {
324+
pub(crate) fn egui_visuals(self) -> egui::Visuals {
325+
match self {
326+
Self::Dark => egui::Visuals::dark(),
327+
Self::Light => egui::Visuals::light(),
268328
}
269329
}
270330
}
@@ -531,9 +591,10 @@ pub struct IntegrationInfo {
531591
/// If the app is running in a Web context, this returns information about the environment.
532592
pub web_info: Option<WebInfo>,
533593

534-
/// Does the system prefer dark mode (over light mode)?
594+
/// Does the OS use dark or light mode?
595+
///
535596
/// `None` means "don't know".
536-
pub prefer_dark_mode: Option<bool>,
597+
pub system_theme: Option<Theme>,
537598

538599
/// Seconds of cpu usage (in seconds) of UI code on the previous frame.
539600
/// `None` if this is the first frame.

eframe/src/native/epi_integration.rs

+4-29
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{epi, WindowInfo};
1+
use crate::{epi, Theme, WindowInfo};
22
use egui_winit::{native_pixels_per_point, WindowSettings};
33
use winit::event_loop::EventLoopWindowTarget;
44

@@ -47,12 +47,7 @@ pub fn window_builder(
4747
max_window_size,
4848
resizable,
4949
transparent,
50-
vsync: _, // used in `fn create_display`
51-
multisampling: _, // used in `fn create_display`
52-
depth_buffer: _, // used in `fn create_display`
53-
stencil_buffer: _, // used in `fn create_display`
54-
hardware_acceleration: _, // used in `fn create_display`
55-
renderer: _, // used in `fn run_native`
50+
..
5651
} = native_options;
5752

5853
let window_icon = icon_data.clone().and_then(load_icon);
@@ -187,6 +182,7 @@ impl EpiIntegration {
187182
event_loop: &EventLoopWindowTarget<E>,
188183
max_texture_side: usize,
189184
window: &winit::window::Window,
185+
system_theme: Option<Theme>,
190186
storage: Option<Box<dyn epi::Storage>>,
191187
#[cfg(feature = "glow")] gl: Option<std::sync::Arc<glow::Context>>,
192188
#[cfg(feature = "wgpu")] render_state: Option<egui_wgpu::RenderState>,
@@ -195,12 +191,10 @@ impl EpiIntegration {
195191

196192
*egui_ctx.memory() = load_egui_memory(storage.as_deref()).unwrap_or_default();
197193

198-
let prefer_dark_mode = prefer_dark_mode();
199-
200194
let frame = epi::Frame {
201195
info: epi::IntegrationInfo {
202196
web_info: None,
203-
prefer_dark_mode,
197+
system_theme,
204198
cpu_usage: None,
205199
native_pixels_per_point: Some(native_pixels_per_point(window)),
206200
window_info: read_window_info(window, egui_ctx.pixels_per_point()),
@@ -213,12 +207,6 @@ impl EpiIntegration {
213207
render_state,
214208
};
215209

216-
if prefer_dark_mode == Some(true) {
217-
egui_ctx.set_visuals(egui::Visuals::dark());
218-
} else {
219-
egui_ctx.set_visuals(egui::Visuals::light());
220-
}
221-
222210
let mut egui_winit = egui_winit::State::new(event_loop);
223211
egui_winit.set_max_texture_side(max_texture_side);
224212
let pixels_per_point = window.scale_factor() as f32;
@@ -376,16 +364,3 @@ pub fn load_egui_memory(_storage: Option<&dyn epi::Storage>) -> Option<egui::Mem
376364
#[cfg(not(feature = "persistence"))]
377365
None
378366
}
379-
380-
#[cfg(feature = "dark-light")]
381-
fn prefer_dark_mode() -> Option<bool> {
382-
match dark_light::detect() {
383-
dark_light::Mode::Dark => Some(true),
384-
dark_light::Mode::Light => Some(false),
385-
}
386-
}
387-
388-
#[cfg(not(feature = "dark-light"))]
389-
fn prefer_dark_mode() -> Option<bool> {
390-
None
391-
}

eframe/src/native/run.rs

+14
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,22 @@ pub fn run_glow(
6666
let mut painter = egui_glow::Painter::new(gl.clone(), None, "")
6767
.unwrap_or_else(|error| panic!("some OpenGL error occurred {}\n", error));
6868

69+
let system_theme = native_options.system_theme();
6970
let mut integration = epi_integration::EpiIntegration::new(
7071
&event_loop,
7172
painter.max_texture_side(),
7273
gl_window.window(),
74+
system_theme,
7375
storage,
7476
Some(gl.clone()),
7577
#[cfg(feature = "wgpu")]
7678
None,
7779
);
80+
integration.egui_ctx.set_visuals(
81+
system_theme
82+
.unwrap_or(native_options.default_theme)
83+
.egui_visuals(),
84+
);
7885

7986
{
8087
let event_loop_proxy = egui::mutex::Mutex::new(event_loop.create_proxy());
@@ -248,15 +255,22 @@ pub fn run_wgpu(
248255

249256
let render_state = painter.get_render_state().expect("Uninitialized");
250257

258+
let system_theme = native_options.system_theme();
251259
let mut integration = epi_integration::EpiIntegration::new(
252260
&event_loop,
253261
painter.max_texture_side().unwrap_or(2048),
254262
&window,
263+
system_theme,
255264
storage,
256265
#[cfg(feature = "glow")]
257266
None,
258267
Some(render_state.clone()),
259268
);
269+
integration.egui_ctx.set_visuals(
270+
system_theme
271+
.unwrap_or(native_options.default_theme)
272+
.egui_visuals(),
273+
);
260274

261275
{
262276
let event_loop_proxy = egui::mutex::Mutex::new(event_loop.create_proxy());

egui_demo_app/src/wrap_app.rs

-6
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,6 @@ impl WrapApp {
112112
}
113113
}
114114

115-
if cc.integration_info.prefer_dark_mode == Some(false) {
116-
cc.egui_ctx.set_visuals(egui::Visuals::light()); // use light mode if explicitly asked for
117-
} else {
118-
cc.egui_ctx.set_visuals(egui::Visuals::dark()); // use dark mode if there is no preference, or the preference is dark mode
119-
}
120-
121115
slf
122116
}
123117

0 commit comments

Comments
 (0)