gpui: Support windows dark mode title bar (#23700)

Matin Aniss and 张小白 created

This will allow Windows GPUI applications that utilise the native title
bar to support the dark mode variant when the system user has dark mode
enabled in their system settings. [Related Win32
information](https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/ui/apply-windows-themes)

| Before  | After |
| ------------- | ------------- |
|
![image](https://github.com/user-attachments/assets/50f3d131-8f41-4b91-8012-f8120b150033)
|
![image](https://github.com/user-attachments/assets/a36a6c6b-a469-49ba-85a8-9b55db9ea20f)
|

Release Notes:

- N/A

---------

Co-authored-by: 张小白 <364772080@qq.com>

Change summary

crates/gpui/src/platform/windows/events.rs |  8 ++++++--
crates/gpui/src/platform/windows/util.rs   | 18 +++++++++++++++++-
crates/gpui/src/platform/windows/window.rs |  2 +-
3 files changed, 24 insertions(+), 4 deletions(-)

Detailed changes

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

@@ -89,7 +89,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),
+        WM_DWMCOLORIZATIONCOLORCHANGED => handle_system_theme_changed(handle, state_ptr),
         WM_GPUI_CURSOR_STYLE_CHANGED => handle_cursor_changed(lparam, state_ptr),
         _ => None,
     };
@@ -1215,7 +1215,10 @@ fn handle_system_command(wparam: WPARAM, state_ptr: Rc<WindowsWindowStatePtr>) -
     None
 }
 
-fn handle_system_theme_changed(state_ptr: Rc<WindowsWindowStatePtr>) -> Option<isize> {
+fn handle_system_theme_changed(
+    handle: HWND,
+    state_ptr: Rc<WindowsWindowStatePtr>,
+) -> Option<isize> {
     let mut callback = state_ptr
         .state
         .borrow_mut()
@@ -1224,6 +1227,7 @@ fn handle_system_theme_changed(state_ptr: Rc<WindowsWindowStatePtr>) -> Option<i
         .take()?;
     callback();
     state_ptr.state.borrow_mut().callbacks.appearance_changed = Some(callback);
+    set_dwm_window_appearance(handle);
     Some(0)
 }
 

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

@@ -3,7 +3,7 @@ use std::sync::OnceLock;
 use ::util::ResultExt;
 use windows::{
     Wdk::System::SystemServices::RtlGetVersion,
-    Win32::{Foundation::*, UI::WindowsAndMessaging::*},
+    Win32::{Foundation::*, Graphics::Dwm::*, UI::WindowsAndMessaging::*},
     UI::{
         Color,
         ViewManagement::{UIColorType, UISettings},
@@ -139,6 +139,22 @@ pub(crate) fn load_cursor(style: CursorStyle) -> HCURSOR {
     }))
 }
 
+pub(crate) fn set_dwm_window_appearance(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(),
+    };
+    unsafe {
+        DwmSetWindowAttribute(
+            hwnd,
+            DWMWA_USE_IMMERSIVE_DARK_MODE,
+            &dark_mode_enabled as *const _ as _,
+            std::mem::size_of::<BOOL>() as u32,
+        )
+        .log_err();
+    }
+}
+
 #[inline]
 pub(crate) fn logical_point(x: f32, y: f32, scale_factor: f32) -> Point<Pixels> {
     Point {

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);
         state_ptr.state.borrow_mut().border_offset.update(hwnd)?;
         let placement = retrieve_window_placement(
             hwnd,