Code to encode key events

This commit is contained in:
Kovid Goyal 2021-01-11 11:12:49 +05:30
parent c0b6078438
commit c8a9336160
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
11 changed files with 286 additions and 23663 deletions

1
.gitattributes vendored
View File

@ -1,6 +1,5 @@
kitty/wcwidth-std.h linguist-generated=true
kitty/emoji.h linguist-generated=true
kitty/keys.h linguist-generated=true
kitty/charsets.c linguist-generated=true
kitty/key_encoding.py linguist-generated=true
kitty/unicode-data.c linguist-generated=true

View File

@ -5,7 +5,6 @@ import subprocess
files_to_exclude = '''\
kitty/wcwidth-std.h
kitty/glfw.c
kitty/keys.h
kitty/charsets.c
kitty/unicode-data.c
kitty/key_encoding.py

View File

@ -1,128 +0,0 @@
Key encoding for extended keyboard protocol
===============================================
See :ref:`extended-key-protocol` for more information and `this table in JSON
format <https://github.com/kovidgoyal/kitty/blob/master/key_encoding.json>`_.
===================== ======================
Name Encoded representation
0 ``G``
1 ``H``
2 ``I``
3 ``J``
4 ``K``
5 ``L``
6 ``M``
7 ``N``
8 ``O``
9 ``P``
A ``S``
APOSTROPHE ``B``
B ``T``
BACKSLASH ``t``
BACKSPACE ``1``
C ``U``
CAPS LOCK ``:``
COMMA ``C``
D ``V``
DELETE ``3``
DOWN ``6``
E ``W``
END ``-``
ENTER ``z``
EQUAL ``R``
ESCAPE ``y``
F ``X``
F1 ``/``
F10 ``]``
F11 ``{``
F12 ``}``
F13 ``@``
F14 ``%``
F15 ``$``
F16 ``#``
F17 ``BA``
F18 ``BB``
F19 ``BC``
F2 ``*``
F20 ``BD``
F21 ``BE``
F22 ``BF``
F23 ``BG``
F24 ``BH``
F25 ``BI``
F3 ``?``
F4 ``&``
F5 ``<``
F6 ``>``
F7 ``(``
F8 ``)``
F9 ``[``
G ``Y``
GRAVE ACCENT ``v``
H ``Z``
HOME ``.``
I ``a``
INSERT ``2``
J ``b``
K ``c``
KP 0 ``BJ``
KP 1 ``BK``
KP 2 ``BL``
KP 3 ``BM``
KP 4 ``BN``
KP 5 ``BO``
KP 6 ``BP``
KP 7 ``BQ``
KP 8 ``BR``
KP 9 ``BS``
KP ADD ``BX``
KP DECIMAL ``BT``
KP DIVIDE ``BU``
KP ENTER ``BY``
KP EQUAL ``BZ``
KP MULTIPLY ``BV``
KP SUBTRACT ``BW``
L ``d``
LEFT ``5``
LEFT ALT ``Bc``
LEFT BRACKET ``s``
LEFT CONTROL ``Bb``
LEFT SHIFT ``Ba``
LEFT SUPER ``Bd``
M ``e``
MINUS ``D``
N ``f``
NUM LOCK ``=``
O ``g``
P ``h``
PAGE DOWN ``9``
PAGE UP ``8``
PAUSE ``!``
PERIOD ``E``
PRINT SCREEN ``^``
Q ``i``
R ``j``
RIGHT ``4``
RIGHT ALT ``Bg``
RIGHT BRACKET ``u``
RIGHT CONTROL ``Bf``
RIGHT SHIFT ``Be``
RIGHT SUPER ``Bh``
S ``k``
SCROLL LOCK ``+``
SEMICOLON ``Q``
SLASH ``F``
SPACE ``A``
T ``l``
TAB ``0``
U ``m``
UP ``7``
V ``n``
W ``o``
WORLD 1 ``w``
WORLD 2 ``x``
X ``p``
Y ``q``
Z ``r``
===================== ======================

2
glfw/glfw3.h vendored
View File

@ -1379,7 +1379,7 @@ typedef enum {
typedef struct GLFWkeyevent
{
// The [keyboard key](@ref keys) that was pressed or released.
uint32_t key;
uint32_t key, shifted_key, alternate_key;
// The platform-specific identifier of the key.
int native_key;

2
kitty/glfw-wrapper.h generated
View File

@ -1117,7 +1117,7 @@ typedef enum {
typedef struct GLFWkeyevent
{
// The [keyboard key](@ref keys) that was pressed or released.
uint32_t key;
uint32_t key, shifted_key, alternate_key;
// The platform-specific identifier of the key.
int native_key;

224
kitty/key_encoding.c Normal file
View File

@ -0,0 +1,224 @@
/*
* key_encoding.c
* Copyright (C) 2021 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#include "keys.h"
#include "charsets.h"
typedef enum { SHIFT=1, ALT=2, CTRL=4, SUPER=8 } ModifierMasks;
typedef enum { PRESS = 0, REPEAT = 1, RELEASE = 2} KeyAction;
typedef struct {
uint32_t key, shifted_key, alternate_key;
struct {
bool shift, alt, ctrl, super;
unsigned value;
char encoded[4];
} mods;
KeyAction action;
bool cursor_key_mode, disambiguate, report_all_event_types, report_alternate_key;
const char *text;
bool has_text;
} KeyEvent;
typedef struct {
uint32_t key, shifted_key, alternate_key;
bool add_alternates, has_mods, add_actions;
char encoded_mods[4];
KeyAction action;
} EncodingData;
static inline void
convert_glfw_mods(int mods, KeyEvent *ev) {
ev->mods.alt = (mods & GLFW_MOD_ALT) > 0, ev->mods.ctrl = (mods & GLFW_MOD_CONTROL) > 0, ev->mods.shift = (mods & GLFW_MOD_SHIFT) > 0, ev->mods.super = (mods & GLFW_MOD_SUPER) > 0;
ev->mods.value = ev->mods.shift ? SHIFT : 0;
if (ev->mods.alt) ev->mods.value |= ALT;
if (ev->mods.ctrl) ev->mods.value |= CTRL;
if (ev->mods.super) ev->mods.value |= SUPER;
snprintf(ev->mods.encoded, sizeof(ev->mods.encoded), "%u", ev->mods.value + 1);
}
static inline int
encode_csi_string(const char csi_trailer, const char *payload, char *output) {
return snprintf(output, KEY_BUFFER_SIZE, "\x1b[%s%c", payload, csi_trailer);
}
static inline void
init_encoding_data(EncodingData *ans, const KeyEvent *ev) {
ans->add_actions = ev->report_all_event_types && ev->action != PRESS;
ans->has_mods = ev->mods.encoded[0] && ev->mods.encoded[0] != '1';
ans->add_alternates = ev->report_alternate_key && (ev->shifted_key > 0 || ev->alternate_key > 0);
if (ans->add_alternates) { ans->shifted_key = ev->shifted_key; ans->alternate_key = ev->alternate_key; }
ans->key = ev->key;
memcpy(ans->encoded_mods, ev->mods.encoded, sizeof(ans->encoded_mods));
}
static inline int
serialize(const EncodingData *data, char *output, const char csi_trailer) {
int pos = 0;
#define P(fmt, ...) pos += snprintf(output + pos, KEY_BUFFER_SIZE - 2 - pos, fmt, __VA_ARGS__)
P("\x1b[%u", data->key);
if (data->add_alternates && (data->shifted_key || data->alternate_key)) {
P("%s", ":");
if (data->shifted_key) P("%u", data->shifted_key);
if (data->alternate_key) P(":%u", data->alternate_key);
}
if (data->has_mods || data->add_actions) {
P(";%s", data->encoded_mods);
if (data->add_actions) P(":%u", data->action + 1);
}
#undef P
output[pos++] = csi_trailer;
output[pos] = 0;
return pos;
}
static int
encode_function_key(const KeyEvent *ev, char *output) {
#define SIMPLE(val) return snprintf(output, KEY_BUFFER_SIZE, "%s", val);
char csi_trailer = 'u';
uint32_t key_number = ev->key;
switch(key_number) {
#define S(x) case GLFW_FKEY_KP_##x: key_number = GLFW_FKEY_##x; break;
S(ENTER) S(HOME) S(END) S(INSERT) S(DELETE) S(PAGE_UP) S(PAGE_DOWN)
#undef S
}
if (ev->cursor_key_mode && !ev->disambiguate && !ev->report_all_event_types) {
switch(key_number) {
case GLFW_FKEY_UP: SIMPLE("\x1bOA");
case GLFW_FKEY_DOWN: SIMPLE("\x1bOB");
case GLFW_FKEY_LEFT: SIMPLE("\x1bOD");
case GLFW_FKEY_RIGHT: SIMPLE("\x1bOC");
case GLFW_FKEY_HOME: SIMPLE("\x1bOH");
case GLFW_FKEY_END: SIMPLE("\x1bOF");
default: break;
}
}
if (!ev->mods.value) {
switch(key_number) {
case GLFW_FKEY_ENTER: SIMPLE("\r");
case GLFW_FKEY_ESCAPE: {
if (ev->disambiguate) { return encode_csi_string('u', "27u", output); }
SIMPLE("\x1b");
}
case GLFW_FKEY_BACKSPACE: SIMPLE("\x7f");
case GLFW_FKEY_TAB: SIMPLE("\t");
default: break;
}
}
if (key_number == GLFW_FKEY_TAB) {
if (ev->mods.value == SHIFT) return encode_csi_string('Z', "", output);
if (ev->mods.value == (CTRL | SHIFT)) return encode_csi_string('Z', "1;5", output);
if (ev->mods.value == ALT) SIMPLE("\x1b\t");
}
if (ev->mods.value == ALT) {
switch(key_number) {
case GLFW_FKEY_TAB: SIMPLE("\x1b\t");
case GLFW_FKEY_ENTER: SIMPLE("\x1b\r");
case GLFW_FKEY_BACKSPACE: SIMPLE("\x1b\x7f");
}
}
#undef SIMPLE
#define S(number, trailer) key_number = number; csi_trailer = trailer; break
switch(key_number) {
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_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, '~');
case GLFW_FKEY_F8: S(19, '~');
case GLFW_FKEY_F9: S(20, '~');
case GLFW_FKEY_F10: S(21, '~');
case GLFW_FKEY_F11: S(23, '~');
case GLFW_FKEY_F12: S(24, '~');
default: break;
}
#undef S
EncodingData ed = {0};
init_encoding_data(&ed, ev);
ed.add_alternates = false;
return serialize(&ed, output, csi_trailer);
}
static int
encode_printable_ascii_key_legacy(const KeyEvent *ev, char *output) {
char shifted_key = 0;
if ('a' <= ev->key && ev->key <= 'z') shifted_key = ev->key + ('A' - 'a');
switch(ev->key) {
#define S(which, val) case which: shifted_key = val; break;
S('0', ')') S('9', '(') S('8', '*') S('7', '&') S('6', '^') S('5', '%') S('4', '$') S('3', '#') S('2', '@') S('1', '!')
S('`', '~') S('-', '_') S('=', '+') S('[', '{') S(']', '}') S('\\', '|') S(';', ':') S('\'', '"') S(',', '<') S('.', '>') S('/', '?')
#undef S
}
if (!ev->mods.value) return snprintf(output, KEY_BUFFER_SIZE, "%c", (char)ev->key);
if (!ev->disambiguate) {
if ((ev->mods.value == ALT || ev->mods.value == (SHIFT | ALT)))
return snprintf(output, KEY_BUFFER_SIZE, "\x1b%c", (shifted_key && ev->mods.shift) ? shifted_key : (char)ev->key);
}
if (ev->mods.value == CTRL && (ev->key != 'i' && ev->key != 'm' && ev->key != '[' && ev->key != '@'))
return snprintf(output, KEY_BUFFER_SIZE, "%c", ev->key & 0x7f);
return 0;
}
static int
encode_key(const KeyEvent *ev, char *output) {
if (!ev->report_all_event_types && ev->action == RELEASE) return 0;
if (GLFW_FKEY_FIRST <= ev->key && ev->key <= GLFW_FKEY_LAST) return encode_function_key(ev, output);
EncodingData ed = {0};
init_encoding_data(&ed, ev);
bool simple_encoding_ok = !ed.add_actions && !ed.add_alternates;
if (32 <= ev->key && ev->key <= 126 && simple_encoding_ok) {
int ret = encode_printable_ascii_key_legacy(ev, output);
if (ret > 0) return ret;
}
if (simple_encoding_ok && !ed.has_mods) return encode_utf8(ev->key, output);
return serialize(&ed, output, 'u');
}
static inline bool
is_ascii_control_char(char c) {
return (0 <= c && c <= 31) || c == 127;
}
int
encode_glfw_key_event(const GLFWkeyevent *e, const bool cursor_key_mode, const unsigned key_encoding_flags, char *output) {
KeyEvent ev = {
.key = e->key, .shifted_key = e->shifted_key, .alternate_key = e->alternate_key,
.text = e->text,
.cursor_key_mode = cursor_key_mode,
.disambiguate = key_encoding_flags & 1,
.report_all_event_types = key_encoding_flags & 2,
.report_alternate_key = key_encoding_flags & 4
};
ev.has_text = e->text && !is_ascii_control_char(e->text[0]);
switch (e->action) {
case GLFW_PRESS: ev.action = PRESS; break;
case GLFW_REPEAT: ev.action = REPEAT; break;
case GLFW_RELEASE: ev.action = RELEASE; break;
}
if (ev.has_text && (ev.action == PRESS || ev.action == REPEAT)) return SEND_TEXT_TO_CHILD;
convert_glfw_mods(e->mods, &ev);
return encode_key(&ev, output);
}

View File

@ -11,44 +11,6 @@
#include "glfw-wrapper.h"
#include "control-codes.h"
static bool needs_special_handling[128 * 16] = {0};
const char*
key_to_bytes(int glfw_key, bool smkx, bool extended, int mods, int action) {
if ((action & 3) == 3) return NULL;
if ((unsigned)glfw_key >= sizeof(key_map)/sizeof(key_map[0]) || glfw_key < 0) return NULL;
uint16_t key = key_map[glfw_key];
if (key == UINT8_MAX) return NULL;
KeyboardMode mode = extended ? EXTENDED : (smkx ? APPLICATION : NORMAL);
return key_lookup(key, mode, mods, action);
}
#define SPECIAL_INDEX(key) ((key & 0x7f) | ( (mods & 0xF) << 7))
#define IS_ALT_MODS(mods) (mods == GLFW_MOD_ALT || mods == (GLFW_MOD_ALT | GLFW_MOD_SHIFT))
typedef struct { int mods, native_key; } NativeKey;
static NativeKey *native_special_keys = NULL;
static size_t native_special_keys_capacity = 0, native_special_keys_count = 0;
void
set_special_key_combo(int glfw_key, int mods, bool is_native) {
if (is_native) {
if (native_special_keys_count >= native_special_keys_capacity) {
native_special_keys_capacity = MAX(128u, 2 * native_special_keys_capacity);
native_special_keys = realloc(native_special_keys, sizeof(native_special_keys[0]) * native_special_keys_capacity);
if (native_special_keys == NULL) fatal("Out of memory");
}
native_special_keys[native_special_keys_count].mods = mods;
native_special_keys[native_special_keys_count++].native_key = glfw_key;
} else {
uint16_t key = key_map[glfw_key];
if (key != UINT8_MAX) {
key = SPECIAL_INDEX(key);
needs_special_handling[key] = true;
}
}
}
static inline Window*
active_window(void) {
Tab *t = global_state.callback_os_window->tabs + global_state.callback_os_window->active_tab;
@ -75,42 +37,6 @@ is_modifier_key(int key) {
}
}
static inline void
send_key_to_child(Window *w, int key, int mods, int action) {
Screen *screen = w->render_data.screen;
const char *data = key_to_bytes(key, screen->modes.mDECCKM, screen->modes.mEXTENDED_KEYBOARD, mods, action);
if (data) {
if (screen->modes.mEXTENDED_KEYBOARD) {
if (*data == 1) schedule_write_to_child(w->id, 1, (data + 1), 1);
else write_escape_code_to_child(screen, APC, data + 1);
} else {
if (*data > 2 && data[1] == 0x1b && data[2] == '[') { // CSI code
write_escape_code_to_child(screen, CSI, data + 3);
} else schedule_write_to_child(w->id, 1, (data + 1), *data);
}
}
}
static inline bool
is_ascii_control_char(char c) {
return c == 0 || (1 <= c && c <= 31) || c == 127;
}
static inline bool
check_if_special(int key, int mods, int native_key) {
uint16_t qkey = (0 <= key && key < (ssize_t)arraysz(key_map)) ? key_map[key] : UINT8_MAX;
bool special = false;
if (qkey != UINT8_MAX) {
qkey = SPECIAL_INDEX(qkey);
special = needs_special_handling[qkey];
}
for (size_t i = 0; !special && i < native_special_keys_count; i++) {
if (native_key == native_special_keys[i].native_key && mods == native_special_keys[i].mods)
special = true;
}
return special;
}
static inline void
update_ime_position(OSWindow *os_window, Window* w, Screen *screen) {
unsigned int cell_width = os_window->fonts_data->cell_width, cell_height = os_window->fonts_data->cell_height;
@ -120,12 +46,10 @@ update_ime_position(OSWindow *os_window, Window* w, Screen *screen) {
glfwUpdateIMEState(global_state.callback_os_window->handle, 2, left, top, cell_width, cell_height);
}
#define debug(...) if (OPT(debug_keyboard)) printf(__VA_ARGS__);
void
on_key_input(GLFWkeyevent *ev) {
Window *w = active_window();
int action = ev->action, native_key = ev->native_key, key = ev->key, mods = ev->mods;
const int action = ev->action, native_key = ev->native_key, key = ev->key, mods = ev->mods;
const char *text = ev->text ? ev->text : "";
debug("on_key_input: glfw key: %d native_code: 0x%x action: %s mods: 0x%x text: '%s' state: %d ",
@ -167,18 +91,15 @@ on_key_input(GLFWkeyevent *ev) {
) call_boss(process_sequence, "iiii", key, native_key, action, mods);
return;
}
bool has_text = text[0] && !is_ascii_control_char(text[0]);
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
if (check_if_special(key, mods, native_key)) {
PyObject *ret = PyObject_CallMethod(global_state.boss, "dispatch_special_key", "iiii", key, native_key, action, mods);
if (ret == NULL) { PyErr_Print(); }
else {
bool consumed = ret == Py_True;
Py_DECREF(ret);
if (consumed) {
debug("handled as shortcut\n");
return;
}
PyObject *ret = PyObject_CallMethod(global_state.boss, "dispatch_possible_special_key", "iiii", key, native_key, action, mods);
if (ret == NULL) { PyErr_Print(); }
else {
bool consumed = ret == Py_True;
Py_DECREF(ret);
if (consumed) {
debug("handled as shortcut\n");
return;
}
}
}
@ -189,15 +110,14 @@ on_key_input(GLFWkeyevent *ev) {
if (screen->scrolled_by && action == GLFW_PRESS && !is_modifier_key(key)) {
screen_history_scroll(screen, SCROLL_FULL, false); // scroll back to bottom
}
bool ok_to_send = action == GLFW_PRESS || action == GLFW_REPEAT || screen->modes.mEXTENDED_KEYBOARD;
if (ok_to_send) {
if (has_text) {
schedule_write_to_child(w->id, 1, text, strlen(text));
debug("sent text to child\n");
} else {
send_key_to_child(w, key, mods, action);
debug("sent key to child\n");
}
char encoded_key[KEY_BUFFER_SIZE] = {0};
int size = encode_glfw_key_event(ev, screen->modes.mDECCKM, screen->key_encoding_flags, encoded_key);
if (size == SEND_TEXT_TO_CHILD) {
schedule_write_to_child(w->id, 1, text, strlen(text));
debug("sent text to child\n");
} else if (size > 0) {
schedule_write_to_child(w->id, 1, encoded_key, size);
debug("sent key to child\n");
} else {
debug("ignoring as keyboard mode does not allow %s events\n", action == GLFW_RELEASE ? "release" : "repeat");
}
@ -207,9 +127,16 @@ void
fake_scroll(Window *w, int amount, bool upwards) {
if (!w) return;
int key = upwards ? GLFW_KEY_UP : GLFW_KEY_DOWN;
GLFWkeyevent ev = {.key = key };
char encoded_key[KEY_BUFFER_SIZE] = {0};
Screen *screen = w->render_data.screen;
while (amount-- > 0) {
send_key_to_child(w, key, 0, GLFW_PRESS);
send_key_to_child(w, key, 0, GLFW_RELEASE);
ev.action = GLFW_PRESS;
int size = encode_glfw_key_event(&ev, screen->modes.mDECCKM, screen->key_encoding_flags, encoded_key);
if (size > 0) schedule_write_to_child(w->id, 1, encoded_key, size);
ev.action = GLFW_RELEASE;
size = encode_glfw_key_event(&ev, screen->modes.mDECCKM, screen->key_encoding_flags, encoded_key);
if (size > 0) schedule_write_to_child(w->id, 1, encoded_key, size);
}
}
@ -217,14 +144,6 @@ fake_scroll(Window *w, int amount, bool upwards) {
#define PA(fmt, ...) if(!PyArg_ParseTuple(args, fmt, __VA_ARGS__)) return NULL;
#define M(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL}
PYWRAP1(key_to_bytes) {
int glfw_key, smkx, extended, mods, action;
PA("ippii", &glfw_key, &smkx, &extended, &mods, &action);
const char *ans = key_to_bytes(glfw_key, smkx & 1, extended & 1, mods, action);
if (ans == NULL) return Py_BuildValue("y#", "", 0);
return Py_BuildValue("y#", ans + 1, *ans);
}
PYWRAP1(key_for_native_key_name) {
const char *name;
int case_sensitive = 0;
@ -238,23 +157,28 @@ PYWRAP1(key_for_native_key_name) {
Py_RETURN_NONE;
}
static PyObject*
pyencode_key_for_tty(PyObject *self UNUSED, PyObject *args, PyObject *kw) {
char *kwds[] = {"key", "shifted_key", "alternate_key", "mods", "action", "text", "cursor_key_mode", "key_encoding_flags"};
unsigned int key = 0, shifted_key = 0, alternate_key = 0, mods = 0, action = 0, key_encoding_flags = 0;
const char *text = NULL;
int cursor_key_mode = 0;
if (!PyArg_ParseTupleAndKeywords(args, kw, "IIIIIspI", kwds, &key, &shifted_key, &alternate_key, &mods, &action, &text, &cursor_key_mode, &key_encoding_flags)) return NULL;
GLFWkeyevent ev = { .key = key, .shifted_key = shifted_key, .alternate_key = alternate_key, .text = text, .action = action, .mods = mods };
char output[KEY_BUFFER_SIZE+1] = {0};
int num = encode_glfw_key_event(&ev, cursor_key_mode, key_encoding_flags, output);
if (num == SEND_TEXT_TO_CHILD) return PyUnicode_FromString(text);
return PyUnicode_FromString(output);
}
static PyMethodDef module_methods[] = {
M(key_to_bytes, METH_VARARGS),
M(key_for_native_key_name, METH_VARARGS),
M(encode_key_for_tty, METH_VARARGS | METH_KEYWORDS),
{0}
};
void
finalize(void) {
free(native_special_keys);
}
bool
init_keys(PyObject *module) {
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
if (Py_AtExit(finalize) != 0) {
PyErr_SetString(PyExc_RuntimeError, "Failed to register the keys at exit handler");
return false;
}
return true;
}

23420
kitty/keys.h

File diff suppressed because it is too large Load Diff

View File

@ -80,6 +80,3 @@
#define BRACKETED_PASTE (2004 << 5)
#define BRACKETED_PASTE_START "200~"
#define BRACKETED_PASTE_END "201~"
// Extended keyboard protocol
#define EXTENDED_KEYBOARD (2017 << 5)

View File

@ -150,6 +150,7 @@ void
screen_reset(Screen *self) {
if (self->linebuf == self->alt_linebuf) screen_toggle_screen_buffer(self, true, true);
if (self->overlay_line.is_active) deactivate_overlay_line(self);
self->key_encoding_flags = 0;
self->last_graphic_char = 0;
self->main_savepoint.is_valid = false;
self->alt_savepoint.is_valid = false;
@ -750,7 +751,6 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) {
SIMPLE_MODE(IRM)
SIMPLE_MODE(DECARM)
SIMPLE_MODE(BRACKETED_PASTE)
SIMPLE_MODE(EXTENDED_KEYBOARD)
SIMPLE_MODE(FOCUS_TRACKING)
MOUSE_MODE(MOUSE_BUTTON_TRACKING, mouse_tracking_mode, BUTTON_MODE)
MOUSE_MODE(MOUSE_MOTION_TRACKING, mouse_tracking_mode, MOTION_MODE)
@ -1143,7 +1143,7 @@ screen_restore_modes(Screen *self) {
if (m == NULL) m = &empty_modes;
#define S(name) set_mode_from_const(self, name, m->m##name)
S(DECTCEM); S(DECSCNM); S(DECSCNM); S(DECOM); S(DECAWM); S(DECARM); S(DECCKM);
S(BRACKETED_PASTE); S(FOCUS_TRACKING); S(EXTENDED_KEYBOARD);
S(BRACKETED_PASTE); S(FOCUS_TRACKING);
self->modes.mouse_tracking_mode = m->mouse_tracking_mode;
self->modes.mouse_tracking_protocol = m->mouse_tracking_protocol;
#undef S
@ -1490,7 +1490,6 @@ report_mode_status(Screen *self, unsigned int which, bool private) {
KNOWN_MODE(DECARM);
KNOWN_MODE(DECCKM);
KNOWN_MODE(BRACKETED_PASTE);
KNOWN_MODE(EXTENDED_KEYBOARD);
KNOWN_MODE(FOCUS_TRACKING);
#undef KNOWN_MODE
case ALTERNATE_SCREEN:
@ -2201,7 +2200,6 @@ WRAP0(scroll_until_cursor)
static int name##_set(Screen *self, PyObject *val, void UNUSED *closure) { if (val == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete attribute"); return -1; } set_mode_from_const(self, uname, PyObject_IsTrue(val) ? true : false); return 0; }
MODE_GETSET(in_bracketed_paste_mode, BRACKETED_PASTE)
MODE_GETSET(extended_keyboard, EXTENDED_KEYBOARD)
MODE_GETSET(focus_tracking_enabled, FOCUS_TRACKING)
MODE_GETSET(auto_repeat_enabled, DECARM)
MODE_GETSET(cursor_visible, DECTCEM)
@ -2859,7 +2857,6 @@ static PyMethodDef methods[] = {
static PyGetSetDef getsetters[] = {
GETSET(in_bracketed_paste_mode)
GETSET(extended_keyboard)
GETSET(auto_repeat_enabled)
GETSET(focus_tracking_enabled)
GETSET(cursor_visible)

View File

@ -14,7 +14,7 @@ typedef enum ScrollTypes { SCROLL_LINE = -999999, SCROLL_PAGE, SCROLL_FULL } Scr
typedef struct {
bool mLNM, mIRM, mDECTCEM, mDECSCNM, mDECOM, mDECAWM, mDECCOLM, mDECARM, mDECCKM,
mBRACKETED_PASTE, mFOCUS_TRACKING, mEXTENDED_KEYBOARD, mDECSACE;
mBRACKETED_PASTE, mFOCUS_TRACKING, mDECSACE;
MouseTrackingMode mouse_tracking_mode;
MouseTrackingProtocol mouse_tracking_protocol;
bool eight_bit_controls; // S8C1T
@ -129,6 +129,7 @@ typedef struct {
HYPERLINK_POOL_HANDLE hyperlink_pool;
ANSIBuf as_ansi_buf;
char_type last_graphic_char;
unsigned key_encoding_flags;
} Screen;