fix(tiles): a tile that joined before its pane existed resends its size

A session Run makes while the grid is open joins as a tile right away, so
the tile connects and sends its size before Run starts the pane. The
server only records a resize for a session with no PTY and spawns the pane
at 120x40, and Run's own resize step measures the parked main terminal
(display: none, so nothing). Measured live for Shell and Claude: a 97x17
tile over a 120x40 pane, for good (#464).

The chrome refresh now remembers each tile's last-seen pid and calls
TerminalTile.paneStarted() when it appears or changes. paneStarted()
forgets the sent size and sends it; a hidden tile (a zoomed neighbour)
sends nothing and keeps it forgotten, so its next fit() sends it, which a
plain fit({ force: true }) would lose. Keyed on the sessions map, so a
handleInit after an SSE drop counts too.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-10-06 19:46:04 +02:00
parent f1e5b82ecc
commit fa9d5879b3
8 changed files with 109 additions and 3 deletions
+15 -1
View File
@@ -791,6 +791,8 @@ Object.assign(CodemanApp.prototype, {
name: header.name,
zoomBtn: header.zoomBtn,
renaming: false,
// The pid this tile last saw, so a pane that starts later is noticed.
pid: this.sessions.get(sessionId)?.pid ?? null,
});
grid.ids.push(sessionId);
this._renderTileHeader(sessionId);
@@ -1187,7 +1189,19 @@ Object.assign(CodemanApp.prototype, {
_renderTileChrome() {
const grid = this._tileGrid;
if (!grid?.open) return;
for (const id of grid.tiles.keys()) this._renderTileHeader(id);
for (const [id, entry] of grid.tiles) {
this._renderTileHeader(id);
// A pane that started after the tile connected (a session Run made
// while the grid is open, an Attach from elsewhere) was spawned at the
// server's default size: the tile's own resize went out before there
// was a PTY to take it, and Run's resize measures the parked main
// terminal (nothing). Keyed on the sessions map, so a handleInit after
// an SSE drop is seen too; a render skipped during an inline tab rename
// is caught up by the rename's own render.
const pid = this.sessions.get(id)?.pid ?? null;
if (pid !== null && pid !== entry.pid) entry.tile.paneStarted?.();
entry.pid = pid;
}
},
/**