mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-16 13:34:48 +02:00
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
117 lines
4.2 KiB
Python
117 lines
4.2 KiB
Python
#!/usr/bin/env python
|
|
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
|
|
from collections.abc import Iterable
|
|
from enum import IntFlag
|
|
from functools import partial
|
|
from typing import NamedTuple
|
|
|
|
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
|
|
from .window_list import WindowGroup, WindowList
|
|
|
|
|
|
class BorderColor(IntFlag):
|
|
# These are indices into the array of colors in the border vertex shader
|
|
default_bg, active, inactive, window_bg, bell, tab_bar_bg, tab_bar_margin_color, tab_bar_left_edge_color, tab_bar_right_edge_color = range(9)
|
|
|
|
|
|
class Border(NamedTuple):
|
|
left: int
|
|
top: int
|
|
right: int
|
|
bottom: int
|
|
color: BorderColor
|
|
|
|
|
|
def vertical_edge(rects: list[Border], color: BorderColor, width: int, top: int, bottom: int, left: int) -> None:
|
|
if width > 0:
|
|
rects.append(Border(left, top, left + width, bottom, color))
|
|
|
|
|
|
def horizontal_edge(rects: list[Border], color: BorderColor, height: int, left: int, right: int, top: int) -> None:
|
|
if height > 0:
|
|
rects.append(Border(left, top, right, top + height, color))
|
|
|
|
|
|
def add_borders(rects: list[Border], color: BorderColor, wg: WindowGroup) -> None:
|
|
geometry = wg.geometry
|
|
if geometry is None:
|
|
return
|
|
pl, pt = wg.effective_padding('left'), wg.effective_padding('top')
|
|
pr, pb = wg.effective_padding('right'), wg.effective_padding('bottom')
|
|
left = geometry.left - pl
|
|
top = geometry.top - pt
|
|
lr = geometry.right
|
|
right = lr + pr
|
|
bt = geometry.bottom
|
|
bottom = bt + pb
|
|
h = partial(horizontal_edge, rects, color)
|
|
v = partial(vertical_edge, rects, color)
|
|
width = wg.effective_border()
|
|
bt = bottom
|
|
lr = right
|
|
left -= width
|
|
top -= width
|
|
right += width
|
|
bottom += width
|
|
pl = pr = pb = pt = width
|
|
h(pt, left, right, top)
|
|
h(pb, left, right, bt)
|
|
v(pl, top, bottom, left)
|
|
v(pr, top, bottom, lr)
|
|
|
|
|
|
def load_borders_program() -> None:
|
|
program_for('border').compile(BORDERS_PROGRAM)
|
|
init_borders_program()
|
|
|
|
|
|
class Borders:
|
|
|
|
def __init__(self, os_window_id: int, tab_id: int):
|
|
self.os_window_id = os_window_id
|
|
self.tab_id = tab_id
|
|
|
|
def __call__(
|
|
self,
|
|
all_windows: WindowList,
|
|
current_layout: LayoutType,
|
|
tab_bar_rects: Iterable[Border],
|
|
draw_window_borders: bool = True,
|
|
) -> None:
|
|
opts = get_options()
|
|
draw_active_borders = opts.active_border_color is not None
|
|
draw_minimal_borders = opts.draw_minimal_borders and max(opts.window_margin_width) < 1
|
|
rects: list[Border] = []
|
|
for br in current_layout.blank_rects:
|
|
rects.append(Border(*br, BorderColor.default_bg))
|
|
rects.extend(tab_bar_rects)
|
|
bw = 0
|
|
groups = tuple(all_windows.iter_all_layoutable_groups(only_visible=True))
|
|
if groups:
|
|
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
|
|
# 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
|
|
add_borders(rects, color, wg)
|
|
|
|
if draw_minimal_borders:
|
|
for border_line in current_layout.get_minimal_borders(all_windows):
|
|
rects.append(Border(*border_line.edges, border_line.color))
|
|
set_borders_rects(self.os_window_id, self.tab_id, rects)
|