Skip to content

HiDPI audit, third wave: every drawable widget, and nineteen more that were not scaling - #213

Merged
tannevaled merged 2 commits into
mainfrom
feat/hidpi-audit-wave3
Aug 16, 2026
Merged

HiDPI audit, third wave: every drawable widget, and nineteen more that were not scaling#213
tannevaled merged 2 commits into
mainfrom
feat/hidpi-audit-wave3

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

The catalogue now holds 124 of the toolkit's 129 drawable widgets — everything except five that fail for a different reason, named below. This is the sweep the instrument was built for.

Nineteen named a defect, in three kinds

Row and strip heights that stayed put while their contents grewMenuBar, Notebook's tab strip, Table and TreeTable's header and rows, Gantt's rows/header/label column, Timeline's markers and pads, FileChooser's button strip and path bar, Window's title bar and tool buttons, Agenda's header/hour/gutter/day cells, Calendar's header/cells/nav buttons.

Whole control geometries laid out in fixed pixels, which at twice the scale sat in the top-left corner of a box twice their size — PagingToolbar's buttons and gaps, SpinButton's stepper column, TimePicker's cells, ColorPicker's square, hue strip, alpha bar and swatches.

Chart insetsChartPad, which four of the five charts read and none of them scaled, plus ScatterChart's dot and BarChart's gutter.

Two things the instrument learned

Four widgets could not be drawn from their zero value at all and took the whole audit down with a nil dereference. They are constructed properly now, and the audit recovers from a panicking Draw and reports it as a finding rather than dying — one widget's nil must not cost the other hundred-and-twenty their result.

ColorPickerWidth/Height stay logical constants — they are compile-time and cannot call scaled() — with ColorPickerNaturalSize() for the device-pixel footprint, the same shape as ExpanderHeaderHeight().

Five left out, with their measurement

Scale, RangeSlider, ColorChooser, ColorPicker and Agenda come out off by two or four device pixels at twice the scale — 12 becoming 28 where 24 was due, or one run merging into its neighbour — rather than not scaling at all, which is what every widget fixed by this audit looked like (12 staying 12).

That is a scaled metric composed with an unscaled one-pixel something: a border that thickened beside a pad that scaled, or a /2 that rounds the other way at twice the size. It needs reading those five Draws, not widening a tolerance — which would then hide the class this does catch, as an earlier version of this instrument proved by declaring the very defect it was written to find to be within tolerance. Tracked in #212.

🤖 Generated with Claude Code

tannevaled and others added 2 commits August 16, 2026 18:32
…t were not scaling

The catalogue now holds 124 of the toolkit's 129 drawable widgets -- everything
except five that fail for a different reason, named below. This is the sweep the
instrument was built for.

Nineteen named a defect, and they fall into three kinds:

  Row and strip heights that stayed put while their contents grew: MenuBar,
  Notebook's tab strip, Table and TreeTable's header and rows, Gantt's rows,
  header and label column, Timeline's markers and pads, FileChooser's button
  strip and path bar, Window's title bar and tool buttons, Agenda's header,
  hour, gutter and day cells, Calendar's header, cells and nav buttons.

  Whole control geometries laid out in fixed pixels, which at twice the scale
  sat in the top-left corner of a box twice their size: PagingToolbar's buttons
  and gaps, SpinButton's stepper column, TimePicker's cells, ColorPicker's
  square, hue strip, alpha bar and swatches.

  Chart insets: ChartPad, which four of the five charts read and none of them
  scaled, plus ScatterChart's dot and BarChart's gutter.

Four widgets could not be drawn from their zero value at all and took the whole
audit down with a nil dereference; they are constructed properly now, and the
audit recovers from a panicking Draw and reports it as a finding rather than
dying, because one widget's nil must not cost the other hundred-and-twenty
their result.

ColorPickerWidth/Height stay LOGICAL constants -- they are compile-time and
cannot call scaled() -- with ColorPickerNaturalSize() for the device-pixel
footprint, the same shape as ExpanderHeaderHeight().

Left out with their measurement: Scale, RangeSlider, ColorChooser, ColorPicker
and Agenda come out off by two or four device pixels rather than not scaling at
all. That is a scaled metric composed with an unscaled one-pixel something, a
different class from the one this catches, and it needs reading those five Draws
rather than widening a tolerance that would hide the real class.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The coverage gate is per FUNCTION, and a new accessor nobody called was at zero.
It is also the one thing worth asserting about it: at twice the scale a host
laying out to the old constants would give the picker half the room it needs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 5346e1f into main Aug 16, 2026
1 check passed
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.

1 participant