mirror of
https://github.com/emilk/egui.git
synced 2026-07-19 13:08:54 +00:00
Sync window theme with egui theme
This commit is contained in:
@@ -243,6 +243,12 @@ pub struct ViewportState {
|
||||
// ----------------------
|
||||
// Cross-frame statistics:
|
||||
pub num_multipass_in_row: usize,
|
||||
|
||||
/// The last theme we sent to the native window via [`ViewportCommand::SetTheme`],
|
||||
/// used to avoid sending redundant commands.
|
||||
///
|
||||
/// See [`crate::Options::sync_window_theme`].
|
||||
pub(crate) last_sent_window_theme: Option<crate::SystemTheme>,
|
||||
}
|
||||
|
||||
/// What called [`Context::request_repaint`] or [`Context::request_discard`]?
|
||||
@@ -2385,6 +2391,8 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
self.sync_window_theme();
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
self.debug_painting();
|
||||
|
||||
@@ -2396,6 +2404,38 @@ impl Context {
|
||||
output
|
||||
}
|
||||
|
||||
/// Keep the native window theme in sync with the egui [`ThemePreference`],
|
||||
/// if [`crate::Options::sync_window_theme`] is enabled.
|
||||
///
|
||||
/// Sends a [`ViewportCommand::SetTheme`] to the current viewport whenever the
|
||||
/// derived theme changes, so the native window decorations match the egui theme.
|
||||
fn sync_window_theme(&self) {
|
||||
if !self.options(|o| o.sync_window_theme) {
|
||||
return;
|
||||
}
|
||||
|
||||
use crate::{SystemTheme, ThemePreference};
|
||||
let window_theme = match self.options(|o| o.theme_preference) {
|
||||
ThemePreference::System => SystemTheme::SystemDefault,
|
||||
ThemePreference::Dark => SystemTheme::Dark,
|
||||
ThemePreference::Light => SystemTheme::Light,
|
||||
};
|
||||
|
||||
let changed = self.write(|ctx| {
|
||||
let viewport = ctx.viewport();
|
||||
if viewport.last_sent_window_theme == Some(window_theme) {
|
||||
false
|
||||
} else {
|
||||
viewport.last_sent_window_theme = Some(window_theme);
|
||||
true
|
||||
}
|
||||
});
|
||||
|
||||
if changed {
|
||||
self.send_viewport_cmd(ViewportCommand::SetTheme(window_theme));
|
||||
}
|
||||
}
|
||||
|
||||
/// Called at the end of the pass.
|
||||
#[cfg(debug_assertions)]
|
||||
fn debug_painting(&self) {
|
||||
|
||||
@@ -216,6 +216,18 @@ pub struct Options {
|
||||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
pub(crate) system_theme: Option<Theme>,
|
||||
|
||||
/// If `true`, egui will keep the native window theme in sync with
|
||||
/// [`Self::theme_preference`] by sending a [`crate::ViewportCommand::SetTheme`]
|
||||
/// to the root viewport whenever the preference changes.
|
||||
///
|
||||
/// This makes the native window decorations (title bar, borders, …) match the
|
||||
/// theme selected inside egui.
|
||||
///
|
||||
/// Set this to `false` if you want to manage the native window theme yourself.
|
||||
///
|
||||
/// This is `true` by default.
|
||||
pub sync_window_theme: bool,
|
||||
|
||||
/// Global zoom factor of the UI.
|
||||
///
|
||||
/// This is used to calculate the `pixels_per_point`
|
||||
@@ -318,6 +330,7 @@ impl Default for Options {
|
||||
theme_preference: Default::default(),
|
||||
fallback_theme: Theme::Dark,
|
||||
system_theme: None,
|
||||
sync_window_theme: true,
|
||||
zoom_factor: 1.0,
|
||||
zoom_with_keyboard: true,
|
||||
quit_shortcuts: vec![crate::KeyboardShortcut::new(
|
||||
@@ -381,6 +394,7 @@ impl Options {
|
||||
theme_preference,
|
||||
fallback_theme: _,
|
||||
system_theme: _,
|
||||
sync_window_theme,
|
||||
zoom_factor,
|
||||
zoom_with_keyboard,
|
||||
quit_shortcuts: _, // not shown in ui
|
||||
@@ -429,6 +443,8 @@ impl Options {
|
||||
.show(ui, |ui| {
|
||||
theme_preference.radio_buttons(ui);
|
||||
|
||||
ui.checkbox(sync_window_theme, "Sync window theme with egui theme");
|
||||
|
||||
let style = std::sync::Arc::make_mut(match theme {
|
||||
Theme::Dark => dark_style,
|
||||
Theme::Light => light_style,
|
||||
|
||||
Reference in New Issue
Block a user