Skip to content

Commit 84abdbb

Browse files
bitplaneclaude
andcommitted
Fix terminal resize handling by sending SIGWINCH to asciinema process
Replace approach of signaling pane processes with proper SIGWINCH signal to the asciinema recording process itself. This correctly triggers "r" (resize) events in cast files when switching between panes of different dimensions. - Send SIGWINCH to asciinema_pid instead of pane process group - Asciinema detects terminal size changes and records resize events - Ensures proper playback with correct terminal dimensions - Fix recordings showing wrong terminal size when switching panes This resolves issues where pane switching didn't generate resize events in recordings, causing playback to display with incorrect dimensions. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 07d0fd4 commit 84abdbb

2 files changed

Lines changed: 23 additions & 6 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "tvmux"
33
description = "terminal multiplexer recorder"
4-
version = "0.5.0"
4+
version = "0.5.1"
55
authors = [
66
{ name = "Gareth Davidson", email = "gaz@bitplane.net" }
77
]

src/tvmux/models/recording.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,23 @@ def switch_pane(self, new_pane_id: str):
121121

122122
self.active_pane = new_pane_id
123123

124+
# Send SIGWINCH to the new pane's process group to trigger resize handling
125+
self._send_sigwinch(new_pane_id)
126+
127+
def _send_sigwinch(self, pane_id: str):
128+
"""Send SIGWINCH signal to asciinema process to handle terminal resize in recording."""
129+
if not self.asciinema_pid:
130+
logger.warning("No asciinema process to send SIGWINCH to")
131+
return
132+
133+
try:
134+
subprocess.run([
135+
"kill", "-SIGWINCH", str(self.asciinema_pid)
136+
], check=True)
137+
logger.debug(f"Sent SIGWINCH to asciinema process {self.asciinema_pid} for pane {pane_id}")
138+
except subprocess.CalledProcessError as e:
139+
logger.warning(f"Failed to send SIGWINCH to asciinema process {self.asciinema_pid}: {e}")
140+
124141
def stop(self):
125142
"""Stop recording."""
126143
if not self.active:
@@ -225,7 +242,7 @@ def _dump_pane(self, pane_id: str):
225242
f.write("\033[?7h") # Enable auto-wrap mode
226243
f.write("\033[?25h") # Show cursor (will be overridden later if needed)
227244

228-
# Get primary buffer content
245+
# 4. Get and send primary buffer content
229246
primary_result = subprocess.run([
230247
"tmux", "capture-pane", "-t", pane_target, "-e", "-p"
231248
], capture_output=True, text=True)
@@ -234,11 +251,11 @@ def _dump_pane(self, pane_id: str):
234251
primary_content = primary_result.stdout.rstrip('\n')
235252
f.write(primary_content)
236253

237-
# 4. If in alternate screen mode, switch to it
254+
# 5. If in alternate screen mode, switch to it
238255
if alternate_on:
239256
f.write("\033[?1049h") # Enable alternate screen buffer
240257

241-
# 5. If alt mode is on, dump the contents of the alt buffer
258+
# 6. If alt mode is on, dump the contents of the alt buffer
242259
alt_result = subprocess.run([
243260
"tmux", "capture-pane", "-t", pane_target, "-a", "-e", "-p"
244261
], capture_output=True, text=True)
@@ -251,11 +268,11 @@ def _dump_pane(self, pane_id: str):
251268
# Use alternate screen cursor position
252269
cursor_x, cursor_y = alt_saved_x, alt_saved_y
253270

254-
# 6. Set up scroll region, cursor visibility, raw mode, etc.
271+
# 7. Set up scroll region, cursor visibility, raw mode, etc.
255272
# TODO: Get actual scroll region from tmux if available
256273
# For now, just handle cursor visibility
257274

258-
# 7. Reposition the text cursor
275+
# 8. Reposition the text cursor
259276
config = get_config()
260277
if config.annotations.include_cursor_state:
261278
row = cursor_y + 1 # Convert to 1-based

0 commit comments

Comments
 (0)