Add draw_borders_when_focused option

Adds a new configuration option `draw_borders_when_focused` that allows
borders to be drawn around windows when the OS window is focused,
regardless of the layout or number of windows.

This is useful for:
- Seeing which terminal window has focus in layouts like stack that
  normally don't show borders
- Showing borders even when there's only a single window
- Providing visual feedback about OS window focus state

When enabled, borders use the active_border_color when the OS window is
focused and inactive_border_color when unfocused. This behavior only
applies when the option is enabled, preserving existing behavior by
default.

The implementation:
- Adds the draw_borders_when_focused config option (default: no)
- Modifies border drawing logic to check OS window focus state
- Triggers border redraw when OS window focus changes
- Only affects behavior when the option is explicitly enabled
This commit is contained in:
Jackie Li 2025-10-13 20:07:47 +01:00
parent 220099a3ed
commit 09e16adf8b
No known key found for this signature in database
GPG key ID: 9D44BB781C299FEF
6 changed files with 34 additions and 3 deletions

View file

@ -6,7 +6,7 @@ from enum import IntFlag
from functools import partial
from typing import NamedTuple
from .fast_data_types import BORDERS_PROGRAM, get_options, init_borders_program, set_borders_rects
from .fast_data_types import BORDERS_PROGRAM, current_focused_os_window_id, get_options, init_borders_program, set_borders_rects
from .shaders import program_for
from .typing_compat import LayoutType
from .utils import color_as_int
@ -95,13 +95,16 @@ class Borders:
bw = groups[0].effective_border()
draw_borders = bw > 0 and draw_window_borders
active_group = all_windows.active_group
# Check if this OS window is focused (only if draw_borders_when_focused is enabled)
os_window_focused = current_focused_os_window_id() == self.os_window_id if opts.draw_borders_when_focused else True
for i, wg in enumerate(groups):
window_bg = color_as_int(wg.default_bg)
window_bg = (window_bg << 8) | BorderColor.window_bg
if draw_borders and not draw_minimal_borders:
# Draw the border rectangles
if wg is active_group and draw_active_borders:
# Only check OS window focus if draw_borders_when_focused is enabled
if wg is active_group and draw_active_borders and os_window_focused:
color = BorderColor.active
else:
color = BorderColor.bell if wg.needs_attention else BorderColor.inactive

View file

@ -1854,6 +1854,11 @@ class Boss:
if is_macos and focused:
cocoa_set_menubar_title(w.title or '')
tm.mark_tab_bar_dirty()
# Redraw borders when focus changes if draw_borders_when_focused is enabled
# This ensures borders change color based on OS window focus state
opts = get_options()
if opts.draw_borders_when_focused and tm.active_tab is not None:
tm.active_tab.relayout_borders()
def on_activity_since_last_focus(self, window: Window) -> None:
os_window_id = window.os_window_id

View file

@ -1224,6 +1224,17 @@ drawn.
'''
)
opt('draw_borders_when_focused', 'no',
option_type='to_bool',
long_text='''
Draw borders around windows when the OS window is focused, regardless of the
layout or number of windows. This allows you to see which terminal window has
focus even in layouts like stack that normally don't show borders, or when
there is only a single window. The border color will change to the active color
when focused and inactive color when unfocused.
'''
)
opt('window_margin_width', '0',
option_type='edge_width',
long_text='''

View file

@ -971,6 +971,9 @@ class Parser:
def draw_minimal_borders(self, val: str, ans: dict[str, typing.Any]) -> None:
ans['draw_minimal_borders'] = to_bool(val)
def draw_borders_when_focused(self, val: str, ans: dict[str, typing.Any]) -> None:
ans['draw_borders_when_focused'] = to_bool(val)
def dynamic_background_opacity(self, val: str, ans: dict[str, typing.Any]) -> None:
ans['dynamic_background_opacity'] = to_bool(val)

View file

@ -345,6 +345,7 @@ option_names = (
'detect_urls',
'dim_opacity',
'disable_ligatures',
'draw_borders_when_focused',
'draw_minimal_borders',
'dynamic_background_opacity',
'editor',
@ -543,6 +544,7 @@ class Options:
detect_urls: bool = True
dim_opacity: float = 0.4
disable_ligatures: int = 0
draw_borders_when_focused: bool = False
draw_minimal_borders: bool = True
dynamic_background_opacity: bool = False
editor: str = '.'

View file

@ -418,10 +418,17 @@ class Tab: # {{{
tm = self.tab_manager_ref()
if tm is not None:
ly = self.current_layout
opts = get_options()
# Draw borders if: normal conditions OR new option enabled (regardless of focus)
# When unfocused, borders will automatically use inactive_border_color
draw_borders = (
(ly.needs_window_borders and self.windows.num_visble_groups > 1) or ly.must_draw_borders
or opts.draw_borders_when_focused
)
self.borders(
all_windows=self.windows,
current_layout=ly, tab_bar_rects=tm.tab_bar_rects,
draw_window_borders=(ly.needs_window_borders and self.windows.num_visble_groups > 1) or ly.must_draw_borders
draw_window_borders=draw_borders
)
def create_layout_object(self, name: str) -> Layout: