From 953253de998378b9fe9a79eb33643f3972cc4482 Mon Sep 17 00:00:00 2001 From: Ravi R Kiran Date: Thu, 25 Mar 2021 21:35:21 -0500 Subject: [PATCH 1/3] Implementation of hyper and meta --- docs/keyboard-protocol.rst | 9 ++-- gen-key-constants.py | 2 + glfw/glfw3.h | 45 +++++++++++------ glfw/ibus_glfw.c | 2 +- glfw/input.c | 2 + glfw/x11_window.c | 1 + glfw/xkb_glfw.c | 100 ++++++++++++++++++++++++++++++++----- glfw/xkb_glfw.h | 4 ++ kittens/key_demo/main.py | 6 ++- kitty/cli.py | 4 +- kitty/fast_data_types.pyi | 4 ++ kitty/glfw-wrapper.h | 45 +++++++++++------ kitty/glfw.c | 12 +++++ kitty/key_encoding.c | 10 ++-- kitty/key_encoding.py | 35 +++++++++---- kitty_tests/keys.py | 9 +++- 16 files changed, 221 insertions(+), 69 deletions(-) diff --git a/docs/keyboard-protocol.rst b/docs/keyboard-protocol.rst index 190ee7302..119189c48 100644 --- a/docs/keyboard-protocol.rst +++ b/docs/keyboard-protocol.rst @@ -542,10 +542,11 @@ compatibility reasons. "RAISE_VOLUME", "``57438 u``", "MUTE_VOLUME", "``57439 u``" "LEFT_SHIFT", "``57440 u``", "LEFT_CONTROL", "``57441 u``" "LEFT_ALT", "``57442 u``", "LEFT_SUPER", "``57443 u``" - "LEFT_HYPER", "``57444 u``", "RIGHT_SHIFT", "``57445 u``" - "RIGHT_CONTROL", "``57446 u``", "RIGHT_ALT", "``57447 u``" - "RIGHT_SUPER", "``57448 u``", "RIGHT_HYPER", "``57449 u``" - "ISO_LEVEL3_SHIFT", "``57450 u``", "ISO_LEVEL5_SHIFT", "``57451 u``" + "LEFT_HYPER", "``57444 u``", "LEFT_META", "``57445 u``" + "RIGHT_SHIFT", "``57446 u``", "RIGHT_CONTROL", "``57447 u``" + "RIGHT_ALT", "``57448 u``", "RIGHT_SUPER", "``57449 u``" + "RIGHT_HYPER", "``57450 u``", "RIGHT_META", "``57451 u``" + "ISO_LEVEL3_SHIFT", "``57452 u``", "ISO_LEVEL5_SHIFT", "``57453 u``" .. end functional key table .. }}} diff --git a/gen-key-constants.py b/gen-key-constants.py index dc89025ce..79f6f4ad2 100755 --- a/gen-key-constants.py +++ b/gen-key-constants.py @@ -109,11 +109,13 @@ left_alt Alt_L 0x3A - left_super Super_L 0x37 - left_hyper Hyper_L - - +left_meta Meta_L - - right_shift Shift_R 0x3C - right_control Control_R 0x3E - right_alt Alt_R 0x3D - right_super Super_R 0x36 - right_hyper Hyper_R - - +right_meta Meta_R - - iso_level3_shift ISO_Level3_Shift - - iso_level5_shift ISO_Level5_Shift - - ''' # }}} diff --git a/glfw/glfw3.h b/glfw/glfw3.h index 14fce1227..e2bfeeb32 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -446,14 +446,16 @@ typedef enum { GLFW_FKEY_LEFT_ALT = 0xe062u, GLFW_FKEY_LEFT_SUPER = 0xe063u, GLFW_FKEY_LEFT_HYPER = 0xe064u, - GLFW_FKEY_RIGHT_SHIFT = 0xe065u, - GLFW_FKEY_RIGHT_CONTROL = 0xe066u, - GLFW_FKEY_RIGHT_ALT = 0xe067u, - GLFW_FKEY_RIGHT_SUPER = 0xe068u, - GLFW_FKEY_RIGHT_HYPER = 0xe069u, - GLFW_FKEY_ISO_LEVEL3_SHIFT = 0xe06au, - GLFW_FKEY_ISO_LEVEL5_SHIFT = 0xe06bu, - GLFW_FKEY_LAST = 0xe06bu + GLFW_FKEY_LEFT_META = 0xe065u, + GLFW_FKEY_RIGHT_SHIFT = 0xe066u, + GLFW_FKEY_RIGHT_CONTROL = 0xe067u, + GLFW_FKEY_RIGHT_ALT = 0xe068u, + GLFW_FKEY_RIGHT_SUPER = 0xe069u, + GLFW_FKEY_RIGHT_HYPER = 0xe06au, + GLFW_FKEY_RIGHT_META = 0xe06bu, + GLFW_FKEY_ISO_LEVEL3_SHIFT = 0xe06cu, + GLFW_FKEY_ISO_LEVEL5_SHIFT = 0xe06du, + GLFW_FKEY_LAST = 0xe06du } GLFWFunctionKey; /* end functional key names */ @@ -472,33 +474,44 @@ typedef enum { * If this bit is set one or more Shift keys were held down. */ #define GLFW_MOD_SHIFT 0x0001 -/*! @brief If this bit is set one or more Control keys were held down. - * - * If this bit is set one or more Control keys were held down. - */ -#define GLFW_MOD_ALT 0x0002 /*! @brief If this bit is set one or more Alt keys were held down. * * If this bit is set one or more Alt keys were held down. */ -#define GLFW_MOD_CONTROL 0x0004 +#define GLFW_MOD_ALT 0x0002 +/*! @brief If this bit is set one or more Alt keys were held down. + * + * If this bit is set one or more Alt keys were held down. + */ +#define GLFW_MOD_CONTROL 0x0004 /*! @brief If this bit is set one or more Super keys were held down. * * If this bit is set one or more Super keys were held down. */ #define GLFW_MOD_SUPER 0x0008 +/*! @brief If this bit is set one or more Hyper keys were held down. + * + * If this bit is set one or more Hyper keys were held down. + */ +#define GLFW_MOD_HYPER 0x0010 +/*! @brief If this bit is set one or more Meta keys were held down. + * + * If this bit is set one or more Meta keys were held down. + */ +#define GLFW_MOD_META 0x0020 /*! @brief If this bit is set the Caps Lock key is enabled. * * If this bit is set the Caps Lock key is enabled and the @ref * GLFW_LOCK_KEY_MODS input mode is set. */ -#define GLFW_MOD_CAPS_LOCK 0x0010 +#define GLFW_MOD_CAPS_LOCK 0x0040 /*! @brief If this bit is set the Num Lock key is enabled. * * If this bit is set the Num Lock key is enabled and the @ref * GLFW_LOCK_KEY_MODS input mode is set. + * @note Ravi: Num lock is not supported in this branch */ -#define GLFW_MOD_NUM_LOCK 0x0020 +#define GLFW_MOD_NUM_LOCK 0x0080 /*! @} */ diff --git a/glfw/ibus_glfw.c b/glfw/ibus_glfw.c index 0e36fcd5d..8b65b0a96 100644 --- a/glfw/ibus_glfw.c +++ b/glfw/ibus_glfw.c @@ -388,7 +388,7 @@ ibus_key_state(unsigned int glfw_modifiers, int action) { M(CONTROL, IBUS_CONTROL_MASK); M(ALT, IBUS_MOD1_MASK); M(NUM_LOCK, IBUS_MOD2_MASK); - M(SUPER, IBUS_MOD4_MASK); + /* To do: figure out how to get super/hyper/meta */ #undef M return ans; } diff --git a/glfw/input.c b/glfw/input.c index f07bccfed..911b27b24 100644 --- a/glfw/input.c +++ b/glfw/input.c @@ -625,11 +625,13 @@ _glfwGetKeyName(int key) case GLFW_FKEY_LEFT_ALT: return "LEFT_ALT"; case GLFW_FKEY_LEFT_SUPER: return "LEFT_SUPER"; case GLFW_FKEY_LEFT_HYPER: return "LEFT_HYPER"; + case GLFW_FKEY_LEFT_META: return "LEFT_META"; case GLFW_FKEY_RIGHT_SHIFT: return "RIGHT_SHIFT"; case GLFW_FKEY_RIGHT_CONTROL: return "RIGHT_CONTROL"; case GLFW_FKEY_RIGHT_ALT: return "RIGHT_ALT"; case GLFW_FKEY_RIGHT_SUPER: return "RIGHT_SUPER"; case GLFW_FKEY_RIGHT_HYPER: return "RIGHT_HYPER"; + case GLFW_FKEY_RIGHT_META: return "RIGHT_META"; case GLFW_FKEY_ISO_LEVEL3_SHIFT: return "ISO_LEVEL3_SHIFT"; case GLFW_FKEY_ISO_LEVEL5_SHIFT: return "ISO_LEVEL5_SHIFT"; /* end functional key names */ diff --git a/glfw/x11_window.c b/glfw/x11_window.c index e00545c6c..398e3030a 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -185,6 +185,7 @@ static int translateState(int state) { int mods = 0; + /* Need some way to expose hyper and meta without xkbcommon-x11 */ if (state & ShiftMask) mods |= GLFW_MOD_SHIFT; if (state & ControlMask) diff --git a/glfw/xkb_glfw.c b/glfw/xkb_glfw.c index ca3d148b1..f774e724a 100644 --- a/glfw/xkb_glfw.c +++ b/glfw/xkb_glfw.c @@ -29,6 +29,9 @@ #include #include "internal.h" #include "xkb_glfw.h" +#ifdef _GLFW_X11 +#include +#endif #define debug(...) if (_glfw.hints.init.debugKeyboard) printf(__VA_ARGS__); @@ -141,11 +144,13 @@ glfw_key_for_sym(xkb_keysym_t key) { case XKB_KEY_Alt_L: return GLFW_FKEY_LEFT_ALT; case XKB_KEY_Super_L: return GLFW_FKEY_LEFT_SUPER; case XKB_KEY_Hyper_L: return GLFW_FKEY_LEFT_HYPER; + case XKB_KEY_Meta_L: return GLFW_FKEY_LEFT_META; case XKB_KEY_Shift_R: return GLFW_FKEY_RIGHT_SHIFT; case XKB_KEY_Control_R: return GLFW_FKEY_RIGHT_CONTROL; case XKB_KEY_Alt_R: return GLFW_FKEY_RIGHT_ALT; case XKB_KEY_Super_R: return GLFW_FKEY_RIGHT_SUPER; case XKB_KEY_Hyper_R: return GLFW_FKEY_RIGHT_HYPER; + case XKB_KEY_Meta_R: return GLFW_FKEY_RIGHT_META; case XKB_KEY_ISO_Level3_Shift: return GLFW_FKEY_ISO_LEVEL3_SHIFT; case XKB_KEY_ISO_Level5_Shift: return GLFW_FKEY_ISO_LEVEL5_SHIFT; /* end xkb to glfw */ @@ -257,11 +262,13 @@ glfw_xkb_sym_for_key(uint32_t key) { case GLFW_FKEY_LEFT_ALT: return XKB_KEY_Alt_L; case GLFW_FKEY_LEFT_SUPER: return XKB_KEY_Super_L; case GLFW_FKEY_LEFT_HYPER: return XKB_KEY_Hyper_L; + case GLFW_FKEY_LEFT_META: return XKB_KEY_Meta_L; case GLFW_FKEY_RIGHT_SHIFT: return XKB_KEY_Shift_R; case GLFW_FKEY_RIGHT_CONTROL: return XKB_KEY_Control_R; case GLFW_FKEY_RIGHT_ALT: return XKB_KEY_Alt_R; case GLFW_FKEY_RIGHT_SUPER: return XKB_KEY_Super_R; case GLFW_FKEY_RIGHT_HYPER: return XKB_KEY_Hyper_R; + case GLFW_FKEY_RIGHT_META: return XKB_KEY_Meta_R; case GLFW_FKEY_ISO_LEVEL3_SHIFT: return XKB_KEY_ISO_Level3_Shift; case GLFW_FKEY_ISO_LEVEL5_SHIFT: return XKB_KEY_ISO_Level5_Shift; /* end glfw to xkb */ @@ -308,11 +315,84 @@ glfw_xkb_update_x11_keyboard_id(_GLFWXKBData *xkb) { if (conn) state = xkb_x11_state_new_from_device(keymap, conn, xkb->keyboard_device_id); \ } +static void +glfw_xkb_update_masks(_GLFWXKBData *xkb) { + bool succeeded = false; + unsigned used_bits = 0; /* To avoid using the same bit twice */ + XkbDescPtr xkb_ptr = XkbGetMap( _glfw.x11.display, XkbVirtualModsMask | XkbVirtualModMapMask, XkbUseCoreKbd ); + +#define S( a ) xkb->a##Idx = XKB_MOD_INVALID; xkb->a##Mask = 0 + S(control); S(alt); S(shift); S(super); S(hyper); S(meta); S(capsLock); S(numLock); +#undef S + if ( xkb_ptr ) { + Status status = XkbGetNames( _glfw.x11.display, XkbVirtualModNamesMask, xkb_ptr ); + if ( status == Success ) { + for ( int indx = 0; indx < XkbNumVirtualMods; ++indx ) { + Atom atom = xkb_ptr->names->vmods[indx]; + if ( atom ) { + unsigned mask_rtn = 0; + if ( XkbVirtualModsToReal( xkb_ptr, 1<a##Mask = mask_rtn, used_bits |= mask_rtn + /* Note that the order matters here; earlier is higher priority. */ + S( alt, Alt ); + S( super, Super ); + S( numLock, NumLock ); + S( meta, Meta ); + S( hyper, Hyper ); +#undef S + } + } + } + succeeded = true; + } + XkbFreeNames( xkb_ptr, XkbVirtualModNamesMask, True ); + XkbFreeKeyboard( xkb_ptr, 0, True ); + } + if ( succeeded ) { + unsigned indx, shifted; + for ( indx = 0, shifted = 1; used_bits; ++indx, shifted <<= 1, used_bits >>= 1 ) { +#define S( a ) if ( xkb->a##Mask == shifted ) xkb->a##Idx = indx + S(alt); S(super); S(hyper); S(meta); S(numLock); +#undef S + } + } +#define S(a, n) xkb->a##Idx = xkb_keymap_mod_get_index(xkb->keymap, n); xkb->a##Mask = 1 << xkb->a##Idx; + S(control, XKB_MOD_NAME_CTRL); + S(shift, XKB_MOD_NAME_SHIFT); + S(capsLock, XKB_MOD_NAME_CAPS); + if ( !succeeded ) { + S(numLock, XKB_MOD_NAME_NUM); + S(alt, XKB_MOD_NAME_ALT); + S(super, XKB_MOD_NAME_LOGO); + } +#undef S + debug( "Modifier indices alt:%d super:%d hyper:%d meta:%d num>ock:%d\n", xkb->altIdx, xkb->superIdx, xkb->hyperIdx, xkb->metaIdx, xkb->numLockIdx ); +} + + #else #define xkb_glfw_load_keymap(keymap, map_str) keymap = xkb_keymap_new_from_string(xkb->context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); #define xkb_glfw_load_state(keymap, state) state = xkb_state_new(keymap); +static void +glfw_xkb_update_masks(_GLFWXKBData *xkb) { + /* Should find better solution under evdev or wayland */ + +#define S( a ) xkb->a##Idx = XKB_MOD_INVALID; xkb->a##Mask = 0 + S(hyper); S(meta); +#undef S +#define S(a, n) xkb->a##Idx = xkb_keymap_mod_get_index(xkb->keymap, n); xkb->a##Mask = 1 << xkb->a##Idx; + S(control, XKB_MOD_NAME_CTRL); + S(shift, XKB_MOD_NAME_SHIFT); + S(capsLock, XKB_MOD_NAME_CAPS); + S(numLock, XKB_MOD_NAME_NUM); + S(alt, XKB_MOD_NAME_ALT); + S(super, XKB_MOD_NAME_LOGO); +#undef S +} + #endif static void @@ -416,8 +496,8 @@ active_unknown_modifiers(_GLFWXKBData *xkb, struct xkb_state *state) { static void update_modifiers(_GLFWXKBData *xkb) { XKBStateGroup *group = &xkb->states; -#define S(attr, name) if (xkb_state_mod_index_is_active(group->state, xkb->attr##Idx, XKB_STATE_MODS_EFFECTIVE)) group->modifiers |= GLFW_MOD_##name - S(control, CONTROL); S(alt, ALT); S(shift, SHIFT); S(super, SUPER); S(capsLock, CAPS_LOCK); S(numLock, NUM_LOCK); +#define S(attr, name) if (xkb_state_mod_index_is_active(group->state, xkb->attr##Idx, XKB_STATE_MODS_EFFECTIVE) == 1) group->modifiers |= GLFW_MOD_##name + S(control, CONTROL); S(alt, ALT); S(shift, SHIFT); S(super, SUPER); S(hyper, HYPER); S(meta, META); S(capsLock, CAPS_LOCK); S(numLock, NUM_LOCK); #undef S xkb->states.activeUnknownModifiers = active_unknown_modifiers(xkb, xkb->states.state); @@ -441,18 +521,12 @@ glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str) { return false; } load_compose_tables(xkb); -#define S(a, n) xkb->a##Idx = xkb_keymap_mod_get_index(xkb->keymap, n); xkb->a##Mask = 1 << xkb->a##Idx; - S(control, XKB_MOD_NAME_CTRL); - S(alt, XKB_MOD_NAME_ALT); - S(shift, XKB_MOD_NAME_SHIFT); - S(super, XKB_MOD_NAME_LOGO); - S(capsLock, XKB_MOD_NAME_CAPS); - S(numLock, XKB_MOD_NAME_NUM); -#undef S + + glfw_xkb_update_masks(xkb); size_t capacity = arraysz(xkb->unknownModifiers), j = 0; for (xkb_mod_index_t i = 0; i < capacity; i++) xkb->unknownModifiers[i] = XKB_MOD_INVALID; for (xkb_mod_index_t i = 0; i < xkb_keymap_num_mods(xkb->keymap) && j < capacity - 1; i++) { - if (i != xkb->controlIdx && i != xkb->altIdx && i != xkb->shiftIdx && i != xkb->superIdx && i != xkb->capsLockIdx && i != xkb->numLockIdx) xkb->unknownModifiers[j++] = i; + if (i != xkb->controlIdx && i != xkb->altIdx && i != xkb->shiftIdx && i != xkb->superIdx && i != xkb->hyperIdx && i != xkb->metaIdx && i != xkb->capsLockIdx && i != xkb->numLockIdx) xkb->unknownModifiers[j++] = i; } xkb->states.modifiers = 0; xkb->states.activeUnknownModifiers = 0; @@ -524,6 +598,8 @@ format_mods(unsigned int mods) { if (mods & GLFW_MOD_ALT) pr("alt+"); if (mods & GLFW_MOD_SHIFT) pr("shift+"); if (mods & GLFW_MOD_SUPER) pr("super+"); + if (mods & GLFW_MOD_META) pr("meta+"); + if (mods & GLFW_MOD_HYPER) pr("hyper+"); if (mods & GLFW_MOD_CAPS_LOCK) pr("capslock+"); if (mods & GLFW_MOD_NUM_LOCK) pr("numlock+"); if (p == s) pr("none"); @@ -648,7 +724,7 @@ glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t if (consumed_unknown_mods) { debug("%s", format_xkb_mods(xkb, "consumed_unknown_mods", consumed_unknown_mods)); } else xkb_sym = clean_syms[0]; // xkb returns text even if alt and/or super are pressed - if ( ((GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER) & sg->modifiers) == 0) { + if ( ((GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER | GLFW_MOD_HYPER | GLFW_MOD_META) & sg->modifiers) == 0) { xkb_state_key_get_utf8(sg->state, code_for_sym, key_text, sizeof(key_text)); } text_type = "text"; diff --git a/glfw/xkb_glfw.h b/glfw/xkb_glfw.h index d2c086a3f..f3857ce50 100644 --- a/glfw/xkb_glfw.h +++ b/glfw/xkb_glfw.h @@ -54,12 +54,16 @@ typedef struct { xkb_mod_index_t altIdx; xkb_mod_index_t shiftIdx; xkb_mod_index_t superIdx; + xkb_mod_index_t hyperIdx; + xkb_mod_index_t metaIdx; xkb_mod_index_t capsLockIdx; xkb_mod_index_t numLockIdx; xkb_mod_mask_t controlMask; xkb_mod_mask_t altMask; xkb_mod_mask_t shiftMask; xkb_mod_mask_t superMask; + xkb_mod_mask_t hyperMask; + xkb_mod_mask_t metaMask; xkb_mod_mask_t capsLockMask; xkb_mod_mask_t numLockMask; xkb_mod_index_t unknownModifiers[256]; diff --git a/kittens/key_demo/main.py b/kittens/key_demo/main.py index 4158b68ab..90687b737 100644 --- a/kittens/key_demo/main.py +++ b/kittens/key_demo/main.py @@ -6,7 +6,7 @@ from typing import List from kitty.key_encoding import ( - ALT, CTRL, PRESS, RELEASE, REPEAT, SHIFT, SUPER, KeyEvent, + ALT, CTRL, PRESS, RELEASE, REPEAT, SHIFT, SUPER, HYPER, META, KeyEvent, encode_key_event ) @@ -32,7 +32,9 @@ def on_key_event(self, key_event: KeyEvent, in_bracketed_paste: bool = False) -> SHIFT: 'Shift', ALT: 'Alt', CTRL: 'Ctrl', - SUPER: 'Super'}.items(): + SUPER: 'Super', + HYPER: 'Hyper', + META: 'Meta'}.items(): if key_event.mods & m: lmods.append(name) mods = '+'.join(lmods) diff --git a/kitty/cli.py b/kitty/cli.py index a44d1799e..14e704209 100644 --- a/kitty/cli.py +++ b/kitty/cli.py @@ -761,10 +761,10 @@ def parse_args( def print_shortcut(key_sequence: Iterable[SingleKey], action: KeyAction) -> None: from .fast_data_types import ( - GLFW_MOD_ALT, GLFW_MOD_CONTROL, GLFW_MOD_SHIFT, GLFW_MOD_SUPER, + GLFW_MOD_ALT, GLFW_MOD_CONTROL, GLFW_MOD_SHIFT, GLFW_MOD_SUPER, GLFW_MOD_HYPER, GLFW_MOD_META, glfw_get_key_name ) - mmap = {'shift': GLFW_MOD_SHIFT, 'alt': GLFW_MOD_ALT, 'ctrl': GLFW_MOD_CONTROL, ('cmd' if is_macos else 'super'): GLFW_MOD_SUPER} + mmap = {'shift': GLFW_MOD_SHIFT, 'alt': GLFW_MOD_ALT, 'ctrl': GLFW_MOD_CONTROL, ('cmd' if is_macos else 'super'): GLFW_MOD_SUPER, 'hyper': GLFW_MOD_HYPER, 'meta': GLFW_MOD_META} keys = [] for key_spec in key_sequence: names = [] diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 5b69a9ecb..150fee33e 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -119,11 +119,13 @@ GLFW_FKEY_LEFT_CONTROL: int GLFW_FKEY_LEFT_ALT: int GLFW_FKEY_LEFT_SUPER: int GLFW_FKEY_LEFT_HYPER: int +GLFW_FKEY_LEFT_META: int GLFW_FKEY_RIGHT_SHIFT: int GLFW_FKEY_RIGHT_CONTROL: int GLFW_FKEY_RIGHT_ALT: int GLFW_FKEY_RIGHT_SUPER: int GLFW_FKEY_RIGHT_HYPER: int +GLFW_FKEY_RIGHT_META: int GLFW_FKEY_ISO_LEVEL3_SHIFT: int GLFW_FKEY_ISO_LEVEL5_SHIFT: int # end glfw functional keys @@ -131,6 +133,8 @@ GLFW_MOD_SHIFT: int GLFW_MOD_CONTROL: int GLFW_MOD_ALT: int GLFW_MOD_SUPER: int +GLFW_MOD_HYPER: int +GLFW_MOD_META: int GLFW_MOD_KITTY: int GLFW_MOUSE_BUTTON_1: int GLFW_MOUSE_BUTTON_2: int diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 101cde393..13e053bb6 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -184,14 +184,16 @@ typedef enum { GLFW_FKEY_LEFT_ALT = 0xe062u, GLFW_FKEY_LEFT_SUPER = 0xe063u, GLFW_FKEY_LEFT_HYPER = 0xe064u, - GLFW_FKEY_RIGHT_SHIFT = 0xe065u, - GLFW_FKEY_RIGHT_CONTROL = 0xe066u, - GLFW_FKEY_RIGHT_ALT = 0xe067u, - GLFW_FKEY_RIGHT_SUPER = 0xe068u, - GLFW_FKEY_RIGHT_HYPER = 0xe069u, - GLFW_FKEY_ISO_LEVEL3_SHIFT = 0xe06au, - GLFW_FKEY_ISO_LEVEL5_SHIFT = 0xe06bu, - GLFW_FKEY_LAST = 0xe06bu + GLFW_FKEY_LEFT_META = 0xe065u, + GLFW_FKEY_RIGHT_SHIFT = 0xe066u, + GLFW_FKEY_RIGHT_CONTROL = 0xe067u, + GLFW_FKEY_RIGHT_ALT = 0xe068u, + GLFW_FKEY_RIGHT_SUPER = 0xe069u, + GLFW_FKEY_RIGHT_HYPER = 0xe06au, + GLFW_FKEY_RIGHT_META = 0xe06bu, + GLFW_FKEY_ISO_LEVEL3_SHIFT = 0xe06cu, + GLFW_FKEY_ISO_LEVEL5_SHIFT = 0xe06du, + GLFW_FKEY_LAST = 0xe06du } GLFWFunctionKey; /* end functional key names */ @@ -210,33 +212,44 @@ typedef enum { * If this bit is set one or more Shift keys were held down. */ #define GLFW_MOD_SHIFT 0x0001 -/*! @brief If this bit is set one or more Control keys were held down. - * - * If this bit is set one or more Control keys were held down. - */ -#define GLFW_MOD_ALT 0x0002 /*! @brief If this bit is set one or more Alt keys were held down. * * If this bit is set one or more Alt keys were held down. */ -#define GLFW_MOD_CONTROL 0x0004 +#define GLFW_MOD_ALT 0x0002 +/*! @brief If this bit is set one or more Alt keys were held down. + * + * If this bit is set one or more Alt keys were held down. + */ +#define GLFW_MOD_CONTROL 0x0004 /*! @brief If this bit is set one or more Super keys were held down. * * If this bit is set one or more Super keys were held down. */ #define GLFW_MOD_SUPER 0x0008 +/*! @brief If this bit is set one or more Hyper keys were held down. + * + * If this bit is set one or more Hyper keys were held down. + */ +#define GLFW_MOD_HYPER 0x0010 +/*! @brief If this bit is set one or more Meta keys were held down. + * + * If this bit is set one or more Meta keys were held down. + */ +#define GLFW_MOD_META 0x0020 /*! @brief If this bit is set the Caps Lock key is enabled. * * If this bit is set the Caps Lock key is enabled and the @ref * GLFW_LOCK_KEY_MODS input mode is set. */ -#define GLFW_MOD_CAPS_LOCK 0x0010 +#define GLFW_MOD_CAPS_LOCK 0x0040 /*! @brief If this bit is set the Num Lock key is enabled. * * If this bit is set the Num Lock key is enabled and the @ref * GLFW_LOCK_KEY_MODS input mode is set. + * @note Ravi: Num lock is not supported in this branch */ -#define GLFW_MOD_NUM_LOCK 0x0020 +#define GLFW_MOD_NUM_LOCK 0x0080 /*! @} */ diff --git a/kitty/glfw.c b/kitty/glfw.c index 6e8b87a1f..32201fafb 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -249,6 +249,12 @@ key_to_modifier(uint32_t key) { case GLFW_FKEY_LEFT_SUPER: case GLFW_FKEY_RIGHT_SUPER: return GLFW_MOD_SUPER; + case GLFW_FKEY_LEFT_HYPER: + case GLFW_FKEY_RIGHT_HYPER: + return GLFW_MOD_HYPER; + case GLFW_FKEY_LEFT_META: + case GLFW_FKEY_RIGHT_META: + return GLFW_MOD_META; default: return -1; } @@ -998,11 +1004,13 @@ glfw_get_key_name(PyObject UNUSED *self, PyObject *args) { case GLFW_FKEY_LEFT_ALT: return PyUnicode_FromString("left_alt"); case GLFW_FKEY_LEFT_SUPER: return PyUnicode_FromString("left_super"); case GLFW_FKEY_LEFT_HYPER: return PyUnicode_FromString("left_hyper"); + case GLFW_FKEY_LEFT_META: return PyUnicode_FromString("left_meta"); case GLFW_FKEY_RIGHT_SHIFT: return PyUnicode_FromString("right_shift"); case GLFW_FKEY_RIGHT_CONTROL: return PyUnicode_FromString("right_control"); case GLFW_FKEY_RIGHT_ALT: return PyUnicode_FromString("right_alt"); case GLFW_FKEY_RIGHT_SUPER: return PyUnicode_FromString("right_super"); case GLFW_FKEY_RIGHT_HYPER: return PyUnicode_FromString("right_hyper"); + case GLFW_FKEY_RIGHT_META: return PyUnicode_FromString("right_meta"); case GLFW_FKEY_ISO_LEVEL3_SHIFT: return PyUnicode_FromString("iso_level3_shift"); case GLFW_FKEY_ISO_LEVEL5_SHIFT: return PyUnicode_FromString("iso_level5_shift"); /* end glfw functional key names */ @@ -1507,11 +1515,13 @@ init_glfw(PyObject *m) { ADDC(GLFW_FKEY_LEFT_ALT); ADDC(GLFW_FKEY_LEFT_SUPER); ADDC(GLFW_FKEY_LEFT_HYPER); + ADDC(GLFW_FKEY_LEFT_META); ADDC(GLFW_FKEY_RIGHT_SHIFT); ADDC(GLFW_FKEY_RIGHT_CONTROL); ADDC(GLFW_FKEY_RIGHT_ALT); ADDC(GLFW_FKEY_RIGHT_SUPER); ADDC(GLFW_FKEY_RIGHT_HYPER); + ADDC(GLFW_FKEY_RIGHT_META); ADDC(GLFW_FKEY_ISO_LEVEL3_SHIFT); ADDC(GLFW_FKEY_ISO_LEVEL5_SHIFT); /* end glfw functional keys */ @@ -1520,6 +1530,8 @@ init_glfw(PyObject *m) { ADDC(GLFW_MOD_CONTROL); ADDC(GLFW_MOD_ALT); ADDC(GLFW_MOD_SUPER); + ADDC(GLFW_MOD_HYPER); + ADDC(GLFW_MOD_META); ADDC(GLFW_MOD_KITTY); // --- Mouse ------------------------------------------------------------------- diff --git a/kitty/key_encoding.c b/kitty/key_encoding.c index b379d7fae..9e4450505 100644 --- a/kitty/key_encoding.c +++ b/kitty/key_encoding.c @@ -8,12 +8,12 @@ #include "keys.h" #include "charsets.h" -typedef enum { SHIFT=1, ALT=2, CTRL=4, SUPER=8 } ModifierMasks; +typedef enum { SHIFT=1, ALT=2, CTRL=4, SUPER=8, HYPER=16, META=32} ModifierMasks; typedef enum { PRESS = 0, REPEAT = 1, RELEASE = 2} KeyAction; typedef struct { uint32_t key, shifted_key, alternate_key; struct { - bool shift, alt, ctrl, super; + bool shift, alt, ctrl, super, hyper, meta; unsigned value; char encoded[4]; } mods; @@ -48,11 +48,13 @@ is_modifier_key(const uint32_t key) { static inline void convert_glfw_mods(int mods, KeyEvent *ev) { - ev->mods.alt = (mods & GLFW_MOD_ALT) > 0, ev->mods.ctrl = (mods & GLFW_MOD_CONTROL) > 0, ev->mods.shift = (mods & GLFW_MOD_SHIFT) > 0, ev->mods.super = (mods & GLFW_MOD_SUPER) > 0; + ev->mods.alt = (mods & GLFW_MOD_ALT) > 0, ev->mods.ctrl = (mods & GLFW_MOD_CONTROL) > 0, ev->mods.shift = (mods & GLFW_MOD_SHIFT) > 0, ev->mods.super = (mods & GLFW_MOD_SUPER) > 0, ev->mods.hyper = (mods & GLFW_MOD_HYPER) > 0, ev->mods.meta = (mods & GLFW_MOD_META) > 0; ev->mods.value = ev->mods.shift ? SHIFT : 0; if (ev->mods.alt) ev->mods.value |= ALT; if (ev->mods.ctrl) ev->mods.value |= CTRL; if (ev->mods.super) ev->mods.value |= SUPER; + if (ev->mods.hyper) ev->mods.value |= HYPER; + if (ev->mods.meta) ev->mods.value |= META; snprintf(ev->mods.encoded, sizeof(ev->mods.encoded), "%u", ev->mods.value + 1); } @@ -60,7 +62,7 @@ convert_glfw_mods(int mods, KeyEvent *ev) { static inline void init_encoding_data(EncodingData *ans, const KeyEvent *ev) { ans->add_actions = ev->report_all_event_types && ev->action != PRESS; - ans->has_mods = ev->mods.encoded[0] && ev->mods.encoded[0] != '1'; + ans->has_mods = ev->mods.encoded[0] && ( ev->mods.encoded[0] != '1' || ev->mods.encoded[1] ); ans->add_alternates = ev->report_alternate_key && ((ev->shifted_key > 0 && ev->mods.shift) || ev->alternate_key > 0); if (ans->add_alternates) { if (ev->mods.shift) ans->shifted_key = ev->shifted_key; ans->alternate_key = ev->alternate_key; } ans->action = ev->action; diff --git a/kitty/key_encoding.py b/kitty/key_encoding.py index 35d73ef0d..40a9eaff4 100644 --- a/kitty/key_encoding.py +++ b/kitty/key_encoding.py @@ -115,13 +115,15 @@ 57442: 'LEFT_ALT', 57443: 'LEFT_SUPER', 57444: 'LEFT_HYPER', - 57445: 'RIGHT_SHIFT', - 57446: 'RIGHT_CONTROL', - 57447: 'RIGHT_ALT', - 57448: 'RIGHT_SUPER', - 57449: 'RIGHT_HYPER', - 57450: 'ISO_LEVEL3_SHIFT', - 57451: 'ISO_LEVEL5_SHIFT'} + 57445: 'LEFT_META', + 57446: 'RIGHT_SHIFT', + 57447: 'RIGHT_CONTROL', + 57448: 'RIGHT_ALT', + 57449: 'RIGHT_SUPER', + 57450: 'RIGHT_HYPER', + 57451: 'RIGHT_META', + 57452: 'ISO_LEVEL3_SHIFT', + 57453: 'ISO_LEVEL5_SHIFT'} csi_number_to_functional_number_map = { 2: 57348, 3: 57349, @@ -190,7 +192,7 @@ def parse_shortcut(spec: str) -> ParsedShortcut: key_name = character_key_name_aliases.get(key_name.upper(), key_name) mod_val = 0 if len(parts) > 1: - mods = tuple(config_mod_map.get(x.upper(), SUPER << 8) for x in parts[:-1]) + mods = tuple(config_mod_map.get(x.upper(), META << 8) for x in parts[:-1]) for x in mods: mod_val |= x return ParsedShortcut(mod_val, key_name) @@ -207,6 +209,8 @@ class KeyEvent(NamedTuple): alt: bool = False ctrl: bool = False super: bool = False + hyper: bool = False + meta: bool = False def matches(self, spec: Union[str, ParsedShortcut], types: int = EventType.PRESS | EventType.REPEAT) -> bool: if not self.type & types: @@ -236,6 +240,10 @@ def as_window_system_event(self) -> WindowSystemKeyEvent: mods |= defines.GLFW_MOD_CONTROL if self.super: mods |= defines.GLFW_MOD_SUPER + if self.hyper: + mods |= defines.GLFW_MOD_HYPER + if self.meta: + mods |= defines.GLFW_MOD_META fnm = get_name_to_functional_number_map() @@ -248,7 +256,7 @@ def as_num(key: str) -> int: action=action, text=self.text) -SHIFT, ALT, CTRL, SUPER = 1, 2, 4, 8 +SHIFT, ALT, CTRL, SUPER, HYPER, META = 1, 2, 4, 8, 16, 32 enter_key = KeyEvent(key='ENTER') backspace_key = KeyEvent(key='BACKSPACE') config_mod_map = { @@ -260,7 +268,9 @@ def as_num(key: str) -> int: 'CMD': SUPER, 'SUPER': SUPER, 'CTRL': CTRL, - 'CONTROL': CTRL + 'CONTROL': CTRL, + 'HYPER': HYPER, + 'META': META, } @@ -294,6 +304,7 @@ def key_name(num: int) -> str: return KeyEvent( mods=mods, shift=bool(mods & SHIFT), alt=bool(mods & ALT), ctrl=bool(mods & CTRL), super=bool(mods & SUPER), + hyper=bool(mods & HYPER), meta=bool(mods & META), key=key_name(keynum), shifted_key=key_name(first_section[1] if len(first_section) > 1 else 0), alternate_key=key_name(first_section[2] if len(first_section) > 2 else 0), @@ -346,6 +357,10 @@ def encode_key_event(key_event: KeyEvent) -> str: m |= 4 if key_event.super: m |= 8 + if key_event.hyper: + m |= 16 + if key_event.meta: + m |= 32 if action > 1 or m: ans += f';{m+1}' if action > 1: diff --git a/kitty_tests/keys.py b/kitty_tests/keys.py index 6a6592962..4527d1d57 100644 --- a/kitty_tests/keys.py +++ b/kitty_tests/keys.py @@ -17,7 +17,7 @@ class TestKeys(BaseTest): def test_encode_key_event(self): enc = defines.encode_key_for_tty ae = self.assertEqual - shift, alt, ctrl, super = defines.GLFW_MOD_SHIFT, defines.GLFW_MOD_ALT, defines.GLFW_MOD_CONTROL, defines.GLFW_MOD_SUPER # noqa + shift, alt, ctrl, super, hyper, meta = defines.GLFW_MOD_SHIFT, defines.GLFW_MOD_ALT, defines.GLFW_MOD_CONTROL, defines.GLFW_MOD_SUPER, defines.GLFW_MOD_HYPER, defines.GLFW_MOD_META # noqa press, repeat, release = defines.GLFW_PRESS, defines.GLFW_REPEAT, defines.GLFW_RELEASE # noqa def csi(mods=0, num=1, action=1, shifted_key=0, alternate_key=0, text=None, trailer='u'): @@ -44,6 +44,10 @@ def csi(mods=0, num=1, action=1, shifted_key=0, alternate_key=0, text=None, trai m |= 4 if mods & super: m |= 8 + if mods & hyper: + m |= 16 + if mods & meta: + m |= 32 if action > 1 or m: ans += f';{m+1}' if action > 1: @@ -461,7 +465,7 @@ def mkp(name, *a, **kw): ae(eq(ord('a'), mods=shift, text='AB'), csi(shift, num='a', text='AB')) # test roundtripping via KeyEvent - for mods in range(16): + for mods in range(64): for action in EventType: for key in ('ENTER', 'a', 'TAB', 'F3'): for shifted_key in ('', 'X'): @@ -470,6 +474,7 @@ def mkp(name, *a, **kw): ev = KeyEvent( type=action, mods=mods, key=key, text=text, shifted_key=shifted_key, alternate_key=alternate_key, shift=bool(mods & 1), alt=bool(mods & 2), ctrl=bool(mods & 4), super=bool(mods & 8) + , hyper=bool(mods & 16), meta=bool(mods & 32) ) ec = encode_key_event(ev) q = decode_key_event(ec[2:-1], ec[-1]) From fdfba4ea04ccde6798968ee88034ec1bc644ab69 Mon Sep 17 00:00:00 2001 From: Ravi R Kiran Date: Tue, 30 Mar 2021 14:57:41 -0500 Subject: [PATCH 2/3] Fix pyflakes failures --- kitty/cli.py | 3 ++- kitty_tests/keys.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/kitty/cli.py b/kitty/cli.py index 14e704209..91caf1a04 100644 --- a/kitty/cli.py +++ b/kitty/cli.py @@ -764,7 +764,8 @@ def print_shortcut(key_sequence: Iterable[SingleKey], action: KeyAction) -> None GLFW_MOD_ALT, GLFW_MOD_CONTROL, GLFW_MOD_SHIFT, GLFW_MOD_SUPER, GLFW_MOD_HYPER, GLFW_MOD_META, glfw_get_key_name ) - mmap = {'shift': GLFW_MOD_SHIFT, 'alt': GLFW_MOD_ALT, 'ctrl': GLFW_MOD_CONTROL, ('cmd' if is_macos else 'super'): GLFW_MOD_SUPER, 'hyper': GLFW_MOD_HYPER, 'meta': GLFW_MOD_META} + mmap = {'shift': GLFW_MOD_SHIFT, 'alt': GLFW_MOD_ALT, 'ctrl': GLFW_MOD_CONTROL, ('cmd' if is_macos else 'super'): GLFW_MOD_SUPER, + 'hyper': GLFW_MOD_HYPER, 'meta': GLFW_MOD_META} keys = [] for key_spec in key_sequence: names = [] diff --git a/kitty_tests/keys.py b/kitty_tests/keys.py index 4527d1d57..190e7949c 100644 --- a/kitty_tests/keys.py +++ b/kitty_tests/keys.py @@ -473,8 +473,8 @@ def mkp(name, *a, **kw): for text in ('', 'moose'): ev = KeyEvent( type=action, mods=mods, key=key, text=text, shifted_key=shifted_key, alternate_key=alternate_key, - shift=bool(mods & 1), alt=bool(mods & 2), ctrl=bool(mods & 4), super=bool(mods & 8) - , hyper=bool(mods & 16), meta=bool(mods & 32) + shift=bool(mods & 1), alt=bool(mods & 2), ctrl=bool(mods & 4), super=bool(mods & 8), + hyper=bool(mods & 16), meta=bool(mods & 32) ) ec = encode_key_event(ev) q = decode_key_event(ec[2:-1], ec[-1]) From b074533b29e9cbe7dc8cfe62350c1f6ee03fc266 Mon Sep 17 00:00:00 2001 From: Ravi R Kiran Date: Wed, 31 Mar 2021 08:54:10 -0500 Subject: [PATCH 3/3] Fix regression --- glfw/ibus_glfw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/glfw/ibus_glfw.c b/glfw/ibus_glfw.c index 8b65b0a96..ead564b8f 100644 --- a/glfw/ibus_glfw.c +++ b/glfw/ibus_glfw.c @@ -388,6 +388,7 @@ ibus_key_state(unsigned int glfw_modifiers, int action) { M(CONTROL, IBUS_CONTROL_MASK); M(ALT, IBUS_MOD1_MASK); M(NUM_LOCK, IBUS_MOD2_MASK); + M(SUPER, IBUS_MOD4_MASK); /* To do: figure out how to get super/hyper/meta */ #undef M return ans;