diff --git a/kitty/boss.py b/kitty/boss.py index 9fc748948..87316ef68 100755 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -146,20 +146,34 @@ class DumpCommands: # {{{ class VisualSelect: - def __init__(self, tab_id: int, os_window_id: int, title: str, callback: Callable[[Optional[Tab], Optional[Window]], None]): + def __init__( + self, + tab_id: int, + os_window_id: int, + prev_tab_id: Optional[int], + prev_os_window_id: Optional[int], + title: str, + callback: Callable[[Optional[Tab], Optional[Window]], None], + reactivate_prev_tab: bool + ) -> None: self.tab_id = tab_id self.os_window_id = os_window_id + self.prev_tab_id = prev_tab_id + self.prev_os_window_id = prev_os_window_id self.callback = callback self.window_ids: List[int] = [] self.window_used_for_selection_id = 0 + self.reactivate_prev_tab = reactivate_prev_tab set_os_window_title(self.os_window_id, title) def cancel(self) -> None: self.clear_global_state() + self.activate_prev_tab() self.callback(None, None) def trigger(self, window_id: int) -> None: boss = self.clear_global_state() + self.activate_prev_tab() w = boss.window_id_map.get(window_id) if w is None: self.callback(None, None) @@ -185,6 +199,18 @@ class VisualSelect: boss.mark_window_for_close(w) return boss + def activate_prev_tab(self) -> None: + if not self.reactivate_prev_tab or self.prev_tab_id is None: + return None + boss = get_boss() + tm = boss.os_window_map.get(self.os_window_id) + if tm is not None: + t = tm.tab_for_id(self.prev_tab_id) + if t is not tm.active_tab and t is not None: + tm.set_active_tab(t) + if current_os_window() != self.prev_os_window_id and self.prev_os_window_id is not None: + focus_os_window(self.prev_os_window_id, True) + class Boss: @@ -909,14 +935,21 @@ class Boss: self, tab: Tab, callback: Callable[[Optional[Tab], Optional[Window]], None], choose_msg: str, - only_window_ids: Container[int] = () + only_window_ids: Container[int] = (), + reactivate_prev_tab: bool = False ) -> None: import string self.cancel_current_visual_select() + initial_tab_id: Optional[int] = None + initial_os_window_id = current_os_window() tm = tab.tab_manager_ref() if tm is not None: + if tm.active_tab is not None: + initial_tab_id = tm.active_tab.id tm.set_active_tab(tab) - self.current_visual_select = VisualSelect(tab.id, tab.os_window_id, choose_msg, callback) + if initial_os_window_id != tab.os_window_id: + focus_os_window(tab.os_window_id, True) + self.current_visual_select = VisualSelect(tab.id, tab.os_window_id, initial_tab_id, initial_os_window_id, choose_msg, callback, reactivate_prev_tab) if tab.current_layout.only_active_window_visible: w = self.select_window_in_tab_using_overlay(tab, choose_msg, only_window_ids) self.current_visual_select.window_used_for_selection_id = 0 if w is None else w.id diff --git a/kitty/rc/select_window.py b/kitty/rc/select_window.py index ce1d3958c..b6be27990 100644 --- a/kitty/rc/select_window.py +++ b/kitty/rc/select_window.py @@ -22,11 +22,12 @@ class SelectWindow(RemoteCommand): self: Boolean, if True use tab the command was run in title: A title for this selection exclude_active: Exclude the currently active window from the list to pick + reactivate_prev_tab: Reactivate the previously activated tab when finished ''' short_desc = 'Visually select a window in the specified tab' desc = ( - 'Prints out the id of the selected window. Other commands ' + 'Prints out the id of the selected window. Other commands' ' can then be chained to make use of it.' ) options_spec = MATCH_TAB_OPTION + '\n\n' + '''\ @@ -49,11 +50,19 @@ A title that will be displayed to the user to describe what this selection is fo --exclude-active type=bool-set Exclude the currently active window from the list of windows to pick + + +--reactivate-prev-tab +type=bool-set +When the selection is finished, the tab in the same os window that was activated +before the selection will be reactivated. The last activated os window will also +be refocused. ''' is_asynchronous = True def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType: - ans = {'self': opts.self, 'match': opts.match, 'title': opts.title, 'exclude_active': opts.exclude_active} + ans = {'self': opts.self, 'match': opts.match, 'title': opts.title, 'exclude_active': opts.exclude_active, + 'reactivate_prev_tab': opts.reactivate_prev_tab} return ans def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType: @@ -70,7 +79,10 @@ Exclude the currently active window from the list of windows to pick wids = tab.all_window_ids_except_active_window else: wids = set() - boss.visual_window_select_action(tab, callback, payload_get('title') or 'Choose window', only_window_ids=wids) + boss.visual_window_select_action( + tab, callback, payload_get('title') or 'Choose window', only_window_ids=wids, + reactivate_prev_tab=payload_get('reactivate_prev_tab') + ) break return AsyncResponse()