Re: [PATCH v2 0/3] support for the kernel 7.1 modifier-aware KT_CSI keysym type
Nicolas Pitre <[email protected]> Thu, 25 Jun 2026 12:28:44 -0400 (EDT)
| Newsgroups | dev.linux.lists.kbd |
|---|---|
| Message-ID | <[email protected]> |
On Wed, 24 Jun 2026, Alexey Gladkov wrote:
> On Tue, Jun 23, 2026 at 06:48:55PM -0400, Nicolas Pitre wrote:
> > 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.
>
> Here's what's bothering me. These patches disrupt the logic behind how
> keymaps work.
>
> Previously, userspace determined which modifier key should generate which
> sequence. We had `string F1 = "\033[[A"` and use it in any position:
> `alt keycode 16 = F1`.
That mechanism is untouched. KT_FN strings behave exactly as before and
can still be placed in any position. KT_CSI does not replace them; it is
an additional keysym type alongside them.
> After your patches, modifier handling has been moved to the kernel.
> The escape sequence `ESC[11;03~` will be generated only if Csi_F1 is set
> to `alt keycode 16 = Csi_F1`. So, for Csi_*, the modifier has taken on
> a special meaning. I can't bind the Alt+Csi_F1 sequence to any other
> modifier key.
I think this conflates two separate things, and the one that matters
isn't actually constrained.
1. Csi_F1 does not take over the modifier columns. The kernel only falls
back to the plain entry when the modifier-specific slot is empty.
From c1d2deb6492f ("vt: add fallback to plain map for modifier-aware
key types"):
if (shift_final && keycode < NR_KEYS &&
(!key_map || key_map[keycode] == K_HOLE) && key_maps[0]) {
...
if (type - 0xf0 == KT_CUR || type - 0xf0 == KT_CSI)
key_map = key_maps[0];
}
As soon as you bind, say, shift keycode 16 = Foo, that slot is no
longer K_HOLE, the condition is false, and your explicit binding is
used -- the automatic encoding never runs. The commit log says as
much: "Explicit modifier bindings still take precedence - the
fallback only triggers when the modifier-specific entry is empty." So
the keymap author keeps full control; Csi_F1 in the plain slot is
merely the default for the modifier combinations you leave unbound.
2. What you genuinely cannot do is make the Csi_F1 keysym emit an
encoding that disagrees with the keys physically held -- e.g. get the
Alt form ESC[11;3~ out of a Control press. That is deliberate: k_csi
reads the live modifier state, exactly like xterm, foot, kitty and
every other terminal that speaks these sequences. But if you want a
fixed, hand-picked sequence on a given modifier, that is precisely
what KT_FN strings are for, and they still work in any column:
string AltF1 = "\033[11;3~"
control keycode 16 = AltF1
So nothing that was possible before is lost. KT_CSI is opt-in and
purely additive: it trades manual per-column control of a CSI
sequence's modifier field (which strings still give you) for not
having to enumerate -- and exhaust func_table with -- one string per
modifier combination. That is the whole reason the kernel side
exists.
Nor is this a new departure for the keymap model: KT_CUR arrow keys
already derive their output from runtime state (VC_CKMODE), as does
KT_PAD (VC_APPLIC), and KT_CONS/KT_SHIFT/dead keys have never been
userspace strings either. A keysym type with kernel-defined,
state-dependent behavior is the norm, not the exception; KT_CSI
simply joins that set.
Nicolas