From 9f3dba683e0b308de9d41982089342f532634528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 17 Nov 2021 17:51:41 +0100 Subject: [PATCH] input: refactor: new function: legacy_kbd_protocol() This breaks out all handling of key escapes to-be-sent to the client, to a separate function, legacy_kbd_protocol(). That is, the key press/release handler first handles key generic handling, such as starting and stopping the repeat timer. Then it checks for foot keyboard bindings. If not bindings match, we need to pass the keyboard event to the client. This code has now been separated out into a new function. --- input.c | 212 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 107 insertions(+), 105 deletions(-) diff --git a/input.c b/input.c index 02035909..f5f6d754 100644 --- a/input.c +++ b/input.c @@ -983,6 +983,109 @@ get_current_modifiers(const struct seat *seat, } } +static void +legacy_kbd_protocol(struct seat *seat, struct terminal *term, xkb_keysym_t sym, + enum modifier mods, size_t count, + const uint8_t utf8[static count], uint32_t state) +{ + const struct key_data *keymap; + if (sym == XKB_KEY_Escape && mods == MOD_NONE && term->modify_escape_key) { + static const struct key_data esc = {.seq = "\033[27;1;27~"}; + keymap = &esc; + } else + keymap = keymap_lookup(term, sym, mods); + + if (keymap != NULL) { + term_to_slave(term, keymap->seq, strlen(keymap->seq)); + return; + } + + if (count == 0) + return; + +#define is_control_key(x) ((x) >= 0x40 && (x) <= 0x7f) +#define IS_CTRL(x) ((x) < 0x20 || ((x) >= 0x7f && (x) <= 0x9f)) + + LOG_DBG("term->modify_other_keys=%d, count=%d, is_ctrl=%d (utf8=0x%02x), sym=%d", + term->modify_other_keys_2, count, IS_CTRL(utf8[0]), utf8[0], sym); + + bool ctrl_is_in_effect = (mods & MOD_CTRL) != 0; + bool ctrl_seq = is_control_key(sym) || (count == 1 && IS_CTRL(utf8[0])); + + if (mods != MOD_NONE && (term->modify_other_keys_2 || + (ctrl_is_in_effect && !ctrl_seq))) + { + static const int mod_param_map[32] = { + [MOD_SHIFT] = 2, + [MOD_ALT] = 3, + [MOD_SHIFT | MOD_ALT] = 4, + [MOD_CTRL] = 5, + [MOD_SHIFT | MOD_CTRL] = 6, + [MOD_ALT | MOD_CTRL] = 7, + [MOD_SHIFT | MOD_ALT | MOD_CTRL] = 8, + [MOD_META] = 9, + [MOD_META | MOD_SHIFT] = 10, + [MOD_META | MOD_ALT] = 11, + [MOD_META | MOD_SHIFT | MOD_ALT] = 12, + [MOD_META | MOD_CTRL] = 13, + [MOD_META | MOD_SHIFT | MOD_CTRL] = 14, + [MOD_META | MOD_ALT | MOD_CTRL] = 15, + [MOD_META | MOD_SHIFT | MOD_ALT | MOD_CTRL] = 16, + }; + + xassert(mods < sizeof(mod_param_map) / sizeof(mod_param_map[0])); + int modify_param = mod_param_map[mods]; + xassert(modify_param != 0); + + char reply[1024]; + size_t n = xsnprintf(reply, sizeof(reply), "\x1b[27;%d;%d~", modify_param, sym); + term_to_slave(term, reply, n); + } + + else if (mods & MOD_ALT) { + /* + * When the alt modifier is pressed, we do one out of three things: + * + * 1. we prefix the output bytes with ESC + * 2. we set the 8:th bit in the output byte + * 3. we ignore the alt modifier + * + * #1 is configured with \E[?1036, and is on by default + * + * If #1 has been disabled, we use #2, *if* it's a single + * byte we're emitting. Since this is an UTF-8 terminal, + * we then UTF8-encode the 8-bit character. #2 is + * configured with \E[?1034, and is on by default. + * + * Lastly, if both #1 and #2 have been disabled, the alt + * modifier is ignored. + */ + if (term->meta.esc_prefix) { + term_to_slave(term, "\x1b", 1); + term_to_slave(term, utf8, count); + } + + else if (term->meta.eight_bit && count == 1) { + const wchar_t wc = 0x80 | utf8[0]; + + char wc_as_utf8[8]; + mbstate_t ps = {0}; + size_t chars = wcrtomb(wc_as_utf8, wc, &ps); + + if (chars != (size_t)-1) + term_to_slave(term, wc_as_utf8, chars); + else + term_to_slave(term, wc_as_utf8, count); + } + + else { + /* Alt ignored */ + term_to_slave(term, utf8, count); + } + } else + term_to_slave(term, utf8, count); +} + static void key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, uint32_t key, uint32_t state) @@ -995,7 +1098,6 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, return; } - if (state == XKB_KEY_UP) { stop_repeater(seat, key); return; @@ -1120,24 +1222,6 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, keymap_mods |= seat->kbd.ctrl ? MOD_CTRL : MOD_NONE; keymap_mods |= seat->kbd.meta ? MOD_META : MOD_NONE; - const struct key_data *keymap; - if (sym == XKB_KEY_Escape && keymap_mods == MOD_NONE && term->modify_escape_key) { - static const struct key_data esc = {.seq = "\033[27;1;27~"}; - keymap = &esc; - } else - keymap = keymap_lookup(term, sym, keymap_mods); - - if (keymap != NULL) { - term_to_slave(term, keymap->seq, strlen(keymap->seq)); - - term_reset_view(term); - selection_cancel(term); - goto maybe_repeat; - } - - if (compose_status == XKB_COMPOSE_CANCELLED) - goto maybe_repeat; - /* * Compose, and maybe emit "normal" character */ @@ -1145,13 +1229,13 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, xassert(seat->kbd.xkb_compose_state != NULL || compose_status != XKB_COMPOSE_COMPOSED); + if (compose_status == XKB_COMPOSE_CANCELLED) + goto maybe_repeat; + int count = compose_status == XKB_COMPOSE_COMPOSED ? xkb_compose_state_get_utf8(seat->kbd.xkb_compose_state, NULL, 0) : xkb_state_key_get_utf8(seat->kbd.xkb_state, key, NULL, 0); - if (count <= 0) - goto maybe_repeat; - /* Buffer for translated key. Use a static buffer in most cases, * and use a malloc:ed buffer when necessary */ uint8_t buf[32]; @@ -1166,89 +1250,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, if (seat->kbd.xkb_compose_state != NULL) xkb_compose_state_reset(seat->kbd.xkb_compose_state); -#define is_control_key(x) ((x) >= 0x40 && (x) <= 0x7f) -#define IS_CTRL(x) ((x) < 0x20 || ((x) >= 0x7f && (x) <= 0x9f)) - - LOG_DBG("term->modify_other_keys=%d, count=%d, is_ctrl=%d (utf8=0x%02x), sym=%d", - term->modify_other_keys_2, count, IS_CTRL(utf8[0]), utf8[0], sym); - - bool ctrl_is_in_effect = (keymap_mods & MOD_CTRL) != 0; - bool ctrl_seq = is_control_key(sym) || (count == 1 && IS_CTRL(utf8[0])); - - if (keymap_mods != MOD_NONE && (term->modify_other_keys_2 || - (ctrl_is_in_effect && !ctrl_seq))) - { - static const int mod_param_map[32] = { - [MOD_SHIFT] = 2, - [MOD_ALT] = 3, - [MOD_SHIFT | MOD_ALT] = 4, - [MOD_CTRL] = 5, - [MOD_SHIFT | MOD_CTRL] = 6, - [MOD_ALT | MOD_CTRL] = 7, - [MOD_SHIFT | MOD_ALT | MOD_CTRL] = 8, - [MOD_META] = 9, - [MOD_META | MOD_SHIFT] = 10, - [MOD_META | MOD_ALT] = 11, - [MOD_META | MOD_SHIFT | MOD_ALT] = 12, - [MOD_META | MOD_CTRL] = 13, - [MOD_META | MOD_SHIFT | MOD_CTRL] = 14, - [MOD_META | MOD_ALT | MOD_CTRL] = 15, - [MOD_META | MOD_SHIFT | MOD_ALT | MOD_CTRL] = 16, - }; - - xassert(keymap_mods < sizeof(mod_param_map) / sizeof(mod_param_map[0])); - int modify_param = mod_param_map[keymap_mods]; - xassert(modify_param != 0); - - char reply[1024]; - size_t n = xsnprintf(reply, sizeof(reply), "\x1b[27;%d;%d~", modify_param, sym); - term_to_slave(term, reply, n); - } - - else { - if (mods & (1 << seat->kbd.mod_alt)) { - /* - * When the alt modifier is pressed, we do one out of three things: - * - * 1. we prefix the output bytes with ESC - * 2. we set the 8:th bit in the output byte - * 3. we ignore the alt modifier - * - * #1 is configured with \E[?1036, and is on by default - * - * If #1 has been disabled, we use #2, *if* it's a single - * byte we're emitting. Since this is an UTF-8 terminal, - * we then UTF8-encode the 8-bit character. #2 is - * configured with \E[?1034, and is on by default. - * - * Lastly, if both #1 and #2 have been disabled, the alt - * modifier is ignored. - */ - if (term->meta.esc_prefix) { - term_to_slave(term, "\x1b", 1); - term_to_slave(term, utf8, count); - } - - else if (term->meta.eight_bit && count == 1) { - const wchar_t wc = 0x80 | utf8[0]; - - char utf8[8]; - mbstate_t ps = {0}; - size_t chars = wcrtomb(utf8, wc, &ps); - - if (chars != (size_t)-1) - term_to_slave(term, utf8, chars); - else - term_to_slave(term, utf8, count); - } - - else { - /* Alt ignored */ - term_to_slave(term, utf8, count); - } - } else - term_to_slave(term, utf8, count); - } + legacy_kbd_protocol(seat, term, sym, keymap_mods, count, utf8, state); if (utf8 != buf) free(utf8);