fix(desktop): add win version checks for DWM attr api (#5010)

fix: add win version checks for DWM attr api

This adds version checking before using Windows 11-specific DWM APIs.

Closes HFE-821

The desktop app crashes on startup on older Windows versions (pre-Windows 11)
due to unsupported DWM API calls for dark mode and caption styling.

According to docs at https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute,
both `DWMWA_USE_IMMERSIVE_DARK_MODE` and `DWMWA_CAPTION_COLOR` attributes
are only supported starting with Windows 11 Build 22000.

> DWMWA_USE_IMMERSIVE_DARK_MODE: [...] This value is supported starting
> with Windows 11 Build 22000"

and

> DWMWA_CAPTION_COLOR: [...] This value is supported starting
> with Windows 11 Build 22000.

See https://github.com/hoppscotch/hoppscotch/discussions/4984 for more details,
for reports of app crashing immediately on startup with these errors:

```
Failed to set dark mode: Error { code: HRESULT(0x80070057), message: "The parameter is incorrect." }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
[0417/150158.530:ERROR:window_impl.cc(122)] Failed to unregister class Chrome_WidgetWin_0. Error = 1412
```

The tests were all over the place, both attributes (sometimes!) seems to be present
on Windows 10 1809 and even earlier, only if it was installed with network access,
so perhaps this is due to Windows updates? Other times, they weren't, especially on VMs.

The issue is reproducible on Windows Server 2019 Datacenter (v10.0.17763),
which is equivalent to Windows 10 version 1809.

This version is too old to support DWMWA_USE_IMMERSIVE_DARK_MODE,
which is only **officially supported** starting with Windows 11 Build 22000
according to Microsoft's documentation.

So at the moment, relying on official docs seems to be the right call,
and themes are definitely something app shouldn't crash for regardless.
This commit is contained in:
Shreyas 2025-04-25 16:48:43 +05:30 committed by GitHub
parent 1867f23436
commit 93787f8389
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 34 additions and 19 deletions

View file

@ -12,6 +12,19 @@ use windows::Win32::{
};
use winver::WindowsVersion;
// Windows 11 Build 22000 is the minimum version required for
// DWMWA_USE_IMMERSIVE_DARK_MODE and DWMWA_CAPTION_COLOR.
//
// According to Microsoft documentation:
// https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
//
// "DWMWA_USE_IMMERSIVE_DARK_MODE: Use with DwmSetWindowAttribute.
// [...] This value is supported starting with Windows 11 Build 22000."
//
// "DWMWA_CAPTION_COLOR: Use with DwmSetWindowAttribute.
// [...] This value is supported starting with Windows 11 Build 22000."
const MIN_WIN11_BUILD: u32 = 22000;
#[derive(Debug)]
pub struct WindowsWindow<R: Runtime> {
window: WebviewWindow<R>,
@ -51,30 +64,32 @@ impl<R: Runtime> WindowsWindow<R> {
}
fn set_dark_mode(&self) {
unsafe {
let use_dark_mode = BOOL::from(true);
DwmSetWindowAttribute(
self.hwnd,
DWMWA_USE_IMMERSIVE_DARK_MODE,
ptr::addr_of!(use_dark_mode) as *const c_void,
size_of::<BOOL>().try_into().unwrap(),
)
.expect("Failed to set dark mode");
if let Some(version) = WindowsVersion::detect() {
if version.major() >= 10 && version.build() >= MIN_WIN11_BUILD {
unsafe {
let use_dark_mode = BOOL::from(true);
let _ = DwmSetWindowAttribute(
self.hwnd,
DWMWA_USE_IMMERSIVE_DARK_MODE,
ptr::addr_of!(use_dark_mode) as *const c_void,
size_of::<BOOL>().try_into().unwrap(),
);
}
}
}
}
fn set_caption_color(&self, color: HexColor) {
if let Some(version) = WindowsVersion::detect() {
if version >= WindowsVersion::new(10, 0, 22000) {
if version.major() >= 10 && version.build() >= MIN_WIN11_BUILD {
unsafe {
let color_ref = self.hex_color_to_colorref(color);
DwmSetWindowAttribute(
let _ = DwmSetWindowAttribute(
self.hwnd,
DWMWA_CAPTION_COLOR,
ptr::addr_of!(color_ref) as *const c_void,
size_of::<COLORREF>().try_into().unwrap(),
)
.expect("Failed to set caption color");
);
}
}
}

View file

@ -4972,7 +4972,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-appload"
version = "0.1.0"
source = "git+https://github.com/CuriousCorrelation/tauri-plugin-appload#1c2e8b19db7f1b6af6d00abb907f15cdc2017298"
source = "git+https://github.com/CuriousCorrelation/tauri-plugin-appload#c191e3de23a078b51103dd6fa60259b72f8b1443"
dependencies = [
"base64 0.22.1",
"blake3",

View file

@ -520,7 +520,7 @@ importers:
version: link:../hoppscotch-kernel
'@hoppscotch/plugin-appload':
specifier: github:CuriousCorrelation/tauri-plugin-appload
version: '@CuriousCorrelation/plugin-appload@https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/1c2e8b19db7f1b6af6d00abb907f15cdc2017298'
version: '@CuriousCorrelation/plugin-appload@https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/c191e3de23a078b51103dd6fa60259b72f8b1443'
'@hoppscotch/ui':
specifier: 0.2.2
version: 0.2.2(eslint@8.57.0)(terser@5.34.1)(typescript@5.3.3)(vite@5.4.9(@types/node@22.9.3)(sass@1.79.5)(terser@5.34.1))(vue@3.5.12(typescript@5.3.3))
@ -978,7 +978,7 @@ importers:
version: link:../hoppscotch-kernel
'@hoppscotch/plugin-appload':
specifier: github:CuriousCorrelation/tauri-plugin-appload
version: '@CuriousCorrelation/plugin-appload@https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/1c2e8b19db7f1b6af6d00abb907f15cdc2017298'
version: '@CuriousCorrelation/plugin-appload@https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/c191e3de23a078b51103dd6fa60259b72f8b1443'
'@hoppscotch/ui':
specifier: 0.2.1
version: 0.2.1(eslint@9.12.0(jiti@2.3.3))(terser@5.34.1)(typescript@5.7.2)(vite@5.4.11(@types/node@22.9.3)(sass@1.80.3)(terser@5.34.1))(vue@3.5.12(typescript@5.7.2))
@ -1806,8 +1806,8 @@ packages:
graphql:
optional: true
'@CuriousCorrelation/plugin-appload@https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/1c2e8b19db7f1b6af6d00abb907f15cdc2017298':
resolution: {tarball: https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/1c2e8b19db7f1b6af6d00abb907f15cdc2017298}
'@CuriousCorrelation/plugin-appload@https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/c191e3de23a078b51103dd6fa60259b72f8b1443':
resolution: {tarball: https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/c191e3de23a078b51103dd6fa60259b72f8b1443}
version: 0.1.0
'@CuriousCorrelation/plugin-relay@https://codeload.github.com/CuriousCorrelation/tauri-plugin-relay/tar.gz/68d6b2532c900b4be24a038c49eec4794e990a3d':
@ -13204,7 +13204,7 @@ snapshots:
optionalDependencies:
graphql: 16.9.0
'@CuriousCorrelation/plugin-appload@https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/1c2e8b19db7f1b6af6d00abb907f15cdc2017298':
'@CuriousCorrelation/plugin-appload@https://codeload.github.com/CuriousCorrelation/tauri-plugin-appload/tar.gz/c191e3de23a078b51103dd6fa60259b72f8b1443':
dependencies:
'@tauri-apps/api': 2.1.1