mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 14:18:26 +02:00
committed by
Kovid Goyal
parent
02a34ecd04
commit
25f97f4ce5
@@ -185,6 +185,14 @@ create :file:`~/.config/kitty/mywatcher.py` and use :option:`launch --watcher` =
|
|||||||
# managing all tabs in a single OS Window.
|
# managing all tabs in a single OS Window.
|
||||||
...
|
...
|
||||||
|
|
||||||
|
def on_quit(boss: Boss, window: Window, data: dict[str, Any]) -> None:
|
||||||
|
# called when kitty is about to quit. This is called in *global watchers*
|
||||||
|
# only. It is called twice: once before the quit confirmation dialog is
|
||||||
|
# shown (data['confirmed'] will be False) and once after the user has
|
||||||
|
# confirmed quitting (data['confirmed'] will be True). Setting
|
||||||
|
# data['aborted'] to True will abort the quit in both cases.
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
Every callback is passed a reference to the global ``Boss`` object as well as
|
Every callback is passed a reference to the global ``Boss`` object as well as
|
||||||
the ``Window`` object the action is occurring on. The ``data`` object is a dict
|
the ``Window`` object the action is occurring on. The ``data`` object is a dict
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ from .utils import (
|
|||||||
timed_debug_print,
|
timed_debug_print,
|
||||||
which,
|
which,
|
||||||
)
|
)
|
||||||
from .window import CommandOutput, CwdRequest, Window
|
from .window import CommandOutput, CwdRequest, Window, global_watchers
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|
||||||
@@ -2090,6 +2090,24 @@ class Boss:
|
|||||||
|
|
||||||
quit_confirmation_window_id: int = 0
|
quit_confirmation_window_id: int = 0
|
||||||
|
|
||||||
|
def _call_on_quit_watchers(self, data: dict[str, Any]) -> bool:
|
||||||
|
w = self.active_window
|
||||||
|
if w is None:
|
||||||
|
for window in self.window_id_map.values():
|
||||||
|
w = window
|
||||||
|
break
|
||||||
|
if w is None:
|
||||||
|
return True
|
||||||
|
for watcher in global_watchers().on_quit:
|
||||||
|
try:
|
||||||
|
watcher(self, w, data)
|
||||||
|
except Exception:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
if data.get('aborted'):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
@ac('win', 'Quit, closing all windows')
|
@ac('win', 'Quit, closing all windows')
|
||||||
def quit(self, *args: Any) -> None:
|
def quit(self, *args: Any) -> None:
|
||||||
windows = []
|
windows = []
|
||||||
@@ -2102,6 +2120,8 @@ class Boss:
|
|||||||
num = num_active_windows if x < 0 else len(windows)
|
num = num_active_windows if x < 0 else len(windows)
|
||||||
needs_confirmation = x != 0 and num >= abs(x)
|
needs_confirmation = x != 0 and num >= abs(x)
|
||||||
if not needs_confirmation:
|
if not needs_confirmation:
|
||||||
|
if not self._call_on_quit_watchers({'confirmed': True}):
|
||||||
|
return
|
||||||
set_application_quit_request(IMPERATIVE_CLOSE_REQUESTED)
|
set_application_quit_request(IMPERATIVE_CLOSE_REQUESTED)
|
||||||
return
|
return
|
||||||
if current_application_quit_request() == CLOSE_BEING_CONFIRMED:
|
if current_application_quit_request() == CLOSE_BEING_CONFIRMED:
|
||||||
@@ -2116,6 +2136,8 @@ class Boss:
|
|||||||
tab.set_active_window(w)
|
tab.set_active_window(w)
|
||||||
return
|
return
|
||||||
return
|
return
|
||||||
|
if not self._call_on_quit_watchers({'confirmed': False}):
|
||||||
|
return
|
||||||
msg = msg or _('It has {} windows.').format(num)
|
msg = msg or _('It has {} windows.').format(num)
|
||||||
w = self.confirm(_('Are you sure you want to quit kitty?') + ' ' + msg, self.handle_quit_confirmation, window=active_window, title=_('Quit kitty?'))
|
w = self.confirm(_('Are you sure you want to quit kitty?') + ' ' + msg, self.handle_quit_confirmation, window=active_window, title=_('Quit kitty?'))
|
||||||
self.quit_confirmation_window_id = w.id
|
self.quit_confirmation_window_id = w.id
|
||||||
@@ -2123,6 +2145,10 @@ class Boss:
|
|||||||
|
|
||||||
def handle_quit_confirmation(self, confirmed: bool) -> None:
|
def handle_quit_confirmation(self, confirmed: bool) -> None:
|
||||||
self.quit_confirmation_window_id = 0
|
self.quit_confirmation_window_id = 0
|
||||||
|
if confirmed:
|
||||||
|
if not self._call_on_quit_watchers({'confirmed': True}):
|
||||||
|
set_application_quit_request(NO_CLOSE_REQUESTED)
|
||||||
|
return
|
||||||
set_application_quit_request(IMPERATIVE_CLOSE_REQUESTED if confirmed else NO_CLOSE_REQUESTED)
|
set_application_quit_request(IMPERATIVE_CLOSE_REQUESTED if confirmed else NO_CLOSE_REQUESTED)
|
||||||
|
|
||||||
def notify_on_os_window_death(self, address: str) -> None:
|
def notify_on_os_window_death(self, address: str) -> None:
|
||||||
|
|||||||
@@ -548,6 +548,9 @@ def load_watch_modules(watchers: Iterable[str]) -> Watchers | None:
|
|||||||
w = m.get('on_tab_bar_dirty')
|
w = m.get('on_tab_bar_dirty')
|
||||||
if callable(w):
|
if callable(w):
|
||||||
ans.on_tab_bar_dirty.append(w)
|
ans.on_tab_bar_dirty.append(w)
|
||||||
|
w = m.get('on_quit')
|
||||||
|
if callable(w):
|
||||||
|
ans.on_quit.append(w)
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -305,6 +305,7 @@ class Watchers:
|
|||||||
on_cmd_startstop: list[Watcher]
|
on_cmd_startstop: list[Watcher]
|
||||||
on_color_scheme_preference_change: list[Watcher]
|
on_color_scheme_preference_change: list[Watcher]
|
||||||
on_tab_bar_dirty: list[Watcher]
|
on_tab_bar_dirty: list[Watcher]
|
||||||
|
on_quit: list[Watcher]
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.on_resize = []
|
self.on_resize = []
|
||||||
@@ -315,6 +316,7 @@ class Watchers:
|
|||||||
self.on_cmd_startstop = []
|
self.on_cmd_startstop = []
|
||||||
self.on_color_scheme_preference_change = []
|
self.on_color_scheme_preference_change = []
|
||||||
self.on_tab_bar_dirty = []
|
self.on_tab_bar_dirty = []
|
||||||
|
self.on_quit = []
|
||||||
|
|
||||||
def add(self, others: 'Watchers') -> None:
|
def add(self, others: 'Watchers') -> None:
|
||||||
def merge(base: list[Watcher], other: list[Watcher]) -> None:
|
def merge(base: list[Watcher], other: list[Watcher]) -> None:
|
||||||
@@ -329,12 +331,14 @@ class Watchers:
|
|||||||
merge(self.on_cmd_startstop, others.on_cmd_startstop)
|
merge(self.on_cmd_startstop, others.on_cmd_startstop)
|
||||||
merge(self.on_color_scheme_preference_change, others.on_color_scheme_preference_change)
|
merge(self.on_color_scheme_preference_change, others.on_color_scheme_preference_change)
|
||||||
merge(self.on_tab_bar_dirty, others.on_tab_bar_dirty)
|
merge(self.on_tab_bar_dirty, others.on_tab_bar_dirty)
|
||||||
|
merge(self.on_quit, others.on_quit)
|
||||||
|
|
||||||
def clear(self) -> None:
|
def clear(self) -> None:
|
||||||
del self.on_close[:], self.on_resize[:], self.on_focus_change[:]
|
del self.on_close[:], self.on_resize[:], self.on_focus_change[:]
|
||||||
del self.on_set_user_var[:], self.on_title_change[:], self.on_cmd_startstop[:]
|
del self.on_set_user_var[:], self.on_title_change[:], self.on_cmd_startstop[:]
|
||||||
del self.on_color_scheme_preference_change[:]
|
del self.on_color_scheme_preference_change[:]
|
||||||
del self.on_tab_bar_dirty[:]
|
del self.on_tab_bar_dirty[:]
|
||||||
|
del self.on_quit[:]
|
||||||
|
|
||||||
def copy(self) -> 'Watchers':
|
def copy(self) -> 'Watchers':
|
||||||
ans = Watchers()
|
ans = Watchers()
|
||||||
@@ -346,12 +350,14 @@ class Watchers:
|
|||||||
ans.on_cmd_startstop = self.on_cmd_startstop[:]
|
ans.on_cmd_startstop = self.on_cmd_startstop[:]
|
||||||
ans.on_color_scheme_preference_change = self.on_color_scheme_preference_change[:]
|
ans.on_color_scheme_preference_change = self.on_color_scheme_preference_change[:]
|
||||||
ans.on_tab_bar_dirty = self.on_tab_bar_dirty[:]
|
ans.on_tab_bar_dirty = self.on_tab_bar_dirty[:]
|
||||||
|
ans.on_quit = self.on_quit[:]
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def has_watchers(self) -> bool:
|
def has_watchers(self) -> bool:
|
||||||
return bool(self.on_close or self.on_resize or self.on_focus_change or self.on_color_scheme_preference_change
|
return bool(self.on_close or self.on_resize or self.on_focus_change or self.on_color_scheme_preference_change
|
||||||
or self.on_set_user_var or self.on_title_change or self.on_cmd_startstop or self.on_tab_bar_dirty)
|
or self.on_set_user_var or self.on_title_change or self.on_cmd_startstop or self.on_tab_bar_dirty
|
||||||
|
or self.on_quit)
|
||||||
|
|
||||||
|
|
||||||
def call_watchers(windowref: Callable[[], Optional['Window']], which: str, data: dict[str, Any]) -> None:
|
def call_watchers(windowref: Callable[[], Optional['Window']], which: str, data: dict[str, Any]) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user