diff --git a/docs/changelog.rst b/docs/changelog.rst index d969787f6..00b4dd153 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -46,6 +46,9 @@ To update |kitty|, :doc:`follow the instructions `. - Fix :opt:`active_tab_foreground` not being honored when :opt:`tab_bar_style` is ``slant`` (:iss:`4053`) +- When a :opt:`tab_bar_background` is specified it should extend to the edges + of the OS window (:iss:`4054`) + 0.23.1 [2021-08-17] diff --git a/kitty/border_vertex.glsl b/kitty/border_vertex.glsl index 0bab76ab5..7be459a36 100644 --- a/kitty/border_vertex.glsl +++ b/kitty/border_vertex.glsl @@ -4,6 +4,7 @@ uniform vec3 default_bg; uniform vec3 active_border_color; uniform vec3 inactive_border_color; uniform vec3 bell_border_color; +uniform vec3 tab_bar_bg; in uvec4 rect; // left, top, right, bottom in uint rect_color; out vec3 color; @@ -38,5 +39,5 @@ void main() { gl_Position = vec4(to_opengl(rect[pos.x], rect[pos.y]), 0, 1); int rc = int(rect_color); vec3 window_bg = vec3(to_color(rect_color >> 24), to_color(rect_color >> 16), to_color(rect_color >> 8)); - color = float(1 & rc) * default_bg + float((2 & rc) >> 1) * active_border_color + float((4 & rc) >> 2) * inactive_border_color + float((8 & rc) >> 3) * window_bg + float((16 & rc) >> 4) * bell_border_color; + color = float(1 & rc) * default_bg + float((2 & rc) >> 1) * active_border_color + float((4 & rc) >> 2) * inactive_border_color + float((8 & rc) >> 3) * window_bg + float((16 & rc) >> 4) * bell_border_color + float((32 & rc) >> 5) * tab_bar_bg; } diff --git a/kitty/borders.py b/kitty/borders.py index dac133b95..c379a1ae8 100644 --- a/kitty/borders.py +++ b/kitty/borders.py @@ -3,7 +3,7 @@ # License: GPL v3 Copyright: 2016, Kovid Goyal from enum import IntFlag -from typing import Sequence, Tuple +from typing import Iterable, Sequence, NamedTuple from .fast_data_types import ( BORDERS_PROGRAM, add_borders_rect, compile_program, get_options, @@ -16,7 +16,15 @@ from .window_list import WindowGroup, WindowList class BorderColor(IntFlag): # See the border vertex shader for how these flags become actual colors - default_bg, active, inactive, window_bg, bell = ((1 << i) for i in range(5)) + default_bg, active, inactive, window_bg, bell, tab_bar_bg = ((1 << i) for i in range(6)) + + +class Border(NamedTuple): + left: int + top: int + right: int + bottom: int + color: BorderColor def vertical_edge(os_window_id: int, tab_id: int, color: int, width: int, top: int, bottom: int, left: int) -> None: @@ -71,7 +79,7 @@ class Borders: self, all_windows: WindowList, current_layout: LayoutType, - tab_bar_rects: Sequence[Tuple[int, int, int, int]], + tab_bar_rects: Iterable[Border], draw_window_borders: bool = True, ) -> None: opts = get_options() @@ -81,11 +89,9 @@ class Borders: has_background_image = os_window_has_background_image(self.os_window_id) if not has_background_image: for br in current_layout.blank_rects: - left, top, right, bottom = br - add_borders_rect(self.os_window_id, self.tab_id, left, top, right, bottom, BorderColor.default_bg) + add_borders_rect(self.os_window_id, self.tab_id, *br, BorderColor.default_bg) for tbr in tab_bar_rects: - left, top, right, bottom = tbr - add_borders_rect(self.os_window_id, self.tab_id, left, top, right, bottom, BorderColor.default_bg) + add_borders_rect(self.os_window_id, self.tab_id, *tbr) bw = 0 groups = tuple(all_windows.iter_all_layoutable_groups(only_visible=True)) if groups: diff --git a/kitty/options/definition.py b/kitty/options/definition.py index 608800ba8..4953d18ad 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -1030,7 +1030,7 @@ opt('inactive_tab_font_style', 'normal', ) opt('tab_bar_background', 'none', - option_type='to_color_or_none', + option_type='to_color_or_none', ctype='color_or_none_as_int', long_text=''' Background color for the tab bar. Defaults to using the terminal background color. diff --git a/kitty/options/to-c-generated.h b/kitty/options/to-c-generated.h index 860c7d295..b7a47cab6 100644 --- a/kitty/options/to-c-generated.h +++ b/kitty/options/to-c-generated.h @@ -590,6 +590,19 @@ convert_from_opts_tab_bar_min_tabs(PyObject *py_opts, Options *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); +} + +static void +convert_from_opts_tab_bar_background(PyObject *py_opts, Options *opts) { + PyObject *ret = PyObject_GetAttrString(py_opts, "tab_bar_background"); + if (ret == NULL) return; + convert_from_python_tab_bar_background(ret, opts); + Py_DECREF(ret); +} + static void convert_from_python_foreground(PyObject *val, Options *opts) { opts->foreground = color_as_int(val); @@ -994,6 +1007,8 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *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_foreground(py_opts, opts); if (PyErr_Occurred()) return false; convert_from_opts_background(py_opts, opts); diff --git a/kitty/options/to-c.h b/kitty/options/to-c.h index 5c8126ae4..387ee33fa 100644 --- a/kitty/options/to-c.h +++ b/kitty/options/to-c.h @@ -21,6 +21,13 @@ color_as_int(PyObject *color) { #undef I } +static inline color_type +color_or_none_as_int(PyObject *color) { + if (color == Py_None) return 0; + return color_as_int(color); +} + + static inline color_type active_border_color(PyObject *color) { if (color == Py_None) return 0x00ff00; diff --git a/kitty/shaders.c b/kitty/shaders.c index 2d4076efd..a47330977 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -710,7 +710,7 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GL // }}} // Borders {{{ -enum BorderUniforms { BORDER_viewport, BORDER_background_opacity, BORDER_default_bg, BORDER_active_border_color, BORDER_inactive_border_color, BORDER_bell_border_color, NUM_BORDER_UNIFORMS }; +enum BorderUniforms { BORDER_viewport, BORDER_background_opacity, BORDER_default_bg, BORDER_active_border_color, BORDER_inactive_border_color, BORDER_bell_border_color, BORDER_tab_bar_bg, NUM_BORDER_UNIFORMS }; static GLint border_uniform_locations[NUM_BORDER_UNIFORMS] = {0}; static void @@ -722,6 +722,7 @@ init_borders_program(void) { SET_LOC(active_border_color) SET_LOC(inactive_border_color) SET_LOC(bell_border_color) + SET_LOC(tab_bar_bg) #undef SET_LOC } @@ -761,6 +762,7 @@ draw_borders(ssize_t vao_idx, unsigned int num_border_rects, BorderRect *rect_bu glUniform3f(border_uniform_locations[BORDER_active_border_color], CV3(OPT(active_border_color))); glUniform3f(border_uniform_locations[BORDER_inactive_border_color], CV3(OPT(inactive_border_color))); glUniform3f(border_uniform_locations[BORDER_bell_border_color], CV3(OPT(bell_border_color))); + glUniform3f(border_uniform_locations[BORDER_tab_bar_bg], CV3(OPT(tab_bar_background))); glUniform2ui(border_uniform_locations[BORDER_viewport], viewport_width, viewport_height); color_type default_bg = (num_visible_windows > 1 && !all_windows_have_same_bg) ? OPT(background) : active_window_bg; glUniform3f(border_uniform_locations[BORDER_default_bg], CV3(default_bg)); diff --git a/kitty/state.h b/kitty/state.h index 189b2ebf4..a8934a0a5 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -31,7 +31,7 @@ typedef struct { unsigned int scrollback_pager_history_size; bool scrollback_fill_enlarged_window; char_type *select_by_word_characters; - color_type url_color, background, foreground, active_border_color, inactive_border_color, bell_border_color; + color_type url_color, background, foreground, active_border_color, inactive_border_color, bell_border_color, tab_bar_background; color_type mark1_foreground, mark1_background, mark2_foreground, mark2_background, mark3_foreground, mark3_background; monotonic_t repaint_delay, input_delay; bool focus_follows_mouse; diff --git a/kitty/tab_bar.py b/kitty/tab_bar.py index fbde31651..301027b9b 100644 --- a/kitty/tab_bar.py +++ b/kitty/tab_bar.py @@ -8,13 +8,13 @@ from typing import ( Any, Callable, Dict, List, NamedTuple, Optional, Sequence, Tuple ) +from .borders import Border, BorderColor from .config import build_ansi_color_table from .constants import config_dir from .fast_data_types import ( DECAWM, Screen, cell_size_for_window, get_options, pt_to_px, set_tab_bar_render_data, viewport_for_window ) -from .layout.base import Rect from .rgb import Color, alpha_blend, color_as_sgr, color_from_int, to_color from .types import WindowGeometry, run_once from .typing import EdgeLiteral, PowerlineStyle @@ -386,7 +386,7 @@ class TabBar: self.os_window_id = os_window_id self.num_tabs = 1 self.data_buffer_size = 0 - self.blank_rects: Tuple[Rect, ...] = () + self.blank_rects: Tuple[Border, ...] = () self.laid_out_once = False self.apply_options() @@ -482,21 +482,23 @@ class TabBar: margin = (viewport_width - ncells * cell_width) // 2 + self.margin_width self.window_geometry = g = WindowGeometry( margin, tab_bar.top, viewport_width - margin, tab_bar.bottom, s.columns, s.lines) - blank_rects: List[Rect] = [] - if margin > 0: - blank_rects.append(Rect(0, g.top, g.left, g.bottom + 1)) - blank_rects.append(Rect(g.right - 1, g.top, viewport_width, g.bottom + 1)) + blank_rects: List[Border] = [] if opts.tab_bar_margin_height: + bg = BorderColor.default_bg if opts.tab_bar_edge == 3: # bottom if opts.tab_bar_margin_height.outer: - blank_rects.append(Rect(0, tab_bar.bottom + 1, vw, vh)) + blank_rects.append(Border(0, tab_bar.bottom + 1, vw, vh, bg)) if opts.tab_bar_margin_height.inner: - blank_rects.append(Rect(0, central.bottom + 1, vw, vh)) + blank_rects.append(Border(0, central.bottom + 1, vw, vh, bg)) else: # top if opts.tab_bar_margin_height.outer: - blank_rects.append(Rect(0, 0, vw, tab_bar.top)) + blank_rects.append(Border(0, 0, vw, tab_bar.top, bg)) if opts.tab_bar_margin_height.inner: - blank_rects.append(Rect(0, tab_bar.bottom + 1, vw, central.top)) + blank_rects.append(Border(0, tab_bar.bottom + 1, vw, central.top, bg)) + if margin > 0: + bg = BorderColor.default_bg if opts.tab_bar_background is None else BorderColor.tab_bar_bg + blank_rects.append(Border(0, g.top, g.left, g.bottom + 1, bg)) + blank_rects.append(Border(g.right - 1, g.top, viewport_width, g.bottom + 1, bg)) self.blank_rects = tuple(blank_rects) self.screen_geometry = sg = calculate_gl_geometry(g, vw, vh, cell_width, cell_height)