feat(windows): AppUserModelID at startup and the toast arm

Two halves of the same identity.

`SetCurrentProcessExplicitAppUserModelID` runs before `QGuiApplication::new()`,
which is the documented window: Windows caches the identity with the first
window and a later call fails. Without it the taskbar treats each launch as an
anonymous window and does not group it with the Start-menu shortcut. The
HRESULT is logged on failure -- when this breaks, taskbar grouping and toast
delivery both break silently, and the only symptom would otherwise be
"notifications do not work" with nothing to point at.

The notification arm follows the macOS one, with `app_id` matching the AUMID.
notify-rust's Windows backend forwards summary/body/app_id/image and SILENTLY
DROPS `actions`, so no buttons are attempted: they would look implemented and
do nothing.

The artwork cache is shared rather than duplicated -- its four `cfg` gates now
include Windows, which also retires an unused-import warning there. Its
`file://` resolver gained the two Windows shapes: the empty authority's slash
in front of a drive letter (`/C:/x`, which PathBuf keeps and then never
resolves), and a UNC authority (`file://nas/share/x`), which was being treated
as a path relative to the working directory.

`system_notifications_supported` deliberately stays false on Windows. An
unpackaged desktop app only receives toasts once Windows can RESOLVE its
AppUserModelID, which needs a Start-menu shortcut carrying
System.AppUserModel.ID -- written by the MSI, which does not exist yet. Setting
the process identity is necessary and not sufficient. Advertising the row now
would let the setting be enabled in exactly the builds where nothing can ever
appear. It flips with the MSI.

cc
This commit is contained in:
vicrodh committed 2026-08-27 13:37:25 -06:00
1 parent 114824b7bc
commit 9b0d8d7e0f
4 files changed
+103 -8

No files matched your search

+6
View File
@@ -182,6 +182,12 @@ winresource = "0.1"
# ⚠ NOT COMPILED OR TESTED HERE. This tree builds on Linux; the macOS arm is
# behind cfg, so `cargo build` cannot see it. First real check is a macOS
# build — the Mac mini (192.168.0.69) is where that happens.
[target.'cfg(target_os = "windows")'.dependencies]
# SetCurrentProcessExplicitAppUserModelID: the identity Windows groups the
# taskbar button under and matches a toast's app_id against. 0.61 is already
# in the workspace lock.
windows-sys = { version = "0.61", features = ["Win32_UI_Shell"] }
[target.'cfg(target_os = "macos")'.dependencies]
# DIRECT objc2, added 2026-08-05 for the menu-bar tray: `declare_class!`,
# `msg_send_id!`, `sel!`, `ClassType`, `DeclaredClass`, `mutability` and