The console already drew Lucide marks, but only the console: the path table was private to pf-console-ui and the slot-to-icon map lived in its ring.rs, so neither desktop editor
could reach either. Both drew words on their discs, and the WinUI editor sat on a
purple-to-teal gradient the console's editor had already dropped as decoration. Three shells,
three pictures of one control.
This moves both tables into pf-client-core, derives everything from masters in assets/lucide/, and brings the two desktop editors onto the same footing as the console and
the phones.
What changed
The shared set. 34 Lucide masters at v0.462.0 (the version the console already pinned),
fetched unmodified. scripts/gen-lucide-assets.sh derives from them, in the shape of the
existing gen-os-icons.sh / gen-launcher-icons.sh. pf_client_core::lucide is the one
table; pf-console-ui/src/icons.rs is now aliases into it, so console and GTK cannot draw
one mark differently. overlay_actions::slot_icon is the shared slot-to-mark map.
Verified before committing: all 19 marks the console already drew fold to byte-identical
path data from their masters, so the shared table is provably the same art.
Both quick-action editors. Flat card stage instead of a gradient; discs wear the slot's
mark; the centre draws the ring's own more. WinUI gains the label band under the ring that
the other four editors already had — that's where a disc's name went when the words became
marks. Its Reset changed from a Reset… drop-down to the console's armed row
("Reset to default" → "Press again to reset").
The picker lost its second way to do one thing. The Swap with <clock> rows are gone from
both: dragging one disc onto another swaps them, and any slot can be set outright from the
catalogue above. On Windows the card title and Done button went too — the band names the slot,
the open disc is ringed white, and a pick now closes the card, which is what the GTK popover
always did.
The host card's circle carries the OS mark, not a letter. Which machine this is answers a
more useful question than which letter its name starts with, and the name is spelled out
directly underneath. A host advertising no OS chain keeps its initial.
Shell-wide icons. All 12 GTK sites and all 36 WinUI sites moved to Lucide.
The one that took three attempts: WinUI cannot rasterize UI icons
Worth recording, because it is not obvious and it is a trap for the next person.
Reactor's .icon() builds a WinUI BitmapIcon and drops it into the control with no size
set and with ShowAsMonochrome(false). So a baked PNG is stuck at one colour on every theme and renders at its source pixel count read as DIPs.
Baked at 128 px — enormous on every button. It looked correct in the settings sidebar,
which is what hid it: a NavigationViewItem's template clamps its icon, an ordinary Button does not.
Re-baked at 16 px — right size, still one fixed grey on both themes and on accent fills.
Draw the icon font. A FontIcon is sized by the control and tinted from the foreground
brush, exactly as the SymbolIcon it replaced was. White on an accent button, the theme's
colour in the sidebar, vector at any DPI.
That deleted three PNG bakes, the two-colour split, the LOCALAPPDATA materializer and its
cache, and replaced them with one codepoint per icon plus a 664 kB font.
The font reaches the exe by two routes, because ms-appx:/// resolves to the install folder
either way: build.rs stages it for a dev build, and it is checked in under packaging/assets/ for a shipped one, which pack-msix.ps1 copies into the layout the MSIX,
the installer and the portable zip are all packed from. That script now throws if it is
missing — every icon would otherwise ship as a private-use box.
The brand marks (OS, launcher) keep their baked PNGs and should: they are a fixed
colour. Only UI icons need the theme's brush.
GTK layout faults found on glass
A gtk::Box is horizontal by default and packs a single child at the start, so a child
narrower than the box's requested size lands on its left edge whatever its alignment says.
That put the centre disc's mark and the shortcut preview's chord against the left rim.
Both fixed by letting the child expand.
The slot picker collapsed to a column a character or two wide. min_content_width is ignored when the horizontal policy is Never — the scrolled window propagates its child's
minimum instead, and the child is a ListBox of AdwActionRows whose titles wrap, so its
minimum is one word. set_size_request is a minimum GTK cannot ignore.
Verification
Linux — pf-gtkflow container, pf-console-ui + pf-client-core + punktfunk-client-linux: cargo fmt --check, clippy --all-targets -D warnings, a plain build, and cargo test all
green at the final HEAD; 478 tests pass. Non-vacuity greps confirm all three crates really
recompiled.
⚠ One run aborted in rav1d::cdef::cdef_filter_block_c_erased (panic_cannot_unwind) — the
known environmental SIGABRT in the emulated amd64 image, not a test failure. The commit
involved touched only ui_quick_actions.rs, so pf-client-core's sources were identical to
the passing run either side of it; a re-run is green.
Windows — built and gated on the Arc test laptop (.221): fmt --check, clippy --all-targets -D warnings, cargo test (24 pass), and a release build. Run on glass, where
the icon font was confirmed to resolve — real glyphs, no private-use boxes.
On glass — the GTK shell ran on .21 (GNOME/Wayland) and the WinUI shell on .221 through
several rounds of visual review.
Not verified
The last four changes — picker simplification, the two GTK centring fixes, the picker width,
and the OS-mark avatar — are gated but not eyeballed on Windows: .221 went to sleep before
they landed. They are clippy- and test-clean; the WinUI half of the avatar change in particular
(white bake at 96 px on the accent circle) has not been seen rendered.
GNOME refuses headless screenshots, so the GTK side was reviewed by the user directly rather
than by me.
Notes for review
No CHANGELOG.md entry: that file is protocol/ABI/driver/embedder detail, and this is
client UI only. It belongs in docs/releases/ at release time.
Three GTK AdwStatusPage illustrations keep their Adwaita icon names. That widget takes an
icon name or a GdkPaintable, and a paintable cannot read the widget colour without a GtkSymbolicPaintable subclass — more machinery than three decorative empty states earn.
Dragging is pointer-only, so dropping the swap rows leaves a keyboard user without a
one-gesture swap. Nothing is unreachable — any slot can still be set directly from the
catalogue — but it is one step longer.
The console already drew Lucide marks, but only the console: the path table was private to
`pf-console-ui` and the slot-to-icon map lived in its `ring.rs`, so neither desktop editor
could reach either. Both drew **words** on their discs, and the WinUI editor sat on a
purple-to-teal gradient the console's editor had already dropped as decoration. Three shells,
three pictures of one control.
This moves both tables into `pf-client-core`, derives everything from masters in
`assets/lucide/`, and brings the two desktop editors onto the same footing as the console and
the phones.
## What changed
**The shared set.** 34 Lucide masters at v0.462.0 (the version the console already pinned),
fetched unmodified. `scripts/gen-lucide-assets.sh` derives from them, in the shape of the
existing `gen-os-icons.sh` / `gen-launcher-icons.sh`. `pf_client_core::lucide` is the one
table; `pf-console-ui/src/icons.rs` is now aliases into it, so console and GTK cannot draw
one mark differently. `overlay_actions::slot_icon` is the shared slot-to-mark map.
Verified before committing: all 19 marks the console already drew fold to **byte-identical**
path data from their masters, so the shared table is provably the same art.
**Both quick-action editors.** Flat card stage instead of a gradient; discs wear the slot's
mark; the centre draws the ring's own `more`. WinUI gains the label band under the ring that
the other four editors already had — that's where a disc's name went when the words became
marks. Its Reset changed from a `Reset…` drop-down to the console's armed row
("Reset to default" → "Press again to reset").
**The picker lost its second way to do one thing.** The `Swap with <clock>` rows are gone from
both: dragging one disc onto another swaps them, and any slot can be set outright from the
catalogue above. On Windows the card title and Done button went too — the band names the slot,
the open disc is ringed white, and a pick now closes the card, which is what the GTK popover
always did.
**The host card's circle carries the OS mark, not a letter.** Which machine this is answers a
more useful question than which letter its name starts with, and the name is spelled out
directly underneath. A host advertising no OS chain keeps its initial.
**Shell-wide icons.** All 12 GTK sites and all 36 WinUI sites moved to Lucide.
## The one that took three attempts: WinUI cannot rasterize UI icons
Worth recording, because it is not obvious and it is a trap for the next person.
Reactor's `.icon()` builds a WinUI `BitmapIcon` and drops it into the control **with no size
set** and with `ShowAsMonochrome(false)`. So a baked PNG is stuck at one colour on every theme
*and* renders at its source pixel count read as DIPs.
1. Baked at 128 px — enormous on every button. It looked correct in the settings sidebar,
which is what hid it: a `NavigationViewItem`'s template clamps its icon, an ordinary
`Button` does not.
2. Re-baked at 16 px — right size, still one fixed grey on both themes and on accent fills.
3. **Draw the icon font.** A `FontIcon` is sized by the control and tinted from the foreground
brush, exactly as the `SymbolIcon` it replaced was. White on an accent button, the theme's
colour in the sidebar, vector at any DPI.
That deleted three PNG bakes, the two-colour split, the `LOCALAPPDATA` materializer and its
cache, and replaced them with one codepoint per icon plus a 664 kB font.
The font reaches the exe by two routes, because `ms-appx:///` resolves to the install folder
either way: `build.rs` stages it for a dev build, and it is checked in under
`packaging/assets/` for a shipped one, which `pack-msix.ps1` copies into the layout the MSIX,
the installer and the portable zip are all packed from. That script now throws if it is
missing — every icon would otherwise ship as a private-use box.
The **brand** marks (OS, launcher) keep their baked PNGs and should: they *are* a fixed
colour. Only UI icons need the theme's brush.
## GTK layout faults found on glass
- A `gtk::Box` is horizontal by default and packs a single child at the start, so a child
narrower than the box's requested size lands on its left edge whatever its alignment says.
That put the centre disc's mark and the shortcut preview's chord against the left rim.
Both fixed by letting the child expand.
- The slot picker collapsed to a column **a character or two wide**. `min_content_width` is
*ignored* when the horizontal policy is `Never` — the scrolled window propagates its child's
minimum instead, and the child is a `ListBox` of `AdwActionRow`s whose titles wrap, so its
minimum is one word. `set_size_request` is a minimum GTK cannot ignore.
## Verification
**Linux** — `pf-gtkflow` container, `pf-console-ui` + `pf-client-core` + `punktfunk-client-linux`:
`cargo fmt --check`, `clippy --all-targets -D warnings`, a plain `build`, and `cargo test` all
green at the final HEAD; 478 tests pass. Non-vacuity greps confirm all three crates really
recompiled.
⚠ One run aborted in `rav1d::cdef::cdef_filter_block_c_erased` (`panic_cannot_unwind`) — the
known environmental SIGABRT in the emulated amd64 image, not a test failure. The commit
involved touched only `ui_quick_actions.rs`, so `pf-client-core`'s sources were identical to
the passing run either side of it; a re-run is green.
**Windows** — built and gated on the Arc test laptop (.221): `fmt --check`, `clippy
--all-targets -D warnings`, `cargo test` (24 pass), and a release build. Run on glass, where
the icon font was confirmed to resolve — real glyphs, no private-use boxes.
**On glass** — the GTK shell ran on .21 (GNOME/Wayland) and the WinUI shell on .221 through
several rounds of visual review.
### Not verified
The last four changes — picker simplification, the two GTK centring fixes, the picker width,
and the OS-mark avatar — are **gated but not eyeballed on Windows**: .221 went to sleep before
they landed. They are clippy- and test-clean; the WinUI half of the avatar change in particular
(white bake at 96 px on the accent circle) has not been seen rendered.
GNOME refuses headless screenshots, so the GTK side was reviewed by the user directly rather
than by me.
## Notes for review
- No `CHANGELOG.md` entry: that file is protocol/ABI/driver/embedder detail, and this is
client UI only. It belongs in `docs/releases/` at release time.
- Three GTK `AdwStatusPage` illustrations keep their Adwaita icon names. That widget takes an
icon name or a `GdkPaintable`, and a paintable cannot read the widget colour without a
`GtkSymbolicPaintable` subclass — more machinery than three decorative empty states earn.
- Dragging is pointer-only, so dropping the swap rows leaves a keyboard user without a
one-gesture swap. Nothing is unreachable — any slot can still be set directly from the
catalogue — but it is one step longer.
The console already drew Lucide marks, but only the console: its path
table was private to pf-console-ui and its slot-to-icon map lived in
ring.rs, so the two desktop editors that configure the same ring could
not reach either. The GTK editor drew words on its discs and the WinUI
editor drew words too — three shells, three vocabularies for one ring.
Move both tables down into pf-client-core, where every Rust client
already looks for the ring's model, and derive them from masters in
assets/lucide so a mark cannot drift between shells.
The console's icons.rs keeps aliases only for the marks its own chrome
draws. A slot's mark is no longer among them: the shared table hands
out a NAME, which `by_name` resolves — one lookup rather than an alias
per slot, and no second list to fall out of step with the first.
The icon test widens from the 19 marks the console named to all 34 the
workspace ships, because two more shells now stroke the same strings
and neither has a parser of its own to fail loudly.
The editor is meant to BE the ring, but its discs carried short words
where the in-stream ring carries icons, and it sat on a purple-to-teal
gradient the console's editor had already dropped as decoration. Two
different pictures of one control.
Discs now draw the slot's Lucide mark from the shared table, the centre
draws the ring's own `more`, and the stage is a flat card face like
every other card in this shell.
The rest of the shell's icons move to Lucide too, so one page does not
sit in a different icon language from the page before it. GTK strokes
the same path data with gsk and cairo that Skia strokes on the console,
in the widget's own CSS colour — which is why a mark on a ring disc
comes out white without a second asset: `.pf-ring-disc` says so.
Three status-page illustrations keep their Adwaita names: AdwStatusPage
takes an icon name or a paintable, and a paintable cannot read the
widget colour without a GtkSymbolicPaintable subclass — more machinery
than three decorative empty states are worth.
The stage was a diagonal purple-to-teal gradient, baked to a BMP on
disk because reactor's brushes are flat. It read as a different app,
and the console's editor had already dropped its own for that reason.
It is now a flat card face, and the bitmap writer goes with it.
The discs carried short words and no icons at all. They now draw the
slot's Lucide mark from the shared table, the centre draws the ring's
own `more`, and the name of the disc under the pointer reads out in a
band below the ring — the band the other four editors already have,
and where the name went when the words became marks.
Reset stops being a drop-down menu labelled "Reset…" and becomes the
console's armed row: "Reset to default", then "Press again to reset",
with the line about what it removes under it. Same two presses, same
words as every other client.
The rest of the shell's icons move from Segoe Fluent symbols to the
same Lucide set. WinUI cannot tint them: reactor builds every
BitmapIcon with ShowAsMonochrome(false), so each mark ships baked in
two colours — mid-grey for ordinary surfaces, white for accent-filled
buttons and the ring's dark discs.
Every button's icon rendered enormous. Reactor's `.icon()` builds a
WinUI BitmapIcon and drops it into the control with no size set, and a
BitmapIcon measures at its source PIXEL count read as DIPs — where the
SymbolIcon it replaced self-sized to its glyph. The bake was 128 px, so
every button carried a 128 DIP mark.
It looked correct in the settings sidebar, which is what hid it: a
NavigationViewItem's template clamps its icon, an ordinary Button does
not.
Bake the button marks at 16 px instead, Segoe Fluent's optical weight
in a button. The ring keeps a large bake of its own, because it draws
through Image, which takes an explicit width and height — so a big
source there buys resolution rather than size.
The test asserts the ring bake stays much heavier than the button one:
collapsing the two back into a single bake is exactly the mistake, and
it is invisible until someone opens the app.
Baking PNGs was the wrong call and it showed twice over. Reactor's
`.icon()` builds a BitmapIcon with `ShowAsMonochrome(false)` and no
size, so a baked mark is stuck at ONE colour on every theme and renders
at its source pixel count read as DIPs — a colour that never matches
the theme, and a size each control template clamps or does not.
Draw Lucide's own icon font instead. A FontIcon is sized by the control
and tinted from the foreground brush, exactly as the SymbolIcon it
replaced was: white on an accent button, the theme's colour in the
sidebar, and a vector at any DPI. The ring's discs take the same glyph
through a TextBlock, where the size is the ring's geometry and the ink
is white because a disc is dark on both themes.
Three PNG bakes, the two-colour split, the LOCALAPPDATA materializer
and its cache all go. What replaces them is a codepoint per icon in the
shared table and one 664 kB font.
The font reaches the exe by two routes, because ms-appx:/// resolves to
the install folder either way: build.rs stages it for a dev build, and
it is checked in under packaging/assets for a shipped one, which
pack-msix.ps1 copies into the layout the MSIX, the installer and the
portable zip are all packed from. That script now fails loudly if it is
missing — every icon would otherwise ship as a private-use box.
Clippy caught both, and both are the conversion's own shadow: DIM_INK
lost its last reader when the ring's mark stopped being an opacity on
an Image, and the reset button's armed/unarmed icons collapsed into the
same call once the white bake was gone. The accent fill already says
the button is armed, and the glyph takes the on-accent brush itself.
Both desktop editors offered "Swap with <clock>" rows beside the
catalogue. Dragging one disc onto another already swaps them, and any
slot can be set outright from the catalogue above — so the six rows
only made the list longer.
On Windows the card also carried a title naming the slot and a Done
button. The band above the ring names the slot being edited, the open
disc is ringed white, and a pick now closes the card, which is what the
GTK popover always did. Neither had anything left to say.
Adding the font codepoint to the shared table widened every ALL entry
to three fields; the console's parse-and-fit test still destructured
two. Test-only, so the plain build stayed green and only clippy
--all-targets caught it.
Three layout faults in the GTK editor, two of them one mistake.
A gtk::Box is HORIZONTAL by default and packs a single child at the
start, so a child narrower than the box's requested size lands on its
left edge no matter how it aligns itself. That put the centre disc's
mark and the shortcut preview's chord against the left rim. Both fixes
are the same: let the child expand, so its own centre alignment has
space to centre within.
The slot picker opened at its 320 px floor because a ScrolledWindow
asks for its minimum width unless told to propagate the natural one —
which wrapped entries like "Disconnect, keep the game running" into a
narrow column. It now sizes to the list, between a floor and a ceiling.
Which machine this is answers a more useful question than which letter
its name starts with, and the name is spelled out directly under the
circle anyway. The mark moves out of the status row, where it was the
smallest glyph on the card, and becomes its leading visual.
A host that advertises no OS chain — an older one — keeps the initial,
so nothing regresses to an empty circle.
GTK sets the icon on the Adwaita avatar, which needs show_initials off
first: the widget prefers initials whenever it is allowed to. The
generated background colour stays, and the symbolic mark recolors with
the theme like every other glyph there.
Windows has no theme-aware tint, so the bake changes colour with the
move: mid-grey was chosen to sit on a card face, and it read as smudged
the moment the mark landed on the accent fill. It bakes white now, and
taller, since it is a 22 DIP avatar face rather than a 16 DIP row glyph.
One bake, not two — the row was the grey one's only reader.
The popover collapsed to a column a character or two wide. The earlier
guess — that a ScrolledWindow asks for its minimum unless told to
propagate the natural one — was only half of it: with the horizontal
policy set to Never, `min_content_width` is IGNORED and the scrolled
window propagates its child's minimum instead. The child is a ListBox
of AdwActionRows whose titles wrap, and a wrapping label's minimum
width is one word, so the whole popover shrank to that.
`set_size_request` is a minimum GTK cannot ignore. The natural width
still grows it to fit the rows, up to the existing ceiling.
`windows-client.yml` fails to build this branch on both arm64 and x64,
four errors, all from the commit that gave the host card an OS mark:
hosts.rs:144,145 doc comment on a function parameter
pair.rs:97 avatar(&target.name) — argument #2 missing
stream.rs:37 avatar(&host) — argument #2 missing
`avatar` grew a second parameter and two of its three call sites were
not updated. Neither has an OS chain to pass: `Target` carries name,
address, port, fingerprint, MAC and profile, and no OS field. So both
pass `""`, which is what `avatar` documents as "keeps the monogram" —
and what `stream.rs`'s own header comment already said it wanted.
The parameter comment becomes `//`. Its text was worth keeping; rustc
simply will not take `///` there.
⚠ NOT compiled locally: this crate cannot be built for Windows from a
Mac, and scripts/xcheck.sh does not carry punktfunk-client-windows. CI
is the verifier.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The console already drew Lucide marks, but only the console: the path table was private to
pf-console-uiand the slot-to-icon map lived in itsring.rs, so neither desktop editorcould reach either. Both drew words on their discs, and the WinUI editor sat on a
purple-to-teal gradient the console's editor had already dropped as decoration. Three shells,
three pictures of one control.
This moves both tables into
pf-client-core, derives everything from masters inassets/lucide/, and brings the two desktop editors onto the same footing as the console andthe phones.
What changed
The shared set. 34 Lucide masters at v0.462.0 (the version the console already pinned),
fetched unmodified.
scripts/gen-lucide-assets.shderives from them, in the shape of theexisting
gen-os-icons.sh/gen-launcher-icons.sh.pf_client_core::lucideis the onetable;
pf-console-ui/src/icons.rsis now aliases into it, so console and GTK cannot drawone mark differently.
overlay_actions::slot_iconis the shared slot-to-mark map.Verified before committing: all 19 marks the console already drew fold to byte-identical
path data from their masters, so the shared table is provably the same art.
Both quick-action editors. Flat card stage instead of a gradient; discs wear the slot's
mark; the centre draws the ring's own
more. WinUI gains the label band under the ring thatthe other four editors already had — that's where a disc's name went when the words became
marks. Its Reset changed from a
Reset…drop-down to the console's armed row("Reset to default" → "Press again to reset").
The picker lost its second way to do one thing. The
Swap with <clock>rows are gone fromboth: dragging one disc onto another swaps them, and any slot can be set outright from the
catalogue above. On Windows the card title and Done button went too — the band names the slot,
the open disc is ringed white, and a pick now closes the card, which is what the GTK popover
always did.
The host card's circle carries the OS mark, not a letter. Which machine this is answers a
more useful question than which letter its name starts with, and the name is spelled out
directly underneath. A host advertising no OS chain keeps its initial.
Shell-wide icons. All 12 GTK sites and all 36 WinUI sites moved to Lucide.
The one that took three attempts: WinUI cannot rasterize UI icons
Worth recording, because it is not obvious and it is a trap for the next person.
Reactor's
.icon()builds a WinUIBitmapIconand drops it into the control with no sizeset and with
ShowAsMonochrome(false). So a baked PNG is stuck at one colour on every themeand renders at its source pixel count read as DIPs.
which is what hid it: a
NavigationViewItem's template clamps its icon, an ordinaryButtondoes not.FontIconis sized by the control and tinted from the foregroundbrush, exactly as the
SymbolIconit replaced was. White on an accent button, the theme'scolour in the sidebar, vector at any DPI.
That deleted three PNG bakes, the two-colour split, the
LOCALAPPDATAmaterializer and itscache, and replaced them with one codepoint per icon plus a 664 kB font.
The font reaches the exe by two routes, because
ms-appx:///resolves to the install foldereither way:
build.rsstages it for a dev build, and it is checked in underpackaging/assets/for a shipped one, whichpack-msix.ps1copies into the layout the MSIX,the installer and the portable zip are all packed from. That script now throws if it is
missing — every icon would otherwise ship as a private-use box.
The brand marks (OS, launcher) keep their baked PNGs and should: they are a fixed
colour. Only UI icons need the theme's brush.
GTK layout faults found on glass
gtk::Boxis horizontal by default and packs a single child at the start, so a childnarrower than the box's requested size lands on its left edge whatever its alignment says.
That put the centre disc's mark and the shortcut preview's chord against the left rim.
Both fixed by letting the child expand.
min_content_widthisignored when the horizontal policy is
Never— the scrolled window propagates its child'sminimum instead, and the child is a
ListBoxofAdwActionRows whose titles wrap, so itsminimum is one word.
set_size_requestis a minimum GTK cannot ignore.Verification
Linux —
pf-gtkflowcontainer,pf-console-ui+pf-client-core+punktfunk-client-linux:cargo fmt --check,clippy --all-targets -D warnings, a plainbuild, andcargo testallgreen at the final HEAD; 478 tests pass. Non-vacuity greps confirm all three crates really
recompiled.
⚠ One run aborted in
rav1d::cdef::cdef_filter_block_c_erased(panic_cannot_unwind) — theknown environmental SIGABRT in the emulated amd64 image, not a test failure. The commit
involved touched only
ui_quick_actions.rs, sopf-client-core's sources were identical tothe passing run either side of it; a re-run is green.
Windows — built and gated on the Arc test laptop (.221):
fmt --check,clippy --all-targets -D warnings,cargo test(24 pass), and a release build. Run on glass, wherethe icon font was confirmed to resolve — real glyphs, no private-use boxes.
On glass — the GTK shell ran on .21 (GNOME/Wayland) and the WinUI shell on .221 through
several rounds of visual review.
Not verified
The last four changes — picker simplification, the two GTK centring fixes, the picker width,
and the OS-mark avatar — are gated but not eyeballed on Windows: .221 went to sleep before
they landed. They are clippy- and test-clean; the WinUI half of the avatar change in particular
(white bake at 96 px on the accent circle) has not been seen rendered.
GNOME refuses headless screenshots, so the GTK side was reviewed by the user directly rather
than by me.
Notes for review
CHANGELOG.mdentry: that file is protocol/ABI/driver/embedder detail, and this isclient UI only. It belongs in
docs/releases/at release time.AdwStatusPageillustrations keep their Adwaita icon names. That widget takes anicon name or a
GdkPaintable, and a paintable cannot read the widget colour without aGtkSymbolicPaintablesubclass — more machinery than three decorative empty states earn.one-gesture swap. Nothing is unreachable — any slot can still be set directly from the
catalogue — but it is one step longer.