Skip to content

Windows: expose shared WinUI app icon helper for all top-level windows (including settings) #333

Closed

Description

@turinglambdaai

Problem

Rivet-generated Windows hosts embed the product icon in RT_GROUP_ICON resource ID 1 and Rivet's scaffold platform/windows/host/MainWindow.xaml.cpp explicitly installs that icon via AppWindow.SetIcon(IconId). This only covers the scaffold main window. First-party downstream windows (for example, Fulcrum's windows/SettingsWindow.xaml.cpp) must repeat fragile WinUI/Win32 glue. Fulcrum currently calls appWindow.SetIcon(exe_path), mistakenly passing an executable path to the string overload, which expects a .ico file path. The WinUI settings title bar therefore appears without the product icon, even when the EXE has a valid embedded icon. This is not intentional Windows platform style.

Earlier issues #166 and #282 fixed packaging/resource identity; this issue tracks the remaining secondary-window API and regression-contract gap rather than reopening those completed fixes.

Proposed narrow API

  • Add a small opt-in rivet::system::ApplyAppIcon(Window const&) (or equivalent) in the WinUI-only system header, backed by the generated numeric ID 1 resource, using LoadIconW(GetModuleHandleW(nullptr), MAKEINTRESOURCEW(1)) and AppWindow().SetIcon(Microsoft::UI::IconId{...}); avoid the SetIcon(String) overload for exe paths.
  • Document correct lifetime/ownership of HICON passed to AppWindow and what happens when no icon resource is present, so fallback is deterministic. Keep usage valid both before/after Activate() and in secondary settings/other top-level windows.
  • Make the generated scaffold use the same helper. Do not override platform-native titlebar decisions of macOS or Linux; do not force an icon on borderless launcher overlays.
  • Add a native Windows regression test using two titled WinUI windows and assert both obtain the expected resource icon, including the packaged installed host; check that an absent icon gracefully falls back without crashing.

Scope / ownership

  • Rivet owns reusable Windows window-identity primitives, and the generated packaged icon.
  • Products such as Fulcrum own their navigation, WinUI settings controls, brand art, and whether a window uses a title bar.
  • Fulcrum's urgent fix should use the embedded icon directly without waiting for a new Rivet pin; this enhancement prevents future repeats across downstream applications.

Related: turinglambdaai/fulcrum#104 (planned v0.14.1 patch, including WinUI settings parity and icon fix).

Activity

  1. turinglambdaai commented on Oct 27, 2026

    @turinglambdaai
    OwnerAuthor

    Implementation PR: #334 (fix/windows-shared-app-icon-333). Added reusable rivet::system::ApplyAppIcon for titled WinUI windows, converted scaffold/reference main windows, documented missing-resource fallback and shared HICON ownership, and added a Windows CI packaged Taskboard regression that opens two titled windows and checks both icon pixels plus a missing-resource fallback. Keep this issue open until current-head native Windows CI is green and installed-MSI host acceptance is verified; directory packaging alone does not prove the installed-host requirement.

  2. turinglambdaai commented on Oct 27, 2026

    @turinglambdaai
    OwnerAuthor

    Updated #334: following the Windows native UI CI evidence (the embedded icon was read successfully, with a one-channel-level RGB premultiplication delta), changed the exact-pixel assertion to permit ±1 level while still rejecting generic/unrelated icons. Added the missing real MSI installed-host acceptance: WiX 5 development release, msiexec /i in a disposable runner install directory, both titled windows' WM_GETICON and UIA/RPC assertions against the installed EXE, followed by msiexec /x. The current-head six-workflow checks are still running; do not close until the Windows installed-host run is green. No claim of production publisher signing is made.

  3. added a commit that references this issue on Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions