Do not spam child processes with resize notifications while a drag resize is in progress

Avoids prompt corruption because of shells doing rapid redraws
This commit is contained in:
Kovid Goyal
2026-02-27 09:20:39 +05:30
parent f94051e752
commit ea11959c7f
3 changed files with 39 additions and 15 deletions

View File

@@ -2433,11 +2433,13 @@ class Boss:
vertical_allowed = bool(edges & (TOP_EDGE | BOTTOM_EDGE))
self.drag_resize_of_window = WindowResizeDrag(
is_active=True, horizontal_target_window_id=horizontal.id if horizontal_allowed else 0,
vertical_target_window_id=vertical.id if vertical_allowed else 0,
vertical_target_window_id=vertical.id if vertical_allowed else 0, tab_id=tab.id,
cell_width=cell_width, cell_height=cell_height, initial_x=x, initial_y=y,
width_increases_rightwards=width_increases_rightwards,
height_increases_downwards=height_increases_downwards,
)
for cw in tab:
cw.pause_resize_notifications_to_child()
return True
return False
@@ -2461,6 +2463,9 @@ class Boss:
self.drag_resize_of_window = r._replace(last_step_y=step_y)
def drag_resize_end(self) -> None:
if tab := self.tab_for_id(self.drag_resize_of_window.tab_id):
for cw in tab:
cw.pause_resize_notifications_to_child(pause=False)
self.drag_resize_of_window = WindowResizeDrag()
def open_kitty_website(self) -> None:

View File

@@ -255,6 +255,7 @@ class WindowResizeDrag(NamedTuple):
last_step_y: float = 0
height_increases_downwards: bool = True
width_increases_rightwards: bool = True
tab_id: int = 0
def __bool__(self) -> bool:
return self.is_active

View File

@@ -712,6 +712,7 @@ class Window:
self.kitten_result_processors: list[Callable[['Window', Any], None]] = []
self.child_is_launched = False
self.last_reported_pty_size = (-1, -1, -1, -1)
self._pause_resize_notifications_to_child: tuple[int, int, int, int] | None = None
self.needs_attention = False
self.ignore_focus_changes = self.initial_ignore_focus_changes
self.override_title = override_title
@@ -945,6 +946,33 @@ class Window:
wakeup_io_loop()
wakeup_main_loop()
def pause_resize_notifications_to_child(self, pause: bool = True) -> None:
if pause:
self._pause_resize_notifications_to_child = -1, -1, -1, -1
else:
p, self._pause_resize_notifications_to_child = self._pause_resize_notifications_to_child, None
if p and p[0] > 0:
if self.resize_child(p):
update_ime_position_for_window(self.id, True)
def resize_child(self, current_pty_size: tuple[int, int, int, int]) -> bool:
boss = get_boss()
boss.child_monitor.resize_pty(self.id, *current_pty_size)
self.last_resized_at = monotonic()
self.last_reported_pty_size = current_pty_size
self.notify_child_of_resize()
update_ime_position = False
if not self.child_is_launched:
self.child.mark_terminal_ready()
self.child_is_launched = True
update_ime_position = True
if boss.args.debug_rendering:
now = monotonic()
print(f'[{now:.3f}] Child launched', file=sys.stderr)
elif boss.args.debug_rendering:
print(f'[{monotonic():.3f}] SIGWINCH sent to child in window: {self.id} with size: {current_pty_size}', file=sys.stderr)
return update_ime_position
def set_geometry(self, new_geometry: WindowGeometry) -> None:
if self.destroyed:
return
@@ -957,20 +985,10 @@ class Window:
max(0, new_geometry.right - new_geometry.left), max(0, new_geometry.bottom - new_geometry.top))
update_ime_position = False
if current_pty_size != self.last_reported_pty_size:
boss = get_boss()
boss.child_monitor.resize_pty(self.id, *current_pty_size)
self.last_resized_at = monotonic()
self.last_reported_pty_size = current_pty_size
self.notify_child_of_resize()
if not self.child_is_launched:
self.child.mark_terminal_ready()
self.child_is_launched = True
update_ime_position = True
if boss.args.debug_rendering:
now = monotonic()
print(f'[{now:.3f}] Child launched', file=sys.stderr)
elif boss.args.debug_rendering:
print(f'[{monotonic():.3f}] SIGWINCH sent to child in window: {self.id} with size: {current_pty_size}', file=sys.stderr)
if self._pause_resize_notifications_to_child is None:
update_ime_position = self.resize_child(current_pty_size)
else:
self._pause_resize_notifications_to_child = current_pty_size
else:
mark_os_window_dirty(self.os_window_id)