From 43907026ca85c234f9cc4acc8824c64fb1fc78ea Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 9 Dec 2023 12:22:23 +0000 Subject: [PATCH] Fix resizing the window smaller. Some weird sequence of events was triggering an attempted redraw at the old size, before properly noticing the change and redrawing at the new size. When going from smaller to bigger this just caused a display flicker (in fact not even a perceptible one), but bigger to smaller caused an exception when we tried to draw a big screen in a small window and curses caught us printing outside the screen area. Now seems to work better. --- cursesclient.py | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/cursesclient.py b/cursesclient.py index 3a8479f..d068ed9 100644 --- a/cursesclient.py +++ b/cursesclient.py @@ -19,6 +19,7 @@ class CursesUI(client.Client): def __init__(self): super().__init__() self.selfpipes = [] + self.resized = False def curses_setup(self): self.scr = curses.initscr() @@ -121,9 +122,13 @@ class CursesUI(client.Client): rfds_in.append(sp.rfd) rfds_out, _, _ = select.select(rfds_in, [], []) rfds_out = set(rfds_out) + resized = False for (sp, handler, _) in self.selfpipes: if sp.rfd in rfds_out and sp.check(): - handler() + if handler(): + resized = True + if resized: + return None if 0 in rfds_out: return self.get_wch() else: @@ -147,10 +152,19 @@ class CursesUI(client.Client): def handler(): size = os.get_terminal_size() curses.resizeterm(size.lines, size.columns) - # This is the same way standard curses will do it, which - # is as good a way as any to signal to the main loop that - # we need to do something - curses.unget_wch(curses.KEY_RESIZE) + # Signal to the main loop that we've been resized. If + # curses were doing this itself, we'd see KEY_RESIZE in + # our input stream, but apparently passing that to + # curses.unget_wch does the wrong thing, and instead we + # receive U+019A from get_wch. (0x19A is the numerical + # value of curses.KEY_RESIZE, so it seems reasonably + # obvious what manner of confusion has happened there.) + # + # So instead, we set a flag of our own and return True, + # which causes get_input() to return None, which causes + # the main loop to check the resize flag. + self.resized = True + return True self.selfpipes.append((sp, handler, None)) def get_composer(self): @@ -215,7 +229,14 @@ class CursesUI(client.Client): self.clear() self.activity_stack[-1].render() self.scr.refresh() - ch = self.get_input() + while True: + ch = self.get_input() + if ch is not None: + break + if self.resized: + self.resized = False + ch = curses.KEY_RESIZE + break if ch == ctrl('['): if self.activity_stack[-1] is not self.escape_menu: self.activity_stack.append(self.escape_menu) -- 2.30.2