Add a setting tab_activity_symbol

Fixes #2515
This commit is contained in:
Kovid Goyal 2020-09-08 21:54:56 +05:30
parent 83315f7999
commit 9a54da84dc
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
8 changed files with 48 additions and 3 deletions

View File

@ -27,6 +27,10 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
- Allow specifying watchers in session files and via a command line argument
(:iss:`2933`)
- Add a setting :opt:`tab_activity_symbol` to show a symbol in the tab title
if one of the windows has some activity after it was last focused
(:iss:`2515`)
- macOS: Switch to using the User Notifications framework for notifications.
The current notifications framework has been deprecated in Big Sur. The new
framework only allows notifications from signed and notarized applications,

View File

@ -883,6 +883,17 @@ o('tab_separator', '"{}"'.format(default_tab_separator), option_type=tab_separat
The separator between tabs in the tab bar when using :code:`separator` as the :opt:`tab_bar_style`.'''))
def tab_activity_symbol(x: str) -> Optional[str]:
if x == 'none':
return None
return x or None
o('tab_activity_symbol', 'none', option_type=tab_activity_symbol, long_text=_('''
Some text or a unicode symbol to show on the tab if a window in the tab that does
not have focus has some activity.'''))
def tab_title_template(x: str) -> str:
if x:
for q in '\'"':

View File

@ -1069,6 +1069,9 @@ class Screen:
def has_focus(self) -> bool:
pass
def has_activity_since_last_focus(self) -> bool:
pass
def set_tab_bar_render_data(
os_window_id: int, xstart: float, ystart: float, dx: float, dy: float,

View File

@ -444,6 +444,9 @@ draw_combining_char(Screen *self, char_type ch) {
void
screen_draw(Screen *self, uint32_t och) {
if (is_ignored_char(och)) return;
if (!self->has_activity_since_last_focus && !self->has_focus) {
self->has_activity_since_last_focus = true;
}
uint32_t ch = och < 256 ? self->g_charset[och] : och;
bool is_cc = is_combining_char(ch);
if (UNLIKELY(is_cc)) {
@ -2531,6 +2534,7 @@ focus_changed(Screen *self, PyObject *has_focus_) {
bool has_focus = PyObject_IsTrue(has_focus_) ? true : false;
if (has_focus != previous) {
self->has_focus = has_focus;
if (has_focus) self->has_activity_since_last_focus = false;
if (self->modes.mFOCUS_TRACKING) write_escape_code_to_child(self, CSI, has_focus ? "I" : "O");
Py_RETURN_TRUE;
}
@ -2543,6 +2547,11 @@ has_focus(Screen *self, PyObject *args UNUSED) {
Py_RETURN_FALSE;
}
static PyObject*
has_activity_since_last_focus(Screen *self, PyObject *args UNUSED) {
if (self->has_activity_since_last_focus) Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
WRAP2(cursor_position, 1, 1)
@ -2628,6 +2637,7 @@ static PyMethodDef methods[] = {
MND(paste_bytes, METH_O)
MND(focus_changed, METH_O)
MND(has_focus, METH_NOARGS)
MND(has_activity_since_last_focus, METH_NOARGS)
MND(copy_colors_from, METH_O)
MND(set_marker, METH_VARARGS)
MND(marked_cells, METH_NOARGS)

View File

@ -122,6 +122,7 @@ typedef struct {
DisableLigature disable_ligatures;
PyObject *marker;
bool has_focus;
bool has_activity_since_last_focus;
} Screen;

View File

@ -24,6 +24,7 @@ class TabBarData(NamedTuple):
needs_attention: bool
num_windows: int
layout_name: str
has_activity_since_last_focus: bool
class DrawData(NamedTuple):
@ -40,6 +41,7 @@ class DrawData(NamedTuple):
default_bg: Color
title_template: str
active_title_template: Optional[str]
tab_activity_symbol: Optional[str]
def as_rgb(x: int) -> int:
@ -65,6 +67,12 @@ def draw_title(draw_data: DrawData, screen: Screen, tab: TabBarData, index: int)
screen.cursor.fg = draw_data.bell_fg
screen.draw('🔔 ')
screen.cursor.fg = fg
if tab.has_activity_since_last_focus and draw_data.tab_activity_symbol:
fg = screen.cursor.fg
screen.cursor.fg = draw_data.bell_fg
screen.draw(draw_data.tab_activity_symbol)
screen.cursor.fg = fg
template = draw_data.title_template
if tab.is_active and draw_data.active_title_template is not None:
template = draw_data.active_title_template
@ -226,7 +234,8 @@ class TabBar:
self.opts.tab_fade, self.opts.active_tab_foreground, self.opts.active_tab_background,
self.opts.inactive_tab_foreground, self.opts.inactive_tab_background,
self.opts.tab_bar_background or self.opts.background, self.opts.tab_title_template,
self.opts.active_tab_title_template
self.opts.active_tab_title_template,
self.opts.tab_activity_symbol
)
if self.opts.tab_bar_style == 'separator':
self.draw_func = draw_tab_with_separator

View File

@ -736,13 +736,16 @@ class TabManager: # {{{
for t in self.tabs:
title = (t.name or t.title or appname).strip()
needs_attention = False
has_activity_since_last_focus = False
for w in t:
if w.needs_attention:
needs_attention = True
break
if w.has_activity_since_last_focus:
has_activity_since_last_focus = True
ans.append(TabBarData(
title, t is at, needs_attention,
len(t), t.current_layout.name or ''
len(t), t.current_layout.name or '',
has_activity_since_last_focus
))
return ans

View File

@ -514,6 +514,10 @@ class Window:
def is_active(self) -> bool:
return get_boss().active_window is self
@property
def has_activity_since_last_focus(self) -> bool:
return self.screen.has_activity_since_last_focus()
def on_bell(self) -> None:
if self.opts.command_on_bell and self.opts.command_on_bell != ['none']:
import subprocess