perf(resize): a window resize fits each grid tile once, not twice

A window resize reached every grid tile twice: the grid's own
ResizeObserver refits them (tile-grid.js _scheduleTileGridRefit, 150 ms
trailing), then the main terminal's trailing resize timer (terminal-ui.js
throttledResize, 300 ms) ran _forEachTile(fit) over them again. The second
pass re-measured six panes and sent nothing (_lastSentDims dedupes the PTY
side). The timer now refits the split's Pane B only ({ grid: false }); grid
tiles exist only while the grid owns the terminal, and then its observer
already covers them.

Measured (6 tiles, 20-step window resize and back, headless, tileperf):
fit() 12 -> 6 per resize burst; PTY resizes 6 -> 6; browser layouts
unchanged within noise (85/75 -> 92/71), so this removes wasted calls only.

Live, this code (6 tiles, tileperf): a 20-step window resize, and the resize
back, each ran fit() 6 times and sent 6 PTY resizes (12 and 6 before).

Test: the timer's one _forEachTile call passes { grid: false } (it lives
inside initTerminal, so read from source like the #464 geometry tests);
mutation-checked.

Scope: PR 2. The line is in terminal-ui.js (a PR 1 seam), but on PR 1 alone
_forEachTile reaches only the split's Pane B: the double refit needs the grid.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-10-07 06:30:09 +02:00
parent 5650be5200
commit 409fd658f2
2 changed files with 23 additions and 2 deletions
+5 -2
View File
@@ -1428,8 +1428,11 @@ Object.assign(CodemanApp.prototype, {
// frame — this observer only ever measured Pane A's container, so
// without this call Pane B never learned about a window resize, an
// Alt+B sidebar toggle, or a tab-rail drag, and its PTY silently
// stayed at whatever size it was last dragged to.
this._forEachTile?.((tile) => tile.fit());
// stayed at whatever size it was last dragged to. Grid tiles are left
// out: the grid's own observer (tile-grid.js _scheduleTileGridRefit)
// refits every one of them on the same resize, and a second fit here
// only re-measured six panes to send nothing.
this._forEachTile?.((tile) => tile.fit(), { grid: false });
}, 300); // Trailing-edge: only fire after 300ms of no resize events
};