fix(gui): give both modules one background, and make the window paint it - #14
Merged
Merged
Conversation
The substitution panel sat on the wpfui default and the calculator on our own
base, with the seam visible under the module switch. Nobody had chosen that.
The window carried Background="{DynamicResource BrushBgBase}" the whole time
and it never painted a single pixel.
A Background on a ui:FluentWindow is accepted by the parser, reads exactly like
a working declaration, and does nothing at all. Measured rather than reasoned:
replacing it with a bright literal and rebuilding produced screenshots that
were identical BYTE FOR BYTE, zero difference across 1 872 000 pixels.
Overriding the theme resources its own style reads, WindowBackground and
ApplicationBackgroundBrush, changed nothing either, by the same measurement.
What does work is a Background on the content root inside, which is the only
reason the calculator view ever looked right - it has one.
So the dead attribute goes from both windows and the colour moves onto each
content root. The base stays ours on purpose. The colour it replaced was a
default of the dependency, so a wpfui release could have changed 86 percent of
this window without anyone deciding it, and the base is the first rung of a
four-surface ladder tuned together: a card separates from it at 1.14 contrast
where the other colour gives 1.08, and the palette is slightly cool where the
other is flat grey. Text contrast was never the question - both sit far above
the floor, 15.36 against 14.57 for primary text.
Measured after, by pixel, on all three surfaces: the old colour is now ZERO
pixels on the substitution panel, the calculator and the dialog. The
calculator's own base went from 12.39 to 25.19 percent as the chrome joined
it, and the dialog turns out to have been 63.68 percent of the old colour,
which is how much of it that dead attribute was failing to paint. Stock wpfui
controls re-tuned themselves without help, being roughly 6 percent white over
whatever sits beneath them.
Guarded two ways, because the obvious guard is the one that would have missed
this: a check on the attribute being present would have been green for months
on a declaration that painted nothing. The render guard lays out MainWindow,
renders its content and asserts the colour covering most of the surface, with
a canary on the number of distinct colours so an empty render cannot pass for
the wrong reason. The scan guard refuses a Background on any FluentWindow root
and carries its own canary on how many views it actually walks. Both were seen
red: moving the declaration back onto the window reddens both, removing it
altogether reddens only the render one, which is what makes the pair worth
having rather than one guard twice.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The two halves of one app sat on two different backgrounds, and nobody had chosen either. The substitution panel and the window chrome were on the wpfui default, the calculator on our own palette base, with the seam visible under the module switch.
Why it happened
Backgroundon aui:FluentWindowis accepted by the parser, reads exactly like a working declaration, and paints nothing. Both windows carried one for their whole life. The calculator only looked right because it has its own rootGridbackground, which aGriddoes honour.Measured rather than reasoned - four probes, each rebuilt and screenshotted:
Background="#FF00FF00"onMainWindowApplicationBackgroundBrushandApplicationBackgroundColorWindowBackground(the key its own style setter reads)Backgroundon the root<Grid>insideThe
FluentWindowtemplate pulled out of the package draws aui:ClientAreaBorderwith a correctBackground="{TemplateBinding Panel.Background}", and none of the first three routes reaches it anyway. WhatClientAreaBorderactually paints with is not established and not guessed at here.A sweep giving each of the 14
Backgrounddeclarations in the views its own bright colour found exactly two dead ones, both onFluentWindowroots. The other five that did not show up areBorderelements in hidden states, andBorderhonoursBackgroundfour times over in the same table.What changed
The dead attribute is gone from both windows and the colour moved onto each content root. The base stays ours: the colour it replaced was a default of the dependency, so a wpfui release could have changed 86 percent of this window without anyone deciding it. It is also the first rung of a four-surface ladder tuned together - a card separates from it at 1.14 contrast where the other colour gives 1.08. Text contrast was never in question, 15.36 against 14.57 for primary text, both far above the floor.
Measured after, by pixel, on all three surfaces:
The dialog carried the same dead attribute and nobody had counted it - 63.68 percent of its surface was the wrong colour. Stock wpfui controls re-tuned themselves without help, being roughly 6 percent white over whatever sits beneath them.
Guards
Two of them, because the obvious one is exactly the guard that would have missed this: a check on the attribute being present stays green on a declaration that paints nothing.
MainWindow, renders its content and asserts the colour covering most of the surface, with a canary on the number of distinct colours so a blank render cannot pass for the wrong reason.Backgroundon aFluentWindowroot, with its own canary on how many views it walks and how many windows it finds.Both seen red, on full runs: moving the declaration back onto the window reddens both, removing it altogether reddens only the render one. That second probe is what makes the pair worth having rather than one guard written twice.
Gates
12/12 · Rust 435 unchanged · C# 386 → 392 · harness 146 PASS / 0 FAIL
🤖 Generated with Claude Code