From e083679e0d255f601427c2ae2916257a35dc5c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B0=8F=E7=99=BD?= <364772080@qq.com> Date: Tue, 28 Jan 2025 15:47:55 +0800 Subject: [PATCH] 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 --- crates/gpui/src/platform/windows/events.rs | 43 ++++++++++++++++------ crates/gpui/src/platform/windows/util.rs | 3 +- crates/gpui/src/platform/windows/window.rs | 2 +- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/crates/gpui/src/platform/windows/events.rs b/crates/gpui/src/platform/windows/events.rs index 4ac573766b..b77e53129b 100644 --- a/crates/gpui/src/platform/windows/events.rs +++ b/crates/gpui/src/platform/windows/events.rs @@ -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) -> Op fn handle_system_settings_changed( handle: HWND, + lparam: LPARAM, state_ptr: Rc, ) -> Option { 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) } diff --git a/crates/gpui/src/platform/windows/util.rs b/crates/gpui/src/platform/windows/util.rs index 0fa4451db5..57a2d50ca6 100644 --- a/crates/gpui/src/platform/windows/util.rs +++ b/crates/gpui/src/platform/windows/util.rs @@ -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(), diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index 9dec526d44..d85762680a 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -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,