The Parametric EQ has a tab of its own since #370, but Play is in the
sound FX's tab. A tab that can float keeps both in view. There is one
editor per kind, so the kind's pane is lent to the window and given
back on Dock, the way fullscreen moves the game view.
- A right-click on a document's tab opens a menu with Float and Close.
`DocumentTab` passes the press to `TabStrip`'s new `onMenu`.
- `FloatWindow` sits on the overlay. Its title bar moves it, its lower
right corner sizes it, Dock and the x close it. A press brings it to
the front.
- `floating.ts` is the pure part: where a window opens, held whole on
the screen, sized down to 320 x 200. Nothing of it is remembered.
- One window per kind. Another document of that kind opens there and
closes the one it had. Its tab, if it had one, leaves the row.
- When the row showed the kind, it shows the nearest document whose
kind is not in a window, else the scene (`neighbourOf`).
- Delete, Copy and Paste go to the window pressed last, and back to
the tab showing after a press in the editor (`keyTab`).
- Previews tick and redraw for a kind in a window as for the tab
showing. Fullscreen hides the windows. Loading a project or signing
out closes them.
- Only documents float, Scene and Game stay in the row.
- Hooks: `floatWindows`, `floatDocument`, `keyTarget`.
Tests:
- Unit documents: 16 green, 5 new. Counter-check: `neighbourOf`
without the window check turns its test red.
- e2e 44 (melektaus-atx, after steps 1-12 and 37): ALL PASSED,
505 checks in the chain, 6 new for float, move, size, another
texture, keys, Dock and x.
- Gate (melektaus-atx): CHECK EXIT 0, 274 files, 4236 tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a screen scaled to 125 % or 150 % the editor looked soft beside
a page the browser draws itself. The layout counts in whole CSS
pixels, and most of those fall between two device pixels there. The
GPU averages both: text loses its edges, and a 1 px line becomes a
pixel and a half of mixed colour. Now text and boxes are rounded to
device pixels, and a line is one device pixel wide.
- ui/pixelGrid.ts holds the rule. crispText() makes a text with
Pixi's roundPixels, crisp() does the same for a Graphics of
upright boxes, and hairline() is the width of one device pixel.
- Every text of the interface is made with crispText() instead of
new Text().
- crisp() only rounds where the scale is not a whole number. At
100 % and 200 % nothing changes.
- drawControlBox, drawHeaderBar and drawSectionBand draw their
lines a hairline wide and flush with the edge. The widgets that
draw lines of their own do the same.
- Two bands share exactly the line they draw, and a column still
ends on a whole pixel.
- The stage is nudged by 1/32 px where the scale is not whole. At
150 % every odd pixel is an exact half, and without the nudge one
band came out a row shorter than its neighbours.
- Curves, icons and everything of the game stay unrounded. Rounding
their points would bend them.
- The harness takes deviceScaleFactor as an option, and the hooks
deviceColumn, edgeContrast and pixelGrid read the frame as the
screen gets it.
Not in here: the subpixel smoothing a browser gives its own text.
Pixi draws a text into a transparent picture first, and there only
greyscale smoothing is possible.
Measured at 150 %, edge contrast before and after: top bar 31.5 to
47.8, the lists on the left 68.6 to 86.4, inspector 27.6 to 38.4.
At 100 % it is 46.5, 90.1 and 37.9, and the picture there is the
same as before pixel for pixel, apart from the fps display.
Tests:
- Gate on melektaus-atx: 206 files, 3114 tests (3104 + 10), exit 0
- Full run on melektaus-atx: 1655 of 1656 checks passed, smokes
24/19/21. The one that failed was a condition of the new step
62 itself: it scrolled an inspector that had nothing to scroll.
The step now makes the window lower for that reading.
- e2e 61,62 after that fix: 14 checks. The full run was not
repeated, and CI is switched off for now.
- Ten unit tests, nine in tests/ui/pixel-grid.test.ts
- Eight e2e checks in the new step 62, which runs at 150 %
- Eleven unit counter-probes fail tests
- Four browser counter-probes fail their checks. They ran before
the fix to step 62 and were not repeated for it.
- Screenshots looked at for 125 % and 150 %
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>