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 4ac573766b3f1f00822066b48a537ff2450777e9..b77e53129b127a7eec077859cf3c8d38d4e0d2d2 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 0fa4451db5fdc48fcb7d52b13cb12a95e3bf1e8b..57a2d50ca67cca3b6d45b730de8641a1bd54e679 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 9dec526d444b85063ab9435d8ff4871aa0cd61eb..d85762680adc0d83428e982dbf0cf3d53f2ada00 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,