diff --git a/src/textual_webterm/local_server.py b/src/textual_webterm/local_server.py index ca38d94..4775419 100644 --- a/src/textual_webterm/local_server.py +++ b/src/textual_webterm/local_server.py @@ -445,9 +445,6 @@ class LocalServer: if session is None or not session.is_running(): self.session_manager.on_session_end(session_id) session_id = None - elif hasattr(session, "force_redraw"): - # Force redraw on reconnect to refresh tmux/screen displays - await session.force_redraw() session_created = session_id is not None diff --git a/src/textual_webterm/terminal_session.py b/src/textual_webterm/terminal_session.py index 7687a17..2482b4b 100644 --- a/src/textual_webterm/terminal_session.py +++ b/src/textual_webterm/terminal_session.py @@ -139,13 +139,15 @@ class TerminalSession(Session): await asyncio.sleep(0.1) async def set_terminal_size(self, width: int, height: int) -> None: + """Set terminal size and force a redraw.""" # Track the size for reconnection self._last_width = width self._last_height = height - # First resize the PTY (blocking call in executor) loop = asyncio.get_running_loop() + # Toggle size to force tmux to redraw, then set final size + await loop.run_in_executor(None, self._set_terminal_size, width - 1, height) await loop.run_in_executor(None, self._set_terminal_size, width, height) - # Then resize pyte screen to match (after PTY resize completes) + # Resize pyte screen to match async with self._screen_lock: self._screen.resize(height, width) diff --git a/tests/test_terminal_session.py b/tests/test_terminal_session.py index da6fe54..190c4b8 100644 --- a/tests/test_terminal_session.py +++ b/tests/test_terminal_session.py @@ -377,7 +377,10 @@ class TestTerminalSession: with patch.object(loop, "run_in_executor", new=AsyncMock()) as run_in_executor: await session.set_terminal_size(80, 24) - run_in_executor.assert_awaited_once_with(None, session._set_terminal_size, 80, 24) + # set_terminal_size toggles size (-1 then restore) to force redraw + assert run_in_executor.await_count == 2 + run_in_executor.assert_any_await(None, session._set_terminal_size, 79, 24) + run_in_executor.assert_any_await(None, session._set_terminal_size, 80, 24) def test__set_terminal_size_calls_ioctl(self): from textual_webterm.terminal_session import TerminalSession