use tmux resize-window for explicit window size control
test / unit + widget + golden + a11y (push) Failing after 28s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped

tmux determines window size from its client, not the PTY winsize.
TIOCSWINSZ + SIGWINCH on the master fd has no effect on tmux's
internal dimensions. Use tmux resize-window -t <session> -x -y
to explicitly set the window size on resize.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jeroen Schweitzer
2026-05-01 13:17:56 +02:00
co-authored by Claude Opus 4.6
parent 956279eca4
commit 56d13c71ef
2 changed files with 12 additions and 9 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"exported_at": "2026-05-01T11:11:26Z", "exported_at": "2026-05-01T11:17:56Z",
"decisions": [ "decisions": [
{ {
"id": "D-1", "id": "D-1",
+11 -8
View File
@@ -48,6 +48,7 @@ class _ClaudePaneState extends State<ClaudePane> {
late final Terminal _terminal; late final Terminal _terminal;
StreamSubscription<DaemonEvent>? _eventSub; StreamSubscription<DaemonEvent>? _eventSub;
String? _paneId; String? _paneId;
String? _sessionName;
String? _error; String? _error;
String _statusLine = 'attaching…'; String _statusLine = 'attaching…';
@@ -119,7 +120,7 @@ class _ClaudePaneState extends State<ClaudePane> {
repoRoot = (rootResp.data['path'] as String?) ?? repoRoot; repoRoot = (rootResp.data['path'] as String?) ?? repoRoot;
} }
final sessionName = widget.isPrimary _sessionName = widget.isPrimary
? primarySessionName(repoRoot) ? primarySessionName(repoRoot)
: secondarySessionName(repoRoot, widget.secondaryIndex!); : secondarySessionName(repoRoot, widget.secondaryIndex!);
@@ -133,7 +134,7 @@ class _ClaudePaneState extends State<ClaudePane> {
'new-session', 'new-session',
'-A', '-A',
'-s', '-s',
sessionName, _sessionName!,
'-x', '$cols', '-x', '$cols',
'-y', '$rows', '-y', '$rows',
]; ];
@@ -144,7 +145,7 @@ class _ClaudePaneState extends State<ClaudePane> {
'cwd': repoRoot, 'cwd': repoRoot,
'cols': _terminal.viewWidth, 'cols': _terminal.viewWidth,
'rows': _terminal.viewHeight, 'rows': _terminal.viewHeight,
'title': sessionName, 'title': _sessionName,
}); });
if (!resp.ok) { if (!resp.ok) {
@@ -157,7 +158,7 @@ class _ClaudePaneState extends State<ClaudePane> {
'cwd': repoRoot, 'cwd': repoRoot,
'cols': _terminal.viewWidth, 'cols': _terminal.viewWidth,
'rows': _terminal.viewHeight, 'rows': _terminal.viewHeight,
'title': sessionName, 'title': _sessionName,
}); });
if (!resp.ok) { if (!resp.ok) {
setState(() { setState(() {
@@ -167,7 +168,7 @@ class _ClaudePaneState extends State<ClaudePane> {
} }
setState(() => _statusLine = 'no-tmux · fresh every launch'); setState(() => _statusLine = 'no-tmux · fresh every launch');
} else { } else {
setState(() => _statusLine = 'tmux · $sessionName'); setState(() => _statusLine = 'tmux · $_sessionName');
} }
if (!mounted) return; if (!mounted) return;
@@ -243,9 +244,11 @@ class _ClaudePaneState extends State<ClaudePane> {
final id = _paneId; final id = _paneId;
if (id == null) return; if (id == null) return;
_ipc()?.request('pane.resize', args: {'id': id, 'cols': cols, 'rows': rows}); _ipc()?.request('pane.resize', args: {'id': id, 'cols': cols, 'rows': rows});
// tmux doesn't re-read PTY winsize on SIGWINCH — it needs an // tmux sizes windows by client, not PTY winsize. Explicitly
// explicit refresh-client to update its internal window size. // resize the tmux window to match the TerminalView dimensions.
Process.run('tmux', ['refresh-client', '-C', '$cols,$rows']); if (_sessionName != null) {
Process.run('tmux', ['resize-window', '-t', _sessionName!, '-x', '$cols', '-y', '$rows']);
}
}); });
} }