From 992e90b0a3434fd803c36d3121344d21074f1846 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 31 Aug 2022 22:19:51 +0530 Subject: [PATCH] Fix a regression in 0.26.0 that broke mapping of native keys who key codes did not fit in 21 bits Fixes #5452 --- docs/changelog.rst | 2 ++ kitty/keys.c | 28 ++++++++++++++-------------- kitty_tests/datatypes.py | 3 ++- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 939f970ad..cd879639e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -46,6 +46,8 @@ Detailed list of changes - hints kitten: hyperlink matching: Fix hints occasionally matching text on subsequent line as part of hyperlink (:pull:`5450`) +- Fix a regression in 0.26.0 that broke mapping of native keys who key codes did not fit in 21 bits (:iss:`5452`) + 0.26.1 [2022-08-30] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/kitty/keys.c b/kitty/keys.c index 5cef79f96..5fc95242b 100644 --- a/kitty/keys.c +++ b/kitty/keys.c @@ -284,9 +284,9 @@ static PyMethodDef module_methods[] = { }; // SingleKey {{{ -typedef uint32_t keybitfield; -#define KEY_BITS 21 -#define MOD_BITS 10 +typedef uint64_t keybitfield; +#define KEY_BITS 51 +#define MOD_BITS 12 #if 1 << (MOD_BITS-1) < GLFW_MOD_KITTY #error "Not enough mod bits" #endif @@ -309,9 +309,9 @@ typedef struct { } SingleKey; static inline void -SingleKey_set_vals(SingleKey *self, long key, unsigned short mods, int is_native) { - if (key >= 0 && (unsigned long)key <= BIT_MASK(keybitfield, KEY_BITS)) { - keybitfield k = (keybitfield)(unsigned long)key; +SingleKey_set_vals(SingleKey *self, long long key, unsigned short mods, int is_native) { + if (key >= 0 && (unsigned long long)key <= BIT_MASK(keybitfield, KEY_BITS)) { + keybitfield k = (keybitfield)(unsigned long long)key; self->key.key = k & BIT_MASK(keybitfield, KEY_BITS); } if (!(mods & 1 << (MOD_BITS + 1))) self->key.mods = mods & BIT_MASK(u_int32_t, MOD_BITS); @@ -320,8 +320,8 @@ SingleKey_set_vals(SingleKey *self, long key, unsigned short mods, int is_native static PyObject * SingleKey_new(PyTypeObject *type, PyObject *args, PyObject *kw) { - long key = -1; unsigned short mods = 1 << (MOD_BITS + 1); int is_native = -1; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|Hpl", SingleKey_kwds, &mods, &is_native, &key)) return NULL; + long long key = -1; unsigned short mods = 1 << (MOD_BITS + 1); int is_native = -1; + if (!PyArg_ParseTupleAndKeywords(args, kw, "|HpL", SingleKey_kwds, &mods, &is_native, &key)) return NULL; SingleKey *self = (SingleKey *)type->tp_alloc(type, 0); if (self) SingleKey_set_vals(self, key, mods, is_native); return (PyObject*)self; @@ -341,8 +341,8 @@ SingleKey_repr(PyObject *s) { unsigned int mods = self->key.mods; if (mods) pos += PyOS_snprintf(buf + pos, sizeof(buf) - pos, "mods=%u, ", mods); if (self->key.is_native) pos += PyOS_snprintf(buf + pos, sizeof(buf) - pos, "is_native=True, "); - unsigned long key = self->key.key; - if (key) pos += PyOS_snprintf(buf + pos, sizeof(buf) - pos, "key=%lu, ", key); + unsigned long long key = self->key.key; + if (key) pos += PyOS_snprintf(buf + pos, sizeof(buf) - pos, "key=%llu, ", key); if (buf[pos-1] == ' ') pos -= 2; pos += PyOS_snprintf(buf + pos, sizeof(buf) - pos, ")"); return PyUnicode_FromString(buf); @@ -350,8 +350,8 @@ SingleKey_repr(PyObject *s) { static PyObject* SingleKey_get_key(SingleKey *self, void UNUSED *closure) { - const unsigned long val = self->key.key; - return PyLong_FromUnsignedLong(val); + const unsigned long long val = self->key.key; + return PyLong_FromUnsignedLongLong(val); } static PyObject* @@ -436,8 +436,8 @@ SingleKey_resolve_kitty_mod(SingleKey *self, PyObject *km) { static PyObject* SingleKey_replace(SingleKey *self, PyObject *args, PyObject *kw) { - long key = -2; unsigned short mods = 1 << (MOD_BITS + 1); int is_native = -1; - if (!PyArg_ParseTupleAndKeywords(args, kw, "|Hpl", SingleKey_kwds, &mods, &is_native, &key)) return NULL; + long long key = -2; unsigned short mods = 1 << (MOD_BITS + 1); int is_native = -1; + if (!PyArg_ParseTupleAndKeywords(args, kw, "|HpL", SingleKey_kwds, &mods, &is_native, &key)) return NULL; SingleKey *ans = (SingleKey*)SingleKey_Type.tp_alloc(&SingleKey_Type, 0); if (ans) { if (key == -1) key = 0; diff --git a/kitty_tests/datatypes.py b/kitty_tests/datatypes.py index 1d8dc9492..9369a115f 100644 --- a/kitty_tests/datatypes.py +++ b/kitty_tests/datatypes.py @@ -535,7 +535,7 @@ class TestDataTypes(BaseTest): q('a\x1b[bc', 'ac') q('a\x1b[12;34:43mbc', 'abc') - def test_SingleKey(self): + def test_single_key(self): from kitty.fast_data_types import ( GLFW_MOD_KITTY, GLFW_MOD_SHIFT, SingleKey ) @@ -548,6 +548,7 @@ class TestDataTypes(BaseTest): self.ae(repr(SingleKey(key=23, mods=2, is_native=True)), 'SingleKey(mods=2, is_native=True, key=23)') self.ae(repr(SingleKey(key=23, mods=2)), 'SingleKey(mods=2, key=23)') self.ae(repr(SingleKey(key=23)), 'SingleKey(key=23)') + self.ae(repr(SingleKey(key=0x1008ff57)), 'SingleKey(key=269025111)') self.ae(repr(SingleKey(key=23)._replace(mods=2)), 'SingleKey(mods=2, key=23)') self.ae(repr(SingleKey(key=23)._replace(key=-1, mods=GLFW_MOD_KITTY)), f'SingleKey(mods={GLFW_MOD_KITTY})') self.assertEqual(SingleKey(key=1), SingleKey(key=1))