Exclude the currently active window when visually selecting
This commit is contained in:
parent
8458b9e7d6
commit
dc09a5183a
@ -9,7 +9,8 @@ from contextlib import suppress
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
from typing import (
|
from typing import (
|
||||||
Any, Callable, Dict, Iterable, Iterator, List, Optional, Tuple, Union, cast
|
Any, Callable, Container, Dict, Iterable, Iterator, List, Optional, Tuple,
|
||||||
|
Union, cast
|
||||||
)
|
)
|
||||||
from weakref import WeakValueDictionary
|
from weakref import WeakValueDictionary
|
||||||
|
|
||||||
@ -859,29 +860,38 @@ class Boss:
|
|||||||
self.current_visual_select.cancel()
|
self.current_visual_select.cancel()
|
||||||
self.current_visual_select = None
|
self.current_visual_select = None
|
||||||
|
|
||||||
def visual_window_select_action(self, tab: Tab, callback: Callable[[Optional[Tab], Optional[Window]], None], choose_msg: str) -> None:
|
def visual_window_select_action(
|
||||||
|
self, tab: Tab,
|
||||||
|
callback: Callable[[Optional[Tab], Optional[Window]], None],
|
||||||
|
choose_msg: str,
|
||||||
|
only_window_ids: Container[int] = ()
|
||||||
|
) -> None:
|
||||||
self.cancel_current_visual_select()
|
self.cancel_current_visual_select()
|
||||||
tm = tab.tab_manager_ref()
|
tm = tab.tab_manager_ref()
|
||||||
if tm is not None:
|
if tm is not None:
|
||||||
tm.set_active_tab(tab)
|
tm.set_active_tab(tab)
|
||||||
self.current_visual_select = VisualSelect(tab.id, tab.os_window_id, choose_msg, callback)
|
self.current_visual_select = VisualSelect(tab.id, tab.os_window_id, choose_msg, callback)
|
||||||
if tab.current_layout.only_active_window_visible:
|
if tab.current_layout.only_active_window_visible:
|
||||||
self.select_window_in_tab_using_overlay(tab, choose_msg)
|
self.select_window_in_tab_using_overlay(tab, choose_msg, only_window_ids)
|
||||||
return
|
return
|
||||||
pending_sequences: SubSequenceMap = {}
|
pending_sequences: SubSequenceMap = {}
|
||||||
fmap = get_name_to_functional_number_map()
|
fmap = get_name_to_functional_number_map()
|
||||||
|
num = 0
|
||||||
for idx, window in tab.windows.iter_windows_with_number(only_visible=True):
|
for idx, window in tab.windows.iter_windows_with_number(only_visible=True):
|
||||||
if idx > 9:
|
if only_window_ids and window.id not in only_window_ids:
|
||||||
break
|
continue
|
||||||
num = idx + 1
|
|
||||||
ac = KeyAction('visual_window_select_action_trigger', (window.id,))
|
ac = KeyAction('visual_window_select_action_trigger', (window.id,))
|
||||||
if num == 10:
|
num += 1
|
||||||
|
is_last = num == 10
|
||||||
|
if is_last:
|
||||||
num = 0
|
num = 0
|
||||||
window.screen.set_window_number(num)
|
window.screen.set_window_number(num)
|
||||||
self.current_visual_select.window_ids.append(window.id)
|
self.current_visual_select.window_ids.append(window.id)
|
||||||
for mods in (0, GLFW_MOD_CONTROL, GLFW_MOD_CONTROL | GLFW_MOD_SHIFT, GLFW_MOD_SUPER, GLFW_MOD_ALT, GLFW_MOD_SHIFT):
|
for mods in (0, GLFW_MOD_CONTROL, GLFW_MOD_CONTROL | GLFW_MOD_SHIFT, GLFW_MOD_SUPER, GLFW_MOD_ALT, GLFW_MOD_SHIFT):
|
||||||
pending_sequences[(SingleKey(mods=mods, key=ord(str(num))),)] = ac
|
pending_sequences[(SingleKey(mods=mods, key=ord(str(num))),)] = ac
|
||||||
pending_sequences[(SingleKey(mods=mods, key=fmap[f'KP_{num}']),)] = ac
|
pending_sequences[(SingleKey(mods=mods, key=fmap[f'KP_{num}']),)] = ac
|
||||||
|
if is_last:
|
||||||
|
break
|
||||||
if len(self.current_visual_select.window_ids) > 1:
|
if len(self.current_visual_select.window_ids) > 1:
|
||||||
self.set_pending_sequences(pending_sequences, default_pending_action=KeyAction('visual_window_select_action_trigger', (0,)))
|
self.set_pending_sequences(pending_sequences, default_pending_action=KeyAction('visual_window_select_action_trigger', (0,)))
|
||||||
redirect_mouse_handling(True)
|
redirect_mouse_handling(True)
|
||||||
@ -914,8 +924,9 @@ class Boss:
|
|||||||
ev = WindowSystemMouseEvent(in_tab_bar, window_id, action, modifiers, button, currently_pressed_button, x, y)
|
ev = WindowSystemMouseEvent(in_tab_bar, window_id, action, modifiers, button, currently_pressed_button, x, y)
|
||||||
self.mouse_handler(ev)
|
self.mouse_handler(ev)
|
||||||
|
|
||||||
def select_window_in_tab_using_overlay(self, tab: Tab, msg: str) -> None:
|
def select_window_in_tab_using_overlay(self, tab: Tab, msg: str, only_window_ids: Container[int] = ()) -> None:
|
||||||
windows = tuple((w.id, w.title) for i, w in tab.windows.iter_windows_with_number(only_visible=False))
|
windows = tuple((w.id, w.title) for i, w in tab.windows.iter_windows_with_number(only_visible=False)
|
||||||
|
if not only_window_ids or w.id in only_window_ids)
|
||||||
if len(windows) < 1:
|
if len(windows) < 1:
|
||||||
self.visual_window_select_action_trigger(windows[0][0] if windows else 0)
|
self.visual_window_select_action_trigger(windows[0][0] if windows else 0)
|
||||||
if get_options().enable_audio_bell:
|
if get_options().enable_audio_bell:
|
||||||
|
|||||||
@ -19,6 +19,7 @@ class SelectWindow(RemoteCommand):
|
|||||||
match: The tab to open the new window in
|
match: The tab to open the new window in
|
||||||
self: Boolean, if True use tab the command was run in
|
self: Boolean, if True use tab the command was run in
|
||||||
title: A title for this selection
|
title: A title for this selection
|
||||||
|
exclude_active: Exclude the currently active window from the list to pick
|
||||||
'''
|
'''
|
||||||
|
|
||||||
short_desc = 'Visually select a window in the specified tab'
|
short_desc = 'Visually select a window in the specified tab'
|
||||||
@ -41,11 +42,16 @@ instead of the active tab.
|
|||||||
|
|
||||||
--title
|
--title
|
||||||
A title that will be displayed to the user to describe what this selection is for
|
A title that will be displayed to the user to describe what this selection is for
|
||||||
|
|
||||||
|
|
||||||
|
--exclude-active
|
||||||
|
type=bool-set
|
||||||
|
Exclude the currently active window from the list of windows to pick
|
||||||
'''
|
'''
|
||||||
is_asynchronous = True
|
is_asynchronous = True
|
||||||
|
|
||||||
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
||||||
ans = {'self': opts.self, 'match': opts.match, 'title': opts.title}
|
ans = {'self': opts.self, 'match': opts.match, 'title': opts.title, 'exclude_active': opts.exclude_active}
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType:
|
def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType:
|
||||||
@ -58,7 +64,11 @@ A title that will be displayed to the user to describe what this selection is fo
|
|||||||
responder.send_error('No window selected')
|
responder.send_error('No window selected')
|
||||||
for tab in self.tabs_for_match_payload(boss, window, payload_get):
|
for tab in self.tabs_for_match_payload(boss, window, payload_get):
|
||||||
if tab:
|
if tab:
|
||||||
boss.visual_window_select_action(tab, callback, payload_get('title') or 'Choose window')
|
if payload_get('exclude_active'):
|
||||||
|
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)
|
||||||
break
|
break
|
||||||
return no_response
|
return no_response
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from operator import attrgetter
|
|||||||
from time import monotonic
|
from time import monotonic
|
||||||
from typing import (
|
from typing import (
|
||||||
Any, Deque, Dict, Generator, Iterable, Iterator, List, NamedTuple,
|
Any, Deque, Dict, Generator, Iterable, Iterator, List, NamedTuple,
|
||||||
Optional, Pattern, Sequence, Tuple, Union, cast
|
Optional, Pattern, Sequence, Set, Tuple, Union, cast
|
||||||
)
|
)
|
||||||
|
|
||||||
from .borders import Border, Borders
|
from .borders import Border, Borders
|
||||||
@ -596,6 +596,14 @@ class Tab: # {{{
|
|||||||
if self.current_layout.move_window_to_group(self.windows, group.id):
|
if self.current_layout.move_window_to_group(self.windows, group.id):
|
||||||
self.relayout()
|
self.relayout()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def all_window_ids_except_active_window(self) -> Set[int]:
|
||||||
|
all_window_ids = {w.id for w in self}
|
||||||
|
aw = self.active_window
|
||||||
|
if aw is not None:
|
||||||
|
all_window_ids.discard(aw.id)
|
||||||
|
return all_window_ids
|
||||||
|
|
||||||
@ac('win', '''
|
@ac('win', '''
|
||||||
Focus a visible window by pressing the number of the window. Window numbers are displayed
|
Focus a visible window by pressing the number of the window. Window numbers are displayed
|
||||||
over the windows for easy selection in this mode.
|
over the windows for easy selection in this mode.
|
||||||
@ -605,14 +613,14 @@ class Tab: # {{{
|
|||||||
if tab and window:
|
if tab and window:
|
||||||
tab.set_active_window(window)
|
tab.set_active_window(window)
|
||||||
|
|
||||||
get_boss().visual_window_select_action(self, callback, 'Choose window to switch to')
|
get_boss().visual_window_select_action(self, callback, 'Choose window to switch to', only_window_ids=self.all_window_ids_except_active_window)
|
||||||
|
|
||||||
@ac('win', 'Swap the current window with another window in the current tab, selected visually')
|
@ac('win', 'Swap the current window with another window in the current tab, selected visually')
|
||||||
def swap_with_window(self) -> None:
|
def swap_with_window(self) -> None:
|
||||||
def callback(tab: Optional[Tab], window: Optional[Window]) -> None:
|
def callback(tab: Optional[Tab], window: Optional[Window]) -> None:
|
||||||
if tab and window:
|
if tab and window:
|
||||||
tab.swap_active_window_with(window.id)
|
tab.swap_active_window_with(window.id)
|
||||||
get_boss().visual_window_select_action(self, callback, 'Choose window to swap with')
|
get_boss().visual_window_select_action(self, callback, 'Choose window to swap with', only_window_ids=self.all_window_ids_except_active_window)
|
||||||
|
|
||||||
@ac('win', 'Move active window to the top (make it the first window)')
|
@ac('win', 'Move active window to the top (make it the first window)')
|
||||||
def move_window_to_top(self) -> None:
|
def move_window_to_top(self) -> None:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user