Translate key presses to bytes using a lookup table
This commit is contained in:
parent
b5af266b87
commit
44c897a61a
@ -1,2 +1,2 @@
|
||||
#!/bin/bash
|
||||
cloc --exclude-list-file <(echo -e 'kitty/wcwidth9.h\nkitty/glfw.c\nkitty/glfw.h\nkitty/charsets.c\nkitty/key_encoding.py\nkitty/rgb.py') kitty
|
||||
cloc --exclude-list-file <(echo -e 'kitty/wcwidth9.h\nkitty/glfw.c\nkitty/keys.h\nkitty/charsets.c\nkitty/key_encoding.py\nkitty/rgb.py') kitty
|
||||
|
||||
@ -135,6 +135,7 @@ extern bool init_fontconfig_library(PyObject*);
|
||||
extern bool init_glfw(PyObject *m);
|
||||
extern bool init_sprites(PyObject *module);
|
||||
extern bool init_state(PyObject *module);
|
||||
extern bool init_keys(PyObject *module);
|
||||
extern bool init_shaders(PyObject *module);
|
||||
extern bool init_shaders_debug(PyObject *module);
|
||||
#ifdef __APPLE__
|
||||
@ -164,6 +165,7 @@ PyInit_fast_data_types(void) {
|
||||
if (!init_glfw(m)) return NULL;
|
||||
if (!init_sprites(m)) return NULL;
|
||||
if (!init_state(m)) return NULL;
|
||||
if (!init_keys(m)) return NULL;
|
||||
if (PySys_GetObject("debug_gl") == Py_True) {
|
||||
if (!init_shaders_debug(m)) return NULL;
|
||||
} else {
|
||||
|
||||
47
kitty/keys.c
Normal file
47
kitty/keys.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* keys.c
|
||||
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
|
||||
*
|
||||
* Distributed under terms of the GPL3 license.
|
||||
*/
|
||||
|
||||
#include "keys.h"
|
||||
#include "data-types.h"
|
||||
|
||||
const uint8_t*
|
||||
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];
|
||||
}
|
||||
|
||||
#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}
|
||||
|
||||
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);
|
||||
if (ans == NULL) return Py_BuildValue("y#", "", 0);
|
||||
return Py_BuildValue("y#", ans + 1, *ans);
|
||||
}
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
M(key_to_bytes, METH_VARARGS),
|
||||
{0}
|
||||
};
|
||||
|
||||
bool
|
||||
init_keys(PyObject *module) {
|
||||
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
||||
return true;
|
||||
}
|
||||
32778
kitty/keys.h
Normal file
32778
kitty/keys.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -190,7 +190,7 @@ def interpret_key_event(key, scancode, mods, window, action, get_localized_key=g
|
||||
screen.extended_keyboard
|
||||
):
|
||||
key = get_localized_key(key, scancode)
|
||||
return key_to_bytes(key, screen.cursor_key_mode, screen.extended_keyboard, mods, action)
|
||||
return defines.key_to_bytes(key, screen.cursor_key_mode, screen.extended_keyboard, mods, action)
|
||||
return b''
|
||||
|
||||
|
||||
@ -216,3 +216,74 @@ def get_sent_data(send_text_map, key, scancode, mods, window, action):
|
||||
m = keyboard_mode_name(window.screen)
|
||||
keymap = send_text_map[m]
|
||||
return keymap.get((mods & 0b1111, key))
|
||||
|
||||
|
||||
def generate_key_table():
|
||||
# To run this, use: python3 . -c "from kitty.keys import *; generate_key_table()"
|
||||
import os
|
||||
from functools import partial
|
||||
f = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'keys.h'), 'w')
|
||||
w = partial(print, file=f)
|
||||
w('// auto-generated from keys.py, do not edit!')
|
||||
w('#pragma once')
|
||||
w('#include <stdint.h>')
|
||||
w('#include <limits.h>')
|
||||
number_of_keys = defines.GLFW_KEY_LAST + 1
|
||||
w('static const uint8_t key_map[%d] = {' % number_of_keys)
|
||||
key_count = 0
|
||||
keys = {v: k for k, v in vars(defines).items() if k.startswith('GLFW_KEY_') and k not in 'GLFW_KEY_LAST GLFW_KEY_UNKNOWN'}
|
||||
key_rmap = []
|
||||
for i in range(number_of_keys):
|
||||
k = keys.get(i)
|
||||
if k is None:
|
||||
w('UINT8_MAX,', end=' ')
|
||||
else:
|
||||
w('%d,' % key_count, end=' ')
|
||||
key_rmap.append(i)
|
||||
key_count += 1
|
||||
if key_count > 128:
|
||||
raise OverflowError('Too many keys')
|
||||
w('};\n')
|
||||
number_entries = 0x7f | (0xff << 7)
|
||||
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)
|
||||
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] + [k.rpartition('_')[2]])
|
||||
w('{0x%x, ' % len(b) + ', '.join(map(str, b)) + '}, //', name, 'smkx:', smkx, 'extended:', extended)
|
||||
w('};')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user