Skip to content

Tell the toolkit what a point is worth (#49) - #50

Merged
tannevaled merged 1 commit into
mainfrom
feat/connect-metric-scale
Aug 16, 2026
Merged

Tell the toolkit what a point is worth (#49)#50
tannevaled merged 1 commit into
mainfrom
feat/connect-metric-scale

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Closes #49.

A back-end honouring NativeScale hands the widget tree a framebuffer at the panel's own resolution. The tree lays out in those pixels, so unless something tells it that a point is now two of them, every padding, radius, border and control stays at its logical size and the interface comes out half as large on the sharpest screens. Window crisp, UI tiny — worse than not having asked.

toolkit.SetMetricScale is the documented knob for exactly this, and nothing called it: across window, toolkit and the reader, the only callers were two lines of a toolkit test.

Where

The back-end is the only party that knows the scale, so the back-end sets it — at the point where each one learns it:

back-end when
X11 at bring-up, once Xft.dpi is read
Wayland when the compositor says which screen the surface is on, and again when it changes
Windows, macOS in Open

Only when the caller asked for NativeScale. A window that never asked leaves the setting alone, which is asserted: it is process-wide, and an application that was not thinking about DPI must not find its metrics doubled because something else in the binary was.

Why it is safe to set now

toolkit#209 (v0.163.0) gave the toolkit one scale: Menu and Browser had their own Scale field and answered only to it, so a host that set both risked scaling twice. The field now replaces the global rather than falling back to 1.

Measured, not assumed

The thing #49 said had to be measured first. A reader frame rendered at scale 2 with the toolkit told nothing, and again with it told 2:

800x600 frame: 804 of 480000 pixels differ (0.17%)
they lie within (425,21)-(774,74), across 54 of 600 rows

One band, one widget's worth of chrome drawing its borders at the size the screen deserves, layout unmoved. A double scale would have moved a large share of the frame — two orders of magnitude apart, which is why the guard is a loose bound and not a golden image. The measurement lives in the reader as a permanent test (go-news-reader/reader).

🤖 Generated with Claude Code

A back-end honouring NativeScale hands the widget tree a framebuffer at the
panel's own resolution. The tree lays out in those pixels, so unless something
tells it that a point is now two of them, every padding, radius, border and
control stays at its logical size and the interface comes out half as large on
the sharpest screens. Window crisp, UI tiny -- worse than not having asked.

toolkit.SetMetricScale is the documented knob for exactly this, and nothing
called it: across window, toolkit and the reader the only callers were two lines
of a toolkit test. The back-end is the only party that knows the scale, so the
back-end sets it -- at the point where each one learns it. X11 at bring-up,
Wayland when the compositor says which screen the surface is on (and again when
it changes), Windows and macOS in Open.

Only when the caller asked for NativeScale. A window that never asked leaves the
setting alone, which is asserted: it is process-wide, and an application that
was not thinking about DPI must not find its metrics doubled because something
else in the binary was.

Safe to set now that toolkit v0.163.0 has ONE scale: Menu and Browser defer to
the global instead of answering only to their own field, so a host that sets
both is not scaling anything twice.

Measured, not assumed. A reader frame rendered at scale 2 with the toolkit told
nothing, and again with it told 2, differs in 0.17% of its pixels, in a single
band of 54 rows: chrome drawing its borders at the size the screen deserves,
with the layout unmoved. A double scale would have moved a large share of the
frame. The measurement lives in the reader as a guard.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 3b91eda into main Aug 16, 2026
23 checks passed
tannevaled added a commit that referenced this pull request Aug 17, 2026
A back-end honouring NativeScale hands the widget tree a framebuffer at the
panel's own resolution. The tree lays out in those pixels, so unless something
tells it that a point is now two of them, every padding, radius, border and
control stays at its logical size and the interface comes out half as large on
the sharpest screens. Window crisp, UI tiny -- worse than not having asked.

toolkit.SetMetricScale is the documented knob for exactly this, and nothing
called it: across window, toolkit and the reader the only callers were two lines
of a toolkit test. The back-end is the only party that knows the scale, so the
back-end sets it -- at the point where each one learns it. X11 at bring-up,
Wayland when the compositor says which screen the surface is on (and again when
it changes), Windows and macOS in Open.

Only when the caller asked for NativeScale. A window that never asked leaves the
setting alone, which is asserted: it is process-wide, and an application that
was not thinking about DPI must not find its metrics doubled because something
else in the binary was.

Safe to set now that toolkit v0.163.0 has ONE scale: Menu and Browser defer to
the global instead of answering only to their own field, so a host that sets
both is not scaling anything twice.

Measured, not assumed. A reader frame rendered at scale 2 with the toolkit told
nothing, and again with it told 2, differs in 0.17% of its pixels, in a single
band of 54 rows: chrome drawing its borders at the size the screen deserves,
with the layout unmoved. A double scale would have moved a large share of the
frame. The measurement lives in the reader as a guard.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled deleted the feat/connect-metric-scale branch August 17, 2026 10:25
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.

NativeScale gives a plain widget tree a 2× framebuffer and 1× metrics, so everything comes out half-size

1 participant