From 3216ebc04c43b28970e6efb67b0472af8ee5a954 Mon Sep 17 00:00:00 2001 From: RCD <90105158+Finesssee@users.noreply.github.com> Date: Sat, 10 Oct 2026 22:13:10 +0700 Subject: [PATCH 1/2] Drop no-op class brush call from DWM chrome SetWindowLongPtrW was given GCL_HBRBACKGROUND (-10), which is a SetClassLongPtr index, so the call failed and changed nothing. The tray flyout's erase color comes from the builder background_color (PANEL_FILL), so removing the call keeps the same behavior. Also drops the now-unused CreateSolidBrush import and cached brush. Only apply DWMWA_USE_IMMERSIVE_DARK_MODE to the dark surfaces (Dark, DarkResizable). The light tray flyout (LightPanel) keeps the light title-bar theme. Adds literal-value tests for both. --- apps/desktop-tauri/src-tauri/src/shell/dwm.rs | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/apps/desktop-tauri/src-tauri/src/shell/dwm.rs b/apps/desktop-tauri/src-tauri/src/shell/dwm.rs index 7e0561c9fe..1d0ef98556 100644 --- a/apps/desktop-tauri/src-tauri/src/shell/dwm.rs +++ b/apps/desktop-tauri/src-tauri/src/shell/dwm.rs @@ -88,15 +88,6 @@ unsafe extern "system" { ) -> i32; } -#[cfg(windows)] -#[link(name = "gdi32")] -unsafe extern "system" { - fn CreateSolidBrush(color: u32) -> isize; -} - -#[cfg(windows)] -static DARK_BRUSH: std::sync::OnceLock = std::sync::OnceLock::new(); - #[cfg(windows)] const WM_NCCALCSIZE: u32 = 0x0083; #[cfg(windows)] @@ -204,6 +195,12 @@ impl Chrome { fn border_color(self) -> Option { (self == Self::LightPanel).then_some(PANEL_HAIRLINE) } + + /// Value for `DWMWA_USE_IMMERSIVE_DARK_MODE`. `None` leaves the title bar + /// on the light theme, which the tray flyout uses. + fn immersive_dark_mode(self) -> Option { + (self != Self::LightPanel).then_some(1) + } } /// Eliminate the DWM caption bar by subclassing the window to zero the @@ -246,23 +243,25 @@ fn apply_chrome(win: &tauri::WebviewWindow, chrome: Chrome) { const DWMWA_USE_IMMERSIVE_DARK_MODE: u32 = 20; const DWMWA_CAPTION_COLOR: u32 = 35; - let dark_mode: u32 = 1; let caption_color: u32 = 0x001C1C1E; unsafe { - let r1 = DwmSetWindowAttribute( - hwnd, - DWMWA_USE_IMMERSIVE_DARK_MODE, - &raw const dark_mode as *const c_void, - 4, - ); + if let Some(dark_mode) = chrome.immersive_dark_mode() { + let r1 = DwmSetWindowAttribute( + hwnd, + DWMWA_USE_IMMERSIVE_DARK_MODE, + &raw const dark_mode as *const c_void, + 4, + ); + tracing::info!("dwm: dark_mode={r1:#x}"); + } let r2 = DwmSetWindowAttribute( hwnd, DWMWA_CAPTION_COLOR, &raw const caption_color as *const c_void, 4, ); - tracing::info!("dwm: dark_mode={r1:#x} caption_color={r2:#x}"); + tracing::info!("dwm: caption_color={r2:#x}"); const DWMWA_WINDOW_CORNER_PREFERENCE: u32 = 33; const DWMWA_BORDER_COLOR: u32 = 34; @@ -300,13 +299,6 @@ fn apply_chrome(win: &tauri::WebviewWindow, chrome: Chrome) { let ok = SetWindowSubclass(hwnd, borderless_subclass_proc, BORDERLESS_SUBCLASS_ID, 0); tracing::info!("dwm: subclass installed={ok}"); - // Set background brush to dark (reuse a single GDI brush) - const GCL_HBRBACKGROUND: i32 = -10; - let brush = *DARK_BRUSH.get_or_init(|| CreateSolidBrush(0x001C1C1E)); - if brush != 0 { - SetWindowLongPtrW(hwnd, GCL_HBRBACKGROUND, brush); - } - // Remove WS_CAPTION; only strip WS_THICKFRAME for non-resizable windows const GWL_STYLE: i32 = -16; const WS_CAPTION: isize = 0x00C00000; @@ -375,6 +367,13 @@ mod tests { assert_eq!(Chrome::DarkResizable.border_color(), None); } + #[test] + fn only_the_dark_surfaces_request_immersive_dark_mode() { + assert_eq!(Chrome::Dark.immersive_dark_mode(), Some(1)); + assert_eq!(Chrome::DarkResizable.immersive_dark_mode(), Some(1)); + assert_eq!(Chrome::LightPanel.immersive_dark_mode(), None); + } + #[test] fn only_the_resizable_dark_chrome_keeps_the_resize_frame() { assert!(!Chrome::LightPanel.keeps_resize_frame()); From 58daa8b76b4225972b2c75fcf2adb26280f092c8 Mon Sep 17 00:00:00 2001 From: RCD <90105158+Finesssee@users.noreply.github.com> Date: Sat, 10 Oct 2026 22:28:48 +0700 Subject: [PATCH 2/2] Keep the dark-mode flag on the tray flyout --- apps/desktop-tauri/src-tauri/src/shell/dwm.rs | 31 +++++-------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/apps/desktop-tauri/src-tauri/src/shell/dwm.rs b/apps/desktop-tauri/src-tauri/src/shell/dwm.rs index 1d0ef98556..d1313170da 100644 --- a/apps/desktop-tauri/src-tauri/src/shell/dwm.rs +++ b/apps/desktop-tauri/src-tauri/src/shell/dwm.rs @@ -195,12 +195,6 @@ impl Chrome { fn border_color(self) -> Option { (self == Self::LightPanel).then_some(PANEL_HAIRLINE) } - - /// Value for `DWMWA_USE_IMMERSIVE_DARK_MODE`. `None` leaves the title bar - /// on the light theme, which the tray flyout uses. - fn immersive_dark_mode(self) -> Option { - (self != Self::LightPanel).then_some(1) - } } /// Eliminate the DWM caption bar by subclassing the window to zero the @@ -243,25 +237,23 @@ fn apply_chrome(win: &tauri::WebviewWindow, chrome: Chrome) { const DWMWA_USE_IMMERSIVE_DARK_MODE: u32 = 20; const DWMWA_CAPTION_COLOR: u32 = 35; + let dark_mode: u32 = 1; let caption_color: u32 = 0x001C1C1E; unsafe { - if let Some(dark_mode) = chrome.immersive_dark_mode() { - let r1 = DwmSetWindowAttribute( - hwnd, - DWMWA_USE_IMMERSIVE_DARK_MODE, - &raw const dark_mode as *const c_void, - 4, - ); - tracing::info!("dwm: dark_mode={r1:#x}"); - } + let r1 = DwmSetWindowAttribute( + hwnd, + DWMWA_USE_IMMERSIVE_DARK_MODE, + &raw const dark_mode as *const c_void, + 4, + ); let r2 = DwmSetWindowAttribute( hwnd, DWMWA_CAPTION_COLOR, &raw const caption_color as *const c_void, 4, ); - tracing::info!("dwm: caption_color={r2:#x}"); + tracing::info!("dwm: dark_mode={r1:#x} caption_color={r2:#x}"); const DWMWA_WINDOW_CORNER_PREFERENCE: u32 = 33; const DWMWA_BORDER_COLOR: u32 = 34; @@ -367,13 +359,6 @@ mod tests { assert_eq!(Chrome::DarkResizable.border_color(), None); } - #[test] - fn only_the_dark_surfaces_request_immersive_dark_mode() { - assert_eq!(Chrome::Dark.immersive_dark_mode(), Some(1)); - assert_eq!(Chrome::DarkResizable.immersive_dark_mode(), Some(1)); - assert_eq!(Chrome::LightPanel.immersive_dark_mode(), None); - } - #[test] fn only_the_resizable_dark_chrome_keeps_the_resize_frame() { assert!(!Chrome::LightPanel.keeps_resize_frame());