Skip to content

feat(ui-windows-winui): render-backend dispatch seam + startup probe (#4680 step 3)#4897

Open
proggeramlug wants to merge 3 commits into
mainfrom
feat/4680-winui-seam
Open

feat(ui-windows-winui): render-backend dispatch seam + startup probe (#4680 step 3)#4897
proggeramlug wants to merge 3 commits into
mainfrom
feat/4680-winui-seam

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

What

Implements the step-3 dispatch seam for #4680 (opt-in WinUI 3 / Fluent Windows target), building directly on the step-2 bootstrap probe merged in #4896.

Adds winui::backend — the single decision point the per-widget WinUI 3 mapping reads — plus a process-startup probe so --target windows-winui binaries resolve their render backend at launch.

How

  • winui::backend::active() -> RenderBackend — returns RenderBackend::Fluent when the Windows App SDK bootstrap probe (bootstrap::initialize()) is Ready, else RenderBackend::Win32. Cheap and stable (memoized by the bootstrap cache). Each XAML widget lands behind this check: build a Microsoft.UI.Xaml control on Fluent, else delegate to the existing Win32 constructor.
  • CRT static initializer (.CRT$XCU, anchored with #[used]) registered in the crate runs the probe at process start for any binary that links this staticlib — i.e. exactly the --target windows-winui builds, and never the default --target windows builds (which don't link the crate). So the first widget construction reads an already-resolved backend rather than probing lazily. It never panics (runs before main).
  • PERRY_WINUI_DIAG prints the chosen backend at launch: [perry-winui] render backend: win32|fluent.

Testing

  • cargo test -p perry-ui-windows-winui → green (active_backend_matches_bootstrap_verdict, initialize_is_total_and_idempotent). active() mirrors the bootstrap verdict and is stable; off Windows it is always Win32.
  • Verified on this Windows host (no SDK installed):
    • The startup initializer fires in a linked binary — running the test exe with PERRY_WINUI_DIAG=1 emitted [perry-winui] render backend: win32.
    • The .CRT$XCU section (8 bytes — one initializer pointer) is present in the WHOLEARCHIVE'd perry_ui_windows_winui.lib (llvm-objdump --headers).

Scope / not in this PR

Real Microsoft.UI.Xaml controls need the WinAppSDK winmd projections + runtime (the stock windows crate at 0.58 ships only UWP Windows.UI.Xaml, not WinUI 3's Microsoft.UI.Xaml), so they're the next step. Today the seam always resolves to Win32. Win32 (--target windows) remains the default and is untouched.

Ralph Kuepper added 3 commits June 10, 2026 12:16
…4680 step 3)

Builds on the merged step-2 bootstrap probe (#4896). Add winui::backend, the
single decision point the per-widget WinUI 3 mapping reads: active() returns
RenderBackend::Fluent when the bootstrap probe is Ready, else
RenderBackend::Win32.

Register a CRT static initializer (.CRT$XCU, anchored with #[used]) that runs
the probe at process start for any binary linking this staticlib - i.e. exactly
the --target windows-winui builds, never the default --target windows builds
(which don't link the crate) - so the first widget construction reads an
already-resolved backend. PERRY_WINUI_DIAG prints the chosen backend at launch.
The initializer never panics (runs before main).

Verified on a Windows host without the SDK: the initializer fires in a linked
binary ([perry-winui] render backend: win32 observed via PERRY_WINUI_DIAG), the
.CRT$XCU section is present in the WHOLEARCHIVE'd perry_ui_windows_winui.lib, and
active() mirrors the bootstrap verdict and is stable.

Real Microsoft.UI.Xaml controls still need the WinAppSDK winmd projections +
runtime and are the next step; today the seam always resolves to Win32. Default
--target windows unaffected.
…#4680)

The backend probe could say Ready/Missing but not *why* it was missing. Capture
the bootstrap outcome detail (sentinels for DLL-missing / no-entry-point /
success, otherwise the raw MddBootstrapInitialize HRESULT) and print it under
PERRY_WINUI_DIAG: e.g. "render backend: fluent (bootstrap detail: ready)" or
"win32 (bootstrap detail: MddBootstrapInitialize failed, HRESULT 0x80670016)".

This made the step-2 success path verifiable against the real runtime: with the
Windows App SDK 1.6 dev NuGet restored (bootstrap DLL next to the exe) and the
DDLM/Main/Singleton runtime packages registered, initialize() flips from
RuntimeMissing to Ready/fluent - so both arms of the merged MddBootstrapInitialize2
FFI (#4896) are now exercised. The 0x80670016 case was exactly a registered
framework package with no DDLM, which the new diagnostic pinpoints.

Adds a unit test for the detail formatter (pure function, environment-agnostic).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant