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