Spec for extended keyboard protocol

This commit is contained in:
Kovid Goyal 2017-02-10 11:34:38 +05:30
parent b6c0eb0909
commit 48a2a395c4
5 changed files with 237 additions and 6 deletions

View File

@ -21,7 +21,7 @@
:sc_next_window: pass:quotes[`ctrl+shift+]`]
:sc_ninth_window: pass:quotes[`ctrl+shift+9`]
:sc_paste_from_clipboard: pass:quotes[`ctrl+shift+v`]
:sc_paste_from_selection: pass:quotes[`ctrl+shift+s`]
:sc_paste_from_selection: pass:quotes[`ctrl+shift+s` or `shift+insert`]
:sc_previous_tab: pass:quotes[`ctrl+shift+left`]
:sc_previous_window: pass:quotes[`ctrl+shift+[`]
:sc_scroll_end: pass:quotes[`ctrl+shift+end`]

126
key_encoding.asciidoc Normal file
View File

@ -0,0 +1,126 @@
= Key encoding for extended keyboard protocol
|===
| Name | Number |
| 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 |
|===

View File

@ -109,3 +109,13 @@ 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

View File

@ -2,14 +2,15 @@
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
import json
import os
import re
import subprocess
from collections import defaultdict
base = os.path.dirname(os.path.abspath(__file__))
os.chdir(base)
defns = defaultdict(list)
for line in open('kitty/kitty.conf'):
@ -17,13 +18,32 @@ for line in open('kitty/kitty.conf'):
_, sc, name = line.split(maxsplit=3)
defns[name].append('`' + sc + '`')
defns = [':sc_{}: pass:quotes[{}]'.format(name, ' or '.join(defns[name])) for name in sorted(defns)]
defns = [
':sc_{}: pass:quotes[{}]'.format(name, ' or '.join(defns[name]))
for name in sorted(defns)
]
defns = '\n'.join(defns)
raw = open('README.asciidoc').read()
pat = re.compile(r'^// START_SHORTCUT_BLOCK$.+?^// END_SHORTCUT_BLOCK$', re.M | re.DOTALL)
nraw = pat.sub('// START_SHORTCUT_BLOCK\n' +
defns + '\n// END_SHORTCUT_BLOCK', raw)
pat = re.compile(
r'^// START_SHORTCUT_BLOCK$.+?^// END_SHORTCUT_BLOCK$', re.M | re.DOTALL
)
nraw = pat.sub(
'// START_SHORTCUT_BLOCK\n' + defns + '\n// END_SHORTCUT_BLOCK', raw
)
if raw != nraw:
print('Updating shortcuts block')
open('README.asciidoc', 'w').write(nraw)
raw = subprocess.check_output([
'kitty', '-c',
'from kitty.keys import *; import json; print(json.dumps(key_integer_map()))'
]).decode('utf-8')
key_map = json.loads(raw)
lines = ['|===', '| Name | Number |', '']
for k in sorted(key_map):
lines.append('| {:15s} | {:4d} |'.format(k, key_map[k]))
lines += ['', '|===']
with open('key_encoding.asciidoc', 'w') as f:
print('= Key encoding for extended keyboard protocol\n', file=f)
print('\n'.join(lines), file=f)

View File

@ -301,3 +301,78 @@ the file repeatedly with no overhead.
| y | _y-offset_ -- the row in the pixel data to start from (0-based)
|===
== Keyboard handling
There are various problems with the current state of keyboard handling. They
include:
* No way to use modifiers other than `Ctrl` and `Alt`
* No reliable way to distinguish single `Esc` keypresses from the
start of a escape sequence. Currently, client programs use
fragile timing related hacks for this, leading to bugs, for example:
link:https://github.com/neovim/neovim/issues/2035[neovim #2035]
There are already two distinct keyboard handling modes, _normal mode_ and
_application mode_. These modes generate different escape sequences for the
various special keys (arrow keys, function keys, home/end etc.) Most terminals
start out in normal mode, however, most shell programs like `bash` switch them to
application mode. We propose adding a third mode, named _full mode_ that addresses
the shortcomings listed above.
Switching to the new _full mode_ is accomplished using the standard private
mode DECSET escape sequence
```
<ESC>[?2017h
```
and to leave _full mode_, use DECRST
```
<ESC>[?2017l
```
The number `2017` above is not used for any existing modes, as far as I know.
Client programs can query if the terminal emulator is in _full mode_ by using
the standard link:http://vt100.net/docs/vt510-rm/DECRQM[DECRQM] escape sequence.
The new mode works as follows:
* All printable key presses without modifier keys are sent just as in the
_normal mode_. This means all printable ASCII characters and in addition,
`Enter`, `Space` and `Backspace`. Also any unicode characters generated by
platform specific extended input modes, such as using the `AltGr` key. This
is done so that client programs that are not aware of this mode can still
handle basic text entry, so if a _full mode_ using program crashes and does
not reset, the user can still issue a `reset` command in the shell to restore
normal key handling. Note that this includes pressing the `Shift` modifier
and printable keys.
* For non printable keys and key combinations including one or more modifiers,
an escape sequence encoding the key event is sent. For details on the
escape sequence, see below.
The escape sequence encodes the following properties:
* Type of event: `press,repeat,release`
* Modifiers pressed at the time of the event
* The actual key being pressed
```
<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].
For example:
```
<ESC>_Kpca:88<ESC>\
```
Is the key press event `<Ctrl>+<Alt>+x`.