parent
94106aa79e
commit
399354cbe5
8 changed files with 32 additions and 38 deletions
|
|
@ -190,6 +190,8 @@ Detailed list of changes
|
||||||
- Linux: Fix a bug causing colors to occasionally all go black when using mesa
|
- Linux: Fix a bug causing colors to occasionally all go black when using mesa
|
||||||
>= 25.3.0 with nouveau GPU driver (:iss:`9235`)
|
>= 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]
|
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 ||
|
!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)
|
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) {
|
if (!os_window->tab_bar_data_updated) {
|
||||||
call_boss(update_tab_bar_data, "K", os_window->id);
|
call_boss(update_tab_bar_data, "K", os_window->id);
|
||||||
os_window->tab_bar_data_updated = true;
|
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;
|
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);
|
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;
|
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;
|
unsigned int num_of_visible_windows = 0;
|
||||||
Window *active_window = NULL;
|
Window *active_window = NULL;
|
||||||
for (unsigned int i = 0; i < tab->num_windows; i++) { if (tab->windows[i].visible) num_of_visible_windows++; }
|
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
|
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
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1498,10 +1498,9 @@
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
|
|
||||||
opt('tab_bar_min_tabs', '2',
|
opt('tab_bar_min_tabs', '2', option_type='tab_bar_min_tabs',
|
||||||
option_type='tab_bar_min_tabs', ctype='uint',
|
|
||||||
long_text='The minimum number of tabs that must exist before the tab bar is shown.'
|
long_text='The minimum number of tabs that must exist before the tab bar is shown.'
|
||||||
)
|
)
|
||||||
|
|
||||||
opt('tab_switch_strategy', 'previous',
|
opt('tab_switch_strategy', 'previous',
|
||||||
choices=('last', 'left', 'previous', 'right'),
|
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);
|
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
|
static void
|
||||||
convert_from_python_tab_bar_background(PyObject *val, Options *opts) {
|
convert_from_python_tab_bar_background(PyObject *val, Options *opts) {
|
||||||
opts->tab_bar_background = color_or_none_as_int(val);
|
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;
|
if (PyErr_Occurred()) return false;
|
||||||
convert_from_opts_tab_bar_style(py_opts, opts);
|
convert_from_opts_tab_bar_style(py_opts, opts);
|
||||||
if (PyErr_Occurred()) return false;
|
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);
|
convert_from_opts_tab_bar_background(py_opts, opts);
|
||||||
if (PyErr_Occurred()) return false;
|
if (PyErr_Occurred()) return false;
|
||||||
convert_from_opts_tab_bar_margin_color(py_opts, opts);
|
convert_from_opts_tab_bar_margin_color(py_opts, opts);
|
||||||
|
|
|
||||||
|
|
@ -597,7 +597,7 @@ pyset_borders_rects(PyObject *self UNUSED, PyObject *args) {
|
||||||
|
|
||||||
void
|
void
|
||||||
os_window_regions(OSWindow *os_window, Region *central, Region *tab_bar) {
|
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_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);
|
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;
|
central->left = 0; central->right = os_window->viewport_width;
|
||||||
|
|
@ -950,9 +950,10 @@ PYWRAP1(set_os_window_chrome) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PYWRAP1(mark_tab_bar_dirty) {
|
PYWRAP1(mark_tab_bar_dirty) {
|
||||||
id_type os_window_id = PyLong_AsUnsignedLongLong(args);
|
id_type os_window_id; int should_be_shown;
|
||||||
if (PyErr_Occurred()) return NULL;
|
PA("Kp", &os_window_id, &should_be_shown);
|
||||||
WITH_OS_WINDOW(os_window_id)
|
WITH_OS_WINDOW(os_window_id)
|
||||||
|
os_window->has_too_few_tabs = !should_be_shown;
|
||||||
os_window->tab_bar_data_updated = false;
|
os_window->tab_bar_data_updated = false;
|
||||||
END_WITH_OS_WINDOW
|
END_WITH_OS_WINDOW
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
|
|
@ -1519,7 +1520,7 @@ static PyMethodDef module_methods[] = {
|
||||||
MW(current_application_quit_request, METH_NOARGS),
|
MW(current_application_quit_request, METH_NOARGS),
|
||||||
MW(set_os_window_chrome, METH_VARARGS),
|
MW(set_os_window_chrome, METH_VARARGS),
|
||||||
MW(focus_os_window, 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(run_with_activation_token, METH_O),
|
||||||
MW(change_background_opacity, METH_VARARGS),
|
MW(change_background_opacity, METH_VARARGS),
|
||||||
MW(background_opacity_of, METH_O),
|
MW(background_opacity_of, METH_O),
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,6 @@ typedef struct Options {
|
||||||
bool dynamic_background_opacity;
|
bool dynamic_background_opacity;
|
||||||
float inactive_text_alpha;
|
float inactive_text_alpha;
|
||||||
Edge tab_bar_edge;
|
Edge tab_bar_edge;
|
||||||
unsigned long tab_bar_min_tabs;
|
|
||||||
DisableLigature disable_ligatures;
|
DisableLigature disable_ligatures;
|
||||||
bool force_ltr;
|
bool force_ltr;
|
||||||
bool resize_in_steps;
|
bool resize_in_steps;
|
||||||
|
|
@ -323,6 +322,7 @@ typedef struct OSWindow {
|
||||||
bool has_received_cursor_pos_event;
|
bool has_received_cursor_pos_event;
|
||||||
double mouse_x, mouse_y;
|
double mouse_x, mouse_y;
|
||||||
bool mouse_button_pressed[32];
|
bool mouse_button_pressed[32];
|
||||||
|
bool has_too_few_tabs;
|
||||||
PyObject *window_title;
|
PyObject *window_title;
|
||||||
bool disallow_title_changes, title_is_overriden;
|
bool disallow_title_changes, title_is_overriden;
|
||||||
bool viewport_size_dirty, viewport_updated_at_least_once;
|
bool viewport_size_dirty, viewport_updated_at_least_once;
|
||||||
|
|
|
||||||
|
|
@ -1138,7 +1138,14 @@ def refresh_sprite_positions(self) -> None:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tab_bar_should_be_visible(self) -> bool:
|
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:
|
def _add_tab(self, tab: Tab) -> None:
|
||||||
visible_before = self.tab_bar_should_be_visible
|
visible_before = self.tab_bar_should_be_visible
|
||||||
|
|
@ -1160,9 +1167,14 @@ def _set_active_tab(self, idx: int, store_in_history: bool = True) -> None:
|
||||||
self._active_tab_idx = idx
|
self._active_tab_idx = idx
|
||||||
set_active_tab(self.os_window_id, 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:
|
def tabbar_visibility_changed(self) -> None:
|
||||||
if not self.tab_bar_hidden:
|
if not self.tab_bar_hidden:
|
||||||
self.tab_bar.layout()
|
self.layout_tab_bar()
|
||||||
self.resize(only_tabs=True)
|
self.resize(only_tabs=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
@ -1173,8 +1185,8 @@ def any_window(self) -> Window | None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def mark_tab_bar_dirty(self) -> None:
|
def mark_tab_bar_dirty(self) -> None:
|
||||||
if self.tab_bar_should_be_visible and not self.tab_bar_hidden:
|
should_be_shown = self.tab_bar_should_be_visible and not self.tab_bar_hidden
|
||||||
mark_tab_bar_dirty(self.os_window_id)
|
mark_tab_bar_dirty(self.os_window_id, should_be_shown)
|
||||||
w = self.active_window or self.any_window
|
w = self.active_window or self.any_window
|
||||||
if w is not None:
|
if w is not None:
|
||||||
data = {'tab_manager': self}
|
data = {'tab_manager': self}
|
||||||
|
|
@ -1193,8 +1205,7 @@ def title_changed(self, tab: Tab) -> None:
|
||||||
def resize(self, only_tabs: bool = False) -> None:
|
def resize(self, only_tabs: bool = False) -> None:
|
||||||
if not only_tabs:
|
if not only_tabs:
|
||||||
if not self.tab_bar_hidden:
|
if not self.tab_bar_hidden:
|
||||||
self.tab_bar.layout()
|
self.layout_tab_bar()
|
||||||
self.mark_tab_bar_dirty()
|
|
||||||
for tab in self.tabs:
|
for tab in self.tabs:
|
||||||
tab.relayout()
|
tab.relayout()
|
||||||
|
|
||||||
|
|
@ -1217,15 +1228,12 @@ def set_active_tab(self, tab: Tab, for_keep_focus: Tab | None = None) -> bool:
|
||||||
h.pop()
|
h.pop()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def filtered_tabs(self, filter_expression: str) -> Iterator[Tab]:
|
|
||||||
yield from get_boss().match_tabs(filter_expression, all_tabs=self)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tabs_to_be_shown_in_tab_bar(self) -> Iterable[Tab]:
|
def tabs_to_be_shown_in_tab_bar(self) -> Iterable[Tab]:
|
||||||
f = get_options().tab_bar_filter
|
f = get_options().tab_bar_filter
|
||||||
if f:
|
if f:
|
||||||
at = self.active_tab
|
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 (t for t in self if t is at or t in m)
|
||||||
return self.tabs
|
return self.tabs
|
||||||
|
|
||||||
|
|
@ -1561,6 +1569,5 @@ def apply_options(self) -> None:
|
||||||
self.tab_bar_hidden = get_options().tab_bar_style == 'hidden'
|
self.tab_bar_hidden = get_options().tab_bar_style == 'hidden'
|
||||||
self.tab_bar.apply_options()
|
self.tab_bar.apply_options()
|
||||||
self.update_tab_bar_data()
|
self.update_tab_bar_data()
|
||||||
self.mark_tab_bar_dirty()
|
self.layout_tab_bar()
|
||||||
self.tab_bar.layout()
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue