windows: Implement theme changed events (#16207)

张小白 created

Closes [#16198](https://github.com/zed-industries/zed/issues/16198)

AFAIK, when the system's theme mode or accent color changes, there are
typically two types of broadcast messages:

1. A `WM_SETTINGCHANGE` message, where `lParam` points to the string
"ImmersiveColorSet".
2. A `WM_DWMCOLORIZATIONCOLORCHANGED` message.

I use `WM_DWMCOLORIZATIONCOLORCHANGED` here for simplicity.


https://github.com/user-attachments/assets/422f8e4e-c698-4e7c-8d2d-01f453b9a7b3


Release Notes:

- N/A

Change summary

crates/gpui/src/platform/windows/events.rs | 13 +++++++++++++
1 file changed, 13 insertions(+)

Detailed changes

crates/gpui/src/platform/windows/events.rs 🔗

@@ -84,6 +84,7 @@ pub(crate) fn handle_msg(
         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(state_ptr),
         CURSOR_STYLE_CHANGED => handle_cursor_changed(lparam, state_ptr),
         _ => None,
     };
@@ -1118,6 +1119,18 @@ fn handle_system_command(wparam: WPARAM, state_ptr: Rc<WindowsWindowStatePtr>) -
     None
 }
 
+fn handle_system_theme_changed(state_ptr: Rc<WindowsWindowStatePtr>) -> Option<isize> {
+    let mut callback = state_ptr
+        .state
+        .borrow_mut()
+        .callbacks
+        .appearance_changed
+        .take()?;
+    callback();
+    state_ptr.state.borrow_mut().callbacks.appearance_changed = Some(callback);
+    Some(0)
+}
+
 fn parse_syskeydown_msg_keystroke(wparam: WPARAM) -> Option<Keystroke> {
     let modifiers = current_modifiers();
     if !modifiers.alt {