From 606aa1543ee78aca2fbb7e878634dea348ef0224 Mon Sep 17 00:00:00 2001 From: mcrmck Date: Mon, 23 Mar 2026 21:44:48 -0400 Subject: [PATCH] Fix multi-OS-window drag bugs and KeyError crash on tab drag Two fixes: 1. boss.py: scope window drag is_dest to the receiving OS window only. Previously all tab managers got is_dest=True with the same window-local coordinates. Since every OS window's viewport starts at (0,0), a drag at (x,y) in Window 1 also matched windows in Window 2 at the same coords, causing spurious highlights and incorrect drop-target state in the second window. 2. tabs.py: filter synthetic tab IDs (< 0) from all_tabs in on_tab_drop_move. The '+' new-tab indicator uses tab_id=-1. If a tab drag started while window_drag_active or tab_bar_show_new_tab_button was set, the -1 ended up in tab_being_dropped.tab_ids, then tab_bar_data crashed with KeyError when it tried tmap[-1]. --- kitty/boss.py | 2 +- kitty/tabs.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kitty/boss.py b/kitty/boss.py index 8dc58060c..0cc9528b5 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -1934,7 +1934,7 @@ class Boss: window_id, drag_started = get_window_being_dragged()[:2] if window_id and drag_started: for q in self.all_tab_managers: - q.on_window_drop_move(window_id, not is_leave, x, y) + q.on_window_drop_move(window_id, (not is_leave) and (q is tm), x, y) def on_drop(self, os_window_id: int, drop: dict[str, bytes] | int, from_self: bool, x: int, y: int) -> None: if isinstance(drop, int): diff --git a/kitty/tabs.py b/kitty/tabs.py index 5d528ff84..3861a8d36 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -1644,9 +1644,9 @@ class TabManager: # {{{ self.layout_tab_bar() return if self.tab_bar_should_be_visible: - all_tabs = [t.tab_id for t in self.tab_bar.last_laid_out_tabs] + all_tabs = [t.tab_id for t in self.tab_bar.last_laid_out_tabs if t.tab_id >= 0] else: - all_tabs = [t.tab_id for t in self.tab_bar_data] + all_tabs = [t.tab_id for t in self.tab_bar_data if t.tab_id >= 0] force_update = False if self.tab_being_dropped is None: tab = get_boss().tab_for_id(tab_id)