Re: [PATCH v2 0/3] support for the kernel 7.1 modifier-aware KT_CSI keysym type

Alexey Gladkov <[email protected]> Thu, 25 Jun 2026 23:40:23 +0200
Newsgroups dev.linux.lists.kbd
Message-ID <[email protected]>
On Thu, Jun 25, 2026 at 12:28:44PM -0400, Nicolas Pitre wrote:
> 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.

I guess I didn't mean it that way. I didn't say you broke KT_FN. You broke
KT_CUR.

> > 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.

Yes, the old mechanism (KT_FN) still exists and can still be used.

What I'm trying to say is that Csi_* significantly changes the user
experience. If now the user controls what will be in which position.
However, Csi_F1 changes its output depending on the active modifiers.

KT_CONS is a bad example. KT_CONS is just a separate type. I can even
assign it to Ctrl-X to switch to my especially favorite console. I can use
Console_63 anywhere in the keymap, and it will always take me to console
63 and it will work regardless of any active modifiers. 

It's the same story with KT_PAD/KT_DEAD. You can put them anywhere you
like in the keymap and they will behave the same way.

That's not the case with KT_CSI.

Let me give you another example. In the last release, I implemented
initial support for converting xkb keymaps to kernel keymaps. The
conversion generates a keymap on the fly from xkbcommon. xkbsupport
encodes layout/group using KG_SHIFTL and KG_SHIFTR. So a single
combination cycles through several layouts:

- group 1: plain
- group 2: shiftl
- group 3: shiftr
- group 4: shiftl | shiftr

(this idea isn't new. It has been used in debian for a long time in the
console-setup, and also in ubuntu and some others).

This makes it impossible to use Csi_* in it, since Csi_F1 in the second
layout will be recognized by the kernel as "F1 with Shift".

And this seems to apply not only to KT_CSI, but also to the existing
KT_CUR: k_cur() uses the same csi_modifier_param(). If the arrows end up
in a layout group other than the first one via shiftl/shiftr, an extra
Shift modifier will be generated in the escape sequence. And that's a real
regression in userspace.

I hope I've made my concerns more clear.

-- 
Rgrds, legion