From 6ec58f58cec51a1ef7173e29aa1a92d2783550ce Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 2 Sep 2018 18:46:10 +0530 Subject: [PATCH] Allow mapping shortcuts using the raw key code from the OS Fixes #848 --- docs/changelog.rst | 9 +++++++++ kitty/config.py | 16 ++++++++++++---- kitty/config_data.py | 15 +++++++++++++++ kitty/keys.c | 18 ++++++------------ 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 4177fd687..fc8c5fbb7 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -3,6 +3,15 @@ Changelog |kitty| is a feature full, cross-platform, *fast*, GPU based terminal emulator. +0.12.1 [future] +------------------------------ + +- Allow mapping shortcuts using the raw key code from the OS (:iss:`848`) + +- Allow mapping of individual keypresses without modifiers as shortcuts + +- Fix legacy invocation of icat as `kitty icat` not working (:iss:`850`) + 0.12.0 [2018-09-01] ------------------------------ diff --git a/kitty/config.py b/kitty/config.py index fe74d2787..942ba9be3 100644 --- a/kitty/config.py +++ b/kitty/config.py @@ -35,14 +35,22 @@ named_keys = { def parse_shortcut(sc): parts = sc.split('+') - mods = parse_mods(parts[:-1], sc) - if mods is None: - return None, None, None + mods = 0 + if len(parts) > 1: + mods = parse_mods(parts[:-1], sc) + if mods is None: + return None, None, None key = parts[-1].upper() key = getattr(defines, 'GLFW_KEY_' + named_keys.get(key, key), None) is_native = False if key is None: - key = defines.key_for_native_key_name(parts[-1]) + if parts[-1].startswith('0x'): + try: + key = int(parts[-1], 16) + except Exception: + pass + else: + key = defines.key_for_native_key_name(parts[-1]) is_native = key is not None return mods, is_native, key diff --git a/kitty/config_data.py b/kitty/config_data.py index aace1abd0..2d69a3220 100644 --- a/kitty/config_data.py +++ b/kitty/config_data.py @@ -95,6 +95,21 @@ for a list of key names. The name to use is the part after the :code:`XKB_KEY_` prefix. Note that you should only use an XKB key name for keys that are not present in the list of GLFW keys. +Finally, you can use raw system key codes to map keys. To see the system key code +for a key, start kitty with the :option:`kitty --debug-keyboard` option. Then kitty will +output some debug text for every key event. In that text look for ``native_code`` +the value of that becomes the key name in the shortcut. For example: + +.. code-block:: none + + on_key_input: glfw key: 65 native_code: 0x61 action: PRESS mods: 0x0 text: 'a' + +Here, the key name for the :kbd:`A` key is :kbd:`0x61` and you can use it with:: + + map ctrl+0x61 something + +to map :kbd:`ctrl+a` to something. + You can use the special action :code:`no_op` to unmap a keyboard shortcut that is assigned in the default configuration. diff --git a/kitty/keys.c b/kitty/keys.c index 0a56fa619..58e0e8781 100644 --- a/kitty/keys.c +++ b/kitty/keys.c @@ -103,13 +103,9 @@ check_if_special(int key, int mods, int scancode) { qkey = SPECIAL_INDEX(qkey); special = needs_special_handling[qkey]; } -#ifdef __APPLE__ - (void)scancode; -#else - for (size_t i = 0; !special && i < native_special_keys_count; i++) { - if (scancode == native_special_keys[i].scancode && mods == native_special_keys[i].mods) special = true; - } -#endif + for (size_t i = 0; !special && i < native_special_keys_count; i++) { + if (scancode == native_special_keys[i].scancode && mods == native_special_keys[i].mods) special = true; + } return special; } @@ -127,7 +123,7 @@ update_ime_position(OSWindow *os_window, Window* w, Screen *screen) { void on_key_input(int key, int scancode, int action, int mods, const char* text, int state) { Window *w = active_window(); - debug("on_key_input: glfw key: %d native_code: %d action: %s mods: 0x%x text: '%s' state: %d ", + debug("on_key_input: glfw key: %d native_code: 0x%x action: %s mods: 0x%x text: '%s' state: %d ", key, scancode, (action == GLFW_RELEASE ? "RELEASE" : (action == GLFW_PRESS ? "PRESS" : "REPEAT")), mods, text, state); @@ -222,15 +218,13 @@ PYWRAP1(key_for_native_key_name) { const char *name; int case_sensitive = 0; PA("s|p", &name, case_sensitive); -#ifdef __APPLE__ - Py_RETURN_NONE; -#else +#ifndef __APPLE__ if (glfwGetXKBScancode) { // if this function is called before GLFW is initialized glfwGetXKBScancode will be NULL int scancode = glfwGetXKBScancode(name, case_sensitive); if (scancode) return Py_BuildValue("i", scancode); } - Py_RETURN_NONE; #endif + Py_RETURN_NONE; } static PyMethodDef module_methods[] = {