The menu was a stock Win32 popup: light-mode on a dark taskbar,
DPI-virtualized (blurry on every scaled laptop), no icons. Now the
process opts into the system dark mode via the uxtheme ordinals
(135/136 - the same undocumented calls Explorer/PowerToys/Notepad++
make; menus never got a documented opt-in, and there is no WinUI tray
API to move to), a PerMonitorV2 manifest makes menu and icon crisp, the
multi-size .ico serves the DPI-correct frame, and items carry Segoe
Fluent glyph bitmaps - with the UAC shield on the elevated service
actions, per Explorer's convention. Rounded corners come free on
Windows 11. Everything degrades gracefully: missing ordinals mean the
classic light menu, a missing icon font means no glyphs.
New: a connect toast on the idle-to-streaming edge - title "<device>
connected" (from the summary's new client_name), body the mode
("Streaming 2560x1440 @ 120 fps") - via NIF_INFO, which Windows 11
renders as a native toast. The tray tags itself with the AUMID
unom.punktfunk.tray and the installer registers it under
Classes\AppUserModelId (DisplayName "Punktfunk" + the brand icon), so
the toast is attributed to Punktfunk with the logo. Unregistered dev
runs degrade to generic attribution, older hosts to a nameless title;
a tray started mid-session never fires a stale toast.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
49 lines
2.3 KiB
Rust
49 lines
2.3 KiB
Rust
//! Embed the Windows version-info + icon resources into `punktfunk-tray.exe`: ordinal 1 is the
|
||
//! exe/file icon, ordinals 2–6 are the status-variant tray icons `src/win.rs` loads by id
|
||
//! (running / stopped / error / streaming / degraded). Same winresource pattern as
|
||
//! `clients/windows/build.rs`.
|
||
|
||
fn main() {
|
||
// cfg(windows) is the HOST (skips the Linux/macOS workspace stub build); CARGO_CFG_WINDOWS
|
||
// is the TARGET (mirrors the Windows client's build.rs).
|
||
#[cfg(windows)]
|
||
if std::env::var_os("CARGO_CFG_WINDOWS").is_some() {
|
||
let branding = "../../packaging/windows/branding";
|
||
let icons = [
|
||
(format!("{branding}/punktfunk.ico"), "1"),
|
||
(format!("{branding}/punktfunk-tray-running.ico"), "2"),
|
||
(format!("{branding}/punktfunk-tray-stopped.ico"), "3"),
|
||
(format!("{branding}/punktfunk-tray-error.ico"), "4"),
|
||
(format!("{branding}/punktfunk-tray-streaming.ico"), "5"),
|
||
(format!("{branding}/punktfunk-tray-degraded.ico"), "6"),
|
||
];
|
||
let mut res = winresource::WindowsResource::new();
|
||
for (path, id) in &icons {
|
||
println!("cargo:rerun-if-changed={path}");
|
||
res.set_icon_with_id(path, id);
|
||
}
|
||
// Task Manager / Explorer identity (matches the host's "Punktfunk Host").
|
||
res.set("FileDescription", "Punktfunk Tray");
|
||
res.set("ProductName", "Punktfunk");
|
||
// PerMonitorV2: without a DPI manifest the process is virtualized and its menu
|
||
// GDI-stretched — visibly blurry on any scaled display (most Windows 11 laptops).
|
||
res.set_manifest(
|
||
r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||
<application>
|
||
<!-- Windows 10/11 -->
|
||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||
</application>
|
||
</compatibility>
|
||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||
<windowsSettings>
|
||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||
</windowsSettings>
|
||
</application>
|
||
</assembly>"#,
|
||
);
|
||
res.compile().expect("embed windows icon resources");
|
||
}
|
||
}
|