mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 14:18:26 +02:00
Cleanup previous PR
This commit is contained in:
@@ -167,6 +167,9 @@ Detailed list of changes
|
||||
- Allow dragging window borders to resize kitty windows in all the different
|
||||
layouts, controlled by :opt:`window_drag_tolerance` (:pull:`9447`)
|
||||
|
||||
- Allow showing :opt:`configurable window titles <window_title_bar>` for individual kitty
|
||||
windows via a window title bar (:pull:`9450`)
|
||||
|
||||
- A command palette to browse and trigger all mapped and unmapped actions
|
||||
(:pull:`9545`)
|
||||
|
||||
|
||||
@@ -813,7 +813,7 @@ prepare_to_render_os_window(OSWindow *os_window, monotonic_t now, unsigned int *
|
||||
if (WD.screen->start_visual_bell_at != 0) needs_render = true;
|
||||
// Prepare window title bar screen data for GPU
|
||||
WindowRenderData *trd = &w->window_title_render_data;
|
||||
if (trd->screen) {
|
||||
if (trd->screen && trd->geometry.bottom > trd->geometry.top && trd->geometry.right > trd->geometry.left) {
|
||||
trd->screen->cursor_render_info.is_visible = false;
|
||||
if (send_cell_data_to_gpu(trd->vao_idx, trd->screen, os_window)) needs_render = true;
|
||||
}
|
||||
@@ -878,7 +878,7 @@ render_prepared_os_window(OSWindow *os_window, unsigned int active_window_id, co
|
||||
draw_cells(&WD, os_window, is_active_window, false, num_of_visible_windows == 1, w);
|
||||
if (WD.screen->start_visual_bell_at != 0) set_maximum_wait(ANIMATION_SAMPLE_WAIT);
|
||||
WindowRenderData *trd = &w->window_title_render_data;
|
||||
if (trd->screen && num_visible_windows > 1 && trd->geometry.right > trd->geometry.left && trd->geometry.bottom > trd->geometry.top)
|
||||
if (trd->screen && trd->geometry.right > trd->geometry.left && trd->geometry.bottom > trd->geometry.top)
|
||||
draw_cells(trd, os_window, i == tab->active_window, true, false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1389,6 +1389,9 @@ class Screen:
|
||||
def insert_characters(self, num: int) -> None:
|
||||
pass
|
||||
|
||||
def delete_characters(self, num: int) -> None: ...
|
||||
def erase_characters(self, num: int) -> None: ...
|
||||
|
||||
def line_edge_colors(self) -> Tuple[int, int]:
|
||||
pass
|
||||
|
||||
|
||||
@@ -369,13 +369,12 @@ class Layout:
|
||||
self.update_visibility(all_windows)
|
||||
self.blank_rects = []
|
||||
# Set show_title_bar flag on each visible window before layout
|
||||
opts = get_options()
|
||||
min_windows = opts.window_title_bar_min_windows
|
||||
visible_groups = list(all_windows.iter_all_layoutable_groups(only_visible=True))
|
||||
num_visible = len(visible_groups)
|
||||
min_windows = get_options().window_title_bar_min_windows
|
||||
visible_groups = tuple(all_windows.iter_all_layoutable_groups(only_visible=True))
|
||||
show_title_bar = min_windows > 0 and len(visible_groups) >= min_windows
|
||||
for wg in visible_groups:
|
||||
for w in wg.windows:
|
||||
w.show_title_bar = min_windows > 0 and num_visible >= min_windows
|
||||
w.show_title_bar = show_title_bar
|
||||
self.do_layout(all_windows)
|
||||
|
||||
def layout_single_window_group(self, wg: WindowGroup, add_blank_rects: bool = True) -> None:
|
||||
|
||||
@@ -1472,6 +1472,7 @@ opt('window_title_bar', 'top',
|
||||
long_text='''
|
||||
Control the position of the window title bar relative to the window content.
|
||||
Use :opt:`window_title_bar_min_windows` to control when title bars are shown.
|
||||
Use :opt:`window_title_template` to format the displayed window title.
|
||||
'''
|
||||
)
|
||||
|
||||
|
||||
6
kitty/options/parse.py
generated
6
kitty/options/parse.py
generated
@@ -1515,9 +1515,6 @@ class Parser:
|
||||
|
||||
choices_for_window_title_bar = frozenset(('top', 'bottom'))
|
||||
|
||||
def window_title_bar_min_windows(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['window_title_bar_min_windows'] = positive_int(val)
|
||||
|
||||
def window_title_bar_active_background(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['window_title_bar_active_background'] = to_color_or_none(val)
|
||||
|
||||
@@ -1538,6 +1535,9 @@ class Parser:
|
||||
def window_title_bar_inactive_foreground(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['window_title_bar_inactive_foreground'] = to_color_or_none(val)
|
||||
|
||||
def window_title_bar_min_windows(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['window_title_bar_min_windows'] = positive_int(val)
|
||||
|
||||
def window_title_template(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['window_title_template'] = tab_title_template(val)
|
||||
|
||||
|
||||
4
kitty/options/types.py
generated
4
kitty/options/types.py
generated
@@ -501,12 +501,12 @@ option_names = (
|
||||
'window_resize_step_cells',
|
||||
'window_resize_step_lines',
|
||||
'window_title_bar',
|
||||
'window_title_bar_min_windows',
|
||||
'window_title_bar_active_background',
|
||||
'window_title_bar_active_foreground',
|
||||
'window_title_bar_align',
|
||||
'window_title_bar_inactive_background',
|
||||
'window_title_bar_inactive_foreground',
|
||||
'window_title_bar_min_windows',
|
||||
'window_title_template',
|
||||
)
|
||||
|
||||
@@ -702,12 +702,12 @@ class Options:
|
||||
window_resize_step_cells: int = 2
|
||||
window_resize_step_lines: int = 2
|
||||
window_title_bar: choices_for_window_title_bar = 'top'
|
||||
window_title_bar_min_windows: int = 0
|
||||
window_title_bar_active_background: kitty.fast_data_types.Color | None = None
|
||||
window_title_bar_active_foreground: kitty.fast_data_types.Color | None = None
|
||||
window_title_bar_align: choices_for_window_title_bar_align = 'center'
|
||||
window_title_bar_inactive_background: kitty.fast_data_types.Color | None = None
|
||||
window_title_bar_inactive_foreground: kitty.fast_data_types.Color | None = None
|
||||
window_title_bar_min_windows: int = 0
|
||||
window_title_template: str = '{fmt.fg.red}{bell_symbol}{activity_symbol}{fmt.fg.window}{progress_percent}{title}'
|
||||
action_alias: dict[str, str] = {}
|
||||
env: dict[str, str] = {}
|
||||
|
||||
@@ -61,7 +61,6 @@ from .typing_compat import EdgeLiteral, SessionTab, SessionType, TypedDict
|
||||
from .utils import cmdline_for_hold, color_as_int, log_error, platform_window_id, resolved_shell, shlex_split, which
|
||||
from .window import CwdRequest, Watchers, Window, WindowCreationSpec, WindowDict, global_watchers
|
||||
from .window_list import WindowList
|
||||
from .window_title_bar import WindowTitleBarManager
|
||||
|
||||
P = ParamSpec('P')
|
||||
T = TypeVar('T')
|
||||
@@ -171,7 +170,6 @@ class Tab: # {{{
|
||||
self.name = getattr(session_tab, 'name', '')
|
||||
self.enabled_layouts = [x.lower() for x in getattr(session_tab, 'enabled_layouts', None) or get_options().enabled_layouts]
|
||||
self.borders = Borders(self.os_window_id, self.id)
|
||||
self.window_title_bar_manager = WindowTitleBarManager(self.os_window_id, self.id)
|
||||
self.windows: WindowList = WindowList(self)
|
||||
self._last_used_layout: str | None = None
|
||||
self._current_layout_name: str | None = None
|
||||
@@ -441,8 +439,15 @@ class Tab: # {{{
|
||||
self.name = title or ''
|
||||
self.mark_tab_bar_dirty()
|
||||
|
||||
def update_window_title_bars(self) -> None:
|
||||
active_group = self.windows.active_group
|
||||
for wg in self.windows.iter_all_layoutable_groups(only_visible=True):
|
||||
is_active = wg is active_group
|
||||
for w in wg.windows:
|
||||
w.update_title_bar(is_active=is_active)
|
||||
|
||||
def title_changed(self, window: Window) -> None:
|
||||
self.window_title_bar_manager.update(self.windows)
|
||||
self.update_window_title_bars()
|
||||
if window is self.active_window:
|
||||
tm = self.tab_manager_ref()
|
||||
if tm is not None:
|
||||
@@ -471,7 +476,7 @@ class Tab: # {{{
|
||||
current_layout=ly, tab_bar_rects=tm.tab_bar_rects,
|
||||
draw_window_borders=draw_borders
|
||||
)
|
||||
self.window_title_bar_manager.update(self.windows)
|
||||
self.update_window_title_bars()
|
||||
|
||||
def create_layout_object(self, name: str) -> Layout:
|
||||
return create_layout_object_for(name, self.os_window_id, self.id)
|
||||
|
||||
@@ -659,6 +659,7 @@ class Window:
|
||||
creation_spec: WindowCreationSpec | None = None
|
||||
created_in_session_name: str = ''
|
||||
serialized_id: int = 0
|
||||
show_title_bar: bool = False # must be set before calling set_geometry
|
||||
|
||||
@classmethod
|
||||
@contextmanager
|
||||
@@ -733,7 +734,6 @@ class Window:
|
||||
self.tabref: Callable[[], TabType | None] = weakref.ref(tab)
|
||||
self.destroyed = False
|
||||
self.geometry: WindowGeometry = WindowGeometry(0, 0, 0, 0, 0, 0)
|
||||
self.show_title_bar: bool = False
|
||||
self._title_bar_screen: Any = None
|
||||
self.needs_layout = True
|
||||
self.is_visible_in_layout: bool = True
|
||||
@@ -1029,8 +1029,8 @@ class Window:
|
||||
|
||||
# Handle title bar screen
|
||||
if show_tb:
|
||||
from .window_title_bar import WindowTitleBarScreen
|
||||
if self._title_bar_screen is None:
|
||||
from .window_title_bar import WindowTitleBarScreen
|
||||
self._title_bar_screen = WindowTitleBarScreen(self.os_window_id, cell_width, cell_height)
|
||||
tb_geom = WindowGeometry(
|
||||
left=g.left, top=tb_top, right=g.right, bottom=tb_bottom,
|
||||
@@ -1053,8 +1053,7 @@ class Window:
|
||||
update_ime_position_for_window(self.id, True)
|
||||
|
||||
def update_title_bar(self, is_active: bool = False) -> None:
|
||||
pts = self._title_bar_screen
|
||||
if pts is None:
|
||||
if (pts := self._title_bar_screen) is None:
|
||||
return
|
||||
from .progress import ProgressState
|
||||
from .window_title_bar import WindowTitleData
|
||||
@@ -1076,20 +1075,18 @@ class Window:
|
||||
needs_attention=self.needs_attention,
|
||||
has_activity_since_last_focus=has_activity,
|
||||
)
|
||||
rendered_title = pts.render(data, progress_percent)
|
||||
|
||||
# If template evaluates to empty string, zero title bar geometry to hide it
|
||||
if not rendered_title:
|
||||
set_window_title_bar_render_data(
|
||||
self.os_window_id, self.tab_id, self.id, pts.screen,
|
||||
0, 0, 0, 0,
|
||||
)
|
||||
else:
|
||||
if pts.render(data, progress_percent):
|
||||
g = pts.geometry
|
||||
set_window_title_bar_render_data(
|
||||
self.os_window_id, self.tab_id, self.id, pts.screen,
|
||||
g.left, g.top, g.right, g.bottom,
|
||||
)
|
||||
else:
|
||||
set_window_title_bar_render_data(
|
||||
self.os_window_id, self.tab_id, self.id, pts.screen,
|
||||
0, 0, 0, 0,
|
||||
)
|
||||
|
||||
def close(self) -> None:
|
||||
get_boss().mark_window_for_close(self)
|
||||
|
||||
@@ -12,9 +12,9 @@ from .fast_data_types import (
|
||||
get_options,
|
||||
)
|
||||
from .rgb import color_as_sgr, color_from_int, to_color
|
||||
from .tab_bar import draw_attributed_string, safe_builtins
|
||||
from .types import WindowGeometry, run_once
|
||||
from .utils import color_as_int, log_error, sgr_sanitizer_pat
|
||||
from .window_list import WindowList
|
||||
from .utils import color_as_int, log_error
|
||||
|
||||
|
||||
@lru_cache
|
||||
@@ -30,12 +30,6 @@ def _compile_template(template: str) -> Any:
|
||||
_report_template_failure(template, str(e))
|
||||
|
||||
|
||||
safe_builtins = {
|
||||
'max': max, 'min': min, 'str': str, 'repr': repr, 'abs': abs,
|
||||
'len': len, 'chr': chr, 'ord': ord,
|
||||
}
|
||||
|
||||
|
||||
def _resolve_color(opt_val: Any, fallback_val: Any) -> Any:
|
||||
if opt_val is None:
|
||||
return fallback_val
|
||||
@@ -85,17 +79,6 @@ class WindowTitleFormatter:
|
||||
noitalic = '\x1b[23m'
|
||||
|
||||
|
||||
def _draw_attributed_string(title: str, screen: Screen) -> None:
|
||||
if '\x1b' in title:
|
||||
for x in sgr_sanitizer_pat(for_splitting=True).split(title):
|
||||
if x.startswith('\x1b') and x.endswith('m'):
|
||||
screen.apply_sgr(x[2:-1])
|
||||
else:
|
||||
screen.draw(x)
|
||||
else:
|
||||
screen.draw(title)
|
||||
|
||||
|
||||
class WindowTitleData(NamedTuple):
|
||||
title: str
|
||||
is_active: bool
|
||||
@@ -199,45 +182,19 @@ class WindowTitleBarScreen:
|
||||
align = opts.window_title_bar_align
|
||||
|
||||
if align == 'left':
|
||||
_draw_attributed_string(title_str, s)
|
||||
draw_attributed_string(title_str, s)
|
||||
else:
|
||||
# Measure the title length by drawing to cursor position 0
|
||||
# and checking where the cursor ends up
|
||||
_draw_attributed_string(title_str, s)
|
||||
draw_attributed_string(title_str, s)
|
||||
title_len = s.cursor.x
|
||||
s.cursor.x = 0
|
||||
s.erase_in_line(2, False)
|
||||
s.cursor.fg = fg
|
||||
s.cursor.bg = bg
|
||||
|
||||
if align == 'center':
|
||||
pad = max(0, (s.columns - title_len) // 2)
|
||||
else: # right
|
||||
pad = max(0, s.columns - title_len)
|
||||
|
||||
for _ in range(pad):
|
||||
s.draw(' ')
|
||||
_draw_attributed_string(title_str, s)
|
||||
|
||||
# Fill remaining cells with background
|
||||
while s.cursor.x < s.columns:
|
||||
s.draw(' ')
|
||||
|
||||
if pad:
|
||||
s.cursor.x = 0
|
||||
s.insert_characters(pad)
|
||||
s.cursor.x = 0
|
||||
s.erase_characters(pad)
|
||||
return title_str
|
||||
|
||||
|
||||
class WindowTitleBarManager:
|
||||
|
||||
def __init__(self, os_window_id: int, tab_id: int):
|
||||
self.os_window_id = os_window_id
|
||||
self.tab_id = tab_id
|
||||
|
||||
def update(self, all_windows: WindowList) -> None:
|
||||
active_group = all_windows.active_group
|
||||
for wg in all_windows.iter_all_layoutable_groups(only_visible=True):
|
||||
is_active = wg is active_group
|
||||
for w in wg.windows:
|
||||
w.update_title_bar(is_active=is_active)
|
||||
|
||||
def destroy(self) -> None:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user