diff --git a/docs/keyboard-protocol.rst b/docs/keyboard-protocol.rst index b84faf8a8..e65426cdd 100644 --- a/docs/keyboard-protocol.rst +++ b/docs/keyboard-protocol.rst @@ -72,7 +72,8 @@ The shifted key is simply the upper-case version of ``unicode-codepoint``, or more technically, the shifted version. So `a` becomes `A` and so on, based on the current keyboard layout. This is needed to be able to match against a shortcut such as :kbd:`ctrl+plus` which depending on the type of keyboard could -be either :kbd:`ctrl+shift+equal` or :kbd:`ctrl+plus`. +be either :kbd:`ctrl+shift+equal` or :kbd:`ctrl+plus`. Note that the shifted +key must be present only if shift is also present in the modifiers. The *base layout key* is the key corresponding to the physical key in the standard PC-101 key layout. So for example, if the user is using a Cyrillic diff --git a/kitty/key_encoding.c b/kitty/key_encoding.c index 5a735ee59..82d28a111 100644 --- a/kitty/key_encoding.c +++ b/kitty/key_encoding.c @@ -51,8 +51,8 @@ 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->add_alternates = ev->report_alternate_key && (ev->shifted_key > 0 || ev->alternate_key > 0); - if (ans->add_alternates) { ans->shifted_key = ev->shifted_key; ans->alternate_key = ev->alternate_key; } + 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; ans->key = ev->key; memcpy(ans->encoded_mods, ev->mods.encoded, sizeof(ans->encoded_mods)); diff --git a/kitty/keys.py b/kitty/keys.py index e5e3fc6e4..763b04a8e 100644 --- a/kitty/keys.py +++ b/kitty/keys.py @@ -10,7 +10,8 @@ from .typing import ScreenType def keyboard_mode_name(screen: ScreenType) -> str: - if screen.current_key_encoding_flags() & 0b1000: + flags = screen.current_key_encoding_flags() + if flags: return 'kitty' return 'application' if screen.cursor_key_mode else 'normal' diff --git a/kitty_tests/keys.py b/kitty_tests/keys.py index a65e221c6..f2271c08e 100644 --- a/kitty_tests/keys.py +++ b/kitty_tests/keys.py @@ -15,12 +15,20 @@ class TestKeys(BaseTest): shift, alt, ctrl, super = defines.GLFW_MOD_SHIFT, defines.GLFW_MOD_ALT, defines.GLFW_MOD_CONTROL, defines.GLFW_MOD_SUPER # noqa press, repeat, release = defines.GLFW_PRESS, defines.GLFW_REPEAT, defines.GLFW_RELEASE # noqa - def csi(mods=0, num=1, action=1, trailer='u'): + def csi(mods=0, num=1, action=1, shifted_key=0, alternate_key=0, trailer='u'): ans = '\033[' if isinstance(num, str): num = ord(num) - if num != 1 or mods: + if num != 1 or mods or shifted_key or alternate_key: ans += f'{num}' + if shifted_key or alternate_key: + if isinstance(shifted_key, str): + shifted_key = ord(shifted_key) + ans += ':' + (f'{shifted_key}' if shifted_key else '') + if alternate_key: + if isinstance(alternate_key, str): + alternate_key = ord(alternate_key) + ans += f':{alternate_key}' if mods or action > 1: m = 0 if mods & shift: @@ -403,6 +411,14 @@ class TestKeys(BaseTest): ae(tq(ord('a'), action=defines.GLFW_RELEASE), csi(num='a', action=3)) ae(tq(ord('a'), action=defines.GLFW_RELEASE, mods=shift), csi(shift, num='a', action=3)) + # test alternate key reporting + aq = partial(enc, key_encoding_flags=0b100) + ae(aq(ord('a')), 'a') + ae(aq(ord('a'), shifted_key=ord('A')), 'a') + ae(aq(ord('a'), mods=shift, shifted_key=ord('A')), csi(shift, 'a', shifted_key='A')) + ae(aq(ord('a'), alternate_key=ord('A')), csi(num='a', alternate_key='A')) + ae(aq(ord('a'), mods=shift, shifted_key=ord('A'), alternate_key=ord('b')), csi(shift, 'a', shifted_key='A', alternate_key='b')) + def test_encode_mouse_event(self): NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOCOL, URXVT_PROTOCOL = range(4) L, M, R = 1, 2, 3