mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-05 15:09:42 +02:00
fix(terminal): compare capture geometry only on a visible-frame response
Only a visible-frame capture positions its rows absolutely, so only that frame can be damaged by a terminal of the wrong size. A `full=1` body is linear scrollback closed by a relative cursor move, which is relative precisely so the browser's row count need not match the pane's, and a `history` body is the byte stream, which carries no row alignment to protect. The geometry comparison ran on all three, so it fired most often on the one response it cannot help: `_fullHistoryLoaded` is empty on the first select of every non-shell session per page, and a session whose pane a desktop tab holds too tall to ever fit then paid a second whole-scrollback capture, reset and replay on every page load and every first tab switch. `framePositionsRowsAbsolutely` gates both the captured-geometry comparison and `sizeMovedUnderLoad`. A size that moved under a byte-stream or scrollback replay is healed by xterm's own reflow plus the SIGWINCH the trailing `sendResize` already sends. A pane WIDER than the terminal damages the same frame a second way, so `captureCols` is now compared rather than only logged. `formatPaneSnapshot` paints each row out to the pane's own width, so a narrower browser wraps every painted row, and the wrap on the last one scrolls the whole frame up by a row. The terminal response no longer falls back to `session.ptyCols`/`ptyRows` when the capture reported no geometry. The cursor query is what produces the absolute addressing in the first place, so a capture that lost it returned a raw frame that was never positioned, and a byte-history response was never positioned either. Naming the session's own PTY size there described a frame that does not exist and invited a repair for damage that is not present. `_ptyCols` is also written only by `resize()` while the PTY is spawned at the size queried from tmux, so it can be wrong on its own terms. Both fields are now absent instead, and the `Session` getters added for that fallback go with it. Two browser cases cover the new behaviour and each fails without its fix: a `mux-full-history` response with both dimensions mismatched asserts one fetch (two without the gate), and a `mux-visible` response wider than the terminal but short enough to fit asserts two (one without the width comparison). Corrects a claim in the comment above `capturedGeometry` in tmux-manager.ts. Both replay paths do not address rows absolutely; the full-history one ends in a relative move, which is the whole reason the gate is right. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3edf9aae2f
commit
5cfb98fb8b
@@ -10,13 +10,27 @@ its own height onto its last line, so the overflow rows overwrite one another
|
||||
and the rows underneath are lost. Against a 50-row pane, a 30-row terminal
|
||||
rendered 28 of a 45-line command and drew the surviving frame twice.
|
||||
|
||||
Nothing in the response said what height the frame was built for, so the client
|
||||
could not detect this. A capture now reports the geometry it was really taken at
|
||||
through `capturedGeometry` on `PaneCaptureOptions`, and the terminal response
|
||||
carries it as `captureCols` and `captureRows`. When the captured pane is taller
|
||||
than the terminal, or the size that produced the capture did not survive the
|
||||
load, `selectSession` replays once at the size that stuck. `resizeRetry` caps
|
||||
that at one attempt, so two competing fits cannot trade replays forever.
|
||||
A pane wider than the terminal damages the same frame a second way. Each row is
|
||||
painted out to the pane's own width, so a narrower terminal wraps every painted
|
||||
row, and the wrap on the last one scrolls the whole frame up by a row.
|
||||
|
||||
Nothing in the response said what geometry the frame was built for, so the client
|
||||
could not detect either case. A capture now reports the geometry it was really
|
||||
taken at through `capturedGeometry` on `PaneCaptureOptions`, and the terminal
|
||||
response carries it as `captureCols` and `captureRows`. When the captured pane is
|
||||
taller or wider than the terminal, or the size that produced the capture did not
|
||||
survive the load, `selectSession` replays once at the size that stuck.
|
||||
`resizeRetry` caps that at one attempt, so two competing fits cannot trade
|
||||
replays forever.
|
||||
|
||||
That comparison runs on a visible-frame response only. A full-history response is
|
||||
linear scrollback closed by a relative cursor move, and a byte-history response
|
||||
carries no row alignment at all, so a size mismatch damages neither and a replay
|
||||
repairs neither. Gating on the source matters because the first load of every
|
||||
non-shell session per page takes the full-history path, where an ungated
|
||||
comparison would capture the whole tmux scrollback a second time. A response
|
||||
whose capture reported no geometry now omits both fields rather than naming the
|
||||
session's own PTY size, which describes no frame that was ever positioned.
|
||||
|
||||
That repairs the case where a capture won a race against the resize meant to
|
||||
precede it. It does not repair a capture whose pane was too tall because
|
||||
|
||||
Reference in New Issue
Block a user