Implement the extended keyboard protocol
This commit is contained in:
parent
45334d6b35
commit
0f8b83755a
@ -3,126 +3,126 @@
|
||||
See link:protocol-extensions.asciidoc#keyboard-handling[Keyboard Handling protocol extension]
|
||||
|
||||
|===
|
||||
| Name | Number
|
||||
| Name | Encoded representation
|
||||
|
||||
| 0 | 48
|
||||
| 1 | 49
|
||||
| 2 | 50
|
||||
| 3 | 51
|
||||
| 4 | 52
|
||||
| 5 | 53
|
||||
| 6 | 54
|
||||
| 7 | 55
|
||||
| 8 | 56
|
||||
| 9 | 57
|
||||
| A | 65
|
||||
| APOSTROPHE | 39
|
||||
| B | 66
|
||||
| BACKSLASH | 92
|
||||
| BACKSPACE | 259
|
||||
| C | 67
|
||||
| CAPS LOCK | 280
|
||||
| COMMA | 44
|
||||
| D | 68
|
||||
| DELETE | 261
|
||||
| DOWN | 264
|
||||
| E | 69
|
||||
| END | 269
|
||||
| ENTER | 257
|
||||
| EQUAL | 61
|
||||
| ESCAPE | 256
|
||||
| F | 70
|
||||
| F1 | 290
|
||||
| F10 | 299
|
||||
| F11 | 300
|
||||
| F12 | 301
|
||||
| F13 | 302
|
||||
| F14 | 303
|
||||
| F15 | 304
|
||||
| F16 | 305
|
||||
| F17 | 306
|
||||
| F18 | 307
|
||||
| F19 | 308
|
||||
| F2 | 291
|
||||
| F20 | 309
|
||||
| F21 | 310
|
||||
| F22 | 311
|
||||
| F23 | 312
|
||||
| F24 | 313
|
||||
| F25 | 314
|
||||
| F3 | 292
|
||||
| F4 | 293
|
||||
| F5 | 294
|
||||
| F6 | 295
|
||||
| F7 | 296
|
||||
| F8 | 297
|
||||
| F9 | 298
|
||||
| G | 71
|
||||
| GRAVE ACCENT | 96
|
||||
| H | 72
|
||||
| HOME | 268
|
||||
| I | 73
|
||||
| INSERT | 260
|
||||
| J | 74
|
||||
| K | 75
|
||||
| KP 0 | 320
|
||||
| KP 1 | 321
|
||||
| KP 2 | 322
|
||||
| KP 3 | 323
|
||||
| KP 4 | 324
|
||||
| KP 5 | 325
|
||||
| KP 6 | 326
|
||||
| KP 7 | 327
|
||||
| KP 8 | 328
|
||||
| KP 9 | 329
|
||||
| KP ADD | 334
|
||||
| KP DECIMAL | 330
|
||||
| KP DIVIDE | 331
|
||||
| KP ENTER | 335
|
||||
| KP EQUAL | 336
|
||||
| KP MULTIPLY | 332
|
||||
| KP SUBTRACT | 333
|
||||
| L | 76
|
||||
| LEFT | 263
|
||||
| LEFT ALT | 342
|
||||
| LEFT BRACKET | 91
|
||||
| LEFT CONTROL | 341
|
||||
| LEFT SHIFT | 340
|
||||
| LEFT SUPER | 343
|
||||
| M | 77
|
||||
| MINUS | 45
|
||||
| N | 78
|
||||
| NUM LOCK | 282
|
||||
| O | 79
|
||||
| P | 80
|
||||
| PAGE DOWN | 267
|
||||
| PAGE UP | 266
|
||||
| PAUSE | 284
|
||||
| PERIOD | 46
|
||||
| PRINT SCREEN | 283
|
||||
| Q | 81
|
||||
| R | 82
|
||||
| RIGHT | 262
|
||||
| RIGHT ALT | 346
|
||||
| RIGHT BRACKET | 93
|
||||
| RIGHT CONTROL | 345
|
||||
| RIGHT SHIFT | 344
|
||||
| RIGHT SUPER | 347
|
||||
| S | 83
|
||||
| SCROLL LOCK | 281
|
||||
| SEMICOLON | 59
|
||||
| SLASH | 47
|
||||
| SPACE | 32
|
||||
| T | 84
|
||||
| TAB | 258
|
||||
| U | 85
|
||||
| UP | 265
|
||||
| V | 86
|
||||
| W | 87
|
||||
| WORLD 1 | 161
|
||||
| WORLD 2 | 162
|
||||
| X | 88
|
||||
| Y | 89
|
||||
| Z | 90
|
||||
| 0 | `BM`
|
||||
| 1 | `BN`
|
||||
| 2 | `BO`
|
||||
| 3 | `BP`
|
||||
| 4 | `BQ`
|
||||
| 5 | `BR`
|
||||
| 6 | `BS`
|
||||
| 7 | `BT`
|
||||
| 8 | `BU`
|
||||
| 9 | `BV`
|
||||
| A | `Bd`
|
||||
| APOSTROPHE | `BD`
|
||||
| B | `Be`
|
||||
| BACKSLASH | `CU`
|
||||
| BACKSPACE | `HH`
|
||||
| C | `Bf`
|
||||
| CAPS LOCK | `Hc`
|
||||
| COMMA | `BI`
|
||||
| D | `Bg`
|
||||
| DELETE | `HJ`
|
||||
| DOWN | `HM`
|
||||
| E | `Bh`
|
||||
| END | `HR`
|
||||
| ENTER | `HF`
|
||||
| EQUAL | `BZ`
|
||||
| ESCAPE | `HE`
|
||||
| F | `Bi`
|
||||
| F1 | `IC`
|
||||
| F10 | `IL`
|
||||
| F11 | `IM`
|
||||
| F12 | `IN`
|
||||
| F13 | `IO`
|
||||
| F14 | `IP`
|
||||
| F15 | `IQ`
|
||||
| F16 | `IR`
|
||||
| F17 | `IS`
|
||||
| F18 | `IT`
|
||||
| F19 | `IU`
|
||||
| F2 | `ID`
|
||||
| F20 | `IV`
|
||||
| F21 | `IW`
|
||||
| F22 | `IX`
|
||||
| F23 | `IY`
|
||||
| F24 | `IZ`
|
||||
| F25 | `Ia`
|
||||
| F3 | `IE`
|
||||
| F4 | `IF`
|
||||
| F5 | `IG`
|
||||
| F6 | `IH`
|
||||
| F7 | `II`
|
||||
| F8 | `IJ`
|
||||
| F9 | `IK`
|
||||
| G | `Bj`
|
||||
| GRAVE ACCENT | `CY`
|
||||
| H | `CA`
|
||||
| HOME | `HQ`
|
||||
| I | `CB`
|
||||
| INSERT | `HI`
|
||||
| J | `CC`
|
||||
| K | `CD`
|
||||
| KP 0 | `Ig`
|
||||
| KP 1 | `Ih`
|
||||
| KP 2 | `Ii`
|
||||
| KP 3 | `Ij`
|
||||
| KP 4 | `JA`
|
||||
| KP 5 | `JB`
|
||||
| KP 6 | `JC`
|
||||
| KP 7 | `JD`
|
||||
| KP 8 | `JE`
|
||||
| KP 9 | `JF`
|
||||
| KP ADD | `JK`
|
||||
| KP DECIMAL | `JG`
|
||||
| KP DIVIDE | `JH`
|
||||
| KP ENTER | `JL`
|
||||
| KP EQUAL | `JM`
|
||||
| KP MULTIPLY | `JI`
|
||||
| KP SUBTRACT | `JJ`
|
||||
| L | `CE`
|
||||
| LEFT | `HL`
|
||||
| LEFT ALT | `JS`
|
||||
| LEFT BRACKET | `CT`
|
||||
| LEFT CONTROL | `JR`
|
||||
| LEFT SHIFT | `JQ`
|
||||
| LEFT SUPER | `JT`
|
||||
| M | `CF`
|
||||
| MINUS | `BJ`
|
||||
| N | `CG`
|
||||
| NUM LOCK | `He`
|
||||
| O | `CH`
|
||||
| P | `CI`
|
||||
| PAGE DOWN | `HP`
|
||||
| PAGE UP | `HO`
|
||||
| PAUSE | `Hg`
|
||||
| PERIOD | `BK`
|
||||
| PRINT SCREEN | `Hf`
|
||||
| Q | `CJ`
|
||||
| R | `CK`
|
||||
| RIGHT | `HK`
|
||||
| RIGHT ALT | `JW`
|
||||
| RIGHT BRACKET | `CV`
|
||||
| RIGHT CONTROL | `JV`
|
||||
| RIGHT SHIFT | `JU`
|
||||
| RIGHT SUPER | `JX`
|
||||
| S | `CL`
|
||||
| SCROLL LOCK | `Hd`
|
||||
| SEMICOLON | `BX`
|
||||
| SLASH | `BL`
|
||||
| SPACE | `g`
|
||||
| T | `CM`
|
||||
| TAB | `HG`
|
||||
| U | `CN`
|
||||
| UP | `HN`
|
||||
| V | `CO`
|
||||
| W | `CP`
|
||||
| WORLD 1 | `ER`
|
||||
| WORLD 2 | `ES`
|
||||
| X | `CQ`
|
||||
| Y | `CR`
|
||||
| Z | `CS`
|
||||
|
||||
|===
|
||||
|
||||
@ -259,6 +259,7 @@ class Boss(Thread):
|
||||
is_key_pressed[key] = action == GLFW_PRESS
|
||||
self.start_cursor_blink()
|
||||
self.cursor_blink_zero_time = monotonic()
|
||||
func = None
|
||||
if action == GLFW_PRESS or action == GLFW_REPEAT:
|
||||
func = get_shortcut(self.opts.keymap, mods, key, scancode)
|
||||
if func is not None:
|
||||
@ -267,24 +268,24 @@ class Boss(Thread):
|
||||
passthrough = f()
|
||||
if not passthrough:
|
||||
return
|
||||
tab = self.active_tab
|
||||
if tab is None:
|
||||
return
|
||||
window = self.active_window
|
||||
if window is not None:
|
||||
yield window
|
||||
if func is not None:
|
||||
f = getattr(tab, func, getattr(window, func, None))
|
||||
if f is not None:
|
||||
passthrough = f()
|
||||
if not passthrough:
|
||||
return
|
||||
if window.screen.auto_repeat_enabled or action == GLFW_PRESS:
|
||||
if window.char_grid.scrolled_by and key not in MODIFIER_KEYS:
|
||||
window.scroll_end()
|
||||
data = interpret_key_event(key, scancode, mods, window)
|
||||
if data:
|
||||
window.write_to_child(data)
|
||||
tab = self.active_tab
|
||||
if tab is None:
|
||||
return
|
||||
window = self.active_window
|
||||
if window is None:
|
||||
return
|
||||
yield window
|
||||
if func is not None:
|
||||
f = getattr(tab, func, getattr(window, func, None))
|
||||
if f is not None:
|
||||
passthrough = f()
|
||||
if not passthrough:
|
||||
return
|
||||
if window.char_grid.scrolled_by and key not in MODIFIER_KEYS:
|
||||
window.scroll_end()
|
||||
data = interpret_key_event(key, scancode, mods, window, action)
|
||||
if data:
|
||||
window.write_to_child(data)
|
||||
|
||||
@callback
|
||||
def on_focus(self, window, focused):
|
||||
|
||||
@ -2,7 +2,9 @@
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import kitty.fast_data_types as defines
|
||||
import string
|
||||
|
||||
from . import fast_data_types as defines
|
||||
from .terminfo import key_as_bytes
|
||||
|
||||
smkx_key_map = {
|
||||
@ -80,22 +82,60 @@ def get_localized_key(key, scancode):
|
||||
return valid_localized_key_names.get((name or '').upper(), key)
|
||||
|
||||
|
||||
def interpret_key_event(key, scancode, mods, window):
|
||||
action_map = {defines.GLFW_PRESS: b'p', defines.GLFW_RELEASE: b'r', defines.GLFW_REPEAT: b't'}
|
||||
|
||||
|
||||
def base64_encode(integer, chars=string.ascii_uppercase + string.ascii_lowercase + string.digits + '+/'):
|
||||
ans = ''
|
||||
while integer > 0:
|
||||
integer, remainder = divmod(integer, 36)
|
||||
ans = chars[remainder] + ans
|
||||
return ans
|
||||
|
||||
|
||||
def key_extended_map():
|
||||
ans = {}
|
||||
for k in dir(defines):
|
||||
if k.startswith('GLFW_KEY_'):
|
||||
val = getattr(defines, k)
|
||||
if val < defines.GLFW_KEY_LAST and val != defines.GLFW_KEY_UNKNOWN:
|
||||
ans[k[9:]] = base64_encode(val)
|
||||
return ans
|
||||
|
||||
|
||||
key_extended_map = key_extended_map()
|
||||
|
||||
|
||||
def extended_key_event(key, scancode, mods, action):
|
||||
if key >= defines.GLFW_KEY_LAST or key == defines.GLFW_KEY_UNKNOWN or (
|
||||
# Shifted printable key should be handled by interpret_text_event()
|
||||
mods == defines.GLFW_MOD_SHIFT and 32 <= key <= 126):
|
||||
return b''
|
||||
if mods == 0 and key in (defines.GLFW_KEY_BACKSPACE, defines.GLFW_KEY_ENTER):
|
||||
return smkx_key_map[key]
|
||||
return '\033_K{}{:x}:{}\033\\'.format(action_map[action], mods, key_extended_map[key]).encode('ascii')
|
||||
|
||||
|
||||
def interpret_key_event(key, scancode, mods, window, action):
|
||||
screen = window.screen
|
||||
if screen.extended_keyboard:
|
||||
return extended_key_event(key, scancode, mods, action)
|
||||
data = bytearray()
|
||||
key = get_localized_key(key, scancode)
|
||||
if mods == defines.GLFW_MOD_CONTROL and key in control_codes:
|
||||
# Map Ctrl-key to ascii control code
|
||||
data.extend(control_codes[key])
|
||||
elif mods == defines.GLFW_MOD_ALT and key in alt_codes:
|
||||
# Map Alt+key to Esc-key
|
||||
data.extend(alt_codes[key])
|
||||
else:
|
||||
key_map = get_key_map(window.screen)
|
||||
x = key_map.get(key)
|
||||
if x is not None:
|
||||
if mods == defines.GLFW_MOD_SHIFT:
|
||||
x = SHIFTED_KEYS.get(key, x)
|
||||
data.extend(x)
|
||||
if action == defines.GLFW_PRESS or (action == defines.GLFW_REPEAT and screen.auto_repeat_enabled):
|
||||
key = get_localized_key(key, scancode)
|
||||
if mods == defines.GLFW_MOD_CONTROL and key in control_codes:
|
||||
# Map Ctrl-key to ascii control code
|
||||
data.extend(control_codes[key])
|
||||
elif mods == defines.GLFW_MOD_ALT and key in alt_codes:
|
||||
# Map Alt+key to Esc-key
|
||||
data.extend(alt_codes[key])
|
||||
else:
|
||||
key_map = get_key_map(screen)
|
||||
x = key_map.get(key)
|
||||
if x is not None:
|
||||
if mods == defines.GLFW_MOD_SHIFT:
|
||||
x = SHIFTED_KEYS.get(key, x)
|
||||
data.extend(x)
|
||||
return bytes(data)
|
||||
|
||||
|
||||
@ -109,13 +149,3 @@ def interpret_text_event(codepoint, mods):
|
||||
def get_shortcut(keymap, mods, key, scancode):
|
||||
key = get_localized_key(key, scancode)
|
||||
return keymap.get((mods & 0b1111, key))
|
||||
|
||||
|
||||
def key_integer_map():
|
||||
ans = {}
|
||||
for k in dir(defines):
|
||||
if k.startswith('GLFW_KEY_'):
|
||||
val = getattr(defines, k)
|
||||
if val < defines.GLFW_KEY_LAST and val != defines.GLFW_KEY_UNKNOWN:
|
||||
ans[k[9:]] = val
|
||||
return ans
|
||||
|
||||
@ -37,15 +37,15 @@ if raw != nraw:
|
||||
|
||||
raw = subprocess.check_output([
|
||||
'kitty', '-c',
|
||||
'from kitty.keys import *; import json; print(json.dumps(key_integer_map()))'
|
||||
'from kitty.keys import *; import json; print(json.dumps(key_extended_map))'
|
||||
]).decode('utf-8')
|
||||
key_map = json.loads(raw)
|
||||
lines = [
|
||||
'See link:protocol-extensions.asciidoc#keyboard-handling[Keyboard Handling protocol extension]',
|
||||
'', '|===', '| Name | Number', ''
|
||||
'', '|===', '| Name | Encoded representation', ''
|
||||
]
|
||||
for k in sorted(key_map):
|
||||
lines.append('| {:15s} | {}'.format(k.replace('_', ' '), key_map[k]))
|
||||
lines.append('| {:15s} | `{}`'.format(k.replace('_', ' '), key_map[k]))
|
||||
lines += ['', '|===']
|
||||
with open('key_encoding.asciidoc', 'w') as f:
|
||||
print('= Key encoding for extended keyboard protocol\n', file=f)
|
||||
|
||||
@ -365,15 +365,18 @@ The escape sequence encodes the following properties:
|
||||
<ESC>_K<type><modifiers>:<key><ESC>\
|
||||
```
|
||||
|
||||
Where `<type>` is one of `p` -- press, `r` -- release and `t` -- repeat.
|
||||
Modifiers is zero or more of `c` -- Control, `a` -- Alt, `s` -- Shift and `m` -- Meta.
|
||||
`<key>` is a number corresponding to the key pressed. The key name to number mapping
|
||||
is defined in link:key_encoding.asciidoc[this table].
|
||||
Where `<type>` is one of `p` -- press, `r` -- release and `t` -- repeat.
|
||||
Modifiers is a bitmask represented as a single hexadecimal digit in lower case.
|
||||
Shift -- `0x1`, Control -- `0x2`, Alt -- `0x4` and Super -- `0x8`. `<key>` is
|
||||
a number (in lowercase hexadecimal) corresponding to the key pressed. The key name to
|
||||
number mapping is defined in link:key_encoding.asciidoc[this table].
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
<ESC>_Kpca:88<ESC>\
|
||||
<ESC>_Kp6:58<ESC>\ is <Ctrl>+<Alt>+x (press)
|
||||
<ESC>_Krf:10a<ESC>\ is <Ctrl>+<Alt>+<Shift>+<Super>+PageUp (release)
|
||||
```
|
||||
|
||||
Is the key press event `<Ctrl>+<Alt>+x`.
|
||||
There is a `:` between the modifiers and the key-press so that in the future
|
||||
more modifiers can be added, if needed.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user