windows: Prefer WM_SETTINGCHANGE when handing theme changed events (#23727)
I recently noticed that on my Windows 11 machine, Zed no longer receive the `WM_DWMCOLORIZATIONCOLORCHANGED` message when the system theme changes. This functionality was present in the past. While this change might be unexpected, it's understandable given Microsoft's history of system updates. This pull request proposes an alternative approach using the `WM_SETTINGCHANGE` message to handle theme changes. Release Notes: - N/A
This commit is contained in:
@@ -2,15 +2,18 @@ use std::rc::Rc;
|
||||
|
||||
use ::util::ResultExt;
|
||||
use anyhow::Context as _;
|
||||
use windows::Win32::{
|
||||
Foundation::*,
|
||||
Graphics::Gdi::*,
|
||||
System::SystemServices::*,
|
||||
UI::{
|
||||
Controls::*,
|
||||
HiDpi::*,
|
||||
Input::{Ime::*, KeyboardAndMouse::*},
|
||||
WindowsAndMessaging::*,
|
||||
use windows::{
|
||||
core::PCWSTR,
|
||||
Win32::{
|
||||
Foundation::*,
|
||||
Graphics::Gdi::*,
|
||||
System::SystemServices::*,
|
||||
UI::{
|
||||
Controls::*,
|
||||
HiDpi::*,
|
||||
Input::{Ime::*, KeyboardAndMouse::*},
|
||||
WindowsAndMessaging::*,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -88,8 +91,7 @@ pub(crate) fn handle_msg(
|
||||
WM_IME_STARTCOMPOSITION => handle_ime_position(handle, state_ptr),
|
||||
WM_IME_COMPOSITION => handle_ime_composition(handle, lparam, state_ptr),
|
||||
WM_SETCURSOR => handle_set_cursor(lparam, state_ptr),
|
||||
WM_SETTINGCHANGE => handle_system_settings_changed(handle, state_ptr),
|
||||
WM_DWMCOLORIZATIONCOLORCHANGED => handle_system_theme_changed(handle, state_ptr),
|
||||
WM_SETTINGCHANGE => handle_system_settings_changed(handle, lparam, state_ptr),
|
||||
WM_GPUI_CURSOR_STYLE_CHANGED => handle_cursor_changed(lparam, state_ptr),
|
||||
_ => None,
|
||||
};
|
||||
@@ -1187,6 +1189,7 @@ fn handle_set_cursor(lparam: LPARAM, state_ptr: Rc<WindowsWindowStatePtr>) -> Op
|
||||
|
||||
fn handle_system_settings_changed(
|
||||
handle: HWND,
|
||||
lparam: LPARAM,
|
||||
state_ptr: Rc<WindowsWindowStatePtr>,
|
||||
) -> Option<isize> {
|
||||
let mut lock = state_ptr.state.borrow_mut();
|
||||
@@ -1198,6 +1201,22 @@ fn handle_system_settings_changed(
|
||||
// window border offset
|
||||
lock.border_offset.update(handle).log_err();
|
||||
drop(lock);
|
||||
|
||||
// lParam is a pointer to a string that indicates the area containing the system parameter
|
||||
// that was changed.
|
||||
let parameter = PCWSTR::from_raw(lparam.0 as _);
|
||||
if unsafe { !parameter.is_null() && !parameter.is_empty() } {
|
||||
if let Some(parameter_string) = unsafe { parameter.to_string() }.log_err() {
|
||||
log::info!("System settings changed: {}", parameter_string);
|
||||
match parameter_string.as_str() {
|
||||
"ImmersiveColorSet" => {
|
||||
handle_system_theme_changed(handle, state_ptr);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Force to trigger WM_NCCALCSIZE event to ensure that we handle auto hide
|
||||
// taskbar correctly.
|
||||
notify_frame_changed(handle);
|
||||
@@ -1227,7 +1246,7 @@ fn handle_system_theme_changed(
|
||||
.take()?;
|
||||
callback();
|
||||
state_ptr.state.borrow_mut().callbacks.appearance_changed = Some(callback);
|
||||
set_dwm_window_appearance(handle);
|
||||
configure_dwm_dark_mode(handle);
|
||||
Some(0)
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,8 @@ pub(crate) fn load_cursor(style: CursorStyle) -> HCURSOR {
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn set_dwm_window_appearance(hwnd: HWND) {
|
||||
/// This function is used to configure the dark mode for the window built-in title bar.
|
||||
pub(crate) fn configure_dwm_dark_mode(hwnd: HWND) {
|
||||
let dark_mode_enabled: BOOL = match system_appearance().log_err().unwrap_or_default() {
|
||||
WindowAppearance::Dark | WindowAppearance::VibrantDark => true.into(),
|
||||
WindowAppearance::Light | WindowAppearance::VibrantLight => false.into(),
|
||||
|
||||
@@ -443,7 +443,7 @@ impl WindowsWindow {
|
||||
let state_ptr = context.inner.take().unwrap()?;
|
||||
let hwnd = creation_result?;
|
||||
register_drag_drop(state_ptr.clone())?;
|
||||
set_dwm_window_appearance(hwnd);
|
||||
configure_dwm_dark_mode(hwnd);
|
||||
state_ptr.state.borrow_mut().border_offset.update(hwnd)?;
|
||||
let placement = retrieve_window_placement(
|
||||
hwnd,
|
||||
|
||||
Reference in New Issue
Block a user