From: Nicolas Pitre Date: Tue, 3 Feb 2026 04:52:46 +0000 (-0500) Subject: vt: add modifier support to cursor keys X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4af70f151671da6acd7a1d7bae1469c576673d2d;p=thirdparty%2Fkernel%2Flinux.git vt: add modifier support to cursor keys Generate xterm-style CSI sequences with modifier parameters for arrow keys when Shift, Alt, or Ctrl are held. For example, Shift+Up produces ESC [ 1 ; 2 A instead of plain ESC [ A. The modifier encoding follows the standard xterm convention: mod = 1 + (shift ? 1 : 0) + (alt ? 2 : 0) + (ctrl ? 4 : 0) When no modifiers are pressed, the original behavior is preserved. Explicit keymap bindings for modified cursor keys (e.g., "shift keycode 103 = Find") take precedence over this automatic modifier encoding. Signed-off-by: Nicolas Pitre Link: https://patch.msgid.link/20260203045457.1049793-2-nico@fluxnic.net Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 13bc048f45e86..cb907a3b9d3d9 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -765,14 +765,39 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag) pr_err("k_fn called with value=%d\n", value); } +/* + * Compute xterm-style modifier parameter for CSI sequences. + * Returns 1 + (shift ? 1 : 0) + (alt ? 2 : 0) + (ctrl ? 4 : 0) + */ +static int csi_modifier_param(void) +{ + int mod = 1; + + if (shift_state & (BIT(KG_SHIFT) | BIT(KG_SHIFTL) | BIT(KG_SHIFTR))) + mod += 1; + if (shift_state & (BIT(KG_ALT) | BIT(KG_ALTGR))) + mod += 2; + if (shift_state & (BIT(KG_CTRL) | BIT(KG_CTRLL) | BIT(KG_CTRLR))) + mod += 4; + return mod; +} + static void k_cur(struct vc_data *vc, unsigned char value, char up_flag) { static const char cur_chars[] = "BDCA"; + int mod; if (up_flag) return; - applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE)); + mod = csi_modifier_param(); + if (mod > 1) { + char buf[] = { 0x1b, '[', '1', ';', '0' + mod, cur_chars[value], 0x00 }; + + puts_queue(vc, buf); + } else { + applkey(vc, cur_chars[value], vc_kbd_mode(kbd, VC_CKMODE)); + } } static void k_pad(struct vc_data *vc, unsigned char value, char up_flag)