From c1d2deb6492fbd900392f4ebd47572ca4903d0fe Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 2 Feb 2026 23:52:48 -0500 Subject: [PATCH] vt: add fallback to plain map for modifier-aware key types When a key is pressed with modifiers (Shift, Ctrl, Alt, etc.) and the modifier-specific keymap has no binding (K_HOLE) or doesn't exist, fall back to the plain keymap if the plain entry is a modifier-aware type (KT_CUR or KT_CSI). This allows arrow keys and CSI navigation keys to automatically handle all modifier combinations with just a single plain map entry. The key handlers (k_cur and k_csi) read the modifier state at runtime and encode it into the output sequence. For example, with just: keycode 103 = Up keycode 104 = Csi_Home All these combinations now work automatically: Up -> ESC [ A Shift+Up -> ESC [ 1 ; 2 A Ctrl+Up -> ESC [ 1 ; 5 A Home -> ESC [ 1 ~ Shift+Home -> ESC [ 1 ; 2 ~ Ctrl+Home -> ESC [ 1 ; 5 ~ Previously, each modifier combination required an explicit keymap entry, which was tedious and consumed keymap slots. Explicit modifier bindings still take precedence - the fallback only triggers when the modifier-specific entry is empty. Signed-off-by: Nicolas Pitre Link: https://patch.msgid.link/20260203045457.1049793-4-nico@fluxnic.net Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/keyboard.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 44fd67eb723a..dfdea0842149 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1498,6 +1498,21 @@ static void kbd_keycode(unsigned int keycode, int down, bool hw_raw) param.ledstate = kbd->ledflagstate; key_map = key_maps[shift_final]; + /* + * Fall back to the plain map if modifiers are active, the modifier- + * specific map is missing or has no entry, and the plain map has a + * modifier-aware key type (KT_CUR or KT_CSI). These handlers encode + * the modifier state into the emitted escape sequence. + */ + if (shift_final && keycode < NR_KEYS && + (!key_map || key_map[keycode] == K_HOLE) && key_maps[0]) { + unsigned short plain = key_maps[0][keycode]; + unsigned char type = KTYP(plain); + + if (type >= 0xf0 && (type - 0xf0 == KT_CUR || type - 0xf0 == KT_CSI)) + key_map = key_maps[0]; + } + rc = atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, ¶m); if (rc == NOTIFY_STOP || !key_map) { -- 2.47.3