* [PATCH 0/3] support for the kernel 7.1 modifier-aware KT_CSI keysym type
@ 2026-06-12 1:48 Nicolas Pitre
2026-06-12 1:48 ` [PATCH 1/3] libkeymap: add support for " Nicolas Pitre
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Nicolas Pitre @ 2026-06-12 1:48 UTC (permalink / raw)
To: kbd; +Cc: gladkov.alexey
Linux kernel 7.1 introduces modifier-aware escape sequence generation
for the console keyboard:
4af70f151671 ("vt: add modifier support to cursor keys")
5cba06c71c71 ("vt: add KT_CSI keysym type for modifier-aware CSI sequences")
c1d2deb6492f ("vt: add fallback to plain map for modifier-aware key types")
The new KT_CSI keysym type produces xterm-style CSI tilde sequences
(ESC [ n ~, or ESC [ n ; mod ~ when Shift/Alt/Control are held) with
the modifier state encoded at runtime. A single plain map entry covers
all modifier combinations, instead of consuming a func_table string
slot per combination. These changes are in Linus's tree and part of
the 7.1 release.
This series adds the userspace counterpart:
Patch 1 teaches libkeymap the Csi_* keysym names (Csi_Home, Csi_End,
Csi_Delete, Csi_Insert, Csi_PgUp, Csi_PgDn, Csi_F1..Csi_F20, matching
the kernel UAPI values) and documents modifier-aware keys in
keymaps(5).
Patch 2 adds a contrib script (with optional systemd unit) that
reconciles the "linux" terminfo entry with the loaded keymap: F1-F5
in CSI form and Backtab as ESC [ Z are not what the stock terminfo
entry expects. The script rebuilds an /etc/terminfo override from the
distribution's pristine entry and tags it with a marker so it never
touches an administrator-provided override.
Patch 3 converts the shared i386 keymap include files to the new
keysyms. Legacy copies of the include files are preserved for systems
running older kernels. On a pre-7.1 kernel the new keysyms load
without effect on Unicode-mode consoles, so function and navigation
keys would be inert there; the legacy includes retain the historical
behavior.
Tested with make check, and the terminfo script exercised live
(keymap loading, override creation/idempotence/removal, restoration)
on Fedora 43.
Nicolas Pitre (3):
libkeymap: add support for KT_CSI keysym type
Add kbd-terminfo-fixup script and systemd service
keymaps: convert include files to use CSI keysyms
.gitignore | 1 +
Makefile.am | 16 ++
configure.ac | 18 ++
contrib/kbd-terminfo-fixup | 222 ++++++++++++++++++
contrib/kbd-terminfo-fixup.service.in | 13 +
.../i386/include/linux-keys-bare-legacy.inc | 170 ++++++++++++++
data/keymaps/i386/include/linux-keys-bare.inc | 76 ++----
.../i386/include/linux-keys-extd-legacy.inc | 37 +++
data/keymaps/i386/include/linux-keys-extd.inc | 23 +-
.../linux-with-modeshift-altgr-legacy.inc | 101 ++++++++
.../include/linux-with-modeshift-altgr.inc | 52 ++--
docs/man/man5/keymaps.5 | 77 ++++++
src/libkeymap/ksyms.c | 3 +-
src/libkeymap/syms.ktyp.h | 39 +++
tests/data/keymap0-summary.txt | 26 ++
15 files changed, 770 insertions(+), 104 deletions(-)
create mode 100755 contrib/kbd-terminfo-fixup
create mode 100644 contrib/kbd-terminfo-fixup.service.in
create mode 100644 data/keymaps/i386/include/linux-keys-bare-legacy.inc
create mode 100644 data/keymaps/i386/include/linux-keys-extd-legacy.inc
create mode 100644 data/keymaps/i386/include/linux-with-modeshift-altgr-legacy.inc
--
2.54.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/3] libkeymap: add support for KT_CSI keysym type
2026-06-12 1:48 [PATCH 0/3] support for the kernel 7.1 modifier-aware KT_CSI keysym type Nicolas Pitre
@ 2026-06-12 1:48 ` Nicolas Pitre
2026-06-22 8:45 ` Alexey Gladkov
2026-06-12 1:48 ` [PATCH 2/3] Add kbd-terminfo-fixup script and systemd service Nicolas Pitre
2026-06-12 1:48 ` [PATCH 3/3] keymaps: convert include files to use CSI keysyms Nicolas Pitre
2 siblings, 1 reply; 6+ messages in thread
From: Nicolas Pitre @ 2026-06-12 1:48 UTC (permalink / raw)
To: kbd; +Cc: gladkov.alexey
Add support for the new KT_CSI keysym type which provides modifier-aware
CSI escape sequences for navigation and function keys. This eliminates
the need to exhaust the limited func_table string entries for modifier
combinations.
The new Csi_* keysyms (Csi_Home, Csi_End, Csi_Delete, Csi_Insert,
Csi_PgUp, Csi_PgDn, Csi_F1-F20) generate tilde-format CSI sequences
with automatic modifier encoding when used with a supporting kernel.
The kernel automatically falls back to the plain keymap entry when
modifiers are held, encoding the modifier state into the output
sequence, so only plain map entries need to be defined.
Also add documentation for modifier-aware keys to keymaps(5), and
update the libkeymap test fixture for the extended symbol table.
Note: Requires Linux kernel 7.1 or later for KT_CSI support. On older
kernels these keysyms load without effect on consoles in Unicode mode
(the affected keys produce no output), and are rejected with EINVAL on
non-Unicode consoles (loadkeys reports an error for each such entry
but carries on).
Signed-off-by: Nicolas Pitre <nico@fluxnic.net>
---
docs/man/man5/keymaps.5 | 77 ++++++++++++++++++++++++++++++++++
src/libkeymap/ksyms.c | 3 +-
src/libkeymap/syms.ktyp.h | 39 +++++++++++++++++
tests/data/keymap0-summary.txt | 26 ++++++++++++
4 files changed, 144 insertions(+), 1 deletion(-)
diff --git a/docs/man/man5/keymaps.5 b/docs/man/man5/keymaps.5
index 072afe3..bfa75aa 100644
--- a/docs/man/man5/keymaps.5
+++ b/docs/man/man5/keymaps.5
@@ -353,6 +353,83 @@ and describe how two bytes are combined to form a third one
(when a dead accent or compose key is used).
This is used to get accented letters and the like on a standard
keyboard.
+.SH "MODIFIER-AWARE KEYS"
+Certain key types automatically encode the current modifier state into
+the escape sequence they produce. This eliminates the need to define
+separate keymap entries for each modifier combination.
+.SS "Cursor Keys"
+The cursor keys (Up, Down, Left, Right) automatically include modifier
+information when Shift, Alt, or Control are held. With no modifiers,
+they produce the standard sequences (e.g., ESC [ A for Up). With
+modifiers, they produce extended sequences in the format ESC [ 1 ; \fImod\fP X,
+where \fImod\fP encodes the modifier state and X is the direction letter.
+.LP
+The modifier value is calculated as: 1 + (Shift?1:0) + (Alt?2:0) + (Control?4:0).
+AltGr counts as Alt for this purpose.
+For example, Shift+Up produces ESC [ 1 ; 2 A, and Control+Alt+Up
+produces ESC [ 1 ; 7 A.
+.SS "CSI Keys"
+The Csi_* keysyms provide similar modifier-aware behavior for navigation
+and function keys, generating sequences in the CSI tilde format
+(ESC [ \fIn\fP ~ or ESC [ \fIn\fP ; \fImod\fP ~ with modifiers).
+.LP
+Available CSI keysyms and their unmodified sequences:
+.RS
+.TP 16
+.B Csi_Home
+ESC [ 1 ~
+.TP
+.B Csi_Insert
+ESC [ 2 ~
+.TP
+.B Csi_Delete
+ESC [ 3 ~
+.TP
+.B Csi_End
+ESC [ 4 ~
+.TP
+.B Csi_PgUp
+ESC [ 5 ~
+.TP
+.B Csi_PgDn
+ESC [ 6 ~
+.TP
+.B Csi_F1 \fR...\fB Csi_F12
+ESC [ 11 ~ through ESC [ 24 ~ (skipping 16 and 22)
+.TP
+.B Csi_F13 \fR...\fB Csi_F20
+ESC [ 25 ~ through ESC [ 34 ~ (skipping 27 and 30)
+.RE
+.LP
+Note: The Csi_F* sequences follow the xterm numbering scheme, including
+its gaps in the parameter numbering, which differs from the traditional
+Linux console F1-F5 sequences (ESC [ [ A through ESC [ [ E).
+.SS "Fallback Behavior"
+When a cursor or CSI key is pressed with modifiers, and no explicit binding
+exists for that modifier combination, the kernel automatically falls back
+to the plain (unmodified) keymap entry. The modifier state is still encoded
+in the output sequence.
+.LP
+This means you only need to define the plain keymap entry:
+.LP
+.RS
+.nf
+keycode 102 = Csi_Home
+.fi
+.RE
+.LP
+and all modifier combinations (Shift+Home, Control+Home, etc.) will
+automatically produce the correct modified sequences without additional
+keymap entries.
+.LP
+.B Note:
+Modifier-aware key behavior requires Linux kernel 7.1 or later.
+On older kernels, cursor keys produce their traditional unmodified
+sequences, and Csi_* keysyms have no effect: on a console in Unicode
+mode the corresponding keys produce no output, while on a non-Unicode
+console
+.BR loadkeys (1)
+reports an error for each Csi_* entry.
.SH ABBREVIATIONS
Various abbreviations can be used with kbd-0.96 and later.
.TP
diff --git a/src/libkeymap/ksyms.c b/src/libkeymap/ksyms.c
index 219e5f2..98d1cf3 100644
--- a/src/libkeymap/ksyms.c
+++ b/src/libkeymap/ksyms.c
@@ -52,7 +52,8 @@ static const syms_entry syms[] = {
{ NULL, 0 }, /* KT_LETTER */
E(sticky_syms), /* KT_SLOCK */
{ NULL, 0 }, /* KT_DEAD2 */
- E(brl_syms) /* KT_BRL */
+ E(brl_syms), /* KT_BRL */
+ E(csi_syms) /* KT_CSI */
};
#undef E
diff --git a/src/libkeymap/syms.ktyp.h b/src/libkeymap/syms.ktyp.h
index 504d67e..aca0fc6 100644
--- a/src/libkeymap/syms.ktyp.h
+++ b/src/libkeymap/syms.ktyp.h
@@ -588,3 +588,42 @@ static const char *const brl_syms[] = {
"Brl_dot9",
"Brl_dot10"
};
+
+/*
+ * Keysyms whose KTYP is KT_CSI.
+ * Index is the CSI parameter number for ESC [ <index> ~ sequences.
+ */
+static const char *const csi_syms[] = {
+ "", /* 0: unused */
+ "Csi_Home", /* 1: ESC [ 1 ~ */
+ "Csi_Insert", /* 2: ESC [ 2 ~ */
+ "Csi_Delete", /* 3: ESC [ 3 ~ */
+ "Csi_End", /* 4: ESC [ 4 ~ */
+ "Csi_PgUp", /* 5: ESC [ 5 ~ */
+ "Csi_PgDn", /* 6: ESC [ 6 ~ */
+ "", "", "", "", /* 7-10: unused */
+ "Csi_F1", /* 11: ESC [ 11 ~ */
+ "Csi_F2", /* 12: ESC [ 12 ~ */
+ "Csi_F3", /* 13: ESC [ 13 ~ */
+ "Csi_F4", /* 14: ESC [ 14 ~ */
+ "Csi_F5", /* 15: ESC [ 15 ~ */
+ "", /* 16: unused */
+ "Csi_F6", /* 17: ESC [ 17 ~ */
+ "Csi_F7", /* 18: ESC [ 18 ~ */
+ "Csi_F8", /* 19: ESC [ 19 ~ */
+ "Csi_F9", /* 20: ESC [ 20 ~ */
+ "Csi_F10", /* 21: ESC [ 21 ~ */
+ "", /* 22: unused */
+ "Csi_F11", /* 23: ESC [ 23 ~ */
+ "Csi_F12", /* 24: ESC [ 24 ~ */
+ "Csi_F13", /* 25: ESC [ 25 ~ */
+ "Csi_F14", /* 26: ESC [ 26 ~ */
+ "", /* 27: unused */
+ "Csi_F15", /* 28: ESC [ 28 ~ */
+ "Csi_F16", /* 29: ESC [ 29 ~ */
+ "", /* 30: unused */
+ "Csi_F17", /* 31: ESC [ 31 ~ */
+ "Csi_F18", /* 32: ESC [ 32 ~ */
+ "Csi_F19", /* 33: ESC [ 33 ~ */
+ "Csi_F20", /* 34: ESC [ 34 ~ */
+};
diff --git a/tests/data/keymap0-summary.txt b/tests/data/keymap0-summary.txt
index 0b66c06..6f757fd 100644
--- a/tests/data/keymap0-summary.txt
+++ b/tests/data/keymap0-summary.txt
@@ -810,6 +810,32 @@ nr of compose definitions in actual use: 0
0x0e08 Brl_dot8
0x0e09 Brl_dot9
0x0e0a Brl_dot10
+0x0f01 Csi_Home
+0x0f02 Csi_Insert
+0x0f03 Csi_Delete
+0x0f04 Csi_End
+0x0f05 Csi_PgUp
+0x0f06 Csi_PgDn
+0x0f0b Csi_F1
+0x0f0c Csi_F2
+0x0f0d Csi_F3
+0x0f0e Csi_F4
+0x0f0f Csi_F5
+0x0f11 Csi_F6
+0x0f12 Csi_F7
+0x0f13 Csi_F8
+0x0f14 Csi_F9
+0x0f15 Csi_F10
+0x0f17 Csi_F11
+0x0f18 Csi_F12
+0x0f19 Csi_F13
+0x0f1a Csi_F14
+0x0f1c Csi_F15
+0x0f1d Csi_F16
+0x0f1f Csi_F17
+0x0f20 Csi_F18
+0x0f21 Csi_F19
+0x0f22 Csi_F20
The following synonyms are recognized:
--
2.54.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/3] Add kbd-terminfo-fixup script and systemd service
2026-06-12 1:48 [PATCH 0/3] support for the kernel 7.1 modifier-aware KT_CSI keysym type Nicolas Pitre
2026-06-12 1:48 ` [PATCH 1/3] libkeymap: add support for " Nicolas Pitre
@ 2026-06-12 1:48 ` Nicolas Pitre
2026-06-12 1:48 ` [PATCH 3/3] keymaps: convert include files to use CSI keysyms Nicolas Pitre
2 siblings, 0 replies; 6+ messages in thread
From: Nicolas Pitre @ 2026-06-12 1:48 UTC (permalink / raw)
To: kbd; +Cc: gladkov.alexey
This script handles two terminfo mismatches with the linux terminal:
1. The Linux console has a long-standing discrepancy where F1-F5 use
non-standard sequences (\e[[A through \e[[E) while F6 and above use
standard CSI sequences (\e[17~ etc.). The new Csi_F1 through Csi_F5
keysyms (Linux kernel 7.1 and later) fix this by making F1-F5 use
CSI sequences as well (\e[11~ through \e[15~). However, the terminfo
entry for "linux" still expects the old sequences, causing
applications to not recognize F1-F5.
2. The Backtab keysym produces the standard backtab sequence \e[Z,
but the linux terminfo entry expects \e^I (ESC + Tab).
Some applications may recognize these sequences regardless of terminfo,
but not all do. The kbd-terminfo-fixup script ensures consistent
behavior across all terminfo-aware applications by detecting Csi_F*
and Backtab keysyms in the current keymap (via dumpkeys) and installing
an updated "linux" terminfo entry in /etc/terminfo/.
The override is always rebuilt from the distribution's pristine
terminfo entry (looked up in /usr/share/terminfo, /lib/terminfo or
/usr/lib/terminfo) rather than from the active search path, so the
script never feeds on its own output and fixups that are no longer
needed are automatically dropped when the keymap changes. Rewrites
are skipped when the installed override is already up to date.
The generated entry is tagged with a "(kbd-terminfo-fixup)" marker in
its terminfo description field. An /etc/terminfo/l/linux file without
that marker is treated as the administrator's own and is never
overwritten or removed.
A systemd service unit is provided to run this automatically at boot,
after systemd-vconsole-setup.service loads the keymap. The service is
only installed when systemd is detected. The unit file is generated
at make time so that the libexec path is fully expanded.
Configure options:
--with-systemdsystemunitdir=DIR Set systemd unit directory
(auto-detected via pkg-config)
Signed-off-by: Nicolas Pitre <nico@fluxnic.net>
---
.gitignore | 1 +
Makefile.am | 16 ++
configure.ac | 18 +++
contrib/kbd-terminfo-fixup | 222 ++++++++++++++++++++++++++
contrib/kbd-terminfo-fixup.service.in | 13 ++
5 files changed, 270 insertions(+)
create mode 100755 contrib/kbd-terminfo-fixup
create mode 100644 contrib/kbd-terminfo-fixup.service.in
diff --git a/.gitignore b/.gitignore
index 539fe88..4f4913f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -105,3 +105,4 @@ tests/libkbdfile/libkbdfile-test[0-9][0-9]
tests/libkeymap/libkeymap-test[0-9][0-9]
tests/libkfont/libkfont-test[0-9][0-9]
tests/testsuite
+contrib/kbd-terminfo-fixup.service
diff --git a/Makefile.am b/Makefile.am
index f722e97..9eafcae 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,6 +33,22 @@ EXTRA_DIST = \
CREDITS \
contrib docs
+pkglibexec_SCRIPTS = contrib/kbd-terminfo-fixup
+
+if HAVE_SYSTEMD
+systemdsystemunit_DATA = contrib/kbd-terminfo-fixup.service
+endif
+
+# Substitute directory variables at make time so they are fully
+# expanded (configure would leave ${exec_prefix} unexpanded).
+contrib/kbd-terminfo-fixup.service: contrib/kbd-terminfo-fixup.service.in Makefile
+ $(AM_V_GEN)$(MKDIR_P) contrib && \
+ $(SED) -e 's|@libexecdir[@]|$(libexecdir)|g' \
+ -e 's|@PACKAGE[@]|$(PACKAGE)|g' \
+ $(srcdir)/contrib/kbd-terminfo-fixup.service.in > $@
+
+CLEANFILES = contrib/kbd-terminfo-fixup.service
+
SUBDIRS = src data po docs
if BUILD_TESTS
SUBDIRS += tests
diff --git a/configure.ac b/configure.ac
index ffd67fe..a3f30ec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -368,6 +368,22 @@ AS_IF([test "x$USE_XKB" != xno],
[USE_XKB=no])
AM_CONDITIONAL(USE_XKB, test "$USE_XKB" = "yes")
+AC_ARG_WITH([systemdsystemunitdir],
+ [AS_HELP_STRING([--with-systemdsystemunitdir=DIR],
+ [directory for systemd service files @<:@default=auto@:>@])],
+ [],
+ [with_systemdsystemunitdir=auto]
+)
+AS_IF([test "$with_systemdsystemunitdir" = "auto"], [
+ PKG_CHECK_VAR([systemdsystemunitdir], [systemd], [systemdsystemunitdir],
+ [with_systemdsystemunitdir="$systemdsystemunitdir"],
+ [with_systemdsystemunitdir=no])
+])
+AS_IF([test "$with_systemdsystemunitdir" != "no"], [
+ AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
+])
+AM_CONDITIONAL(HAVE_SYSTEMD, test "$with_systemdsystemunitdir" != "no")
+
AC_MSG_NOTICE([generation of Makefiles...])
# Remove -h (dereference) from am__tar
@@ -431,4 +447,6 @@ AC_MSG_RESULT([
standalone libkeymap: ${BUILD_LIBKEYMAP}
standalone libkfont: ${BUILD_LIBKFONT}
xkb support: ${USE_XKB}
+
+ systemd unit dir: ${with_systemdsystemunitdir}
])
diff --git a/contrib/kbd-terminfo-fixup b/contrib/kbd-terminfo-fixup
new file mode 100755
index 0000000..965460d
--- /dev/null
+++ b/contrib/kbd-terminfo-fixup
@@ -0,0 +1,222 @@
+#!/bin/sh
+# kbd-terminfo-fixup - Update terminfo when new kbd keysym bindings are used
+#
+# This script handles two terminfo mismatches:
+#
+# 1. The Linux console has a long-standing discrepancy where F1-F5 use
+# non-standard sequences (\e[[A through \e[[E) while F6 and above use
+# standard CSI sequences. The Csi_F1 through Csi_F5 keysyms fix this.
+#
+# 2. The Backtab keysym produces the standard \e[Z sequence, but the
+# linux terminfo entry expects \e^I (ESC + Tab).
+#
+# This script detects when these keysyms are in use and installs a
+# modified "linux" terminfo entry in /etc/terminfo so applications can
+# correctly recognize them.
+#
+# The override is always rebuilt from the distribution's pristine entry
+# (never from the active search path, which may include a previous
+# override), so fixups that are no longer needed are automatically
+# dropped when the keymap changes. The generated entry is tagged with a
+# "(kbd-terminfo-fixup)" marker in its description; an existing
+# /etc/terminfo/l/linux without that marker is considered the
+# administrator's own and is never modified or removed.
+#
+# Some applications may recognize these sequences regardless of terminfo,
+# but not all do. This ensures consistent behavior across all
+# terminfo-aware applications.
+#
+# Usage: kbd-terminfo-fixup [--update | --remove | --check]
+#
+# Options:
+# --update Create/update terminfo if CSI keysyms detected (default)
+# --remove Remove system terminfo override
+# --check Check if CSI keysyms are in use (exit 0 if yes)
+
+set -e
+
+TERMINFO_DIR="${TERMINFO_DIR:-/etc/terminfo}"
+MARKER="kbd-terminfo-fixup"
+
+# Check which Csi_F1-F5 keysyms are in use
+# (-w prevents e.g. Csi_F11 from matching as Csi_F1)
+detect_csi_keys() {
+ dumpkeys 2>/dev/null | grep -woE 'Csi_F[1-5]' | sort -u
+}
+
+# Check if Backtab keysym is in use
+detect_backtab() {
+ if dumpkeys 2>/dev/null | grep -qw 'Backtab'; then
+ echo "Backtab"
+ fi
+}
+
+# The compiled entry stores the description string verbatim, so the
+# marker added by this script can be detected with a plain grep.
+override_is_ours() {
+ grep -q "(${MARKER})" "${TERMINFO_DIR}/l/linux" 2>/dev/null
+}
+
+# Print the distribution's pristine "linux" entry, one capability per
+# line, bypassing $TERMINFO_DIR so we never read back our own override.
+pristine_entry() {
+ for dir in /usr/share/terminfo /lib/terminfo /usr/lib/terminfo; do
+ if [ -e "$dir/l/linux" ]; then
+ TERMINFO="$dir" infocmp -1 -x linux 2>/dev/null || true
+ return 0
+ fi
+ done
+ # Unusual layout: fall back to the default search path
+ infocmp -1 -x linux 2>/dev/null || true
+}
+
+# Tag the entry description so we can recognize our own override later
+add_marker() {
+ sed "/^linux|/{/(${MARKER})/!s/,\$/ (${MARKER}),/;}"
+}
+
+do_check() {
+ csi_keys=$(detect_csi_keys)
+ backtab=$(detect_backtab)
+ if [ -n "$csi_keys" ] || [ -n "$backtab" ]; then
+ [ -n "$csi_keys" ] && echo "CSI function keys in use: $csi_keys"
+ [ -n "$backtab" ] && echo "Backtab keysym in use"
+ return 0
+ else
+ echo "No CSI function keys (F1-F5) or Backtab detected"
+ return 1
+ fi
+}
+
+do_update() {
+ target="${TERMINFO_DIR}/l/linux"
+
+ # Never touch an override file we did not create
+ if [ -f "$target" ] && ! override_is_ours; then
+ echo "$target was not created by this script; leaving it alone"
+ return 0
+ fi
+
+ csi_keys=$(detect_csi_keys)
+ backtab=$(detect_backtab)
+
+ if [ -z "$csi_keys" ] && [ -z "$backtab" ]; then
+ # No CSI keys or Backtab - remove override if present
+ do_remove quiet
+ return 0
+ fi
+
+ pristine=$(pristine_entry)
+ if [ -z "$pristine" ]; then
+ echo "Cannot read the 'linux' terminfo entry" >&2
+ return 1
+ fi
+
+ # Build the desired entry from the pristine one
+ sed_expr=""
+ for key in $csi_keys; do
+ fnum="${key#Csi_F}"
+ # Csi_Fn produces \E[1n~ for n in 1..5
+ sed_expr="${sed_expr}s/kf${fnum}=[^,]*/kf${fnum}=\\\\E[1${fnum}~/;"
+ done
+ if [ -n "$backtab" ]; then
+ sed_expr="${sed_expr}s/kcbt=[^,]*/kcbt=\\\\E[Z/;"
+ fi
+
+ desired=$(printf '%s\n' "$pristine" | sed "$sed_expr")
+
+ if [ "$desired" = "$pristine" ]; then
+ # The distribution entry already has the right sequences
+ do_remove quiet
+ echo "Terminfo already has correct sequences"
+ return 0
+ fi
+
+ desired=$(printf '%s\n' "$desired" | add_marker)
+
+ # Skip rewriting if our existing override is already up to date
+ if [ -f "$target" ]; then
+ current=$(TERMINFO="$TERMINFO_DIR" infocmp -1 -x linux 2>/dev/null | grep -v '^#' || true)
+ if [ "$(printf '%s\n' "$desired" | grep -v '^#' || true)" = "$current" ]; then
+ echo "Terminfo already up to date"
+ return 0
+ fi
+ fi
+
+ echo "Updating terminfo for:" $csi_keys $backtab
+
+ # Create terminfo directory if needed
+ mkdir -p "${TERMINFO_DIR}/l"
+
+ # Compile the modified terminfo
+ printf '%s\n' "$desired" | tic -x -o "$TERMINFO_DIR" -
+
+ echo "Terminfo updated in $target"
+}
+
+do_remove() {
+ quiet="${1:-}"
+ target="${TERMINFO_DIR}/l/linux"
+ if [ ! -f "$target" ]; then
+ [ "$quiet" = "quiet" ] || echo "No system terminfo override found"
+ return 0
+ fi
+ if ! override_is_ours; then
+ [ "$quiet" = "quiet" ] || echo "$target was not created by this script; leaving it alone"
+ return 0
+ fi
+ rm -f "$target"
+ [ "$quiet" = "quiet" ] || echo "Removed $target"
+ # Clean up the subdirectory if empty, but leave $TERMINFO_DIR
+ # itself alone: it usually belongs to the distribution
+ rmdir "${TERMINFO_DIR}/l" 2>/dev/null || true
+}
+
+show_usage() {
+ cat <<EOF
+Usage: kbd-terminfo-fixup [--update | --remove | --check]
+
+Update system terminfo when new kbd keysym bindings are used.
+
+Options:
+ --update Create/update terminfo if new keysyms detected, or remove
+ the override if not (default)
+ --remove Remove system terminfo override
+ --check Check if new keysyms are in use
+
+This script handles two cases:
+
+1. The Linux console has a long-standing discrepancy where F1-F5 use
+ non-standard sequences (\e[[A through \e[[E) while F6 and above use
+ standard CSI sequences (\e[17~ etc.). The Csi_F1 through Csi_F5 keysyms
+ fix this by making F1-F5 use CSI sequences (\e[11~ through \e[15~).
+
+2. The Backtab keysym produces the standard backtab sequence \e[Z,
+ but the linux terminfo entry expects \e^I (ESC + Tab).
+
+This script detects when these keysyms are in use and installs a
+modified "linux" terminfo entry accordingly.
+
+Some applications may recognize these sequences regardless of terminfo,
+but not all do. This ensures consistent behavior across all
+terminfo-aware applications.
+
+The modified entry is rebuilt from the distribution's pristine terminfo
+entry, installed to /etc/terminfo/ (which takes precedence over the
+default system entry), and tagged with a "($MARKER)" marker
+in its description. An /etc/terminfo/l/linux file without that marker
+is treated as the administrator's own and is never touched.
+EOF
+}
+
+case "${1:---update}" in
+ --update) do_update ;;
+ --remove) do_remove ;;
+ --check) do_check ;;
+ --help|-h) show_usage ;;
+ *)
+ echo "Unknown option: $1" >&2
+ show_usage >&2
+ exit 1
+ ;;
+esac
diff --git a/contrib/kbd-terminfo-fixup.service.in b/contrib/kbd-terminfo-fixup.service.in
new file mode 100644
index 0000000..df9591e
--- /dev/null
+++ b/contrib/kbd-terminfo-fixup.service.in
@@ -0,0 +1,13 @@
+[Unit]
+Description=Update terminfo for CSI function keys
+Documentation=man:keymaps(5)
+After=systemd-vconsole-setup.service
+ConditionPathExists=/dev/tty0
+
+[Service]
+Type=oneshot
+ExecStart=@libexecdir@/@PACKAGE@/kbd-terminfo-fixup --update
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
--
2.54.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/3] keymaps: convert include files to use CSI keysyms
2026-06-12 1:48 [PATCH 0/3] support for the kernel 7.1 modifier-aware KT_CSI keysym type Nicolas Pitre
2026-06-12 1:48 ` [PATCH 1/3] libkeymap: add support for " Nicolas Pitre
2026-06-12 1:48 ` [PATCH 2/3] Add kbd-terminfo-fixup script and systemd service Nicolas Pitre
@ 2026-06-12 1:48 ` Nicolas Pitre
2026-06-22 8:58 ` Alexey Gladkov
2 siblings, 1 reply; 6+ messages in thread
From: Nicolas Pitre @ 2026-06-12 1:48 UTC (permalink / raw)
To: kbd; +Cc: gladkov.alexey
Convert the shared keymap include files to use the new Csi_* keysyms
for function keys (F1-F12) and navigation keys (Home, End, Insert,
Delete, PageUp, PageDown). This fixes the long-standing discrepancy
where F1-F5 used non-standard sequences (\e[[A through \e[[E) while
F6 and above used standard CSI sequences.
The Csi_* keysyms automatically encode modifier state into the output
sequence, so explicit shift/control bindings for F13-F36 are no longer
needed and have been removed. The alt/control-alt bindings for console
switching (Console_1 through Console_24) and other special actions
(Scroll_Backward, Scroll_Forward, Boot) are preserved.
Updated files:
- linux-keys-bare.inc
- linux-keys-extd.inc
- linux-with-modeshift-altgr.inc
Legacy versions of these files are preserved as *-legacy.inc for
keymaps that need the old F1-F246 keysym behavior.
Note: Standalone keymaps that don't use these include files (such as
defkeymap.map and various language-specific keymaps) are not updated
and will continue to use the legacy keysyms.
Note: The Csi_* keysyms require Linux kernel 7.1 or later. Keymaps
built from these include files will leave the function and navigation
keys inoperative on older kernels (and loadkeys additionally reports
errors for them on non-Unicode consoles). Systems that must run
pre-7.1 kernels should use the *-legacy.inc include files instead.
Signed-off-by: Nicolas Pitre <nico@fluxnic.net>
---
.../i386/include/linux-keys-bare-legacy.inc | 170 ++++++++++++++++++
data/keymaps/i386/include/linux-keys-bare.inc | 76 +++-----
.../i386/include/linux-keys-extd-legacy.inc | 37 ++++
data/keymaps/i386/include/linux-keys-extd.inc | 23 +--
.../linux-with-modeshift-altgr-legacy.inc | 101 +++++++++++
.../include/linux-with-modeshift-altgr.inc | 52 ++----
6 files changed, 356 insertions(+), 103 deletions(-)
create mode 100644 data/keymaps/i386/include/linux-keys-bare-legacy.inc
create mode 100644 data/keymaps/i386/include/linux-keys-extd-legacy.inc
create mode 100644 data/keymaps/i386/include/linux-with-modeshift-altgr-legacy.inc
diff --git a/data/keymaps/i386/include/linux-keys-bare-legacy.inc b/data/keymaps/i386/include/linux-keys-bare-legacy.inc
new file mode 100644
index 0000000..30379aa
--- /dev/null
+++ b/data/keymaps/i386/include/linux-keys-bare-legacy.inc
@@ -0,0 +1,170 @@
+# Linux-specific (and language-independent) keys
+#
+# This file describes function keys, console switching keys,
+# keypad, cursor keys, and SysRq, ScrollLock, Pause
+#
+# It does not use the AltGr modifier, so that the user can opt
+# to have both Alt keys produce the same effect.
+# As a consequence, the Hex_* keys are missing, as are
+# control altgr keycode 83 = Boot
+# control altgr keycode 111 = Boot
+#
+# One culture-specific item that will be overridden in many keymaps
+# is the KP_Period: many countries have a KP_Comma instead.
+#
+# One user-preference item will be the function of the Delete key.
+#
+# Old keyboards have 10 function keys, and keymaps have
+# sometimes used shift+F1 = F11, and sometimes shift+F1 = F13.
+# Here we assume an enhanced keyboard (with 12 function keys).
+#
+plain keycode 59 = F1
+plain keycode 60 = F2
+plain keycode 61 = F3
+plain keycode 62 = F4
+plain keycode 63 = F5
+plain keycode 64 = F6
+plain keycode 65 = F7
+plain keycode 66 = F8
+plain keycode 67 = F9
+plain keycode 68 = F10
+plain keycode 87 = F11
+plain keycode 88 = F12
+shift keycode 59 = F13
+shift keycode 60 = F14
+shift keycode 61 = F15
+shift keycode 62 = F16
+shift keycode 63 = F17
+shift keycode 64 = F18
+shift keycode 65 = F19
+shift keycode 66 = F20
+shift keycode 67 = F21
+shift keycode 68 = F22
+shift keycode 87 = F23
+shift keycode 88 = F24
+control keycode 59 = F25
+control keycode 60 = F26
+control keycode 61 = F27
+control keycode 62 = F28
+control keycode 63 = F29
+control keycode 64 = F30
+control keycode 65 = F31
+control keycode 66 = F32
+control keycode 67 = F33
+control keycode 68 = F34
+control keycode 87 = F35
+control keycode 88 = F36
+#
+# The canonical assignment for F37-F48 uses
+# control shift keycode 59 = F37
+# etc. If you want that, load linux-keys-extd.inc
+#
+# Both Alt+Fn and Control+Alt+Fn switch to Console n
+# (in order to please Linux / dosemu / X).
+# Here Consoles 1..12. For 13..24 load linux-keys-extd.inc
+#
+alt keycode 59 = Console_1
+alt keycode 60 = Console_2
+alt keycode 61 = Console_3
+alt keycode 62 = Console_4
+alt keycode 63 = Console_5
+alt keycode 64 = Console_6
+alt keycode 65 = Console_7
+alt keycode 66 = Console_8
+alt keycode 67 = Console_9
+alt keycode 68 = Console_10
+alt keycode 87 = Console_11
+alt keycode 88 = Console_12
+control alt keycode 59 = Console_1
+control alt keycode 60 = Console_2
+control alt keycode 61 = Console_3
+control alt keycode 62 = Console_4
+control alt keycode 63 = Console_5
+control alt keycode 64 = Console_6
+control alt keycode 65 = Console_7
+control alt keycode 66 = Console_8
+control alt keycode 67 = Console_9
+control alt keycode 68 = Console_10
+control alt keycode 87 = Console_11
+control alt keycode 88 = Console_12
+
+#
+# Tab and Backtab
+#
+keycode 15 = Tab
+shift keycode 15 = Backtab
+alt keycode 15 = Meta_Tab
+
+#
+# Keypad keys
+#
+keycode 69 = Num_Lock
+keycode 98 = KP_Divide
+keycode 55 = KP_Multiply
+keycode 74 = KP_Subtract
+keycode 78 = KP_Add
+keycode 96 = KP_Enter
+#
+keycode 71 = KP_7
+keycode 72 = KP_8
+keycode 73 = KP_9
+keycode 75 = KP_4
+keycode 76 = KP_5
+keycode 77 = KP_6
+keycode 79 = KP_1
+keycode 80 = KP_2
+keycode 81 = KP_3
+keycode 82 = KP_0
+#
+keycode 83 = KP_Period # or KP_Comma
+control alt keycode 83 = Boot
+#
+alt keycode 71 = Ascii_7
+alt keycode 72 = Ascii_8
+alt keycode 73 = Ascii_9
+alt keycode 75 = Ascii_4
+alt keycode 76 = Ascii_5
+alt keycode 77 = Ascii_6
+alt keycode 79 = Ascii_1
+alt keycode 80 = Ascii_2
+alt keycode 81 = Ascii_3
+alt keycode 82 = Ascii_0
+#
+# The four cursor keys
+#
+keycode 103 = Up
+keycode 105 = Left
+keycode 106 = Right
+keycode 108 = Down
+alt keycode 103 = KeyboardSignal
+alt keycode 105 = Decr_Console
+alt keycode 106 = Incr_Console
+#
+# The six edit keys
+#
+keycode 110 = Insert
+keycode 102 = Home # Find
+keycode 104 = PageUp # Prior
+keycode 111 = Remove
+keycode 107 = End # Select
+keycode 109 = PageDown # Next
+shift keycode 104 = Scroll_Backward
+shift keycode 109 = Scroll_Forward
+control alt keycode 111 = Boot
+#
+# The three system keys
+#
+keycode 84 = Last_Console # Alt+SysRq/PrintScrn
+#keycode 99 = VoidSymbol # SysRq/PrintScrn
+keycode 99 = Compose # SysRq/PrintScrn
+alt keycode 99 = Control_backslash
+control keycode 99 = Control_backslash
+
+plain keycode 70 = Scroll_Lock
+shift keycode 70 = Show_Memory
+control keycode 70 = Show_State
+alt keycode 70 = Show_Registers
+
+keycode 101 = Break # Ctrl+Break/Pause
+keycode 119 = Pause # Break/Pause
+
diff --git a/data/keymaps/i386/include/linux-keys-bare.inc b/data/keymaps/i386/include/linux-keys-bare.inc
index 30379aa..998b7bf 100644
--- a/data/keymaps/i386/include/linux-keys-bare.inc
+++ b/data/keymaps/i386/include/linux-keys-bare.inc
@@ -14,50 +14,25 @@
#
# One user-preference item will be the function of the Delete key.
#
-# Old keyboards have 10 function keys, and keymaps have
-# sometimes used shift+F1 = F11, and sometimes shift+F1 = F13.
-# Here we assume an enhanced keyboard (with 12 function keys).
-#
-plain keycode 59 = F1
-plain keycode 60 = F2
-plain keycode 61 = F3
-plain keycode 62 = F4
-plain keycode 63 = F5
-plain keycode 64 = F6
-plain keycode 65 = F7
-plain keycode 66 = F8
-plain keycode 67 = F9
-plain keycode 68 = F10
-plain keycode 87 = F11
-plain keycode 88 = F12
-shift keycode 59 = F13
-shift keycode 60 = F14
-shift keycode 61 = F15
-shift keycode 62 = F16
-shift keycode 63 = F17
-shift keycode 64 = F18
-shift keycode 65 = F19
-shift keycode 66 = F20
-shift keycode 67 = F21
-shift keycode 68 = F22
-shift keycode 87 = F23
-shift keycode 88 = F24
-control keycode 59 = F25
-control keycode 60 = F26
-control keycode 61 = F27
-control keycode 62 = F28
-control keycode 63 = F29
-control keycode 64 = F30
-control keycode 65 = F31
-control keycode 66 = F32
-control keycode 67 = F33
-control keycode 68 = F34
-control keycode 87 = F35
-control keycode 88 = F36
-#
-# The canonical assignment for F37-F48 uses
-# control shift keycode 59 = F37
-# etc. If you want that, load linux-keys-extd.inc
+# Function keys use Csi_* keysyms which generate standard CSI sequences
+# and automatically encode modifier state. This fixes the long-standing
+# discrepancy where F1-F5 used non-standard sequences (\e[[A through
+# \e[[E) while F6 and above used standard CSI sequences.
+#
+# For the legacy F1-F246 keysyms, use linux-keys-bare-legacy.inc instead.
+#
+keycode 59 = Csi_F1
+keycode 60 = Csi_F2
+keycode 61 = Csi_F3
+keycode 62 = Csi_F4
+keycode 63 = Csi_F5
+keycode 64 = Csi_F6
+keycode 65 = Csi_F7
+keycode 66 = Csi_F8
+keycode 67 = Csi_F9
+keycode 68 = Csi_F10
+keycode 87 = Csi_F11
+keycode 88 = Csi_F12
#
# Both Alt+Fn and Control+Alt+Fn switch to Console n
# (in order to please Linux / dosemu / X).
@@ -142,12 +117,12 @@ alt keycode 106 = Incr_Console
#
# The six edit keys
#
-keycode 110 = Insert
-keycode 102 = Home # Find
-keycode 104 = PageUp # Prior
-keycode 111 = Remove
-keycode 107 = End # Select
-keycode 109 = PageDown # Next
+keycode 110 = Csi_Insert
+keycode 102 = Csi_Home # Find
+keycode 104 = Csi_PgUp # Prior
+keycode 111 = Csi_Delete
+keycode 107 = Csi_End # Select
+keycode 109 = Csi_PgDn # Next
shift keycode 104 = Scroll_Backward
shift keycode 109 = Scroll_Forward
control alt keycode 111 = Boot
@@ -167,4 +142,3 @@ alt keycode 70 = Show_Registers
keycode 101 = Break # Ctrl+Break/Pause
keycode 119 = Pause # Break/Pause
-
diff --git a/data/keymaps/i386/include/linux-keys-extd-legacy.inc b/data/keymaps/i386/include/linux-keys-extd-legacy.inc
new file mode 100644
index 0000000..401a456
--- /dev/null
+++ b/data/keymaps/i386/include/linux-keys-extd-legacy.inc
@@ -0,0 +1,37 @@
+#
+# More function keys and console assignments
+# These are not in the main map in order to save keymaps
+# Load after the main keymap, or include in the main keymap.
+#
+keymaps 5,9
+
+control shift keycode 59 = F37
+control shift keycode 60 = F38
+control shift keycode 61 = F39
+control shift keycode 62 = F40
+control shift keycode 63 = F41
+control shift keycode 64 = F42
+control shift keycode 65 = F43
+control shift keycode 66 = F44
+control shift keycode 67 = F45
+control shift keycode 68 = F46
+control shift keycode 87 = F47
+control shift keycode 88 = F48
+#
+alt shift keycode 59 = Console_13
+alt shift keycode 60 = Console_14
+alt shift keycode 61 = Console_15
+alt shift keycode 62 = Console_16
+alt shift keycode 63 = Console_17
+alt shift keycode 64 = Console_18
+alt shift keycode 65 = Console_19
+alt shift keycode 66 = Console_20
+alt shift keycode 67 = Console_21
+alt shift keycode 68 = Console_22
+alt shift keycode 87 = Console_23
+alt shift keycode 88 = Console_24
+#
+# It would be reasonable to add lines like
+# control alt shift keycode 59 = Console_13
+# but that would again require an extra key map, and is not worth it.
+#
diff --git a/data/keymaps/i386/include/linux-keys-extd.inc b/data/keymaps/i386/include/linux-keys-extd.inc
index 401a456..79a7019 100644
--- a/data/keymaps/i386/include/linux-keys-extd.inc
+++ b/data/keymaps/i386/include/linux-keys-extd.inc
@@ -1,23 +1,14 @@
#
-# More function keys and console assignments
-# These are not in the main map in order to save keymaps
+# Extended console assignments
+#
+# These are not in the main map in order to save keymaps.
# Load after the main keymap, or include in the main keymap.
#
-keymaps 5,9
-
-control shift keycode 59 = F37
-control shift keycode 60 = F38
-control shift keycode 61 = F39
-control shift keycode 62 = F40
-control shift keycode 63 = F41
-control shift keycode 64 = F42
-control shift keycode 65 = F43
-control shift keycode 66 = F44
-control shift keycode 67 = F45
-control shift keycode 68 = F46
-control shift keycode 87 = F47
-control shift keycode 88 = F48
+# Note: F37-F48 bindings have been removed as CSI keysyms automatically
+# encode modifier state. For the legacy bindings, use linux-keys-extd-legacy.inc
#
+keymaps 9
+
alt shift keycode 59 = Console_13
alt shift keycode 60 = Console_14
alt shift keycode 61 = Console_15
diff --git a/data/keymaps/i386/include/linux-with-modeshift-altgr-legacy.inc b/data/keymaps/i386/include/linux-with-modeshift-altgr-legacy.inc
new file mode 100644
index 0000000..29012ba
--- /dev/null
+++ b/data/keymaps/i386/include/linux-with-modeshift-altgr-legacy.inc
@@ -0,0 +1,101 @@
+# For keymaps in which AltGr_Lock is used to switch between two alphabets.
+#
+# A common construction is
+# alt keycode 42 = AltGr_Lock
+# altgr alt keycode 42 = AltGr_Lock
+#
+# All Linux keys have the same meaning with or without AltGr.
+# No convention for Hex_* has been established.
+
+include "linux-keys-bare"
+
+keycode 100 = AltGr
+
+altgr keycode 59 = F1
+altgr keycode 60 = F2
+altgr keycode 61 = F3
+altgr keycode 62 = F4
+altgr keycode 63 = F5
+altgr keycode 64 = F6
+altgr keycode 65 = F7
+altgr keycode 66 = F8
+altgr keycode 67 = F9
+altgr keycode 68 = F10
+altgr keycode 87 = F11
+altgr keycode 88 = F12
+altgr shift keycode 59 = F13
+altgr shift keycode 60 = F14
+altgr shift keycode 61 = F15
+altgr shift keycode 62 = F16
+altgr shift keycode 63 = F17
+altgr shift keycode 64 = F18
+altgr shift keycode 65 = F19
+altgr shift keycode 66 = F20
+altgr shift keycode 67 = F21
+altgr shift keycode 68 = F22
+altgr shift keycode 87 = F23
+altgr shift keycode 88 = F24
+altgr control keycode 59 = F25
+altgr control keycode 60 = F26
+altgr control keycode 61 = F27
+altgr control keycode 62 = F28
+altgr control keycode 63 = F29
+altgr control keycode 64 = F30
+altgr control keycode 65 = F31
+altgr control keycode 66 = F32
+altgr control keycode 67 = F33
+altgr control keycode 68 = F34
+altgr control keycode 87 = F35
+altgr control keycode 88 = F36
+#
+altgr alt keycode 59 = Console_1
+altgr alt keycode 60 = Console_2
+altgr alt keycode 61 = Console_3
+altgr alt keycode 62 = Console_4
+altgr alt keycode 63 = Console_5
+altgr alt keycode 64 = Console_6
+altgr alt keycode 65 = Console_7
+altgr alt keycode 66 = Console_8
+altgr alt keycode 67 = Console_9
+altgr alt keycode 68 = Console_10
+altgr alt keycode 87 = Console_11
+altgr alt keycode 88 = Console_12
+altgr control alt keycode 59 = Console_1
+altgr control alt keycode 60 = Console_2
+altgr control alt keycode 61 = Console_3
+altgr control alt keycode 62 = Console_4
+altgr control alt keycode 63 = Console_5
+altgr control alt keycode 64 = Console_6
+altgr control alt keycode 65 = Console_7
+altgr control alt keycode 66 = Console_8
+altgr control alt keycode 67 = Console_9
+altgr control alt keycode 68 = Console_10
+altgr control alt keycode 87 = Console_11
+altgr control alt keycode 88 = Console_12
+#
+altgr alt keycode 71 = Ascii_7
+altgr alt keycode 72 = Ascii_8
+altgr alt keycode 73 = Ascii_9
+altgr alt keycode 75 = Ascii_4
+altgr alt keycode 76 = Ascii_5
+altgr alt keycode 77 = Ascii_6
+altgr alt keycode 79 = Ascii_1
+altgr alt keycode 80 = Ascii_2
+altgr alt keycode 81 = Ascii_3
+altgr alt keycode 82 = Ascii_0
+#
+altgr alt keycode 103 = KeyboardSignal
+altgr alt keycode 105 = Decr_Console
+altgr alt keycode 106 = Incr_Console
+#
+altgr shift keycode 104 = Scroll_Backward
+altgr shift keycode 109 = Scroll_Forward
+#
+# altgr control keycode 83 = Boot
+altgr control alt keycode 83 = Boot
+# altgr control keycode 111 = Boot
+altgr control alt keycode 111 = Boot
+#
+# an exception - altgr changes the function
+#
+altgr keycode 70 = Show_Registers
diff --git a/data/keymaps/i386/include/linux-with-modeshift-altgr.inc b/data/keymaps/i386/include/linux-with-modeshift-altgr.inc
index 29012ba..2a00681 100644
--- a/data/keymaps/i386/include/linux-with-modeshift-altgr.inc
+++ b/data/keymaps/i386/include/linux-with-modeshift-altgr.inc
@@ -6,47 +6,27 @@
#
# All Linux keys have the same meaning with or without AltGr.
# No convention for Hex_* has been established.
+#
+# Note: shift/control altgr F-key bindings have been removed as CSI keysyms
+# automatically encode modifier state. For legacy bindings, use
+# linux-with-modeshift-altgr-legacy.inc instead.
include "linux-keys-bare"
keycode 100 = AltGr
-altgr keycode 59 = F1
-altgr keycode 60 = F2
-altgr keycode 61 = F3
-altgr keycode 62 = F4
-altgr keycode 63 = F5
-altgr keycode 64 = F6
-altgr keycode 65 = F7
-altgr keycode 66 = F8
-altgr keycode 67 = F9
-altgr keycode 68 = F10
-altgr keycode 87 = F11
-altgr keycode 88 = F12
-altgr shift keycode 59 = F13
-altgr shift keycode 60 = F14
-altgr shift keycode 61 = F15
-altgr shift keycode 62 = F16
-altgr shift keycode 63 = F17
-altgr shift keycode 64 = F18
-altgr shift keycode 65 = F19
-altgr shift keycode 66 = F20
-altgr shift keycode 67 = F21
-altgr shift keycode 68 = F22
-altgr shift keycode 87 = F23
-altgr shift keycode 88 = F24
-altgr control keycode 59 = F25
-altgr control keycode 60 = F26
-altgr control keycode 61 = F27
-altgr control keycode 62 = F28
-altgr control keycode 63 = F29
-altgr control keycode 64 = F30
-altgr control keycode 65 = F31
-altgr control keycode 66 = F32
-altgr control keycode 67 = F33
-altgr control keycode 68 = F34
-altgr control keycode 87 = F35
-altgr control keycode 88 = F36
+altgr keycode 59 = Csi_F1
+altgr keycode 60 = Csi_F2
+altgr keycode 61 = Csi_F3
+altgr keycode 62 = Csi_F4
+altgr keycode 63 = Csi_F5
+altgr keycode 64 = Csi_F6
+altgr keycode 65 = Csi_F7
+altgr keycode 66 = Csi_F8
+altgr keycode 67 = Csi_F9
+altgr keycode 68 = Csi_F10
+altgr keycode 87 = Csi_F11
+altgr keycode 88 = Csi_F12
#
altgr alt keycode 59 = Console_1
altgr alt keycode 60 = Console_2
--
2.54.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/3] libkeymap: add support for KT_CSI keysym type
2026-06-12 1:48 ` [PATCH 1/3] libkeymap: add support for " Nicolas Pitre
@ 2026-06-22 8:45 ` Alexey Gladkov
0 siblings, 0 replies; 6+ messages in thread
From: Alexey Gladkov @ 2026-06-22 8:45 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: kbd
On Thu, Jun 11, 2026 at 09:48:55PM -0400, Nicolas Pitre wrote:
> Add support for the new KT_CSI keysym type which provides modifier-aware
> CSI escape sequences for navigation and function keys. This eliminates
> the need to exhaust the limited func_table string entries for modifier
> combinations.
>
> The new Csi_* keysyms (Csi_Home, Csi_End, Csi_Delete, Csi_Insert,
> Csi_PgUp, Csi_PgDn, Csi_F1-F20) generate tilde-format CSI sequences
> with automatic modifier encoding when used with a supporting kernel.
>
> The kernel automatically falls back to the plain keymap entry when
> modifiers are held, encoding the modifier state into the output
> sequence, so only plain map entries need to be defined.
>
> Also add documentation for modifier-aware keys to keymaps(5), and
> update the libkeymap test fixture for the extended symbol table.
>
> Note: Requires Linux kernel 7.1 or later for KT_CSI support. On older
> kernels these keysyms load without effect on consoles in Unicode mode
> (the affected keys produce no output), and are rejected with EINVAL on
> non-Unicode consoles (loadkeys reports an error for each such entry
> but carries on).
>
> Signed-off-by: Nicolas Pitre <nico@fluxnic.net>
> ---
> docs/man/man5/keymaps.5 | 77 ++++++++++++++++++++++++++++++++++
> src/libkeymap/ksyms.c | 3 +-
> src/libkeymap/syms.ktyp.h | 39 +++++++++++++++++
> tests/data/keymap0-summary.txt | 26 ++++++++++++
> 4 files changed, 144 insertions(+), 1 deletion(-)
>
> diff --git a/docs/man/man5/keymaps.5 b/docs/man/man5/keymaps.5
> index 072afe3..bfa75aa 100644
> --- a/docs/man/man5/keymaps.5
> +++ b/docs/man/man5/keymaps.5
> @@ -353,6 +353,83 @@ and describe how two bytes are combined to form a third one
> (when a dead accent or compose key is used).
> This is used to get accented letters and the like on a standard
> keyboard.
> +.SH "MODIFIER-AWARE KEYS"
> +Certain key types automatically encode the current modifier state into
> +the escape sequence they produce. This eliminates the need to define
> +separate keymap entries for each modifier combination.
> +.SS "Cursor Keys"
> +The cursor keys (Up, Down, Left, Right) automatically include modifier
> +information when Shift, Alt, or Control are held. With no modifiers,
> +they produce the standard sequences (e.g., ESC [ A for Up). With
> +modifiers, they produce extended sequences in the format ESC [ 1 ; \fImod\fP X,
> +where \fImod\fP encodes the modifier state and X is the direction letter.
> +.LP
> +The modifier value is calculated as: 1 + (Shift?1:0) + (Alt?2:0) + (Control?4:0).
> +AltGr counts as Alt for this purpose.
> +For example, Shift+Up produces ESC [ 1 ; 2 A, and Control+Alt+Up
> +produces ESC [ 1 ; 7 A.
> +.SS "CSI Keys"
> +The Csi_* keysyms provide similar modifier-aware behavior for navigation
> +and function keys, generating sequences in the CSI tilde format
> +(ESC [ \fIn\fP ~ or ESC [ \fIn\fP ; \fImod\fP ~ with modifiers).
> +.LP
> +Available CSI keysyms and their unmodified sequences:
> +.RS
> +.TP 16
> +.B Csi_Home
> +ESC [ 1 ~
> +.TP
> +.B Csi_Insert
> +ESC [ 2 ~
> +.TP
> +.B Csi_Delete
> +ESC [ 3 ~
> +.TP
> +.B Csi_End
> +ESC [ 4 ~
> +.TP
> +.B Csi_PgUp
> +ESC [ 5 ~
> +.TP
> +.B Csi_PgDn
> +ESC [ 6 ~
> +.TP
> +.B Csi_F1 \fR...\fB Csi_F12
> +ESC [ 11 ~ through ESC [ 24 ~ (skipping 16 and 22)
> +.TP
> +.B Csi_F13 \fR...\fB Csi_F20
> +ESC [ 25 ~ through ESC [ 34 ~ (skipping 27 and 30)
> +.RE
> +.LP
> +Note: The Csi_F* sequences follow the xterm numbering scheme, including
> +its gaps in the parameter numbering, which differs from the traditional
> +Linux console F1-F5 sequences (ESC [ [ A through ESC [ [ E).
> +.SS "Fallback Behavior"
> +When a cursor or CSI key is pressed with modifiers, and no explicit binding
> +exists for that modifier combination, the kernel automatically falls back
> +to the plain (unmodified) keymap entry. The modifier state is still encoded
> +in the output sequence.
> +.LP
> +This means you only need to define the plain keymap entry:
> +.LP
> +.RS
> +.nf
> +keycode 102 = Csi_Home
> +.fi
> +.RE
> +.LP
> +and all modifier combinations (Shift+Home, Control+Home, etc.) will
> +automatically produce the correct modified sequences without additional
> +keymap entries.
> +.LP
> +.B Note:
> +Modifier-aware key behavior requires Linux kernel 7.1 or later.
> +On older kernels, cursor keys produce their traditional unmodified
> +sequences, and Csi_* keysyms have no effect: on a console in Unicode
> +mode the corresponding keys produce no output, while on a non-Unicode
> +console
> +.BR loadkeys (1)
> +reports an error for each Csi_* entry.
> .SH ABBREVIATIONS
> Various abbreviations can be used with kbd-0.96 and later.
> .TP
> diff --git a/src/libkeymap/ksyms.c b/src/libkeymap/ksyms.c
> index 219e5f2..98d1cf3 100644
> --- a/src/libkeymap/ksyms.c
> +++ b/src/libkeymap/ksyms.c
> @@ -52,7 +52,8 @@ static const syms_entry syms[] = {
> { NULL, 0 }, /* KT_LETTER */
> E(sticky_syms), /* KT_SLOCK */
> { NULL, 0 }, /* KT_DEAD2 */
> - E(brl_syms) /* KT_BRL */
> + E(brl_syms), /* KT_BRL */
> + E(csi_syms) /* KT_CSI */
> };
In src/libkeymap/summary.c:81, you forgot to change the value of NR_TYPES.
As a result, the new KT_CSI == 15 will not appear in the output of
`dumpkeys --long-info`.
>
> #undef E
> diff --git a/src/libkeymap/syms.ktyp.h b/src/libkeymap/syms.ktyp.h
> index 504d67e..aca0fc6 100644
> --- a/src/libkeymap/syms.ktyp.h
> +++ b/src/libkeymap/syms.ktyp.h
> @@ -588,3 +588,42 @@ static const char *const brl_syms[] = {
> "Brl_dot9",
> "Brl_dot10"
> };
> +
> +/*
> + * Keysyms whose KTYP is KT_CSI.
> + * Index is the CSI parameter number for ESC [ <index> ~ sequences.
> + */
> +static const char *const csi_syms[] = {
> + "", /* 0: unused */
> + "Csi_Home", /* 1: ESC [ 1 ~ */
> + "Csi_Insert", /* 2: ESC [ 2 ~ */
> + "Csi_Delete", /* 3: ESC [ 3 ~ */
> + "Csi_End", /* 4: ESC [ 4 ~ */
> + "Csi_PgUp", /* 5: ESC [ 5 ~ */
> + "Csi_PgDn", /* 6: ESC [ 6 ~ */
> + "", "", "", "", /* 7-10: unused */
> + "Csi_F1", /* 11: ESC [ 11 ~ */
> + "Csi_F2", /* 12: ESC [ 12 ~ */
> + "Csi_F3", /* 13: ESC [ 13 ~ */
> + "Csi_F4", /* 14: ESC [ 14 ~ */
> + "Csi_F5", /* 15: ESC [ 15 ~ */
> + "", /* 16: unused */
> + "Csi_F6", /* 17: ESC [ 17 ~ */
> + "Csi_F7", /* 18: ESC [ 18 ~ */
> + "Csi_F8", /* 19: ESC [ 19 ~ */
> + "Csi_F9", /* 20: ESC [ 20 ~ */
> + "Csi_F10", /* 21: ESC [ 21 ~ */
> + "", /* 22: unused */
> + "Csi_F11", /* 23: ESC [ 23 ~ */
> + "Csi_F12", /* 24: ESC [ 24 ~ */
> + "Csi_F13", /* 25: ESC [ 25 ~ */
> + "Csi_F14", /* 26: ESC [ 26 ~ */
> + "", /* 27: unused */
> + "Csi_F15", /* 28: ESC [ 28 ~ */
> + "Csi_F16", /* 29: ESC [ 29 ~ */
> + "", /* 30: unused */
> + "Csi_F17", /* 31: ESC [ 31 ~ */
> + "Csi_F18", /* 32: ESC [ 32 ~ */
> + "Csi_F19", /* 33: ESC [ 33 ~ */
> + "Csi_F20", /* 34: ESC [ 34 ~ */
> +};
> diff --git a/tests/data/keymap0-summary.txt b/tests/data/keymap0-summary.txt
> index 0b66c06..6f757fd 100644
> --- a/tests/data/keymap0-summary.txt
> +++ b/tests/data/keymap0-summary.txt
> @@ -810,6 +810,32 @@ nr of compose definitions in actual use: 0
> 0x0e08 Brl_dot8
> 0x0e09 Brl_dot9
> 0x0e0a Brl_dot10
> +0x0f01 Csi_Home
> +0x0f02 Csi_Insert
> +0x0f03 Csi_Delete
> +0x0f04 Csi_End
> +0x0f05 Csi_PgUp
> +0x0f06 Csi_PgDn
> +0x0f0b Csi_F1
> +0x0f0c Csi_F2
> +0x0f0d Csi_F3
> +0x0f0e Csi_F4
> +0x0f0f Csi_F5
> +0x0f11 Csi_F6
> +0x0f12 Csi_F7
> +0x0f13 Csi_F8
> +0x0f14 Csi_F9
> +0x0f15 Csi_F10
> +0x0f17 Csi_F11
> +0x0f18 Csi_F12
> +0x0f19 Csi_F13
> +0x0f1a Csi_F14
> +0x0f1c Csi_F15
> +0x0f1d Csi_F16
> +0x0f1f Csi_F17
> +0x0f20 Csi_F18
> +0x0f21 Csi_F19
> +0x0f22 Csi_F20
>
> The following synonyms are recognized:
>
> --
> 2.54.0
>
--
Rgrds, legion
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 3/3] keymaps: convert include files to use CSI keysyms
2026-06-12 1:48 ` [PATCH 3/3] keymaps: convert include files to use CSI keysyms Nicolas Pitre
@ 2026-06-22 8:58 ` Alexey Gladkov
0 siblings, 0 replies; 6+ messages in thread
From: Alexey Gladkov @ 2026-06-22 8:58 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: kbd
On Thu, Jun 11, 2026 at 09:48:57PM -0400, Nicolas Pitre wrote:
> Convert the shared keymap include files to use the new Csi_* keysyms
> for function keys (F1-F12) and navigation keys (Home, End, Insert,
> Delete, PageUp, PageDown). This fixes the long-standing discrepancy
> where F1-F5 used non-standard sequences (\e[[A through \e[[E) while
> F6 and above used standard CSI sequences.
>
> The Csi_* keysyms automatically encode modifier state into the output
> sequence, so explicit shift/control bindings for F13-F36 are no longer
> needed and have been removed. The alt/control-alt bindings for console
> switching (Console_1 through Console_24) and other special actions
> (Scroll_Backward, Scroll_Forward, Boot) are preserved.
>
> Updated files:
> - linux-keys-bare.inc
> - linux-keys-extd.inc
> - linux-with-modeshift-altgr.inc
>
> Legacy versions of these files are preserved as *-legacy.inc for
> keymaps that need the old F1-F246 keysym behavior.
>
> Note: Standalone keymaps that don't use these include files (such as
> defkeymap.map and various language-specific keymaps) are not updated
> and will continue to use the legacy keysyms.
>
> Note: The Csi_* keysyms require Linux kernel 7.1 or later. Keymaps
> built from these include files will leave the function and navigation
> keys inoperative on older kernels (and loadkeys additionally reports
> errors for them on non-Unicode consoles). Systems that must run
> pre-7.1 kernels should use the *-legacy.inc include files instead.
Existing keymaps continue to include files with their original names
such as linux-keys-bare.inc, etc. After an update, they automatically
become CSI variants. The presence of *-legacy.inc files alongside them
does not help keymaps that are already installed: none of them are
selected automatically.
This patch will break systems with pre-7.1 kernel.
I need to think about how to handle such migration.
> Signed-off-by: Nicolas Pitre <nico@fluxnic.net>
> ---
> .../i386/include/linux-keys-bare-legacy.inc | 170 ++++++++++++++++++
> data/keymaps/i386/include/linux-keys-bare.inc | 76 +++-----
> .../i386/include/linux-keys-extd-legacy.inc | 37 ++++
> data/keymaps/i386/include/linux-keys-extd.inc | 23 +--
> .../linux-with-modeshift-altgr-legacy.inc | 101 +++++++++++
> .../include/linux-with-modeshift-altgr.inc | 52 ++----
> 6 files changed, 356 insertions(+), 103 deletions(-)
> create mode 100644 data/keymaps/i386/include/linux-keys-bare-legacy.inc
> create mode 100644 data/keymaps/i386/include/linux-keys-extd-legacy.inc
> create mode 100644 data/keymaps/i386/include/linux-with-modeshift-altgr-legacy.inc
>
> diff --git a/data/keymaps/i386/include/linux-with-modeshift-altgr-legacy.inc b/data/keymaps/i386/include/linux-with-modeshift-altgr-legacy.inc
> new file mode 100644
> index 0000000..29012ba
> --- /dev/null
> +++ b/data/keymaps/i386/include/linux-with-modeshift-altgr-legacy.inc
> @@ -0,0 +1,101 @@
> +# For keymaps in which AltGr_Lock is used to switch between two alphabets.
> +#
> +# A common construction is
> +# alt keycode 42 = AltGr_Lock
> +# altgr alt keycode 42 = AltGr_Lock
> +#
> +# All Linux keys have the same meaning with or without AltGr.
> +# No convention for Hex_* has been established.
> +
> +include "linux-keys-bare"
linux-with-modeshift-altgr-legacy.inc should include linux-keys-bare-legacy,
not the new linux-keys-bare.
--
Rgrds, legion
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-06-22 8:58 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-12 1:48 [PATCH 0/3] support for the kernel 7.1 modifier-aware KT_CSI keysym type Nicolas Pitre
2026-06-12 1:48 ` [PATCH 1/3] libkeymap: add support for " Nicolas Pitre
2026-06-22 8:45 ` Alexey Gladkov
2026-06-12 1:48 ` [PATCH 2/3] Add kbd-terminfo-fixup script and systemd service Nicolas Pitre
2026-06-12 1:48 ` [PATCH 3/3] keymaps: convert include files to use CSI keysyms Nicolas Pitre
2026-06-22 8:58 ` Alexey Gladkov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.