Define special numbers in one place only

This commit is contained in:
Kovid Goyal 2021-01-12 05:17:15 +05:30
parent 2b12bcc07f
commit f06eee8fe1
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 54 additions and 35 deletions

View File

@ -19,26 +19,8 @@ To solve these issues and others, kitty has created a new keyboard protocol,
that is backward compatible but allows applications to opt-in to support more
advanced usages. The protocol is based on initial work in `fixterms
<http://www.leonerd.org.uk/hacks/fixterms/>`_, however, it corrects various
issues in that proposal, namely:
* No way to disambiguate :kbd:`Esc` keypresses, other than using 8-bit controls
which are undesirable for other reasons
* Incorrectly claims special keys are sometimes encoded using ``CSI letter`` encodings when it
is actually ``ESC O letter``.
* Makes no mention of cursor key mode and how it changes encodings
* Incorrectly encoding shifted keys when shift modifier is used
* No way to have non-conflicting escape codes for :kbd:`alt+letter,
ctrl+letter, ctrl+alt+letter` key presses
* No way to specify both shifted and unshifted keys for robust shortcut
matching (think matching :kbd:`ctrl+shift+equal` and :kbd:`ctrl+plus`)
* No way to specify alternate layout key. This is useful for keyboard layouts
such as Cyrillic where you want the shortcut :kbd:`ctrl+c` to work when
pressing the :kbd:`ctrl+ц` on the keyboard.
* No way to report repeat and release key events, only key press events
* No way to report key events without text, useful for gaming. Think of using
the :kbd:`WASD` keys to control movement.
* A very small subset of all possible functional keys are specified.
issues in that proposal, listed at the :ref:`bottom of this document
<fixterms_bugs>`.
A basic overview
------------------
@ -321,7 +303,7 @@ Functional key definitions
----------------------------
All numbers are in the Unicode Private Use Area (``57344 - 63743``) except
for a handful of keys that use numbers under 32 (C0 control codes) for legacy
for a handful of keys that use numbers under 32 and 127 (C0 control codes) for legacy
compatibility reasons.
.. {{{
@ -331,9 +313,9 @@ compatibility reasons.
:header: "Name", "CSI sequence"
"ESCAPE", "CSI 57344 ... u"
"ENTER", "CSI 57345 ... u"
"TAB", "CSI 57346 ... u"
"BACKSPACE", "CSI 57347 ... u"
"ENTER", "CSI 13 ... u"
"TAB", "CSI 9 ... u"
"BACKSPACE", "CSI 127 ... u"
"INSERT", "CSI 2 ... ~"
"DELETE", "CSI 3 ... ~"
"LEFT", "CSI 1 ... D"
@ -352,7 +334,7 @@ compatibility reasons.
"MENU", "CSI 57363 ... u"
"F1", "CSI 1 ... P or CSI 11 ... ~"
"F2", "CSI 1 ... Q or CSI 12 ... ~"
"F3", "CSI 1 ... R or CSI 13 ... ~"
"F3", "CSI 1 ... R or CSI 57366 ... ~"
"F4", "CSI 1 ... S or CSI 14 ... ~"
"F5", "CSI 15 ... ~"
"F6", "CSI 17 ... ~"
@ -437,3 +419,28 @@ compatibility reasons.
.. end functional key table
.. }}}
.. _fixterms_bugs:
Bugs in fixterms
-------------------
* No way to disambiguate :kbd:`Esc` keypresses, other than using 8-bit controls
which are undesirable for other reasons
* Incorrectly claims special keys are sometimes encoded using ``CSI letter`` encodings when it
is actually ``ESC O letter``.
* ``Enter`` and ``F3`` are both assigned the number 13.
* Makes no mention of cursor key mode and how it changes encodings
* Incorrectly encoding shifted keys when shift modifier is used, for
instance, for :kbd:`ctrl+shift+I`.
* No way to have non-conflicting escape codes for :kbd:`alt+letter,
ctrl+letter, ctrl+alt+letter` key presses
* No way to specify both shifted and unshifted keys for robust shortcut
matching (think matching :kbd:`ctrl+shift+equal` and :kbd:`ctrl+plus`)
* No way to specify alternate layout key. This is useful for keyboard layouts
such as Cyrillic where you want the shortcut :kbd:`ctrl+c` to work when
pressing the :kbd:`ctrl+ц` on the keyboard.
* No way to report repeat and release key events, only key press events
* No way to report key events for presses that generate text, useful for
gaming. Think of using the :kbd:`WASD` keys to control movement.
* Only a small subset of all possible functional keys are assigned numbers.

View File

@ -115,13 +115,14 @@ mute_volume XF86AudioMute -
functional_encoding_overrides = {
'insert': 2, 'delete': 3, 'page_up': 5, 'page_down': 6,
'home': 7, 'end': 8, 'f1': 11, 'f2': 12, 'f3': 13, 'f4': 14,
'home': 7, 'end': 8, 'tab': 9, 'f1': 11, 'f2': 12, 'enter': 13, 'f4': 14,
'f5': 15, 'f6': 17, 'f7': 18, 'f8': 19, 'f9': 20, 'f10': 21,
'f11': 23, 'f12': 24
'f11': 23, 'f12': 24, 'backspace': 127
}
different_trailer_functionals = {
'up': 'A', 'down': 'B', 'right': 'C', 'left': 'D', 'end': 'F', 'home': 'H',
'f1': 'P', 'f2': 'Q', 'f3': 'R', 'f4': 'S'
'f1': 'P', 'f2': 'Q', 'f3': 'R', 'f4': 'S', 'enter': 'u', 'tab': 'u',
'backspace': 'u'
}
functional_key_names: List[str] = []
name_to_code: Dict[str, int] = {}
@ -188,11 +189,13 @@ def generate_functional_table() -> None:
' :header: "Name", "CSI sequence"',
''
]
enc_lines = []
for name, code in name_to_code.items():
if name in functional_encoding_overrides or name in different_trailer_functionals:
code = oc = functional_encoding_overrides.get(name, code)
trailer = different_trailer_functionals.get(name, '~')
code = code if trailer == '~' else 1
code = code if trailer in '~u' else 1
enc_lines.append((' ' * 8) + f"case GLFW_FKEY_{name.upper()}: S({code}, '{trailer}');")
if code == 1 and name not in ('up', 'down', 'left', 'right'):
trailer += f' or CSI {oc} ... ~'
else:
@ -201,6 +204,7 @@ def generate_functional_table() -> None:
lines.append(f' {name} "CSI {code} ... {trailer}"')
lines.append('')
patch_file('docs/keyboard-protocol.rst', 'functional key table', '\n'.join(lines), start_marker='.. ', end_marker='')
patch_file('kitty/key_encoding.c', 'special numbers', '\n'.join(enc_lines))
def main() -> None:

View File

@ -132,20 +132,24 @@ encode_function_key(const KeyEvent *ev, char *output) {
#define S(number, trailer) key_number = number; csi_trailer = trailer; break
switch(key_number) {
/* start special numbers (auto generated by gen-key-constants.py do not edit) */
case GLFW_FKEY_ENTER: S(13, 'u');
case GLFW_FKEY_TAB: S(9, 'u');
case GLFW_FKEY_BACKSPACE: S(127, 'u');
case GLFW_FKEY_INSERT: S(2, '~');
case GLFW_FKEY_DELETE: S(3, '~');
case GLFW_FKEY_LEFT: S(1, 'D');
case GLFW_FKEY_RIGHT: S(1, 'C');
case GLFW_FKEY_UP: S(1, 'A');
case GLFW_FKEY_DOWN: S(1, 'B');
case GLFW_FKEY_LEFT: S(1, 'C');
case GLFW_FKEY_RIGHT: S(1, 'D');
case GLFW_FKEY_PAGE_UP: S(5, '~');
case GLFW_FKEY_PAGE_DOWN: S(6, '~');
case GLFW_FKEY_HOME: S(1, 'H');
case GLFW_FKEY_END: S(1, 'F');
case GLFW_FKEY_F1: S(1, 'P');
case GLFW_FKEY_F2: S(1, 'Q');
case GLFW_FKEY_F3: S(1, 'R');
case GLFW_FKEY_F4: S(1, 'S');
case GLFW_FKEY_INSERT: S(2, '~');
case GLFW_FKEY_DELETE: S(3, '~');
case GLFW_FKEY_PAGE_UP: S(5, '~');
case GLFW_FKEY_PAGE_DOWN: S(6, '~');
case GLFW_FKEY_F5: S(15, '~');
case GLFW_FKEY_F6: S(17, '~');
case GLFW_FKEY_F7: S(18, '~');
@ -154,6 +158,7 @@ encode_function_key(const KeyEvent *ev, char *output) {
case GLFW_FKEY_F10: S(21, '~');
case GLFW_FKEY_F11: S(23, '~');
case GLFW_FKEY_F12: S(24, '~');
/* end special numbers */
default: break;
}
#undef S

View File

@ -8,6 +8,9 @@ from . import BaseTest
class TestKeys(BaseTest):
def test_encode_key_event(self):
pass
def test_encode_mouse_event(self):
NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOCOL, URXVT_PROTOCOL = range(4)
L, M, R = 1, 2, 3