home · contact · privacy
Handle dtach forgetting our hiding of the cursor.
authorChristian Heller <c.heller@plomlompom.de>
Thu, 25 Sep 2025 18:22:38 +0000 (20:22 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Thu, 25 Sep 2025 18:22:38 +0000 (20:22 +0200)
src/ircplom/testing.py
src/ircplom/tui_base.py

index 57de47061dd3b7f390acd6b948904f7f553ebda9..bc87e55c2592e4367982ebd536517178ce230d31 100644 (file)
@@ -28,7 +28,7 @@ class TestTerminal(QueueMixin, TerminalInterface):
     def flush(self) -> None:
         pass
 
-    def calc_geometry(self) -> None:
+    def set_size_hide_cursor(self) -> None:
         self.size = TerminalInterface.__annotations__['size'](0, 0)
 
     def wrap(self, line: str) -> list[str]:
index 73115a1ba492de1d0d33ef8c80af3481ba53bb0a..e9aba282bb5a3a53cafce26141861b447233f462 100644 (file)
@@ -408,8 +408,8 @@ class TerminalInterface(ABC):
         'Combine multiple contexts into one and run keypress loop.'
 
     @abstractmethod
-    def calc_geometry(self) -> None:
-        '(Re-)calculate .size..'
+    def set_size_hide_cursor(self) -> None:
+        '(Re-)calculate .size, ensure hiding of terminal cursor.'
 
     @abstractmethod
     def flush(self) -> None:
@@ -482,8 +482,8 @@ class BaseTui(QueueMixin):
         self._term.flush()
 
     def _set_screen(self) -> None:
-        'Calc screen geometry into windows, then call .redraw_affected.'
-        self._term.calc_geometry()
+        'Hide cursor, calc screen geometry into wins, call .redraw_affected.'
+        self._term.set_size_hide_cursor()
         for window in self._windows:
             window.set_geometry()
         self._status_line.set_geometry(_YX(self._term.size.y - 2,
@@ -642,11 +642,19 @@ class Terminal(QueueMixin, TerminalInterface):
     @contextmanager
     def setup(self) -> Generator:
         print(self._blessed.clear, end='')
+        # NB: Though it might seem the proper place, not using blessed's
+        # hidden_cursor() context manager here, instead opting for the
+        # .set_size_hide_cursor called on BaseTui.__init__ and on SIGWINCH,
+        # since terminal session detachers like dtach can forget an initial
+        # cursor hiding, so we do it each time the screen is configured a-new;
+        # we *do* however ensure a visible cursor in the end, as the
+        # hidden_cursor() context manager would, implicitly assuming that that
+        # is the "normal" terminal state the user wanted to return to
         with (self._blessed.raw(),
               self._blessed.fullscreen(),
-              self._blessed.hidden_cursor(),
               Loop(iterator=self._get_keypresses(), _q_out=self._q_out)):
             yield self
+        print(self._blessed.normal_cursor, end='', flush=True)
 
     @property
     def _cursor_yx(self) -> _YX:
@@ -657,7 +665,9 @@ class Terminal(QueueMixin, TerminalInterface):
         print(self._blessed.move_yx(yx.y, yx.x), end='')
         self._cursor_yx_ = yx
 
-    def calc_geometry(self) -> None:
+    def set_size_hide_cursor(self) -> None:
+        # NB: see note on .setup why cursor hiding here rather than there
+        print(self._blessed.hide_cursor, end='', flush=True)
         self.size = _YX(self._blessed.height, self._blessed.width)
 
     def flush(self) -> None: