Show a bell on the tab if a bell occurs in one of the windows in the tab and the window is not the currently focused window. Fixes #514

This commit is contained in:
Kovid Goyal 2018-05-02 21:44:14 +05:30
parent 2a52acdef4
commit efcd3a5df7
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 41 additions and 4 deletions

View File

@ -6,6 +6,9 @@ kitty is a feature full, cross-platform, *fast*, GPU based terminal emulator.
version 0.9.1 [future] version 0.9.1 [future]
------------------------------ ------------------------------
- Show a bell on the tab if a bell occurs in one of the windows in the tab and
the window is not the currently focused window
- macOS: Add support for dead keys - macOS: Add support for dead keys
- Unicode input: When searching by name search for prefix matches as well as - Unicode input: When searching by name search for prefix matches as well as

View File

@ -451,6 +451,7 @@ class Boss:
w = tm.active_window w = tm.active_window
if w is not None: if w is not None:
w.focus_changed(focused) w.focus_changed(focused)
tm.update_tab_bar()
def on_drop(self, os_window_id, paths): def on_drop(self, os_window_id, paths):
tm = self.os_window_map.get(os_window_id) tm = self.os_window_map.get(os_window_id)

View File

@ -1077,6 +1077,7 @@ void
screen_bell(Screen *self) { screen_bell(Screen *self) {
request_window_attention(self->window_id, OPT(enable_audio_bell)); request_window_attention(self->window_id, OPT(enable_audio_bell));
if (OPT(visual_bell_duration) > 0.0f) self->start_visual_bell_at = monotonic(); if (OPT(visual_bell_duration) > 0.0f) self->start_visual_bell_at = monotonic();
CALLBACK("on_bell", NULL);
} }
void void

View File

@ -20,7 +20,7 @@ from .session import resolved_shell
from .utils import color_as_int, log_error from .utils import color_as_int, log_error
from .window import Window, calculate_gl_geometry from .window import Window, calculate_gl_geometry
TabbarData = namedtuple('TabbarData', 'title is_active is_last') TabbarData = namedtuple('TabbarData', 'title is_active is_last needs_attention')
SpecialWindowInstance = namedtuple('SpecialWindow', 'cmd stdin override_title cwd_from cwd overlay_for env') SpecialWindowInstance = namedtuple('SpecialWindow', 'cmd stdin override_title cwd_from cwd overlay_for env')
@ -110,6 +110,11 @@ class Tab: # {{{
if tm is not None: if tm is not None:
tm.update_tab_bar() tm.update_tab_bar()
def on_bell(self, window):
tm = self.tab_manager_ref()
if tm is not None:
tm.update_tab_bar()
def visible_windows(self): def visible_windows(self):
for w in self.windows: for w in self.windows:
if w.is_visible_in_layout: if w.is_visible_in_layout:
@ -310,6 +315,7 @@ class TabBar: # {{{
self.active_bg = as_rgb(color_as_int(opts.active_tab_background)) self.active_bg = as_rgb(color_as_int(opts.active_tab_background))
self.active_fg = as_rgb(color_as_int(opts.active_tab_foreground)) self.active_fg = as_rgb(color_as_int(opts.active_tab_foreground))
self.bell_fg = as_rgb(0xff0000)
def patch_colors(self, spec): def patch_colors(self, spec):
if 'active_tab_foreground' in spec: if 'active_tab_foreground' in spec:
@ -353,10 +359,18 @@ class TabBar: # {{{
for t in data: for t in data:
s.cursor.bg = self.active_bg if t.is_active else 0 s.cursor.bg = self.active_bg if t.is_active else 0
s.cursor.fg = self.active_fg if t.is_active else 0 s.cursor.fg = fg = self.active_fg if t.is_active else 0
s.cursor.bold, s.cursor.italic = self.active_font_style if t.is_active else self.inactive_font_style s.cursor.bold, s.cursor.italic = self.active_font_style if t.is_active else self.inactive_font_style
before = s.cursor.x before = s.cursor.x
s.draw(' ' * self.leading_spaces + t.title + ' ' * self.trailing_spaces) if self.leading_spaces:
s.draw(' ' * self.leading_spaces)
if t.needs_attention:
s.cursor.fg = self.bell_fg
s.draw('🔔 ')
s.cursor.fg = fg
s.draw(t.title)
if self.trailing_spaces:
s.draw(' ' * self.trailing_spaces)
extra = s.cursor.x - before - max_title_length extra = s.cursor.x - before - max_title_length
if extra > 0: if extra > 0:
s.cursor.x -= extra + 1 s.cursor.x -= extra + 1
@ -536,7 +550,12 @@ class TabManager: # {{{
ans = [] ans = []
for t in self.tabs: for t in self.tabs:
title = (t.name or t.title or appname).strip() title = (t.name or t.title or appname).strip()
ans.append(TabbarData(title, t is at, t is self.tabs[-1])) needs_attention = False
for w in t:
if w.needs_attention:
needs_attention = True
break
ans.append(TabbarData(title, t is at, t is self.tabs[-1], needs_attention))
return ans return ans
def activate_tab_at(self, x): def activate_tab_at(self, x):

View File

@ -90,6 +90,7 @@ class Window:
def __init__(self, tab, child, opts, args, override_title=None): def __init__(self, tab, child, opts, args, override_title=None):
self.action_on_close = None self.action_on_close = None
self.needs_attention = False
self.override_title = override_title self.override_title = override_title
self.overlay_window_id = None self.overlay_window_id = None
self.overlay_for = None self.overlay_for = None
@ -214,6 +215,7 @@ class Window:
def focus_changed(self, focused): def focus_changed(self, focused):
if focused: if focused:
self.needs_attention = False
if self.screen.focus_tracking_enabled: if self.screen.focus_tracking_enabled:
self.screen.send_escape_code_to_child(CSI, 'I') self.screen.send_escape_code_to_child(CSI, 'I')
else: else:
@ -228,6 +230,17 @@ class Window:
def icon_changed(self, new_icon): def icon_changed(self, new_icon):
pass # TODO: Implement this pass # TODO: Implement this
@property
def is_active(self):
return get_boss().active_window is self
def on_bell(self):
if not self.is_active:
self.needs_attention = True
tab = self.tabref()
if tab is not None:
tab.on_bell(self)
def change_titlebar_color(self): def change_titlebar_color(self):
val = self.opts.macos_titlebar_color val = self.opts.macos_titlebar_color
if val: if val: