mirror of
https://github.com/kovidgoyal/kitty.git
synced 2025-12-13 20:36:22 +01:00
@@ -190,6 +190,8 @@ Detailed list of changes
|
||||
- Linux: Fix a bug causing colors to occasionally all go black when using mesa
|
||||
>= 25.3.0 with nouveau GPU driver (:iss:`9235`)
|
||||
|
||||
- Fix :opt:`tab_bar_min_tabs` not respecting :opt:`tab_bar_filter` (:iss:`9278`)
|
||||
|
||||
0.44.0 [2025-11-03]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -720,7 +720,7 @@ prepare_to_render_os_window(OSWindow *os_window, monotonic_t now, unsigned int *
|
||||
!global_state.supports_framebuffer_srgb || effective_os_window_alpha(os_window) < 1.f ||
|
||||
os_window->live_resize.in_progress || (os_window->bgimage && os_window->bgimage->texture_id > 0)
|
||||
);
|
||||
if (TD.screen && os_window->num_tabs >= OPT(tab_bar_min_tabs)) {
|
||||
if (TD.screen && os_window->num_tabs && !os_window->has_too_few_tabs) {
|
||||
if (!os_window->tab_bar_data_updated) {
|
||||
call_boss(update_tab_bar_data, "K", os_window->id);
|
||||
os_window->tab_bar_data_updated = true;
|
||||
@@ -817,7 +817,7 @@ render_prepared_os_window(OSWindow *os_window, unsigned int active_window_id, co
|
||||
BorderRects *br = &tab->border_rects;
|
||||
draw_borders(br->vao_idx, br->num_border_rects, br->rect_buf, br->is_dirty, active_window_bg, num_visible_windows, all_windows_have_same_bg, os_window);
|
||||
br->is_dirty = false;
|
||||
if (TD.screen && os_window->num_tabs >= OPT(tab_bar_min_tabs)) draw_cells(&TD, os_window, true, true, false, NULL);
|
||||
if (TD.screen && os_window->num_tabs && !os_window->has_too_few_tabs) draw_cells(&TD, os_window, true, true, false, NULL);
|
||||
unsigned int num_of_visible_windows = 0;
|
||||
Window *active_window = NULL;
|
||||
for (unsigned int i = 0; i < tab->num_windows; i++) { if (tab->windows[i].visible) num_of_visible_windows++; }
|
||||
|
||||
@@ -1065,7 +1065,7 @@ def next_window_id() -> int:
|
||||
pass
|
||||
|
||||
|
||||
def mark_tab_bar_dirty(os_window_id: int) -> None:
|
||||
def mark_tab_bar_dirty(os_window_id: int, should_be_shown: bool) -> None:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@@ -1498,10 +1498,9 @@ The horizontal alignment of the tab bar, can be one of: :code:`left`,
|
||||
'''
|
||||
)
|
||||
|
||||
opt('tab_bar_min_tabs', '2',
|
||||
option_type='tab_bar_min_tabs', ctype='uint',
|
||||
opt('tab_bar_min_tabs', '2', option_type='tab_bar_min_tabs',
|
||||
long_text='The minimum number of tabs that must exist before the tab bar is shown.'
|
||||
)
|
||||
)
|
||||
|
||||
opt('tab_switch_strategy', 'previous',
|
||||
choices=('last', 'left', 'previous', 'right'),
|
||||
|
||||
15
kitty/options/to-c-generated.h
generated
15
kitty/options/to-c-generated.h
generated
@@ -980,19 +980,6 @@ convert_from_opts_tab_bar_style(PyObject *py_opts, Options *opts) {
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_tab_bar_min_tabs(PyObject *val, Options *opts) {
|
||||
opts->tab_bar_min_tabs = PyLong_AsUnsignedLong(val);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_tab_bar_min_tabs(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "tab_bar_min_tabs");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_tab_bar_min_tabs(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_tab_bar_background(PyObject *val, Options *opts) {
|
||||
opts->tab_bar_background = color_or_none_as_int(val);
|
||||
@@ -1509,8 +1496,6 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) {
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_tab_bar_style(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_tab_bar_min_tabs(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_tab_bar_background(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_tab_bar_margin_color(py_opts, opts);
|
||||
|
||||
@@ -597,7 +597,7 @@ pyset_borders_rects(PyObject *self UNUSED, PyObject *args) {
|
||||
|
||||
void
|
||||
os_window_regions(OSWindow *os_window, Region *central, Region *tab_bar) {
|
||||
if (!OPT(tab_bar_hidden) && os_window->num_tabs >= OPT(tab_bar_min_tabs)) {
|
||||
if (!OPT(tab_bar_hidden) && os_window->num_tabs && !os_window->has_too_few_tabs) {
|
||||
long margin_outer = pt_to_px_for_os_window(OPT(tab_bar_margin_height.outer), os_window);
|
||||
long margin_inner = pt_to_px_for_os_window(OPT(tab_bar_margin_height.inner), os_window);
|
||||
central->left = 0; central->right = os_window->viewport_width;
|
||||
@@ -950,9 +950,10 @@ PYWRAP1(set_os_window_chrome) {
|
||||
}
|
||||
|
||||
PYWRAP1(mark_tab_bar_dirty) {
|
||||
id_type os_window_id = PyLong_AsUnsignedLongLong(args);
|
||||
if (PyErr_Occurred()) return NULL;
|
||||
id_type os_window_id; int should_be_shown;
|
||||
PA("Kp", &os_window_id, &should_be_shown);
|
||||
WITH_OS_WINDOW(os_window_id)
|
||||
os_window->has_too_few_tabs = !should_be_shown;
|
||||
os_window->tab_bar_data_updated = false;
|
||||
END_WITH_OS_WINDOW
|
||||
Py_RETURN_NONE;
|
||||
@@ -1519,7 +1520,7 @@ static PyMethodDef module_methods[] = {
|
||||
MW(current_application_quit_request, METH_NOARGS),
|
||||
MW(set_os_window_chrome, METH_VARARGS),
|
||||
MW(focus_os_window, METH_VARARGS),
|
||||
MW(mark_tab_bar_dirty, METH_O),
|
||||
MW(mark_tab_bar_dirty, METH_VARARGS),
|
||||
MW(run_with_activation_token, METH_O),
|
||||
MW(change_background_opacity, METH_VARARGS),
|
||||
MW(background_opacity_of, METH_O),
|
||||
|
||||
@@ -91,7 +91,6 @@ typedef struct Options {
|
||||
bool dynamic_background_opacity;
|
||||
float inactive_text_alpha;
|
||||
Edge tab_bar_edge;
|
||||
unsigned long tab_bar_min_tabs;
|
||||
DisableLigature disable_ligatures;
|
||||
bool force_ltr;
|
||||
bool resize_in_steps;
|
||||
@@ -323,6 +322,7 @@ typedef struct OSWindow {
|
||||
bool has_received_cursor_pos_event;
|
||||
double mouse_x, mouse_y;
|
||||
bool mouse_button_pressed[32];
|
||||
bool has_too_few_tabs;
|
||||
PyObject *window_title;
|
||||
bool disallow_title_changes, title_is_overriden;
|
||||
bool viewport_size_dirty, viewport_updated_at_least_once;
|
||||
|
||||
@@ -1138,7 +1138,14 @@ class TabManager: # {{{
|
||||
|
||||
@property
|
||||
def tab_bar_should_be_visible(self) -> bool:
|
||||
return len(self.tabs) >= get_options().tab_bar_min_tabs
|
||||
count = get_options().tab_bar_min_tabs
|
||||
if count < 1:
|
||||
return True
|
||||
for t in self.tabs_to_be_shown_in_tab_bar:
|
||||
count -= 1
|
||||
if count < 1:
|
||||
return True
|
||||
return count < 1
|
||||
|
||||
def _add_tab(self, tab: Tab) -> None:
|
||||
visible_before = self.tab_bar_should_be_visible
|
||||
@@ -1160,9 +1167,14 @@ class TabManager: # {{{
|
||||
self._active_tab_idx = idx
|
||||
set_active_tab(self.os_window_id, idx)
|
||||
|
||||
def layout_tab_bar(self) -> None:
|
||||
# set tab_bar_should_be_visible so that tab_bar.layout() gets correct dimensions
|
||||
self.mark_tab_bar_dirty()
|
||||
self.tab_bar.layout()
|
||||
|
||||
def tabbar_visibility_changed(self) -> None:
|
||||
if not self.tab_bar_hidden:
|
||||
self.tab_bar.layout()
|
||||
self.layout_tab_bar()
|
||||
self.resize(only_tabs=True)
|
||||
|
||||
@property
|
||||
@@ -1173,8 +1185,8 @@ class TabManager: # {{{
|
||||
return None
|
||||
|
||||
def mark_tab_bar_dirty(self) -> None:
|
||||
if self.tab_bar_should_be_visible and not self.tab_bar_hidden:
|
||||
mark_tab_bar_dirty(self.os_window_id)
|
||||
should_be_shown = self.tab_bar_should_be_visible and not self.tab_bar_hidden
|
||||
mark_tab_bar_dirty(self.os_window_id, should_be_shown)
|
||||
w = self.active_window or self.any_window
|
||||
if w is not None:
|
||||
data = {'tab_manager': self}
|
||||
@@ -1193,8 +1205,7 @@ class TabManager: # {{{
|
||||
def resize(self, only_tabs: bool = False) -> None:
|
||||
if not only_tabs:
|
||||
if not self.tab_bar_hidden:
|
||||
self.tab_bar.layout()
|
||||
self.mark_tab_bar_dirty()
|
||||
self.layout_tab_bar()
|
||||
for tab in self.tabs:
|
||||
tab.relayout()
|
||||
|
||||
@@ -1217,15 +1228,12 @@ class TabManager: # {{{
|
||||
h.pop()
|
||||
return True
|
||||
|
||||
def filtered_tabs(self, filter_expression: str) -> Iterator[Tab]:
|
||||
yield from get_boss().match_tabs(filter_expression, all_tabs=self)
|
||||
|
||||
@property
|
||||
def tabs_to_be_shown_in_tab_bar(self) -> Iterable[Tab]:
|
||||
f = get_options().tab_bar_filter
|
||||
if f:
|
||||
at = self.active_tab
|
||||
m = set(self.filtered_tabs(f))
|
||||
m = set(get_boss().match_tabs(f, all_tabs=self))
|
||||
return (t for t in self if t is at or t in m)
|
||||
return self.tabs
|
||||
|
||||
@@ -1561,6 +1569,5 @@ class TabManager: # {{{
|
||||
self.tab_bar_hidden = get_options().tab_bar_style == 'hidden'
|
||||
self.tab_bar.apply_options()
|
||||
self.update_tab_bar_data()
|
||||
self.mark_tab_bar_dirty()
|
||||
self.tab_bar.layout()
|
||||
self.layout_tab_bar()
|
||||
# }}}
|
||||
|
||||
Reference in New Issue
Block a user