Refactor visual window select infrastructure to make it reuseable

This commit is contained in:
Kovid Goyal
2021-10-17 12:38:03 +05:30
parent c06823dd47
commit 0de319fc73
2 changed files with 61 additions and 53 deletions

View File

@@ -158,6 +158,7 @@ class Boss:
self.update_check_process: Optional[PopenType] = None self.update_check_process: Optional[PopenType] = None
self.window_id_map: WeakValueDictionary[int, Window] = WeakValueDictionary() self.window_id_map: WeakValueDictionary[int, Window] = WeakValueDictionary()
self.startup_colors = {k: opts[k] for k in opts if isinstance(opts[k], Color)} self.startup_colors = {k: opts[k] for k in opts if isinstance(opts[k], Color)}
self.visual_window_select_callback: Optional[Callable[[Tab, Window], None]] = None
self.startup_cursor_text_color = opts.cursor_text_color self.startup_cursor_text_color = opts.cursor_text_color
self.pending_sequences: Optional[SubSequenceMap] = None self.pending_sequences: Optional[SubSequenceMap] = None
self.default_pending_action: Optional[KeyAction] = None self.default_pending_action: Optional[KeyAction] = None
@@ -807,60 +808,58 @@ class Boss:
if matched_action is not None: if matched_action is not None:
self.dispatch_action(matched_action) self.dispatch_action(matched_action)
@ac('win', ''' def visual_window_select_action(self, tab: Tab, callback: Callable[[Tab, Window], None], choose_msg: str) -> None:
Focus a visible window by pressing the number of the window. Window numbers are displayed self.visual_window_select_callback = callback
over the windows for easy selection in this mode. if tab.current_layout.only_active_window_visible:
''') self.select_window_in_tab_using_overlay(tab, choose_msg)
def focus_visible_window(self) -> None: return
tab = self.active_tab pending_sequences: SubSequenceMap = {}
if tab is not None: count = 0
if tab.current_layout.only_active_window_visible: fmap = get_name_to_functional_number_map()
self.select_window_in_tab() for idx, window in tab.windows.iter_windows_with_number(only_visible=True):
return if idx > 9:
pending_sequences: SubSequenceMap = {} break
count = 0 count += 1
fmap = get_name_to_functional_number_map() num = idx + 1
for idx, window in tab.windows.iter_windows_with_number(only_visible=True): ac = KeyAction('visual_window_select_action_trigger', (tab.id, window.id))
if idx > 9: if num == 10:
break num = 0
count += 1 window.screen.set_window_number(num)
num = idx + 1 for mods in (0, GLFW_MOD_CONTROL, GLFW_MOD_CONTROL | GLFW_MOD_SHIFT, GLFW_MOD_SUPER, GLFW_MOD_ALT, GLFW_MOD_SHIFT):
ac = KeyAction('focus_visible_window_trigger', (idx,)) pending_sequences[(SingleKey(mods=mods, key=ord(str(num))),)] = ac
if num == 10: pending_sequences[(SingleKey(mods=mods, key=fmap[f'KP_{num}']),)] = ac
num = 0 if count > 1:
window.screen.set_window_number(num) self.set_pending_sequences(pending_sequences, default_pending_action=KeyAction('visual_window_select_action_trigger', (tab.id,)))
for mods in (0, GLFW_MOD_CONTROL, GLFW_MOD_CONTROL | GLFW_MOD_SHIFT, GLFW_MOD_SUPER, GLFW_MOD_ALT, GLFW_MOD_SHIFT): redirect_mouse_handling(True)
pending_sequences[(SingleKey(mods=mods, key=ord(str(num))),)] = ac self.mouse_handler = self.focus_visible_window_mouse_handler
pending_sequences[(SingleKey(mods=mods, key=fmap[f'KP_{num}']),)] = ac else:
if count > 1: self.visual_window_select_action_trigger(tab.id)
self.set_pending_sequences(pending_sequences, default_pending_action=KeyAction('focus_visible_window_trigger')) if get_options().enable_audio_bell:
redirect_mouse_handling(True) ring_bell()
self.mouse_handler = self.focus_visible_window_mouse_handler
else:
self.focus_visible_window_trigger()
if get_options().enable_audio_bell:
ring_bell()
def focus_visible_window_trigger(self, idx: int = -1) -> None: def visual_window_select_action_trigger(self, tab_id: int, window_id: int = 0) -> None:
tab = self.active_tab
redirect_mouse_handling(False) redirect_mouse_handling(False)
self.clear_pending_sequences() self.clear_pending_sequences()
if tab is not None: for tab in self.all_tabs:
for window in tab: if tab.id == tab_id:
window.screen.set_window_number() for window in tab:
if idx > -1: window.screen.set_window_number()
tab.nth_window(idx) if window.id == window_id:
if self.visual_window_select_callback:
self.visual_window_select_callback(tab, window)
break
self.visual_window_select_callback = None
def focus_visible_window_mouse_handler(self, ev: WindowSystemMouseEvent) -> None: def focus_visible_window_mouse_handler(self, ev: WindowSystemMouseEvent) -> None:
tab = self.active_tab
if ev.button == GLFW_MOUSE_BUTTON_LEFT and ev.action == GLFW_PRESS and ev.window_id: if ev.button == GLFW_MOUSE_BUTTON_LEFT and ev.action == GLFW_PRESS and ev.window_id:
w = self.window_id_map.get(ev.window_id) w = self.window_id_map.get(ev.window_id)
tab = self.active_tab
if w is not None and tab is not None and w in tab: if w is not None and tab is not None and w in tab:
tab.set_active_window(w) tab.set_active_window(w)
self.focus_visible_window_trigger() self.visual_window_select_action_trigger(tab.id)
return return
if ev.button > -1: if ev.button > -1 and tab is not None:
self.focus_visible_window_trigger() self.visual_window_select_action_trigger(tab.id)
def mouse_event( def mouse_event(
self, in_tab_bar: bool, window_id: int, action: int, modifiers: int, button: int, self, in_tab_bar: bool, window_id: int, action: int, modifiers: int, button: int,
@@ -870,12 +869,8 @@ 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)
@ac('win', 'Interactively select a window in the current tab') def select_window_in_tab_using_overlay(self, tab: Tab, msg: str) -> None:
def select_window_in_tab(self) -> None: aw = tab.active_window
tab = self.active_tab
if tab is None:
return
aw = self.active_window
windows = tuple((w.id, w.title) for i, w in tab.windows.iter_windows_with_number(only_visible=False) if w is not aw) windows = tuple((w.id, w.title) for i, w in tab.windows.iter_windows_with_number(only_visible=False) if w is not aw)
tab_id = tab.id tab_id = tab.id
if len(windows) < 1: if len(windows) < 1:
@@ -886,10 +881,13 @@ class Boss:
def chosen(ans: Union[None, int, str]) -> None: def chosen(ans: Union[None, int, str]) -> None:
if isinstance(ans, int): if isinstance(ans, int):
for tab in self.all_tabs: for tab in self.all_tabs:
if tab.id == tab_id: if tab.id == tab_id and self.visual_window_select_callback:
tab.set_active_window(ans) w = self.window_id_map.get(ans)
if w is not None:
self.visual_window_select_callback(tab, w)
break break
self.choose_entry('Choose window to switch to', windows, chosen) self.visual_window_select_callback = None
self.choose_entry(msg, windows, chosen)
@ac('win', ''' @ac('win', '''
Resize the active window interactively Resize the active window interactively

View File

@@ -574,6 +574,16 @@ class Tab: # {{{
if w is not None and w.id != window_id: if w is not None and w.id != window_id:
self.current_layout.move_window_to_group(self.windows, group.id) self.current_layout.move_window_to_group(self.windows, group.id)
@ac('win', '''
Focus a visible window by pressing the number of the window. Window numbers are displayed
over the windows for easy selection in this mode.
''')
def focus_visible_window(self) -> None:
def callback(tab: Tab, window: Window) -> None:
tab.set_active_window(window)
get_boss().visual_window_select_action(self, callback, 'Choose window to switch to')
@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:
n = self.windows.active_group_idx n = self.windows.active_group_idx