From 5c0a4accb383d40bdae9ae092cbca7356d079b8a Mon Sep 17 00:00:00 2001 From: mcrmck Date: Fri, 20 Mar 2026 01:34:01 -0400 Subject: [PATCH] Fix two bugs: splits layout corruption and overlay stuck on early drop exit splits.py: insert_window_next_to called split_and_add on self.pairs_root instead of on the pair found by pair_for_window. split_and_add only handles direct children, so nested dest windows fell to 'else: self.two = pair', silently replacing an entire subtree. Lost windows were re-added by do_layout, producing phantom panes. tabs.py: on_window_drop returned early (window not found) before calling _clear_force_show_title_bars, leaving the drag overlay stuck on screen. --- kitty/layout/splits.py | 2 +- kitty/tabs.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/kitty/layout/splits.py b/kitty/layout/splits.py index 245f000b2..05376695d 100644 --- a/kitty/layout/splits.py +++ b/kitty/layout/splits.py @@ -740,7 +740,7 @@ class Splits(Layout): # Re-insert next to dest pair = self.pairs_root.pair_for_window(dest_wg.id) if pair is not None: - self.pairs_root.split_and_add(dest_wg.id, src_wg.id, horizontal, after) + pair.split_and_add(dest_wg.id, src_wg.id, horizontal, after) else: self.pairs_root.balanced_add(src_wg.id) diff --git a/kitty/tabs.py b/kitty/tabs.py index 3d330aef3..ed23f19c4 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -1858,8 +1858,10 @@ class TabManager: # {{{ self.mark_tab_bar_dirty() def _clear_force_show_title_bars(self) -> None: + log_error('DRAG DEBUG: _clear_force_show_title_bars called') boss = get_boss() for tm in boss.all_tab_managers: + log_error(f'DRAG DEBUG: clearing tm={tm.os_window_id} window_being_dropped={tm.window_being_dropped}') tm._set_drag_target_window(0) tm._set_drag_target_tab(0) for tab in tm: @@ -1888,18 +1890,23 @@ class TabManager: # {{{ boss = get_boss() prev_id = self.window_being_dropped.window_id if self.window_being_dropped else 0 prev_quadrant = self.window_being_dropped.quadrant if self.window_being_dropped else 0 + log_error(f'DRAG DEBUG: _set_drag_target_window window_id={window_id} quadrant={quadrant} prev_id={prev_id} prev_quadrant={prev_quadrant}') if prev_id == window_id and prev_quadrant == quadrant: return if prev_id and (prev_w := boss.window_id_map.get(prev_id)): + log_error(f'DRAG DEBUG: clearing overlay on prev_id={prev_id} tab_id={prev_w.tab_id}') prev_w.is_drag_target = False set_window_drag_overlay(self.os_window_id, prev_w.tab_id, prev_id, 0) if prev_w._title_bar_screen is not None: tab = prev_w.tabref() prev_w.update_title_bar(is_active=tab is not None and tab.active_window is prev_w) + elif prev_id: + log_error(f'DRAG DEBUG: prev_id={prev_id} not found in window_id_map — overlay may be stuck!') if window_id and (new_w := boss.window_id_map.get(window_id)): if quadrant == 5: new_w.is_drag_target = True new_w.update_title_bar(is_active=True) + log_error(f'DRAG DEBUG: setting overlay on window_id={window_id} tab_id={new_w.tab_id} quadrant={quadrant}') set_window_drag_overlay(self.os_window_id, new_w.tab_id, window_id, quadrant) self.window_being_dropped = WindowBeingDropped(window_id=window_id, quadrant=quadrant) else: @@ -1953,6 +1960,7 @@ class TabManager: # {{{ boss = get_boss() w = boss.window_id_map.get(window_id) if w is None: + self._clear_force_show_title_bars() return self._clear_force_show_title_bars() set_window_being_dragged()