diff --git a/CHANGELOG.md b/CHANGELOG.md index 859cf1e6..d0a7bc13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -130,6 +130,9 @@ * Foot process(es) sometimes remaining, using 100% CPU, when closing multiple foot windows at the same time (https://codeberg.org/dnkl/foot/issues/542). +* Regression where `+shift+tab` always produced `\E[Z` instead of + the correct `\E[27;;9~` sequence + (https://codeberg.org/dnkl/foot/issues/547). ### Security diff --git a/input.c b/input.c index 320b1679..96c41a15 100644 --- a/input.c +++ b/input.c @@ -852,8 +852,7 @@ keymap_data_for_sym(xkb_keysym_t sym, size_t *count) } static const struct key_data * -keymap_lookup(struct seat *seat, struct terminal *term, - xkb_keysym_t sym, enum modifier mods) +keymap_lookup(struct terminal *term, xkb_keysym_t sym, enum modifier mods) { size_t count; const struct key_data *info = keymap_data_for_sym(sym, &count); @@ -885,6 +884,18 @@ keymap_lookup(struct seat *seat, struct terminal *term, return NULL; } +UNITTEST +{ + struct terminal term = { + .num_lock_modifier = false, + .keypad_keys_mode = KEYPAD_NUMERICAL, + .cursor_keys_mode = CURSOR_KEYS_NORMAL, + }; + + const struct key_data *info = keymap_lookup(&term, XKB_KEY_ISO_Left_Tab, MOD_SHIFT | MOD_CTRL); + xassert(strcmp(info->seq, "\033[27;6;9~") == 0); +} + static void key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, uint32_t key, uint32_t state) @@ -1036,7 +1047,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, static const struct key_data esc = {.seq = "\033[27;1;27~"}; keymap = &esc; } else - keymap = keymap_lookup(seat, term, sym, keymap_mods); + keymap = keymap_lookup(term, sym, keymap_mods); if (keymap != NULL) { term_to_slave(term, keymap->seq, strlen(keymap->seq)); diff --git a/keymap.h b/keymap.h index f1b4a0ea..f98647c3 100644 --- a/keymap.h +++ b/keymap.h @@ -82,19 +82,17 @@ static const struct key_data key_tab[] = { * 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 isn’t - * present in any of the entries below. However, the entries still map - * to sequences that indicate shift has been pressed. + * mods+shift+tab. */ 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"}, + {MOD_SHIFT | MOD_ALT, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[27;4;9~"}, + {MOD_SHIFT | MOD_CTRL, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[27;6;9~"}, + {MOD_SHIFT | MOD_ALT | MOD_CTRL, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[27;8;9~"}, + {MOD_SHIFT | MOD_META, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[27;10;9~"}, + {MOD_SHIFT | MOD_META | MOD_ALT, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[27;12;9~"}, + {MOD_SHIFT | MOD_META | MOD_CTRL, CURSOR_KEYS_DONTCARE, KEYPAD_DONTCARE, "\033[27;14;9~"}, + {MOD_SHIFT | 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[] = { diff --git a/macros.h b/macros.h index 52c24e0e..7cfe777e 100644 --- a/macros.h +++ b/macros.h @@ -1,5 +1,7 @@ #pragma once +#define PASTE(a, b) a##b +#define XPASTE(a, b) PASTE(a, b) #define DO_PRAGMA(x) _Pragma(#x) #define VERCMP(x, y, cx, cy) ((cx > x) || ((cx == x) && (cy >= y))) @@ -68,6 +70,7 @@ #if GNUC_AT_LEAST(3, 0) || HAS_ATTRIBUTE(constructor) #define CONSTRUCTOR __attribute__((__constructor__)) + #define HAVE_ATTR_CONSTRUCTOR 1 #else #define CONSTRUCTOR #endif @@ -175,6 +178,19 @@ #define UNROLL_LOOP(n) #endif +#ifdef __COUNTER__ + // Supported by GCC 4.3+ and Clang + #define COUNTER_ __COUNTER__ +#else + #define COUNTER_ __LINE__ +#endif + +#if defined(_DEBUG) && defined(HAVE_ATTR_CONSTRUCTOR) + #define UNITTEST static void CONSTRUCTOR XPASTE(unittest_, COUNTER_)(void) +#else + #define UNITTEST static void UNUSED XPASTE(unittest_, COUNTER_)(void) +#endif + #ifdef __clang__ #define IGNORE_WARNING(wflag) \ DO_PRAGMA(clang diagnostic push) \