keymap: handle shift+tab combos correctly, after consuming modifiers

Shift+Tab is an odd bird in XKB; it produces a shifted variant of tab,
ISO_Left_Tab, with Shift being a consumed modifier.

From a terminal perspective, Tab and ISO_Left_Tab are the same key,
with Shift+Tab generating ‘CSI Z’, and all other combos generating a
‘CSI 27;mods;9~’ escape.

Before, when we didn’t filter out consumed modifiers, we could simply
re-use the keymap for Tab when translating ISO_Left_Tab.

This is no longer possible, since shift has been filtered out. As a
result, Shift+Tab no longer generated ‘CSI Z’, but ‘\t’. I.e as if
shift wasn’t being pressed.

This patch adds a separate keymap table for ISO_Left_Tab. It’s MOD_ANY
entry corresponds to Shift+Tab, and emits ‘CSI Z’. All its other
entries *exclude* shift (since it has been consumed), *but*, the
encoded modifier (in the escape sequences) *include* shift.
This commit is contained in:
Daniel Eklöf 2021-02-28 11:50:05 +01:00
parent 6cd72bdee6
commit e4f164d958
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 21 additions and 2 deletions

View file

@ -770,8 +770,8 @@ keymap_data_for_sym(xkb_keysym_t sym, size_t *count)
switch (sym) {
case XKB_KEY_Escape: *count = ALEN(key_escape); return key_escape;
case XKB_KEY_Return: *count = ALEN(key_return); return key_return;
case XKB_KEY_Tab: /* FALLTHROUGH */
case XKB_KEY_ISO_Left_Tab: *count = ALEN(key_tab); return key_tab;
case XKB_KEY_ISO_Left_Tab: *count = ALEN(key_iso_left_tab); return key_iso_left_tab;
case XKB_KEY_Tab: *count = ALEN(key_tab); return key_tab;
case XKB_KEY_BackSpace: *count = ALEN(key_backspace); return key_backspace;
case XKB_KEY_Up: *count = ALEN(key_up); return key_up;
case XKB_KEY_Down: *count = ALEN(key_down); return key_down;

View file

@ -78,6 +78,25 @@ static const struct key_data key_tab[] = {
{MOD_ANY, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\t"},
};
/*
* Shift+Tab produces ISO_Left_Tab
*
* However, all combos (except Shift+Tab) acts as if we pressed
* mods+shift+tab. XKB consumes shift for us, hence MOD_SHIFT isnt
* present in any of the entries below. However, the entries still map
* to sequences that indicate shift has been pressed.
*/
static const struct key_data key_iso_left_tab[] = {
{MOD_ALT, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[27;4;9~"},
{MOD_CTRL, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[27;6;9~"},
{MOD_ALT | MOD_CTRL, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[27;8;9~"},
{MOD_META, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[27;10;9~"},
{MOD_META | MOD_ALT, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[27;12;9~"},
{MOD_META | MOD_CTRL, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[27;14;9~"},
{MOD_META | MOD_ALT | MOD_CTRL, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[27;16;9~"},
{MOD_ANY, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[Z"},
};
static const struct key_data key_backspace[] = {
{MOD_SHIFT, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\x7f"},
{MOD_ALT, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033\x7f"},