mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-04 13:42:33 +02:00
Fix tab bar edge strips: use bg when edge cell has default color
This commit is contained in:
committed by
GitHub
parent
3313e5a6be
commit
6fb8ff1829
@@ -3439,23 +3439,33 @@ effective_cell_edge_color(char_type ch, color_type fg, color_type bg, bool is_le
|
||||
|
||||
|
||||
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);
|
||||
get_line_edge_colors_at_row(Screen *self, index_type y, color_type *left, color_type *right, bool *left_is_default, bool *right_is_default) {
|
||||
// Return the color at the left and right edges of the specified row.
|
||||
// Any of the output pointers may be NULL if that value is not needed.
|
||||
Line *line = range_line_(self, y);
|
||||
if (!line) return false;
|
||||
color_type left_cell_fg = OPT(foreground), left_cell_bg = OPT(background), right_cell_bg = OPT(background), right_cell_fg = OPT(foreground);
|
||||
index_type cell_color_x = 0;
|
||||
char_type left_char = line_get_char(line, cell_color_x);
|
||||
bool reversed = false;
|
||||
colors_for_cell(line, self->color_profile, &cell_color_x, &left_cell_fg, &left_cell_bg, &reversed);
|
||||
if (left_is_default) *left_is_default = (line->gpu_cells[cell_color_x].bg & 0xff) == 0;
|
||||
if (left) *left = effective_cell_edge_color(left_char, left_cell_fg, left_cell_bg, true);
|
||||
if (line->xnum > 0) cell_color_x = line->xnum - 1;
|
||||
char_type right_char = line_get_char(line, cell_color_x);
|
||||
reversed = false;
|
||||
colors_for_cell(line, self->color_profile, &cell_color_x, &right_cell_fg, &right_cell_bg, &reversed);
|
||||
*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);
|
||||
if (right_is_default) *right_is_default = (line->gpu_cells[cell_color_x].bg & 0xff) == 0;
|
||||
if (right) *right = effective_cell_edge_color(right_char, right_cell_fg, right_cell_bg, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
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
|
||||
return get_line_edge_colors_at_row(self, self->cursor->y, left, right, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
update_line_data(Line *line, unsigned int dest_y, uint8_t *data) {
|
||||
|
||||
@@ -332,6 +332,7 @@ bool screen_prompt_supports_click_events(const Screen *, bool *is_relative);
|
||||
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);
|
||||
bool get_line_edge_colors_at_row(Screen *self, index_type y, color_type *left, color_type *right, bool *left_is_default, bool *right_is_default);
|
||||
bool parse_sgr(Screen *screen, const uint8_t *buf, unsigned int num, const char *report_name, bool is_deccara);
|
||||
bool screen_pause_rendering(Screen *self, bool pause, int for_in_ms);
|
||||
void screen_check_pause_rendering(Screen *self, monotonic_t now);
|
||||
|
||||
@@ -1404,13 +1404,39 @@ PYWRAP1(patch_global_colors) {
|
||||
|
||||
PYWRAP1(update_tab_bar_edge_colors) {
|
||||
id_type os_window_id;
|
||||
PA("K", &os_window_id);
|
||||
int is_vertical = 0;
|
||||
PA("K|i", &os_window_id, &is_vertical);
|
||||
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; }
|
||||
Screen *screen = os_window->tab_bar_render_data.screen;
|
||||
if (screen) {
|
||||
bool left_is_default = true, right_is_default = true;
|
||||
bool ok;
|
||||
if (!is_vertical) {
|
||||
ok = get_line_edge_colors_at_row(
|
||||
screen, screen->cursor->y,
|
||||
&os_window->tab_bar_edge_color.left,
|
||||
&os_window->tab_bar_edge_color.right,
|
||||
&left_is_default, &right_is_default);
|
||||
} else {
|
||||
color_type top_color = 0, bottom_color = 0;
|
||||
bool top_is_default = true, bottom_is_default = true;
|
||||
ok = get_line_edge_colors_at_row(screen, 0, &top_color, NULL, &top_is_default, NULL) &&
|
||||
get_line_edge_colors_at_row(screen, screen->lines - 1, &bottom_color, NULL, &bottom_is_default, NULL);
|
||||
if (ok) {
|
||||
os_window->tab_bar_edge_color.left = top_color;
|
||||
os_window->tab_bar_edge_color.right = bottom_color;
|
||||
left_is_default = top_is_default;
|
||||
right_is_default = bottom_is_default;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
return Py_BuildValue("OO",
|
||||
left_is_default ? Py_True : Py_False,
|
||||
right_is_default ? Py_True : Py_False);
|
||||
}
|
||||
}
|
||||
END_WITH_OS_WINDOW
|
||||
Py_RETURN_FALSE;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
|
||||
@@ -619,6 +619,9 @@ class TabBar:
|
||||
self.blank_rects: tuple[Border, ...] = ()
|
||||
self.tab_extents: Sequence[TabExtent] = ()
|
||||
self.laid_out_once = False
|
||||
self.left_edge_is_default = True
|
||||
self.right_edge_is_default = True
|
||||
self._last_viewport: tuple[Region, Region, int, int] | None = None
|
||||
self.apply_options()
|
||||
|
||||
def apply_options(self) -> None:
|
||||
@@ -753,18 +756,23 @@ class TabBar:
|
||||
blank_rects.append(Border(0, tab_bar.bottom, vw, central.top, bg))
|
||||
g = self.window_geometry
|
||||
if self.is_vertical:
|
||||
if opts.tab_bar_margin_color is None:
|
||||
top_bg = bg if self.left_edge_is_default else BorderColor.tab_bar_left_edge_color
|
||||
bottom_bg = bg if self.right_edge_is_default else BorderColor.tab_bar_right_edge_color
|
||||
else:
|
||||
top_bg = bottom_bg = bg
|
||||
if g.left > tab_bar.left:
|
||||
blank_rects.append(Border(tab_bar.left, g.top, g.left, g.bottom, bg))
|
||||
if g.right < tab_bar.right:
|
||||
blank_rects.append(Border(g.right, g.top, tab_bar.right, g.bottom, bg))
|
||||
if g.top > tab_bar.top:
|
||||
blank_rects.append(Border(g.left, tab_bar.top, g.right, g.top, bg))
|
||||
blank_rects.append(Border(g.left, tab_bar.top, g.right, g.top, top_bg))
|
||||
if g.bottom < tab_bar.bottom:
|
||||
blank_rects.append(Border(g.left, g.bottom, g.right, tab_bar.bottom, bg))
|
||||
blank_rects.append(Border(g.left, g.bottom, g.right, tab_bar.bottom, bottom_bg))
|
||||
else:
|
||||
if opts.tab_bar_margin_color is None:
|
||||
left_bg = BorderColor.tab_bar_left_edge_color
|
||||
right_bg = BorderColor.tab_bar_right_edge_color
|
||||
left_bg = bg if self.left_edge_is_default else BorderColor.tab_bar_left_edge_color
|
||||
right_bg = bg if self.right_edge_is_default else BorderColor.tab_bar_right_edge_color
|
||||
else:
|
||||
left_bg = right_bg = bg
|
||||
if g.left > tab_bar.left:
|
||||
@@ -811,15 +819,31 @@ class TabBar:
|
||||
self.window_geometry = g = WindowGeometry(
|
||||
left_margin, tab_bar.top, left_margin + cell_area_width, tab_bar.bottom, s.columns, s.lines)
|
||||
self.laid_out_once = True
|
||||
self._last_viewport = (central, tab_bar, vw, vh)
|
||||
self.update_blank_rects(central, tab_bar, vw, vh)
|
||||
set_tab_bar_render_data(self.os_window_id, self.screen, *g[:4])
|
||||
|
||||
def update(self, data: Sequence[TabBarData]) -> None:
|
||||
def _update_edge_defaults(self, is_vertical: bool) -> bool:
|
||||
"""Call update_tab_bar_edge_colors, update cached is-default flags.
|
||||
Returns True when the flags changed and blank_rects need rebuilding."""
|
||||
result = update_tab_bar_edge_colors(self.os_window_id, int(is_vertical))
|
||||
if result is None:
|
||||
return False
|
||||
left_is_default, right_is_default = result
|
||||
if left_is_default != self.left_edge_is_default or right_is_default != self.right_edge_is_default:
|
||||
self.left_edge_is_default = left_is_default
|
||||
self.right_edge_is_default = right_is_default
|
||||
if self._last_viewport is not None:
|
||||
self.update_blank_rects(*self._last_viewport)
|
||||
return True
|
||||
return False
|
||||
|
||||
def update(self, data: Sequence[TabBarData]) -> bool:
|
||||
if not self.laid_out_once:
|
||||
return
|
||||
return False
|
||||
if self.is_vertical:
|
||||
self.update_vertical(data)
|
||||
return
|
||||
return self.update_vertical(data)
|
||||
|
||||
s = self.screen
|
||||
last_tab = data[-1] if data else None
|
||||
ed = ExtraData()
|
||||
@@ -884,16 +908,16 @@ class TabBar:
|
||||
self.tab_extents = 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)
|
||||
return self._update_edge_defaults(False)
|
||||
|
||||
def update_vertical(self, data: Sequence[TabBarData]) -> None:
|
||||
def update_vertical(self, data: Sequence[TabBarData]) -> bool:
|
||||
s = self.screen
|
||||
self.last_laid_out_tabs = data
|
||||
self.tab_extents = ()
|
||||
s.cursor.x = s.cursor.y = 0
|
||||
s.erase_in_display(2, False)
|
||||
if not data:
|
||||
return
|
||||
return self._update_edge_defaults(True)
|
||||
max_tab_length = max(1, s.columns - 1)
|
||||
tab_line_height = max(1, min(MAX_VERTICAL_TAB_LINES, s.lines // max(1, len(data))))
|
||||
rows_to_draw = min(len(data), max(1, s.lines // tab_line_height))
|
||||
@@ -926,6 +950,7 @@ class TabBar:
|
||||
s.cursor.fg = as_rgb(0xff0000)
|
||||
s.draw('…')
|
||||
self.tab_extents = tuple(cr)
|
||||
return self._update_edge_defaults(True)
|
||||
|
||||
def align_with_factor(self, factor: int = 1) -> None:
|
||||
if not self.tab_extents:
|
||||
|
||||
@@ -1330,7 +1330,9 @@ class TabManager: # {{{
|
||||
watcher(boss, w, data)
|
||||
|
||||
def update_tab_bar_data(self) -> None:
|
||||
self.tab_bar.update(self.tab_bar_data)
|
||||
if self.tab_bar.update(self.tab_bar_data):
|
||||
for tab in self.tabs:
|
||||
tab.relayout_borders()
|
||||
|
||||
def title_changed(self, tab: Tab) -> None:
|
||||
self.mark_tab_bar_dirty()
|
||||
|
||||
Reference in New Issue
Block a user