From 4385acd3c6f3150c646887724f839ed6cc889c49 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 25 Oct 2021 12:21:46 +0530 Subject: [PATCH] A new option to set the tab bar margin color independently --- docs/changelog.rst | 4 ++-- kittens/diff/options/parse.py | 1 - kittens/diff/options/types.py | 1 - kitty/border_vertex.glsl | 3 ++- kitty/borders.py | 2 +- kitty/boss.py | 4 +++- kitty/options/definition.py | 8 ++++++++ kitty/options/parse.py | 3 +++ kitty/options/to-c-generated.h | 15 +++++++++++++++ kitty/options/types.py | 2 ++ kitty/rc/set_colors.py | 11 +++++++---- kitty/shaders.c | 4 +++- kitty/state.c | 2 +- kitty/state.h | 2 +- kitty/tab_bar.py | 2 +- 15 files changed, 49 insertions(+), 15 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 592ec41a2..4c4ec5394 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -109,8 +109,8 @@ To update |kitty|, :doc:`follow the instructions `. - Fix various issues with changing :opt:`tab_bar_background` by remote control (:iss:`4152`) -- All tab bar margins are now drawn using the general background color, instead - of drawing only the left and right margins with the tab bar background color +- A new option :opt:`tab_bar_margin_color` to control the color of the tab bar + margins - Add support for OSC 777 based desktop notifications diff --git a/kittens/diff/options/parse.py b/kittens/diff/options/parse.py index 33d740aee..36af21da5 100644 --- a/kittens/diff/options/parse.py +++ b/kittens/diff/options/parse.py @@ -1,5 +1,4 @@ # generated by gen-config.py DO NOT edit -# vim:fileencoding=utf-8 import typing from kittens.diff.options.utils import parse_map, syntax_aliases diff --git a/kittens/diff/options/types.py b/kittens/diff/options/types.py index 34a7be191..b2998dc9e 100644 --- a/kittens/diff/options/types.py +++ b/kittens/diff/options/types.py @@ -1,5 +1,4 @@ # generated by gen-config.py DO NOT edit -# vim:fileencoding=utf-8 import typing from kitty.conf.utils import KeyAction, KittensKeyMap diff --git a/kitty/border_vertex.glsl b/kitty/border_vertex.glsl index b2dcc7c16..6f1fb9e74 100644 --- a/kitty/border_vertex.glsl +++ b/kitty/border_vertex.glsl @@ -5,6 +5,7 @@ uniform vec3 active_border_color; uniform vec3 inactive_border_color; uniform vec3 bell_border_color; uniform vec3 tab_bar_bg; +uniform vec3 tab_bar_margin_color; in uvec4 rect; // left, top, right, bottom in uint rect_color; out vec3 color; @@ -41,5 +42,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 = W(0, default_bg) + W(1, active_border_color) + W(2, inactive_border_color) + W(3, window_bg) + W(4, bell_border_color) + W(5, tab_bar_bg); + color = W(0, default_bg) + W(1, active_border_color) + W(2, inactive_border_color) + W(3, window_bg) + W(4, bell_border_color) + W(5, tab_bar_bg) + W(6, tab_bar_margin_color); } diff --git a/kitty/borders.py b/kitty/borders.py index bc6b6487c..fcee357d9 100644 --- a/kitty/borders.py +++ b/kitty/borders.py @@ -15,7 +15,7 @@ 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, tab_bar_bg = ((1 << i) for i in range(6)) + default_bg, active, inactive, window_bg, bell, tab_bar_bg, tab_bar_margin_color = ((1 << i) for i in range(7)) class Border(NamedTuple): diff --git a/kitty/boss.py b/kitty/boss.py index a2e17fba7..8a24311c3 100755 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -1688,17 +1688,19 @@ class Boss: window.refresh() def patch_colors(self, spec: Dict[str, Optional[int]], configured: bool = False) -> None: + from kitty.rc.set_colors import nullable_colors opts = get_options() if configured: for k, v in spec.items(): if hasattr(opts, k): if v is None: - if k in ('cursor_text_color', 'tab_bar_background'): + if k in nullable_colors: setattr(opts, k, None) else: setattr(opts, k, color_from_int(v)) for tm in self.all_tab_managers: tm.tab_bar.patch_colors(spec) + tm.tab_bar.layout() tm.mark_tab_bar_dirty() patch_global_colors(spec, configured) diff --git a/kitty/options/definition.py b/kitty/options/definition.py index 69120f324..f40516feb 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -1046,6 +1046,14 @@ opt('tab_bar_background', 'none', long_text=''' Background color for the tab bar. Defaults to using the terminal background color. +''' + ) + +opt('tab_bar_margin_color', 'none', + option_type='to_color_or_none', ctype='color_or_none_as_int', + long_text=''' +Color for the tab bar margin area. Defaults to using the terminal background +color. ''' ) egr() # }}} diff --git a/kitty/options/parse.py b/kitty/options/parse.py index 49d22eeeb..8f8b135e1 100644 --- a/kitty/options/parse.py +++ b/kitty/options/parse.py @@ -1174,6 +1174,9 @@ class Parser: def tab_bar_edge(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: ans['tab_bar_edge'] = tab_bar_edge(val) + def tab_bar_margin_color(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: + ans['tab_bar_margin_color'] = to_color_or_none(val) + def tab_bar_margin_height(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: ans['tab_bar_margin_height'] = tab_bar_margin_height(val) diff --git a/kitty/options/to-c-generated.h b/kitty/options/to-c-generated.h index 09f4ba913..6e26952f7 100644 --- a/kitty/options/to-c-generated.h +++ b/kitty/options/to-c-generated.h @@ -616,6 +616,19 @@ convert_from_opts_tab_bar_background(PyObject *py_opts, Options *opts) { Py_DECREF(ret); } +static void +convert_from_python_tab_bar_margin_color(PyObject *val, Options *opts) { + opts->tab_bar_margin_color = color_or_none_as_int(val); +} + +static void +convert_from_opts_tab_bar_margin_color(PyObject *py_opts, Options *opts) { + PyObject *ret = PyObject_GetAttrString(py_opts, "tab_bar_margin_color"); + if (ret == NULL) return; + convert_from_python_tab_bar_margin_color(ret, opts); + Py_DECREF(ret); +} + static void convert_from_python_foreground(PyObject *val, Options *opts) { opts->foreground = color_as_int(val); @@ -1024,6 +1037,8 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *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); + 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/types.py b/kitty/options/types.py index d3999d85f..9cdb52160 100644 --- a/kitty/options/types.py +++ b/kitty/options/types.py @@ -411,6 +411,7 @@ option_names = ( # {{{ 'tab_bar_align', 'tab_bar_background', 'tab_bar_edge', + 'tab_bar_margin_color', 'tab_bar_margin_height', 'tab_bar_margin_width', 'tab_bar_min_tabs', @@ -548,6 +549,7 @@ class Options: tab_bar_align: choices_for_tab_bar_align = 'left' tab_bar_background: typing.Optional[kitty.rgb.Color] = None tab_bar_edge: int = 3 + tab_bar_margin_color: typing.Optional[kitty.rgb.Color] = None tab_bar_margin_height: TabBarMarginHeight = TabBarMarginHeight(outer=0, inner=0) tab_bar_margin_width: float = 0 tab_bar_min_tabs: int = 2 diff --git a/kitty/rc/set_colors.py b/kitty/rc/set_colors.py index 92f9750b4..f05615b2a 100644 --- a/kitty/rc/set_colors.py +++ b/kitty/rc/set_colors.py @@ -18,22 +18,25 @@ if TYPE_CHECKING: from kitty.cli_stub import SetColorsRCOptions as CLIOptions +nullable_colors = ('cursor_text_color', 'tab_bar_background', 'tab_bar_margin_color') + + def parse_colors(args: Iterable[str]) -> Dict[str, Optional[int]]: colors: Dict[str, Optional[Color]] = {} - nullable_colors: Dict[str, Optional[int]] = {} + nullable_color_map: Dict[str, Optional[int]] = {} for spec in args: if '=' in spec: colors.update(parse_config((spec.replace('=', ' '),))) else: with open(os.path.expanduser(spec), encoding='utf-8', errors='replace') as f: colors.update(parse_config(f)) - for k in ('cursor_text_color', 'tab_bar_background'): + for k in nullable_colors: q = colors.pop(k, False) if q is not False: val = int(q) if isinstance(q, Color) else None - nullable_colors[k] = val + nullable_color_map[k] = val ans: Dict[str, Optional[int]] = {k: int(v) for k, v in colors.items() if isinstance(v, Color)} - ans.update(nullable_colors) + ans.update(nullable_color_map) return ans diff --git a/kitty/shaders.c b/kitty/shaders.c index f2288ef08..c05d2c896 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -790,7 +790,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, BORDER_tab_bar_bg, 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, BORDER_tab_bar_margin_color, NUM_BORDER_UNIFORMS }; static GLint border_uniform_locations[NUM_BORDER_UNIFORMS] = {0}; static void @@ -803,6 +803,7 @@ init_borders_program(void) { SET_LOC(inactive_border_color) SET_LOC(bell_border_color) SET_LOC(tab_bar_bg) + SET_LOC(tab_bar_margin_color) #undef SET_LOC } @@ -843,6 +844,7 @@ draw_borders(ssize_t vao_idx, unsigned int num_border_rects, BorderRect *rect_bu 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))); + glUniform3f(border_uniform_locations[BORDER_tab_bar_margin_color], CV3(OPT(tab_bar_margin_color))); 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.c b/kitty/state.c index ca2be609a..49264d291 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -947,7 +947,7 @@ PYWRAP1(patch_global_colors) { else if (PyLong_Check(val)) OPT(name) = PyLong_AsLong(val); \ } \ } - P(active_border_color); P(inactive_border_color); P(bell_border_color); P(tab_bar_background); + P(active_border_color); P(inactive_border_color); P(bell_border_color); P(tab_bar_background); P(tab_bar_margin_color); if (configured) { P(background); P(url_color); P(mark1_background); P(mark1_foreground); P(mark2_background); P(mark2_foreground); diff --git a/kitty/state.h b/kitty/state.h index caf151742..0f05ff719 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, tab_bar_background; + color_type url_color, background, foreground, active_border_color, inactive_border_color, bell_border_color, tab_bar_background, tab_bar_margin_color; 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 a848e6962..c8b7806d7 100644 --- a/kitty/tab_bar.py +++ b/kitty/tab_bar.py @@ -488,7 +488,7 @@ class TabBar: def update_blank_rects(self, central: Region, tab_bar: Region, vw: int, vh: int) -> None: opts = get_options() blank_rects: List[Border] = [] - bg = BorderColor.default_bg + bg = BorderColor.tab_bar_margin_color if opts.tab_bar_margin_color is not None else BorderColor.default_bg if opts.tab_bar_margin_height: if opts.tab_bar_edge == 3: # bottom if opts.tab_bar_margin_height.outer: