diff --git a/docs/changelog.rst b/docs/changelog.rst index bb0b2b134..a89da491d 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -12,6 +12,9 @@ To update |kitty|, :doc:`follow the instructions `. - Tall and Fat layouts: Add a ``mirrored`` option to put the full size window on the opposite edge of the screen (:iss:`2654`) +- Add an option :opt:`confirm_on_os_window_close` to ask for confirmation + when closing an OS window with multiple kitty windows. + 0.17.4 [2020-05-09] -------------------- diff --git a/kitty/boss.py b/kitty/boss.py index 827f02bb8..99ef36bf1 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -723,8 +723,28 @@ class Boss: text = '\n'.join(parse_uri_list(text)) w.paste(text) + def close_os_window(self) -> None: + tm = self.active_tab_manager + if tm is not None: + self.confirm_os_window_close(tm.os_window_id) + def confirm_os_window_close(self, os_window_id: int) -> None: - mark_os_window_for_close(os_window_id) + if not self.opts.confirm_os_window_close: + mark_os_window_for_close(os_window_id) + return + tm = self.os_window_map.get(os_window_id) + if tm is not None: + w = tm.active_window + self._run_kitten('ask', ['--type=yesno', '--message', _( + 'Are you sure you want to close this OS window, it has {}' + ' windows running?').format(tm.number_of_windows)], + window=w, + custom_callback=partial(self.handle_close_os_window_confirmation, os_window_id) + ) + + def handle_close_os_window_confirmation(self, os_window_id: int, data: Dict[str, Any], *a: Any) -> None: + if data['response'] == 'y': + mark_os_window_for_close(os_window_id) def on_os_window_closed(self, os_window_id: int, viewport_width: int, viewport_height: int) -> None: self.cached_values['window-size'] = viewport_width, viewport_height diff --git a/kitty/config_data.py b/kitty/config_data.py index 3483cfc15..e76094619 100644 --- a/kitty/config_data.py +++ b/kitty/config_data.py @@ -778,6 +778,10 @@ this option can be used to keep the margins as small as possible when resizing t Note that this does not currently work on Wayland. ''')) +o('confirm_os_window_close', 0, option_type=positive_int, long_text=_(''' +Ask for confirmation when closing an OS window that has at least this +number of kitty windows in it. A value of zero disables confirmation. +''')) # }}} g('tabbar') # {{{ @@ -1374,8 +1378,7 @@ if is_macos: k('close_tab', 'kitty_mod+q', 'close_tab', _('Close tab')) if is_macos: k('close_tab', 'cmd+w', 'close_tab', _('Close tab'), add_to_docs=False) - # Not yet implemented - # k('close_os_window', 'shift+cmd+w', 'close_os_window', _('Close os window'), add_to_docs=False) + k('close_os_window', 'shift+cmd+w', 'close_os_window', _('Close OS window'), add_to_docs=False) k('move_tab_forward', 'kitty_mod+.', 'move_tab_forward', _('Move tab forward')) k('move_tab_backward', 'kitty_mod+,', 'move_tab_backward', _('Move tab backward')) k('set_tab_title', 'kitty_mod+alt+t', 'set_tab_title', _('Set tab title')) diff --git a/kitty/tabs.py b/kitty/tabs.py index 32c6ac207..b582c42b9 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -631,6 +631,14 @@ class TabManager: # {{{ if t is not None: return t.active_window + @property + def number_of_windows(self) -> int: + count = 0 + for tab in self: + for window in tab: + count += 1 + return count + def tab_for_id(self, tab_id: int) -> Optional[Tab]: for t in self.tabs: if t.id == tab_id: