feat(compile): embed comctl32 v6 manifest so Windows UI apps get themed controls - #4683
Conversation
Lint fix + Windows smoke verification ✅Lint failure was the 2000-line file-size gate — the manifest additions pushed Verified on a real Windows build (host: Windows 11,
|
Compiled Windows UI apps bound comctl32 v5 because no application manifest was embedded, so every common control (buttons, list views, edit boxes) rendered in the unthemed Win95/classic style regardless of the OS theme — the dated look reported in discussion #3486. Embed a Win32 manifest that declares the Microsoft.Windows.Common-Controls v6 side-by-side dependency, which activates visual styles (the Fluent look) on Windows 10/11. - New windows_app.manifest: comctl32 v6 dependency + asInvoker execution level (keeps UI binaries out of the UAC installer-detection heuristic). - Link step writes it to a temp file and passes /MANIFEST:EMBED /MANIFESTUAC:NO /MANIFESTINPUT: to the linker. Both link.exe and lld-link embed it with no external mt.exe/rc.exe. /MANIFESTUAC:NO avoids a second linker-generated trustInfo block alongside the one in our manifest. - Gated on ctx.needs_ui so console-only binaries stay manifest-free. - Hoisted the manifest to a pub(super) const + added regression tests guarding the v6 dependency and asInvoker level. Part of #4681.
The comctl32 v6 manifest additions pushed link/mod.rs over the 2000-line CI gate (scripts/check_file_size.sh) — the `lint` job failed with "File size limit exceeded". Move the Windows system-library link line and the manifest embed into a sibling link/windows_link.rs module (add_system_libs + embed_app_manifest); mod.rs re-exports WINDOWS_APP_MANIFEST so windows_link_tests still reaches it. mod.rs drops to 1966 lines. No behavior change. Verified on Windows (lld-link): a UI exe embeds the manifest with Common-Controls v6 + a single asInvoker trustInfo block (mt.exe extract), while a console-only exe gets no resource section — the needs_ui gate holds.
45b75ef to
822b48a
Compare
|
Rebased onto latest Also note: main had since grown |
) Continues the #4681 Win32/GDI Fluent polish after #4682 (default DWM chrome) and #4683 (comctl32 v6 themed controls). - Mica backdrop by default: apply_default_window_chrome now also requests DWMWA_SYSTEMBACKDROP_TYPE = DWMSBT_MAINWINDOW at window creation. Visible on the DWM-drawn title bar on Win11 22H2+, ignored (E_INVALIDARG) on older systems. Keeps the opaque client background, so no #1542 black-area regression; full client-area blur-through stays the app.setVibrancy opt-in. - WM_DPICHANGED handling: the main window proc now honors the OS-suggested DPI-scaled rect via SetWindowPos and relayouts the root (mirrors WM_SIZE), so windows stay crisp when dragged across monitors with mixed scaling. DPI awareness was already opted into at startup. - Refreshed the stale geisterhand_style.rs caveat: opacity/border/shadow apply paths are real now (#210/#230 closed). Verified: perry-ui-windows builds, perry links a UI app that creates its window without crashing, and all 18 perry windows_link tests pass. Co-authored-by: Ralph Kuepper <ralph@skelpo.com>
#6051) * fix(link): #6023 LNK1158 'cannot run mt.exe' on Windows MSVC UI builds MSVC link.exe implements /MANIFEST:EMBED by shelling out to the Windows SDK's mt.exe. Perry launches a vswhere-located link.exe from a plain shell (not a vcvars64.bat developer prompt), so the SDK bin dir is not on PATH and every UI build since the comctl32-v6 manifest embed landed (v0.5.1129 / #4683) died with LNK1158. - When the linker is MSVC link.exe, probe for mt.exe: if it isn't on PATH already, locate the Windows SDK bin\<ver>\<arch> dir that holds it (registry KitsRoot10, ProgramFiles roots, legacy path — same probe order as find_msvc_lib_paths) and prepend it to the child's PATH. - If mt.exe can't be found anywhere, skip the manifest embed with a loud warning instead of failing the link — an unthemed app that builds beats a fatal LNK1158 (mirrors the existing manifest-write- failure fallback). lld-link embeds manifests in-process and is untouched. - Pass /IGNORE:4006: /FORCE:MULTIPLE makes the duplicate-definition merge deliberate, and the hundreds of LNK4006 lines it produced buried the real error in the report. Closes #6023 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test/style: rustfmt fix + assert x64-over-x86 arch preference in mt.exe probe cargo fmt wrapped the long fixture array (lint gate), and per CodeRabbit review the newest-version fixture now carries both x64 and x86 mt.exe so the asserted x64 pick actually exercises the arch preference instead of just version ordering. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Ralph <ralph@skelpo.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
What
The biggest fix for the "controls look 40 years old" complaint in discussion #3486. Compiled Windows UI apps bound comctl32 v5 because Perry embedded no application manifest into the linked
.exe, so every common control (buttons, list views, edit boxes…) rendered in the unthemed Win95/classic style regardless of the OS theme. This embeds a Win32 manifest declaring theMicrosoft.Windows.Common-Controlsv6 side-by-side dependency, which activates visual styles (the Fluent look) on Windows 10/11.DWM (#4682) modernizes the frame; this modernizes the controls. Together they close most of the visual gap on the existing Win32 backend.
Changes
windows_app.manifest— comctl32 v6 dependency + anasInvokerexecution level (declaring it explicitly keeps UI binaries out of the UAC installer-detection heuristic)./MANIFEST:EMBED /MANIFESTUAC:NO /MANIFESTINPUT:<path>. Bothlink.exeandlld-linkembed/MANIFESTINPUT:content via/MANIFEST:EMBEDwith no externalmt.exe/rc.exe, so this works on the MSVC path and the cross-from-maclld-linkpath alike./MANIFESTUAC:NOsuppresses the linker's auto-generated UAC fragment so it can't emit a secondtrustInfoblock alongside ours.ctx.needs_uiso console-only binaries stay manifest-free.pub(super) const WINDOWS_APP_MANIFESTand added regression tests guarding the v6 dependency, public key token, andasInvokerlevel.Why not DPI in the manifest
This manifest deliberately does not declare
dpiAware/dpiAwareness. Perry sets DPI awareness at runtime viadpi_compat(issue #303, to keep Win7 startup working and choose per-monitor-v2); a manifest declaration would conflict with that path. DPI stays out of scope here.Testing
cargo test -p perry --bin perry windows_link_tests— 7 passed (5 existing subsystem guards + 2 new manifest guards).cargo check -p perryclean;cargo fmtclean.if is_windowslink branch compiles on the macOS host (notcfg-gated), so the embed code is type-checked here. The actual embedding + control theming needs a Windows runner / manual smoke before merge — confirmdumpbin /manifest(or Resource Hacker) shows the Common-Controls v6 dependency in a built UI.exeand that the ToDo sample renders themed controls.Part of #4681, discussion #3486.