From a055ebcbc73cb7f78034ab876d983ca31346ce00 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sun, 1 Nov 2026 13:30:34 -0800 Subject: [PATCH] Fix #3818: the chosen brightness holds when the system theme differs The theme's colors went into egui's style for the current system theme only. When the system's light or dark setting differed from it or changed while the app ran, egui switched to its other style, which held egui's defaults: tool tips became a white box with gray text, or with the theme's light text. Applying a brightness now sets egui's theme to match, starting from the current style so settings such as the tool tip delay carry over. --- crates/ui-egui/src/theme.rs | 60 +++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/crates/ui-egui/src/theme.rs b/crates/ui-egui/src/theme.rs index e6c06e5dd..3b1a0524d 100644 --- a/crates/ui-egui/src/theme.rs +++ b/crates/ui-egui/src/theme.rs @@ -587,6 +587,15 @@ pub fn apply(ctx: &egui::Context, b: Brightness) { pub fn apply_with(ctx: &egui::Context, b: Brightness, accent: Accent, scheme: Scheme) { let t = Tokens::for_scheme(scheme, b, accent); ctx.data_mut(|d| d.insert_temp(egui::Id::NULL, t)); + // egui keeps a style for each system theme and by default follows the system's setting. The + // chosen brightness sets egui's theme, so these colors stay in force when the system's setting + // differs or changes. A change of theme starts from the current style, which keeps settings + // such as the tool tip delay. + let theme = if t.dark { egui::Theme::Dark } else { egui::Theme::Light }; + if ctx.theme() != theme { + ctx.set_style_of(theme, ctx.global_style()); + } + ctx.set_theme(theme); let mut v = if t.dark { Visuals::dark() } else { Visuals::light() }; v.panel_fill = t.panel; v.window_fill = t.panel; @@ -669,4 +678,55 @@ mod tests { assert_eq!(Scheme::parse(Scheme::Classic.id()), Some(Scheme::Classic)); } } + + /// #3818: the brightness chosen in Preferences stays in force when the system's light or dark + /// setting differs from it or changes while the app runs. Tool tips keep the theme's panel fill + /// and text color instead of egui's own white box and gray text. + #[test] + fn the_theme_holds_whatever_the_system_theme() { + let screen = egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(400.0, 400.0)); + for b in Brightness::ALL { + for scheme in Scheme::ALL { + for (first, then) in [(egui::Theme::Dark, egui::Theme::Light), (egui::Theme::Light, egui::Theme::Dark)] { + let t = Tokens::for_scheme(scheme, b, Accent::default()); + let ctx = egui::Context::default(); + let mut time = 0.0; + let mut tip = None; + for i in 0..5 { + time += 0.5; + let system_theme = Some(if i == 0 { first } else { then }); + let events = if i == 1 { vec![egui::Event::PointerMoved(egui::pos2(30.0, 15.0))] } else { vec![] }; + let input = egui::RawInput { time: Some(time), screen_rect: Some(screen), events, system_theme, ..Default::default() }; + let mut out = ctx.run_ui(input, |ui| { + if i == 0 { + apply_with(ui.ctx(), b, Accent::default(), scheme); + ui.ctx().global_style_mut(|s| s.interaction.tooltip_delay = 0.0); + } + ui.button("Hover me").on_hover_text("Tip text"); + }); + out.textures_delta.clear(); + tip = out.shapes.iter().find_map(|c| match &c.shape { + egui::Shape::Text(s) if s.galley.text() == "Tip text" => Some(s.fallback_color), + _ => None, + }); + } + let v = ctx.global_style().visuals.clone(); + assert_eq!((v.window_fill, v.override_text_color), (t.panel, Some(t.text)), "{scheme:?} {b:?}, system {first:?} then {then:?}"); + assert_eq!(tip, Some(t.text), "{scheme:?} {b:?}, system {first:?} then {then:?}: the tool tip's text"); + } + } + } + } + + /// Changing brightness keeps the interface settings made after the theme was applied, such as + /// General › Show Tool Tips' delay. + #[test] + fn changing_brightness_keeps_other_interface_settings() { + let ctx = egui::Context::default(); + apply(&ctx, Brightness::Dark); + ctx.global_style_mut(|s| s.interaction.tooltip_delay = f32::INFINITY); + apply(&ctx, Brightness::Light); + assert_eq!(ctx.global_style().interaction.tooltip_delay, f32::INFINITY); + assert_eq!(ctx.global_style().visuals.window_fill, Tokens::for_brightness(Brightness::Light).panel); + } }