Use nested switch statements for key lookup
Replace giant key look up table with nested switch statements. A little slower, but reduces memory consumption and makes it easier to add new keyboard modes in the future, if needed. Key lookup was not a performance bottleneck, in any case.
This commit is contained in:
parent
f3c99546d7
commit
204b6fa3e8
17
kitty/keys.c
17
kitty/keys.c
@ -10,19 +10,14 @@
|
||||
#include "screen.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
const uint8_t*
|
||||
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;
|
||||
mods &= 0xF;
|
||||
key |= (mods & 0xF) << 7;
|
||||
key |= (action & 3) << 11;
|
||||
key |= (smkx & 1) << 13;
|
||||
key |= (extended & 1) << 14;
|
||||
if (key >= SIZE_OF_KEY_BYTES_MAP) return NULL;
|
||||
return key_bytes[key];
|
||||
KeyboardMode mode = extended ? EXTENDED : (smkx ? APPLICATION : NORMAL);
|
||||
return key_lookup(key, mode, mods, action);
|
||||
}
|
||||
|
||||
#define SPECIAL_INDEX(key) ((key & 0x7f) | ( (mods & 0xF) << 7))
|
||||
@ -166,8 +161,8 @@ on_key_input(int key, int scancode, int action, int mods) {
|
||||
(action == GLFW_REPEAT && screen->modes.mDECARM) ||
|
||||
screen->modes.mEXTENDED_KEYBOARD
|
||||
) {
|
||||
const uint8_t *data = key_to_bytes(lkey, screen->modes.mDECCKM, screen->modes.mEXTENDED_KEYBOARD, mods, action);
|
||||
if (data) schedule_write_to_child(w->id, (char*)(data + 1), *data);
|
||||
const char *data = key_to_bytes(lkey, screen->modes.mDECCKM, screen->modes.mEXTENDED_KEYBOARD, mods, action);
|
||||
if (data) schedule_write_to_child(w->id, (data + 1), *data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,7 +173,7 @@ on_key_input(int key, int scancode, int action, int mods) {
|
||||
PYWRAP1(key_to_bytes) {
|
||||
int glfw_key, smkx, extended, mods, action;
|
||||
PA("ippii", &glfw_key, &smkx, &extended, &mods, &action);
|
||||
const uint8_t *ans = key_to_bytes(glfw_key, smkx & 1, extended & 1, 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);
|
||||
}
|
||||
|
||||
48883
kitty/keys.h
48883
kitty/keys.h
File diff suppressed because it is too large
Load Diff
100
kitty/keys.py
100
kitty/keys.py
@ -263,46 +263,62 @@ def generate_key_table():
|
||||
if k is not None:
|
||||
w('case %d: return "%s";' % (i, key_name(k)))
|
||||
w('default: return NULL; }}\n')
|
||||
number_entries = 128 * 256
|
||||
inits = []
|
||||
longest = 0
|
||||
for i in range(number_entries):
|
||||
key = i & 0x7f # lowest seven bits
|
||||
if key < key_count:
|
||||
glfw_key = key_rmap[key]
|
||||
k = keys.get(glfw_key)
|
||||
else:
|
||||
k = None
|
||||
if k is None:
|
||||
inits.append(None)
|
||||
else:
|
||||
mods = (i >> 7) & 0b1111
|
||||
rest = i >> 11
|
||||
action = rest & 0b11
|
||||
if action == 0b11: # no such action
|
||||
inits.append(None)
|
||||
w('typedef enum { NORMAL, APPLICATION, EXTENDED } KeyboardMode;\n')
|
||||
w('static inline const char*\nkey_lookup(uint8_t key, KeyboardMode mode, uint8_t mods, uint8_t action) {')
|
||||
i = 1
|
||||
|
||||
def ind(*a):
|
||||
w((' ' * i)[:-1], *a)
|
||||
ind('switch(mode) {')
|
||||
mmap = [(False, False), (True, False), (False, True)]
|
||||
for (smkx, extended), mode in zip(mmap, 'NORMAL APPLICATION EXTENDED'.split()):
|
||||
i += 1
|
||||
ind('case {}:'.format(mode))
|
||||
i += 1
|
||||
ind('switch(action & 3) { case 3: return NULL; ')
|
||||
for action in (defines.GLFW_RELEASE, defines.GLFW_PRESS, defines.GLFW_REPEAT):
|
||||
i += 1
|
||||
ind('case {}: // {}'.format(action, 'RELEASE PRESS REPEAT'.split()[action]))
|
||||
i += 1
|
||||
if action != defines.GLFW_RELEASE or mode == 'EXTENDED':
|
||||
ind('switch (mods & 0xf) { ')
|
||||
i += 1
|
||||
for mods in range(16):
|
||||
key_bytes = {}
|
||||
for key in range(key_count):
|
||||
glfw_key = key_rmap[key]
|
||||
data = key_to_bytes(glfw_key, smkx, extended, mods, action)
|
||||
if data:
|
||||
key_bytes[key] = data, glfw_key
|
||||
i += 1
|
||||
ind('case 0x{:x}:'.format(mods))
|
||||
i += 1
|
||||
if key_bytes:
|
||||
ind('switch(key & 0x7f) { default: return NULL;')
|
||||
i += 1
|
||||
for key, (data, glfw_key) in key_bytes.items():
|
||||
ind('case {}: // {}'.format(key, key_name(keys[glfw_key])))
|
||||
i += 1
|
||||
items = bytearray(data)
|
||||
items.insert(0, len(items))
|
||||
ind('return "{}";'.format(''.join('\\x{:02x}'.format(x) for x in items)))
|
||||
i -= 1
|
||||
i -= 1
|
||||
ind('} // end switch(key)')
|
||||
else:
|
||||
ind('return NULL;')
|
||||
i -= 2
|
||||
i -= 1
|
||||
ind('} // end switch(mods)\n')
|
||||
i -= 1
|
||||
else:
|
||||
smkx = bool(rest & 0b100)
|
||||
extended = bool(rest & 0b1000)
|
||||
data = key_to_bytes(glfw_key, smkx, extended, mods, action)
|
||||
if data:
|
||||
longest = max(len(data), longest)
|
||||
inits.append((data, k, mods, smkx, extended))
|
||||
else:
|
||||
inits.append(None)
|
||||
longest += 1
|
||||
w('#define SIZE_OF_KEY_BYTES_MAP %d\n' % number_entries)
|
||||
w('static const uint8_t key_bytes[%d][%d] = {' % (number_entries, longest))
|
||||
# empty = '{' + ('0, ' * longest) + '},'
|
||||
empty = '{0},'
|
||||
all_mods = {k.rpartition('_')[2]: v for k, v in vars(defines).items() if k.startswith('GLFW_MOD_')}
|
||||
all_mods = {k: v for k, v in sorted(all_mods.items(), key=lambda x: x[0])}
|
||||
for b in inits:
|
||||
if b is None:
|
||||
w(empty)
|
||||
else:
|
||||
b, k, mods, smkx, extended = b
|
||||
b = bytearray(b)
|
||||
name = '+'.join([k for k, v in all_mods.items() if v & mods] + [key_name(k)])
|
||||
w('{%d, ' % len(b) + ', '.join(map(hex, b)) + '}, //', name, 'smkx:', smkx, 'extended:', extended)
|
||||
w('};')
|
||||
ind('return NULL;\n')
|
||||
i -= 1
|
||||
i -= 1
|
||||
ind('}} // end switch(action) in mode {}\n\n'.format(mode))
|
||||
i -= 1
|
||||
i -= 1
|
||||
ind('}')
|
||||
ind('return NULL;')
|
||||
i -= 1
|
||||
w('}')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user