diff --git a/docs/changelog.rst b/docs/changelog.rst index 5a9232bbd..51e09a171 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -150,6 +150,13 @@ consumption to do the same tasks. Detailed list of changes ------------------------------------- +0.45.1 [future] + +- choose-files kitten: Fix JXL image preview not working (:iss:`9323`) + +- Fix tab bar rendering glitches when using :opt:`tab_bar_filter` in some + circumstances (:iss:`9328`) + 0.45.0 [2025-12-24] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index b1a68cf54..8d2f0e560 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1069,6 +1069,8 @@ def mark_tab_bar_dirty(os_window_id: int, should_be_shown: bool) -> None: pass +def is_tab_bar_visible(os_window_id: int) -> bool: ... + def detach_window(os_window_id: int, tab_id: int, window_id: int) -> None: pass diff --git a/kitty/state.c b/kitty/state.c index 34b032e8a..30cd3b99e 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -959,6 +959,18 @@ PYWRAP1(mark_tab_bar_dirty) { Py_RETURN_NONE; } +PYWRAP1(is_tab_bar_visible) { + id_type os_window_id; + PA("K", &os_window_id); + if (!OPT(tab_bar_hidden)) { + WITH_OS_WINDOW(os_window_id) + return os_window->has_too_few_tabs ? Py_NewRef(Py_False) : Py_NewRef(Py_True); + END_WITH_OS_WINDOW + } + Py_RETURN_FALSE; +} + + PYWRAP1(change_background_opacity) { id_type os_window_id; float opacity; @@ -1521,6 +1533,7 @@ static PyMethodDef module_methods[] = { MW(set_os_window_chrome, METH_VARARGS), MW(focus_os_window, METH_VARARGS), MW(mark_tab_bar_dirty, METH_VARARGS), + MW(is_tab_bar_visible, METH_VARARGS), MW(run_with_activation_token, METH_O), MW(change_background_opacity, METH_VARARGS), MW(background_opacity_of, METH_O), diff --git a/kitty/tabs.py b/kitty/tabs.py index d958b0d64..1da86e36b 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -34,6 +34,7 @@ get_boss, get_click_interval, get_options, + is_tab_bar_visible, last_focused_os_window_id, mark_tab_bar_dirty, monotonic, @@ -1148,9 +1149,9 @@ def tab_bar_should_be_visible(self) -> bool: return count < 1 def _add_tab(self, tab: Tab) -> None: - visible_before = self.tab_bar_should_be_visible + visible_before = is_tab_bar_visible(self.os_window_id) self.tabs.append(tab) - if not visible_before and self.tab_bar_should_be_visible: + if visible_before != self.tab_bar_should_be_visible: self.tabbar_visibility_changed() def _set_active_tab(self, idx: int, store_in_history: bool = True) -> None: @@ -1178,7 +1179,7 @@ def any_window(self) -> Window | None: return None def mark_tab_bar_dirty(self) -> None: - should_be_shown = self.tab_bar_should_be_visible and not self.tab_bar_hidden + should_be_shown = not self.tab_bar_hidden and self.tab_bar_should_be_visible mark_tab_bar_dirty(self.os_window_id, should_be_shown) w = self.active_window or self.any_window if w is not None: @@ -1214,11 +1215,14 @@ def set_active_tab(self, tab: Tab, for_keep_focus: Tab | None = None) -> bool: idx = self.tabs.index(tab) except Exception: return False + visible_before = is_tab_bar_visible(self.os_window_id) self.set_active_tab_idx(idx) h = self.active_tab_history if for_keep_focus and len(h) > 2 and h[-2] == for_keep_focus.id and h[-1] != for_keep_focus.id: h.pop() h.pop() + if visible_before != self.tab_bar_should_be_visible: + self.tabbar_visibility_changed() return True @property @@ -1418,7 +1422,7 @@ def new_tab( return t def remove(self, removed_tab: Tab) -> None: - visible_before = self.tab_bar_should_be_visible + visible_before = is_tab_bar_visible(self.os_window_id) active_tab_before_removal = self.active_tab tabs = tuple(self.tabs_to_be_shown_in_tab_bar) remove_tab(self.os_window_id, removed_tab.id)