Fix windows theme and quit

This commit is contained in:
Lennard Kittner
2026-03-20 12:48:48 +01:00
parent 6413102413
commit 2d2f621397
3 changed files with 154 additions and 11 deletions

105
Cargo.lock generated
View File

@@ -829,7 +829,7 @@ dependencies = [
"objc2 0.6.3",
"objc2-app-kit 0.3.2",
"objc2-foundation 0.3.2",
"windows",
"windows 0.61.3",
"x11rb",
"xkbcommon",
"xkeysym",
@@ -1341,6 +1341,7 @@ dependencies = [
"shell-escape",
"thistermination",
"tray-icon",
"windows 0.62.2",
"winit",
]
@@ -3318,11 +3319,23 @@ version = "0.61.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
dependencies = [
"windows-collections",
"windows-core",
"windows-future",
"windows-collections 0.2.0",
"windows-core 0.61.2",
"windows-future 0.2.1",
"windows-link 0.1.3",
"windows-numerics",
"windows-numerics 0.2.0",
]
[[package]]
name = "windows"
version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
dependencies = [
"windows-collections 0.3.2",
"windows-core 0.62.2",
"windows-future 0.3.2",
"windows-numerics 0.3.1",
]
[[package]]
@@ -3331,7 +3344,16 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
dependencies = [
"windows-core",
"windows-core 0.61.2",
]
[[package]]
name = "windows-collections"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
dependencies = [
"windows-core 0.62.2",
]
[[package]]
@@ -3343,8 +3365,21 @@ dependencies = [
"windows-implement",
"windows-interface",
"windows-link 0.1.3",
"windows-result",
"windows-strings",
"windows-result 0.3.4",
"windows-strings 0.4.2",
]
[[package]]
name = "windows-core"
version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link 0.2.1",
"windows-result 0.4.1",
"windows-strings 0.5.1",
]
[[package]]
@@ -3353,9 +3388,20 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
dependencies = [
"windows-core",
"windows-core 0.61.2",
"windows-link 0.1.3",
"windows-threading",
"windows-threading 0.1.0",
]
[[package]]
name = "windows-future"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
dependencies = [
"windows-core 0.62.2",
"windows-link 0.2.1",
"windows-threading 0.2.1",
]
[[package]]
@@ -3398,10 +3444,20 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
dependencies = [
"windows-core",
"windows-core 0.61.2",
"windows-link 0.1.3",
]
[[package]]
name = "windows-numerics"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
dependencies = [
"windows-core 0.62.2",
"windows-link 0.2.1",
]
[[package]]
name = "windows-result"
version = "0.3.4"
@@ -3411,6 +3467,15 @@ dependencies = [
"windows-link 0.1.3",
]
[[package]]
name = "windows-result"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [
"windows-link 0.2.1",
]
[[package]]
name = "windows-strings"
version = "0.4.2"
@@ -3420,6 +3485,15 @@ dependencies = [
"windows-link 0.1.3",
]
[[package]]
name = "windows-strings"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
dependencies = [
"windows-link 0.2.1",
]
[[package]]
name = "windows-sys"
version = "0.45.0"
@@ -3546,6 +3620,15 @@ dependencies = [
"windows-link 0.1.3",
]
[[package]]
name = "windows-threading"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
dependencies = [
"windows-link 0.2.1",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"

View File

@@ -21,3 +21,6 @@ winit = "0.30.13"
[target.'cfg(target_os = "windows")'.dependencies]
image = "0.25.10"
windows = { version = "0.62.2", features = [
"Win32_System_LibraryLoader",
] }

View File

@@ -34,6 +34,11 @@ pub struct TrayApp {
impl ApplicationHandler<Option<DeviceProperties>> for TrayApp {
fn new_events(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop, cause: StartCause) {
if cause == StartCause::Init {
#[cfg(target_os = "windows")]
unsafe {
enable_dark_context_menus();
}
#[cfg(target_os = "windows")]
{
self.tray_icon = Some(
@@ -41,6 +46,7 @@ impl ApplicationHandler<Option<DeviceProperties>> for TrayApp {
.with_menu(Box::new(Menu::new()))
.with_icon(create_tray_icon())
.with_tooltip(NO_COMPATIBLE_DEVICE)
.with_menu_on_left_click(true)
.build()
.unwrap(),
);
@@ -52,6 +58,7 @@ impl ApplicationHandler<Option<DeviceProperties>> for TrayApp {
.with_menu(Box::new(Menu::new()))
.with_title("🎧")
.with_tooltip(NO_COMPATIBLE_DEVICE)
.with_menu_on_left_click(true)
.build()
.unwrap(),
);
@@ -113,6 +120,9 @@ impl TrayApp {
return;
};
#[cfg(target_os = "windows")]
let quit_item = MenuItem::new("Quit", true, None);
let menu = Menu::new();
let mut new_callbacks: HashMap<MenuId, Box<dyn Fn() + Send + Sync>> = HashMap::new();
@@ -123,6 +133,14 @@ impl TrayApp {
let status_item = MenuItem::new(NO_COMPATIBLE_DEVICE, false, None);
menu.append(&status_item).unwrap();
menu.append(&PredefinedMenuItem::separator()).unwrap();
#[cfg(target_os = "windows")]
{
menu.append(&quit_item).unwrap();
new_callbacks.insert(quit_item.id().clone(), Box::new(|| std::process::exit(0)));
}
#[cfg(target_os = "macos")]
menu.append(&PredefinedMenuItem::quit(Some("Quit")))
.unwrap();
@@ -139,6 +157,14 @@ impl TrayApp {
let status_item = MenuItem::new(HEADSET_NOT_CONNECTED, false, None);
menu.append(&status_item).unwrap();
menu.append(&PredefinedMenuItem::separator()).unwrap();
#[cfg(target_os = "windows")]
{
menu.append(&quit_item).unwrap();
new_callbacks.insert(quit_item.id().clone(), Box::new(|| std::process::exit(0)));
}
#[cfg(target_os = "macos")]
menu.append(&PredefinedMenuItem::quit(Some("Quit")))
.unwrap();
@@ -254,6 +280,14 @@ impl TrayApp {
}
menu.append(&PredefinedMenuItem::separator()).unwrap();
#[cfg(target_os = "windows")]
{
menu.append(&quit_item).unwrap();
new_callbacks.insert(quit_item.id().clone(), Box::new(|| std::process::exit(0)));
}
#[cfg(target_os = "macos")]
menu.append(&PredefinedMenuItem::quit(Some("Quit")))
.unwrap();
@@ -262,3 +296,26 @@ impl TrayApp {
self.current_state = Some(Some(device_properties));
}
}
#[cfg(target_os = "windows")]
/// Dark magic to set dark mode
unsafe fn enable_dark_context_menus() {
use windows::core::PCSTR;
use windows::Win32::System::LibraryLoader::{GetProcAddress, LoadLibraryW};
let uxtheme = LoadLibraryW(windows::core::w!("uxtheme.dll")).unwrap();
// SetPreferredAppMode is ordinal 135 (undocumented, no name export)
type SetPreferredAppMode = unsafe extern "system" fn(i32) -> i32;
if let Some(func) = GetProcAddress(uxtheme, PCSTR(135 as *const u8)) {
let set_mode: SetPreferredAppMode = std::mem::transmute(func);
set_mode(1); // 1 = AllowDark (follows system theme)
}
// FlushMenuThemes is ordinal 136 — applies the change immediately
type FlushMenuThemes = unsafe extern "system" fn();
if let Some(func) = GetProcAddress(uxtheme, PCSTR(136 as *const u8)) {
let flush: FlushMenuThemes = std::mem::transmute(func);
flush();
}
}