Icons went soft under UI_SCALE while the clock text beside them stayed sharp, which is visible on a 24" monitor even if it hides on a TV. new_from_file_at_scale rasterises an SVG at its *logical* size. The artwork is vector, but by the time sway scaled the session it was already a fixed raster, and the compositor enlarged that. Text never had the problem because GTK draws it at the real density. GTK 3 has no fractional scaling, so sway advertises the ceiling integer scale and scales the finished buffer down. Measured under sway: scale factor 1 at output scale 1.0, and 2 at 1.25, 1.5 and 2.0. So each icon is now rasterised at size x scale_factor physical pixels and handed to GTK as a cairo surface carrying that device scale. The icon lands at the real density; its logical size, and the whole dock layout, is unchanged. Icons redraw on notify::scale-factor as well as at realize, since the scale factor is not known until a widget is on a display and changes if UI_SCALE is changed under a running session. Browser, DVD, LIVE and all six DVD control icons go through it, in a shared module so the dock and the DVD session cannot diverge. The throbber is drawn rather than loaded and had the same flaw, so it draws on a device-scaled surface too rather than being the one soft thing left in a sharp dock. The artwork is untouched. Verified by rendering the dock under sway at 1.0, 1.25, 1.5 and 2.0 against the previous build: apparent icon size is identical at every scale (28, 35, 42, 56 px), 1.0 is unchanged pixel-for-pixel, and peak edge contrast on the Chrome icon goes from 60 to 99 at 1.25, 49 to 83 at 1.5, and 37 to 82 at 2.0 out of 255. The DVD control bar was checked the same way. Also records that Wonder Ink session-only cookies are confirmed working on the endpoint, which settles the question 0.1.34 shipped as unverified and tells us the session is in cookies rather than localStorage. Co-Authored-By: Claude Opus 5 <[email protected]>
107 lines
4.0 KiB
Markdown
107 lines
4.0 KiB
Markdown
# UI scale
|
||
|
||
Every classroom gets the same design at a size that suits its TV. A 32"
|
||
panel a few feet from the children and a 65" set across a hall want
|
||
different sizes of the same room, not different rooms.
|
||
|
||
## Changing it
|
||
|
||
Edit `/etc/ekklesia-classroom/device.conf` on that endpoint:
|
||
|
||
```
|
||
UI_SCALE=1.25
|
||
```
|
||
|
||
Then restart the classroom shell:
|
||
|
||
```
|
||
sudo systemctl restart getty@tty1
|
||
```
|
||
|
||
That ends the session and the autologin brings it straight back at the
|
||
new size. A reboot does the same. Nothing else needs touching, and no
|
||
CSS or source file is ever edited to change a room's size.
|
||
|
||
## What it scales
|
||
|
||
**Everything.** UI_SCALE is a property of the television, not of one
|
||
program, so it is applied where it reaches the whole session: sway's
|
||
output scale.
|
||
|
||
- Chrome's tabs, omnibox, toolbar icons and menus
|
||
- VLC, and any other application's own interface
|
||
- The dock, the clock, notifications and the DVD control bar
|
||
- Mouse hit targets, because they scale with the widgets
|
||
|
||
The display mode is **not** changed. The panel stays at its native
|
||
1920x1080. Only the logical coordinate space shrinks, which is what
|
||
makes everything drawn in it larger:
|
||
|
||
| UI_SCALE | Logical space | Roughly |
|
||
| --- | --- | --- |
|
||
| 0.8 | 2400x1350 | Small or close-up panel |
|
||
| 1.0 | 1920x1080 | Default. 32–50" classroom TV |
|
||
| 1.25 | 1536x864 | Large room, or a set viewed from further back |
|
||
| 1.5 | 1280x720 | 65"+ |
|
||
|
||
Anything outside 0.8–1.5 is clamped, and anything that is not a number
|
||
falls back to 1.0, so a typo in device.conf cannot produce an unusable
|
||
shell.
|
||
|
||
## Measured
|
||
|
||
Against 1920x1080 under sway, with Chrome 152:
|
||
|
||
| | 1.0 | 1.25 | 1.5 |
|
||
| --- | --- | --- | --- |
|
||
| Chrome tab strip | 40px | 49px (x1.23) | 59px (x1.48) |
|
||
| sway title bar | 25px | 31px (x1.24) | 38px (x1.52) |
|
||
| Classroom dock | 74px | 92px (x1.24) | 110px (x1.49) |
|
||
|
||
Everything scales once, together.
|
||
|
||
## Why our own surfaces do not scale themselves
|
||
|
||
`classroom-scale` runs first in the sway config and sets the output
|
||
scale. From then on the dock, the notifications and the DVD control bar
|
||
are measured in the same logical pixels sway is already scaling, so they
|
||
must render **unscaled** — `SHELL_SCALE` in `classroom_config.py` is
|
||
`1.0`. Scaling them again would apply UI_SCALE twice and the dock would
|
||
come out half again too big.
|
||
|
||
The stylesheet templates still take a scale, and `SHELL_SCALE` is the
|
||
one place it comes from. If compositor scaling ever has to be abandoned,
|
||
setting it back to `ui_scale(config)` restores per-surface scaling
|
||
without touching a template.
|
||
|
||
## Tradeoffs
|
||
|
||
**GTK 3 has no fractional scaling.** At UI_SCALE=1.5 sway advertises an
|
||
integer scale of 2 to GTK, which renders at 2x, and sway scales the
|
||
result down to 1.5x. The dock is the right size but very slightly softer
|
||
than at 1.0. On a TV at classroom distance this is not visible.
|
||
|
||
Icons have to be drawn for that themselves. `new_from_file_at_scale`
|
||
rasterises an SVG at its *logical* size, and the compositor then
|
||
enlarges that finished raster — which made icons visibly soft on a 24"
|
||
monitor while the clock text beside them stayed sharp. `classroom_icons`
|
||
renders each SVG at `size x scale_factor` physical pixels and hands GTK
|
||
a cairo surface carrying that device scale, so the artwork lands at the
|
||
display's real density and the layout is unchanged. Measured on the
|
||
Chrome icon, peak edge contrast at UI_SCALE 1.5 went from 49 to 83 out
|
||
of 255, and at 2.0 from 37 to 82; at 1.0 it is identical to before.
|
||
|
||
**XWayland is softer at fractional scale.** X11 clients have no concept
|
||
of a fractional output scale, so sway renders them at the logical size
|
||
and scales the buffer. Measured on terminal text, scale 1.5 produced
|
||
about 50% more intermediate-tone pixels than scale 1.0 — real, modest
|
||
softening.
|
||
|
||
VLC is the only XWayland application in the classroom, and in DVD mode
|
||
none of its interface is on screen: only video, from a 720x480 disc
|
||
being upscaled regardless. Chrome runs on Wayland natively and is sharp
|
||
at every scale, which is what matters for reading.
|
||
|
||
At UI_SCALE=1.0 nothing is scaled at all and the session is identical to
|
||
one with no scaling.
|