From 40c2012eebd0dabd6e21379e37aa36e7b8a63409 Mon Sep 17 00:00:00 2001 From: zhaolei Date: Thu, 9 Apr 2026 13:03:04 +0800 Subject: [PATCH] Support negative inactive_text_alpha values for active-window-only fading --- kitty/conf/utils.py | 4 ++++ kitty/options/definition.py | 9 ++++++--- kitty/options/parse.py | 6 +++--- kitty/shaders.c | 10 ++++++++-- kitty_tests/options.py | 9 +++++++++ 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/kitty/conf/utils.py b/kitty/conf/utils.py index 946052730..1867bb46f 100644 --- a/kitty/conf/utils.py +++ b/kitty/conf/utils.py @@ -67,6 +67,10 @@ def unit_float(x: ConvertibleToNumbers) -> float: return max(0, min(float(x), 1)) +def signed_unit_float(x: ConvertibleToNumbers) -> float: + return max(-1, min(float(x), 1)) + + def number_with_unit(x: str, default_unit: str, *extra_units: str) -> tuple[float, str]: if (mat := number_unit_pat.match(x)) is not None: try: diff --git a/kitty/options/definition.py b/kitty/options/definition.py index b33b928f8..459b26a32 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -1397,10 +1397,13 @@ opt('bell_border_color', '#ff5a00', ) opt('inactive_text_alpha', '1.0', - option_type='unit_float', ctype='float', + option_type='signed_unit_float', ctype='float', long_text=''' -Fade the text in inactive windows by the specified amount (a number between zero -and one, with zero being fully faded). +Fade the text in inactive windows by the specified amount. This must be a +number between negative one and one. The absolute value controls the actual +opacity, with zero being fully faded and one being fully opaque. Negative +values cause fading to be applied based only on whether the current window is +active, ignoring the extra single-window unfocused case. ''' ) diff --git a/kitty/options/parse.py b/kitty/options/parse.py index f2e6c9024..bdfe71f2f 100644 --- a/kitty/options/parse.py +++ b/kitty/options/parse.py @@ -4,8 +4,8 @@ import typing import collections.abc # noqa: F401, RUF100 from kitty.conf.utils import ( - merge_dicts, positive_float, positive_int, python_string, to_bool, to_cmdline, to_color, - to_color_or_none, unit_float + merge_dicts, positive_float, positive_int, python_string, signed_unit_float, to_bool, to_cmdline, + to_color, to_color_or_none, unit_float ) from kitty.options.utils import ( action_alias, active_tab_title_template, allow_hyperlinks, bell_on_tab, box_drawing_scale, @@ -1045,7 +1045,7 @@ class Parser: ans['inactive_tab_foreground'] = to_color(val) def inactive_text_alpha(self, val: str, ans: dict[str, typing.Any]) -> None: - ans['inactive_text_alpha'] = unit_float(val) + ans['inactive_text_alpha'] = signed_unit_float(val) def initial_window_height(self, val: str, ans: dict[str, typing.Any]) -> None: ans['initial_window_height'] = window_size(val) diff --git a/kitty/shaders.c b/kitty/shaders.c index 2d50e4d49..93aa5d025 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -1405,9 +1405,15 @@ draw_cells(const WindowRenderData *srd, OSWindow *os_window, bool is_active_wind bind_vertex_array(srd->vao_idx); // We draw with inactive text alpha if: // - We're not drawing the tab bar - // - There's only a single window and the os window is not focused // - There are multiple windows and the current window is not active - float current_inactive_text_alpha = is_tab_bar || (!is_single_window && is_active_window) || (is_single_window && screen->cursor_render_info.is_focused) ? 1.0f : (float)OPT(inactive_text_alpha); + // When inactive_text_alpha is negative, its absolute value is used as the + // opacity and fading is based only on whether the current window is active. + float configured_inactive_text_alpha = (float)OPT(inactive_text_alpha); + bool use_active_window_only = configured_inactive_text_alpha < 0.f; + if (configured_inactive_text_alpha < 0.f) configured_inactive_text_alpha = -configured_inactive_text_alpha; + float current_inactive_text_alpha = use_active_window_only ? + (is_tab_bar || is_active_window ? 1.0f : configured_inactive_text_alpha) : + (is_tab_bar || (!is_single_window && is_active_window) || (is_single_window && screen->cursor_render_info.is_focused) ? 1.0f : configured_inactive_text_alpha); float bg_alpha = effective_os_window_alpha(os_window); color_type default_bg = cell_update_uniform_block( diff --git a/kitty_tests/options.py b/kitty_tests/options.py index 4eb56ff6e..c72a9cfe1 100644 --- a/kitty_tests/options.py +++ b/kitty_tests/options.py @@ -311,6 +311,15 @@ def conf_parsing(self): self.ae(opts.kitty_mod, to_modifiers('alt')) self.ae(next(keys_for_func(opts, 'next_layout')).mods, opts.kitty_mod) + opts = p('inactive_text_alpha 0.25') + self.ae(opts.inactive_text_alpha, 0.25) + opts = p('inactive_text_alpha -0.25') + self.ae(opts.inactive_text_alpha, -0.25) + opts = p('inactive_text_alpha 2') + self.ae(opts.inactive_text_alpha, 1.0) + opts = p('inactive_text_alpha -2') + self.ae(opts.inactive_text_alpha, -1.0) + # deprecation handling opts = p('clear_all_shortcuts y', 'send_text all f1 hello') self.ae(len(opts.keyboard_modes[''].keymap), 1)