diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index e9a73d0b0..98b2175a7 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1497,3 +1497,4 @@ def make_x11_window_a_dock_window(x11_window_id: int, strut: Tuple[int, int, int def unicode_database_version() -> Tuple[int, int, int]: ... def wrapped_kitten_names() -> List[str]: ... def expand_ansi_c_escapes(test: str) -> str: ... +def update_tab_bar_edge_colors(os_window_id: int) -> bool: ... diff --git a/kitty/screen.c b/kitty/screen.c index 139ee0c79..b197837f5 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -3972,11 +3972,11 @@ effective_cell_edge_color(char_type ch, color_type fg, color_type bg, bool is_le END_ALLOW_CASE_RANGE } -static PyObject* -line_edge_colors(Screen *self, PyObject *a UNUSED) { +bool +get_line_edge_colors(Screen *self, color_type *left, color_type *right) { // Return the color at the left and right edges of the line with the cursor on it Line *line = range_line_(self, self->cursor->y); - if (!line) { PyErr_SetString(PyExc_IndexError, "Line number out of range"); return NULL; } + if (!line) return false; color_type left_cell_fg = 0, left_cell_bg = 0, right_cell_bg = 0, right_cell_fg = 0; index_type cell_color_x = 0; char_type left_char = line_get_char(line, cell_color_x); @@ -3984,9 +3984,16 @@ line_edge_colors(Screen *self, PyObject *a UNUSED) { if (line->xnum > 0) cell_color_x = line->xnum - 1; char_type right_char = line_get_char(line, cell_color_x); colors_for_cell(line, self->color_profile, &cell_color_x, &right_cell_fg, &right_cell_bg); - unsigned long left = effective_cell_edge_color(left_char, left_cell_fg, left_cell_bg, true); - unsigned long right = effective_cell_edge_color(right_char, right_cell_fg, right_cell_bg, false); - return Py_BuildValue("kk", left, right); + *left = effective_cell_edge_color(left_char, left_cell_fg, left_cell_bg, true); + *right = effective_cell_edge_color(right_char, right_cell_fg, right_cell_bg, false); + return true; +} + +static PyObject* +line_edge_colors(Screen *self, PyObject *a UNUSED) { + color_type left, right; + if (!get_line_edge_colors(self, &left, &right)) { PyErr_SetString(PyExc_IndexError, "Line number out of range"); return NULL; } + return Py_BuildValue("kk", (unsigned long)left, (unsigned long)right); } diff --git a/kitty/screen.h b/kitty/screen.h index a100b7acd..9dea8186e 100644 --- a/kitty/screen.h +++ b/kitty/screen.h @@ -265,6 +265,7 @@ bool screen_detect_url(Screen *screen, unsigned int x, unsigned int y); int screen_cursor_at_a_shell_prompt(const Screen *); bool screen_fake_move_cursor_to_position(Screen *, index_type x, index_type y); bool screen_send_signal_for_key(Screen *, char key); +bool get_line_edge_colors(Screen *self, color_type *left, color_type *right); #define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen); DECLARE_CH_SCREEN_HANDLER(bell) DECLARE_CH_SCREEN_HANDLER(backspace) diff --git a/kitty/state.c b/kitty/state.c index c8e165728..ba3d48edc 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -1124,6 +1124,17 @@ PYWRAP1(patch_global_colors) { Py_RETURN_NONE; } +PYWRAP1(update_tab_bar_edge_colors) { + id_type os_window_id; + PA("K", &os_window_id); + WITH_OS_WINDOW(os_window_id) + if (os_window->tab_bar_render_data.screen) { + if (get_line_edge_colors(os_window->tab_bar_render_data.screen, &os_window->tab_bar_edge_color.left, &os_window->tab_bar_edge_color.right)) { Py_RETURN_TRUE; } + } + END_WITH_OS_WINDOW + Py_RETURN_FALSE; +} + static PyObject* pyset_background_image(PyObject *self UNUSED, PyObject *args) { const char *path; @@ -1348,6 +1359,7 @@ static PyMethodDef module_methods[] = { MW(os_window_font_size, METH_VARARGS), MW(set_os_window_size, METH_VARARGS), MW(get_os_window_size, METH_VARARGS), + MW(update_tab_bar_edge_colors, METH_VARARGS), MW(set_boss, METH_O), MW(get_boss, METH_NOARGS), MW(apply_options_update, METH_NOARGS), diff --git a/kitty/state.h b/kitty/state.h index 06939acf2..8f675d64e 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -195,6 +195,9 @@ typedef struct { unsigned int active_tab, num_tabs, capacity, last_active_tab, last_num_tabs, last_active_window_id; bool focused_at_last_render, needs_render; ScreenRenderData tab_bar_render_data; + struct { + color_type left, right; + } tab_bar_edge_color; bool tab_bar_data_updated; bool is_focused; monotonic_t cursor_blink_zero_time, last_mouse_activity_at; diff --git a/kitty/tab_bar.py b/kitty/tab_bar.py index b63fac27a..d87dea831 100644 --- a/kitty/tab_bar.py +++ b/kitty/tab_bar.py @@ -14,7 +14,7 @@ from .config import build_ansi_color_table from .constants import config_dir from .fast_data_types import ( DECAWM, Color, Region, Screen, cell_size_for_window, get_boss, get_options, - pt_to_px, set_tab_bar_render_data, viewport_for_window, + pt_to_px, set_tab_bar_render_data, update_tab_bar_edge_colors, viewport_for_window, ) from .rgb import alpha_blend, color_as_sgr, color_from_int, to_color from .types import WindowGeometry, run_once @@ -664,6 +664,7 @@ class TabBar: self.cell_ranges = cr s.erase_in_line(0, False) # Ensure no long titles bleed after the last tab self.align() + update_tab_bar_edge_colors(self.os_window_id) def align_with_factor(self, factor: int = 1) -> None: if not self.cell_ranges: