2020from textual .driver import Driver
2121from textual .drivers ._writer_thread import WriterThread
2222from textual .geometry import Size
23+ from textual .message import Message
24+ from textual .messages import TerminalSupportInBandWindowResize
2325
2426if TYPE_CHECKING :
2527 from textual .app import App
@@ -59,6 +61,7 @@ def __init__(
5961 # need to know that we came in here via a SIGTSTP; this flag helps
6062 # keep track of this.
6163 self ._must_signal_resume = False
64+ self ._in_band_window_resize = False
6265
6366 # Put handlers for SIGTSTP and SIGCONT in place. These are necessary
6467 # to support the user pressing Ctrl+Z (or whatever the dev might
@@ -135,6 +138,22 @@ def _enable_bracketed_paste(self) -> None:
135138 """Enable bracketed paste mode."""
136139 self .write ("\x1b [?2004h" )
137140
141+ def _query_in_band_window_resize (self ) -> None :
142+ self .write ("\x1b [?2048$p" )
143+
144+ def _enable_in_band_window_resize (self ) -> None :
145+ self .write ("\x1b [?2048h" )
146+
147+ def _enable_line_wrap (self ) -> None :
148+ self .write ("\x1b [?7h" )
149+
150+ def _disable_line_wrap (self ) -> None :
151+ self .write ("\x1b [?7l" )
152+
153+ def _disable_in_band_window_resize (self ) -> None :
154+ if self ._in_band_window_resize :
155+ self .write ("\x1b [?2048l" )
156+
138157 def _disable_bracketed_paste (self ) -> None :
139158 """Disable bracketed paste mode."""
140159 self .write ("\x1b [?2004l" )
@@ -197,6 +216,8 @@ def _stop_again(*_) -> None:
197216 loop = asyncio .get_running_loop ()
198217
199218 def send_size_event () -> None :
219+ if self ._in_band_window_resize :
220+ return
200221 terminal_size = self ._get_terminal_size ()
201222 width , height = terminal_size
202223 textual_size = Size (width , height )
@@ -253,7 +274,9 @@ def on_terminal_resize(signum, stack) -> None:
253274 send_size_event ()
254275 self ._key_thread .start ()
255276 self ._request_terminal_sync_mode_support ()
277+ self ._query_in_band_window_resize ()
256278 self ._enable_bracketed_paste ()
279+ self ._disable_line_wrap ()
257280
258281 # Appears to fix an issue enabling mouse support in iTerm 3.5.0
259282 self ._enable_mouse_support ()
@@ -330,6 +353,8 @@ def disable_input(self) -> None:
330353 def stop_application_mode (self ) -> None :
331354 """Stop application mode, restore state."""
332355 self ._disable_bracketed_paste ()
356+ self ._enable_line_wrap ()
357+ self ._disable_in_band_window_resize ()
333358 self .disable_input ()
334359
335360 if self .attrs_before is not None :
@@ -401,9 +426,9 @@ def process_selector_events(
401426 # This can occur if the stdin is piped
402427 break
403428 for event in feed (unicode_data ):
404- self .process_event (event )
429+ self .process_message (event )
405430 for event in tick ():
406- self .process_event (event )
431+ self .process_message (event )
407432
408433 try :
409434 while not self .exit_event .is_set ():
@@ -418,3 +443,22 @@ def process_selector_events(
418443 pass
419444 except ParseError :
420445 pass
446+
447+ def process_message (self , message : Message ) -> None :
448+ # intercept in-band window resize
449+ if isinstance (message , TerminalSupportInBandWindowResize ):
450+ # If it is supported, enabled it
451+ if message .supported and not message .enabled :
452+ self ._enable_in_band_window_resize ()
453+ self ._in_band_window_resize = message .supported
454+ elif message .enabled :
455+ self ._in_band_window_resize = message .supported
456+ # Send up-to-date message
457+ super ().process_message (
458+ TerminalSupportInBandWindowResize (
459+ message .supported , self ._in_band_window_resize
460+ )
461+ )
462+ return
463+
464+ super ().process_message (message )
0 commit comments