From b2c7272af185f60ec2fcecdd705ca3676cbb0f6b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Sep 2017 18:06:26 +0530 Subject: [PATCH] Store key combos that need special handling in a table for fast lookup --- kitty/data-types.h | 1 + kitty/keys.c | 6 ++++++ kitty/keys.h | 7 +++++-- kitty/keys.py | 4 +++- kitty/state.c | 28 +++++++++++++++++++++++++++- 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/kitty/data-types.h b/kitty/data-types.h index 75a42ae99..a8e6dd8c0 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -317,3 +317,4 @@ void change_wcwidth(bool use9); void set_mouse_cursor(MouseShape); void mouse_event(int, int); void scroll_event(double, double); +void set_special_key_combo(int glfw_key, int mods); diff --git a/kitty/keys.c b/kitty/keys.c index 9b61acff2..da08f56ac 100644 --- a/kitty/keys.c +++ b/kitty/keys.c @@ -23,6 +23,12 @@ key_to_bytes(int glfw_key, bool smkx, bool extended, int mods, int action) { return key_bytes[key]; } +void +set_special_key_combo(int glfw_key, int mods) { + int k = (glfw_key & 0x7f) | ( (mods & 0xF) << 7); + needs_special_handling[k] = true; +} + #define PYWRAP1(name) static PyObject* py##name(PyObject UNUSED *self, PyObject *args) #define PA(fmt, ...) if(!PyArg_ParseTuple(args, fmt, __VA_ARGS__)) return NULL; #define M(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL} diff --git a/kitty/keys.h b/kitty/keys.h index 158844446..831510e24 100644 --- a/kitty/keys.h +++ b/kitty/keys.h @@ -1,13 +1,15 @@ // auto-generated from keys.py, do not edit! #pragma once #include +#include #include +static bool needs_special_handling[2048] = {0}; static const uint8_t key_map[349] = { UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, 0, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, 1, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, UINT8_MAX, 16, UINT8_MAX, 17, UINT8_MAX, UINT8_MAX, UINT8_MAX, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, UINT8_MAX, 29, 30, 31, 32, 33, 34, 35, 36, UINT8_MAX, 37, 38, 39, 40, 41, 42, 43, 44, UINT8_MAX, UINT8_MAX, 45, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, 46, 47, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, 62, 63, 64, 65, 66, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, UINT8_MAX, UINT8_MAX, UINT8_MAX, 109, 110, 111, 112, 113, 114, 115, 116, 117, }; -#define SIZE_OF_KEY_BYTES_MAP 32767 +#define SIZE_OF_KEY_BYTES_MAP 32768 -static const uint8_t key_bytes[32767][10] = { +static const uint8_t key_bytes[32768][10] = { {0}, {0}, {0}, @@ -32775,4 +32777,5 @@ static const uint8_t key_bytes[32767][10] = { {0}, {0}, {0}, +{0}, }; diff --git a/kitty/keys.py b/kitty/keys.py index 81036205b..9ca080daa 100644 --- a/kitty/keys.py +++ b/kitty/keys.py @@ -227,7 +227,9 @@ def generate_key_table(): w('// auto-generated from keys.py, do not edit!') w('#pragma once') w('#include ') + w('#include ') w('#include ') + w('static bool needs_special_handling[%d] = {0};' % (128 * 16)) number_of_keys = defines.GLFW_KEY_LAST + 1 w('static const uint8_t key_map[%d] = {' % number_of_keys) key_count = 0 @@ -244,7 +246,7 @@ def generate_key_table(): if key_count > 128: raise OverflowError('Too many keys') w('};\n') - number_entries = 0x7f | (0xff << 7) + number_entries = 128 * 256 inits = [] longest = 0 for i in range(number_entries): diff --git a/kitty/state.c b/kitty/state.c index d00661749..e24ed1858 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -126,8 +126,24 @@ color_as_int(PyObject *color) { #undef I } +#define dict_iter(d) { \ + PyObject *key, *value; Py_ssize_t pos; \ + while (PyDict_Next(d, &pos, &key, &value)) + +static inline void +set_special_keys(PyObject *dict) { + dict_iter(dict) { + if (!PyTuple_Check(key)) { PyErr_SetString(PyExc_TypeError, "dict keys for special keys must be tuples"); return; } + int mods = PyLong_AsLong(PyTuple_GET_ITEM(key, 0)); + int glfw_key = PyLong_AsLong(PyTuple_GET_ITEM(key, 1)); + set_special_key_combo(glfw_key, mods); + }} +} + PYWRAP1(set_options) { -#define S(name, convert) { PyObject *ret = PyObject_GetAttrString(args, #name); if (ret == NULL) return NULL; global_state.opts.name = convert(ret); Py_DECREF(ret); if (PyErr_Occurred()) return NULL; } + PyObject *ret; +#define GA(name) ret = PyObject_GetAttrString(args, #name); if (ret == NULL) return NULL; +#define S(name, convert) { GA(name); global_state.opts.name = convert(ret); Py_DECREF(ret); if (PyErr_Occurred()) return NULL; } S(visual_bell_duration, PyFloat_AsDouble); S(enable_audio_bell, PyObject_IsTrue); S(cursor_blink_interval, PyFloat_AsDouble); @@ -139,12 +155,22 @@ PYWRAP1(set_options) { S(open_url_modifiers, PyLong_AsUnsignedLong); S(click_interval, PyFloat_AsDouble); S(url_color, color_as_int); + PyObject *chars = PyObject_GetAttrString(args, "select_by_word_characters"); if (chars == NULL) return NULL; for (size_t i = 0; i < MIN((size_t)PyUnicode_GET_LENGTH(chars), sizeof(OPT(select_by_word_characters))/sizeof(OPT(select_by_word_characters[0]))); i++) { OPT(select_by_word_characters)[i] = PyUnicode_READ(PyUnicode_KIND(chars), PyUnicode_DATA(chars), i); } OPT(select_by_word_characters_count) = PyUnicode_GET_LENGTH(chars); + + GA(keymap); set_special_keys(ret); + Py_DECREF(ret); if (PyErr_Occurred()) return NULL; + GA(send_text_map); + dict_iter(ret) { + set_special_keys(value); + }} + Py_DECREF(ret); if (PyErr_Occurred()) return NULL; + Py_DECREF(chars); #undef S Py_RETURN_NONE;