extended-keyboard.md 4.85 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
* Name: Extended keyboard protocol
* Start Date: 2019-02-06

# Summary

A new extended keyboard protocol for terminal emulators that allows
terminal applications to make full use of the keyboard, including all modifier
keys, special keys, etc. The protocol is opt-in, so has no backwards
compatibility constraints.

# Motivation

There are various problems with the current state of keyboard handling. They
include:

* No way to use modifiers other than ``Ctrl`` and ``Alt``

* No way to reliably use multiple modifier keys, other than, ``Shift+Alt``.

* No way to handle different types of keyboard events, such as press, release or repeat

* 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

# Detail

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
```

To leave *full mode*, use DECRST::

```
    <ESC>[?2017l
```

The number ``2017`` above is not used for any existing modes, as far as is known.
Client programs can query if the terminal emulator is in *full mode* by using
the standard [DECRQM](https://vt100.net/docs/vt510-rm/DECRQM.html) escape sequence.

Further, this specification reserves the numbers ``2018-2025`` for future
keyboard protocols.

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,
59 60 61 62 63 64 65 66 67 68 69 70
    ``Enter``, ``Space`` and ``Backspace``. 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. Note that this means there are no repeat and release events
    for these keys and also for the left and right shift keys.

  * Also any unicode characters generated by platform specific extended input
    modes, such as using the ``AltGr`` or ``Option`` keys must be sent as UTF-8
    representations of the characters. So for example, pressing ``Option+b`` in
    the US layout on a mac would generate the UTF-8 bytes for the ∫ symbol.
71 72 73
    This way terminal applications do not need to care about keyboard layouts
    or extended input modes, text entry even for arbitrary keyboard layouts and
    languages, just works, out of the box.
74 75 76 77 78

  * 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.

79 80 81
  * Keys that are mapped by the terminal emulator for shortcuts/actions
    must not be sent to client programs.

82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
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

Schematically:

```
    <ESC>_K<type><modifiers><key><ESC>\
```

Where ``<type>`` is one of ``p`` -- press, ``r`` -- release and ``t`` --
repeat.  Modifiers is a bitmask represented as a single base64 digit.  Shift --
``0x1``, Alt -- ``0x2``, Control -- ``0x4`` and Super -- ``0x8``.  ``<key>`` is
a short text-string corresponding to the key pressed. The key name to
98 99 100
text-string mapping is defined in [this table](key_encoding.json). ``Super`` is the
platform dependent fourth modifier, for example, the Windows key on
Windows/Linux computers or the Cmd key on macs.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129

Client programs must ignore events for keys they do not know. The mapping in
the above table is stable and will never change, however, new codes might be
added to it in the future, for new keys.

For example:

```
    <ESC>_KpGp<ESC>\  is  <Ctrl>+<Alt>+x (press)
    <ESC>_KrP8<ESC>\  is  <Ctrl>+<Alt>+<Shift>+<Super>+PageUp (release)
```

This encoding means each key event is represented by 8 or 9 printable ASCII
only bytes, for maximum robustness.

Support for this mode is also indicated by the ``fullkbd2017`` boolean capability
in the terminfo database, in case querying for it via DECQRM is inconvenient.

For a demo of this specification, you can install the
[kitty](https://sw.kovidgoyal.net/) terminal emulator and inside it, run:

```
kitty +kitten key_demo
```

# Open Questions

A future protocol for gaming, which has key repeat/key up events for normal key
presses as well.