Skip to content

Commit

Permalink
fix(windows): blinking title bar on changing system settings (#983)
Browse files Browse the repository at this point in the history
* Only redraw on manual set theme

* Add change file

* Ignore update theme on settings change preferred theme is set
  • Loading branch information
Legend-Master authored Oct 1, 2024
1 parent 4dcd231 commit 2fffdc9
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 29 deletions.
5 changes: 5 additions & 0 deletions .changes/windows-theme-redraw-titlebar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tao": patch
---

Fix blinking title bar when changing system settings on Windows
24 changes: 15 additions & 9 deletions src/platform_impl/windows/dark_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,11 @@ fn refresh_immersive_color_policy_state() {

/// Attempt to set a theme on a window, if necessary.
/// Returns the theme that was picked
pub fn try_window_theme(hwnd: HWND, preferred_theme: Option<Theme>) -> Theme {
pub fn try_window_theme(
hwnd: HWND,
preferred_theme: Option<Theme>,
redraw_title_bar: bool,
) -> Theme {
if *DARK_MODE_SUPPORTED {
let is_dark_mode = match preferred_theme {
Some(theme) => theme == Theme::Dark,
Expand All @@ -131,7 +135,7 @@ pub fn try_window_theme(hwnd: HWND, preferred_theme: Option<Theme>) -> Theme {
false => Theme::Light,
};

refresh_titlebar_theme_color(hwnd, is_dark_mode);
refresh_titlebar_theme_color(hwnd, is_dark_mode, redraw_title_bar);

theme
} else {
Expand Down Expand Up @@ -161,7 +165,7 @@ pub fn allow_dark_mode_for_window(hwnd: HWND, is_dark_mode: bool) {
}
}

fn refresh_titlebar_theme_color(hwnd: HWND, is_dark_mode: bool) {
fn refresh_titlebar_theme_color(hwnd: HWND, is_dark_mode: bool, redraw_title_bar: bool) {
if let Some(ver) = *WIN10_BUILD_VERSION {
if ver < 17763 {
let mut is_dark_mode_bigbool: i32 = is_dark_mode.into();
Expand All @@ -187,12 +191,14 @@ fn refresh_titlebar_theme_color(hwnd: HWND, is_dark_mode: bool) {
&dark_mode as *const BOOL as *const c_void,
std::mem::size_of::<BOOL>() as u32,
);
if GetActiveWindow() == hwnd {
DefWindowProcW(hwnd, WM_NCACTIVATE, None, None);
DefWindowProcW(hwnd, WM_NCACTIVATE, WPARAM(true.into()), None);
} else {
DefWindowProcW(hwnd, WM_NCACTIVATE, WPARAM(true.into()), None);
DefWindowProcW(hwnd, WM_NCACTIVATE, None, None);
if redraw_title_bar {
if GetActiveWindow() == hwnd {
DefWindowProcW(hwnd, WM_NCACTIVATE, None, None);
DefWindowProcW(hwnd, WM_NCACTIVATE, WPARAM(true.into()), None);
} else {
DefWindowProcW(hwnd, WM_NCACTIVATE, WPARAM(true.into()), None);
DefWindowProcW(hwnd, WM_NCACTIVATE, None, None);
}
}
}
}
Expand Down
53 changes: 35 additions & 18 deletions src/platform_impl/windows/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ impl<T> EventLoopWindowTarget<T> {
pub fn set_theme(&self, theme: Option<Theme>) {
*self.preferred_theme.lock() = theme;
self.runner_shared.owned_windows(|window| {
let _ = unsafe { SendMessageW(window, WM_SETTINGCHANGE, WPARAM(0), LPARAM(0)) };
let _ = unsafe { SendMessageW(window, *CHANGE_THEME_MSG_ID, WPARAM(0), LPARAM(0)) };
});
}
}
Expand Down Expand Up @@ -624,6 +624,11 @@ lazy_static! {
pub static ref SET_RETAIN_STATE_ON_SIZE_MSG_ID: u32 = unsafe {
RegisterWindowMessageA(s!("Tao::SetRetainMaximized"))
};
/// Message sent by event loop when event loop's prefered theme changed.
/// WPARAM and LPARAM are unused.
pub static ref CHANGE_THEME_MSG_ID: u32 = unsafe {
RegisterWindowMessageA(s!("Tao::ChangeTheme"))
};
/// When the taskbar is created, it registers a message with the "TaskbarCreated" string and then broadcasts this message to all top-level windows
/// When the application receives this message, it should assume that any taskbar icons it added have been removed and add them again.
pub static ref S_U_TASKBAR_RESTART: u32 = unsafe {
Expand Down Expand Up @@ -2072,23 +2077,7 @@ unsafe fn public_window_callback_inner<T: 'static>(
}

win32wm::WM_SETTINGCHANGE => {
use crate::event::WindowEvent::ThemeChanged;

let preferred_theme = subclass_input.window_state.lock().preferred_theme;
let new_theme = try_window_theme(
window,
preferred_theme.or(*subclass_input.event_loop_preferred_theme.lock()),
);
let mut window_state = subclass_input.window_state.lock();

if window_state.current_theme != new_theme {
window_state.current_theme = new_theme;
mem::drop(window_state);
subclass_input.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window.0 as _)),
event: ThemeChanged(new_theme),
});
}
update_theme(subclass_input, window, true);
}

win32wm::WM_NCCALCSIZE => {
Expand Down Expand Up @@ -2197,6 +2186,9 @@ unsafe fn public_window_callback_inner<T: 'static>(
f.set(WindowFlags::MARKER_RETAIN_STATE_ON_SIZE, wparam.0 != 0)
});
result = ProcResult::Value(LRESULT(0));
} else if msg == *CHANGE_THEME_MSG_ID {
update_theme(subclass_input, window, false);
result = ProcResult::Value(LRESULT(0));
} else if msg == *S_U_TASKBAR_RESTART {
let window_state = subclass_input.window_state.lock();
let _ = set_skip_taskbar(window, window_state.skip_taskbar);
Expand All @@ -2216,6 +2208,31 @@ unsafe fn public_window_callback_inner<T: 'static>(
}
}

fn update_theme<T>(
subclass_input: &SubclassInput<T>,
window: HWND,
from_settings_change_event: bool,
) {
let mut window_state = subclass_input.window_state.lock();
let preferred_theme = window_state
.preferred_theme
.or(*subclass_input.event_loop_preferred_theme.lock());
if from_settings_change_event && preferred_theme.is_some() {
return;
}
let new_theme = try_window_theme(window, preferred_theme, !from_settings_change_event);
if window_state.current_theme != new_theme {
window_state.current_theme = new_theme;
mem::drop(window_state);
unsafe {
subclass_input.send_event(Event::WindowEvent {
window_id: RootWindowId(WindowId(window.0 as _)),
event: WindowEvent::ThemeChanged(new_theme),
})
};
}
}

fn is_show_window_contents_while_dragging_enabled() -> bool {
let mut is_enabled: BOOL = BOOL(0);
let result = unsafe {
Expand Down
8 changes: 6 additions & 2 deletions src/platform_impl/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ use crate::{
},
};

use super::keyboard::{KeyEventBuilder, KEY_EVENT_BUILDERS};
use super::{
event_loop::CHANGE_THEME_MSG_ID,
keyboard::{KeyEventBuilder, KEY_EVENT_BUILDERS},
};

/// A simple non-owning wrapper around a window.
#[derive(Clone, Copy)]
Expand Down Expand Up @@ -940,7 +943,7 @@ impl Window {
}
window_state.preferred_theme = theme;
}
unsafe { SendMessageW(self.hwnd(), WM_SETTINGCHANGE, WPARAM(0), LPARAM(0)) };
unsafe { SendMessageW(self.hwnd(), *CHANGE_THEME_MSG_ID, WPARAM(0), LPARAM(0)) };
}

#[inline]
Expand Down Expand Up @@ -1163,6 +1166,7 @@ unsafe fn init<T: 'static>(
attributes
.preferred_theme
.or(*event_loop.preferred_theme.lock()),
false,
);

let window_state = {
Expand Down

0 comments on commit 2fffdc9

Please sign in to comment.