Port shortcut and sequence matching code

This commit is contained in:
Kovid Goyal 2021-01-14 04:26:03 +05:30
parent f94a5f4e5c
commit 6b2ffc774f
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 30 additions and 24 deletions

View File

@ -575,6 +575,10 @@ Note that the escape codes above of the form ``CSI 1 letter`` will omit the
Bugs in fixterms Bugs in fixterms
------------------- -------------------
The following is a list of errata in the `original fixterms proposal
<http://www.leonerd.org.uk/hacks/fixterms/>`_ , corrected in this
specification.
* No way to disambiguate :kbd:`Esc` keypresses, other than using 8-bit controls * No way to disambiguate :kbd:`Esc` keypresses, other than using 8-bit controls
which are undesirable for other reasons which are undesirable for other reasons
* Incorrectly claims special keys are sometimes encoded using ``CSI letter`` encodings when it * Incorrectly claims special keys are sometimes encoded using ``CSI letter`` encodings when it

View File

@ -30,14 +30,14 @@ from .constants import (
) )
from .fast_data_types import ( from .fast_data_types import (
CLOSE_BEING_CONFIRMED, IMPERATIVE_CLOSE_REQUESTED, NO_CLOSE_REQUESTED, CLOSE_BEING_CONFIRMED, IMPERATIVE_CLOSE_REQUESTED, NO_CLOSE_REQUESTED,
ChildMonitor, add_timer, background_opacity_of, change_background_opacity, ChildMonitor, KeyEvent, add_timer, background_opacity_of,
change_os_window_state, cocoa_set_menubar_title, create_os_window, change_background_opacity, change_os_window_state, cocoa_set_menubar_title,
current_application_quit_request, current_os_window, destroy_global_data, create_os_window, current_application_quit_request, current_os_window,
focus_os_window, get_clipboard_string, global_font_size, destroy_global_data, focus_os_window, get_clipboard_string,
mark_os_window_for_close, os_window_font_size, patch_global_colors, global_font_size, mark_os_window_for_close, os_window_font_size,
safe_pipe, set_application_quit_request, set_background_image, set_boss, patch_global_colors, safe_pipe, set_application_quit_request,
set_clipboard_string, set_in_sequence_mode, thread_write, set_background_image, set_boss, set_clipboard_string, set_in_sequence_mode,
toggle_fullscreen, toggle_maximized thread_write, toggle_fullscreen, toggle_maximized
) )
from .keys import get_shortcut, shortcut_matches from .keys import get_shortcut, shortcut_matches
from .layout.base import set_layout_options from .layout.base import set_layout_options
@ -663,20 +663,19 @@ class Boss:
if t is not None: if t is not None:
return t.active_window return t.active_window
def dispatch_special_key(self, key: int, native_key: int, action: int, mods: int) -> bool: def dispatch_possible_special_key(self, ev: KeyEvent) -> bool:
# Handles shortcuts, return True if the key was consumed # Handles shortcuts, return True if the key was consumed
key_action = get_shortcut(self.keymap, mods, key, native_key) key_action = get_shortcut(self.keymap, ev)
if key_action is None: if key_action is None:
sequences = get_shortcut(self.opts.sequence_map, mods, key, native_key) sequences = get_shortcut(self.opts.sequence_map, ev)
if sequences and not isinstance(sequences, KeyAction): if sequences and not isinstance(sequences, KeyAction):
self.pending_sequences = sequences self.pending_sequences = sequences
set_in_sequence_mode(True) set_in_sequence_mode(True)
return True return True
elif isinstance(key_action, KeyAction): elif isinstance(key_action, KeyAction):
self.current_key_press_info = key, native_key, action, mods
return self.dispatch_action(key_action) return self.dispatch_action(key_action)
def process_sequence(self, key: int, native_key: int, action: Any, mods: int) -> None: def process_sequence(self, ev: KeyEvent) -> None:
if not self.pending_sequences: if not self.pending_sequences:
set_in_sequence_mode(False) set_in_sequence_mode(False)
return return
@ -684,7 +683,7 @@ class Boss:
remaining = {} remaining = {}
matched_action = None matched_action = None
for seq, key_action in self.pending_sequences.items(): for seq, key_action in self.pending_sequences.items():
if shortcut_matches(seq[0], mods, key, native_key): if shortcut_matches(seq[0], ev):
seq = seq[1:] seq = seq[1:]
if seq: if seq:
remaining[seq] = key_action remaining[seq] = key_action

View File

@ -157,6 +157,7 @@ def remove_markup(text: str) -> str:
return { return {
'layouts': 'https://sw.kovidgoyal.net/kitty/index.html#layouts', 'layouts': 'https://sw.kovidgoyal.net/kitty/index.html#layouts',
'sessions': 'https://sw.kovidgoyal.net/kitty/index.html#sessions', 'sessions': 'https://sw.kovidgoyal.net/kitty/index.html#sessions',
'functional': 'https://sw.kovidgoyal.net/kitty/keyboard-protocol.html#functional-key-definitions',
}[m.group(2)] }[m.group(2)]
return str(m.group(2)) return str(m.group(2))

View File

@ -135,7 +135,8 @@ as color16 to color255.''')
_('Keyboard shortcuts'), _('Keyboard shortcuts'),
_('''\ _('''\
Keys are identified simply by their lowercase unicode characters. For example: Keys are identified simply by their lowercase unicode characters. For example:
``a`` for the A key, ``[`` for the left square bracket key, etc. ``a`` for the A key, ``[`` for the left square bracket key, etc. For functional
keys, such as ``Enter or Escape`` the names are present at :ref:`functional`.
For a list of modifier names, see: For a list of modifier names, see:
:link:`GLFW mods <https://www.glfw.org/docs/latest/group__mods.html>` :link:`GLFW mods <https://www.glfw.org/docs/latest/group__mods.html>`

View File

@ -4,8 +4,9 @@
from typing import Optional, Union from typing import Optional, Union
from .constants import SingleKey
from .config import KeyAction, KeyMap, SequenceMap, SubSequenceMap from .config import KeyAction, KeyMap, SequenceMap, SubSequenceMap
from .constants import SingleKey
from .fast_data_types import KeyEvent
from .typing import ScreenType from .typing import ScreenType
@ -16,15 +17,15 @@ def keyboard_mode_name(screen: ScreenType) -> str:
return 'application' if screen.cursor_key_mode else 'normal' return 'application' if screen.cursor_key_mode else 'normal'
def get_shortcut(keymap: Union[KeyMap, SequenceMap], mods: int, key: int, native_key: int) -> Optional[Union[KeyAction, SubSequenceMap]]: def get_shortcut(keymap: Union[KeyMap, SequenceMap], ev: KeyEvent) -> Optional[Union[KeyAction, SubSequenceMap]]:
mods &= 0b1111 mods = ev.mods & 0b1111
ans = keymap.get(SingleKey(mods, False, key)) ans = keymap.get(SingleKey(mods, False, ev.key))
if ans is None: if ans is None:
ans = keymap.get(SingleKey(mods, True, native_key)) ans = keymap.get(SingleKey(mods, True, ev.native_key))
return ans return ans
def shortcut_matches(s: SingleKey, mods: int, key: int, native_key: int) -> bool: def shortcut_matches(s: SingleKey, ev: KeyEvent) -> bool:
mods &= 0b1111 mods = ev.mods & 0b1111
q = native_key if s[1] else key q = ev.native_key if s.is_native else ev.key
return bool(s[0] & 0b1111 == mods & 0b1111 and s[2] == q) return bool(s.mods & 0b1111 == mods & 0b1111 and s.key == q)