input: modify other keys 2 should use all mods, ignore consumed mods (#9289)

Fixes #8900

Our xterm modify other keys state 2 encoding was stripped consumed mods
from the keyboard event. This doesn't match xterm or other popular
terminal emulators (but most importantly: xterm). Use the full set of
mods and add a test to verify this.

Reproduction:

```
printf '\033[>4;2m'
cat
```

Then press `ctrl+shift+h` and compare across terminals.
1.2.x
Mitchell Hashimoto 2025-10-20 14:41:35 -07:00
parent d2a459b7c2
commit 36f647e875
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
1 changed files with 22 additions and 2 deletions

View File

@ -346,6 +346,10 @@ fn legacy(
// ever be a multi-codepoint sequence that triggers this.
if (it.nextCodepoint() != null) break :modify_other;
// The mods we encode for this are just the binding mods (shift, ctrl,
// super, alt).
const mods = self.event.mods.binding();
// This copies xterm's `ModifyOtherKeys` function that returns
// whether modify other keys should be encoded for the given
// input.
@ -355,7 +359,7 @@ fn legacy(
break :should_modify true;
// If we have anything other than shift pressed, encode.
var mods_no_shift = binding_mods;
var mods_no_shift = mods;
mods_no_shift.shift = false;
if (!mods_no_shift.empty()) break :should_modify true;
@ -370,7 +374,7 @@ fn legacy(
if (should_modify) {
for (function_keys.modifiers, 2..) |modset, code| {
if (!binding_mods.equal(modset)) continue;
if (!mods.equal(modset)) continue;
return try std.fmt.bufPrint(
buf,
"\x1B[27;{};{}~",
@ -1984,6 +1988,22 @@ test "legacy: ctrl+shift+char with modify other state 2" {
try testing.expectEqualStrings("\x1b[27;6;72~", actual);
}
test "legacy: ctrl+shift+char with modify other state 2 and consumed mods" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .key_h,
.mods = .{ .ctrl = true, .shift = true },
.consumed_mods = .{ .shift = true },
.utf8 = "H",
},
.modify_other_keys_state_2 = true,
};
const actual = try enc.legacy(&buf);
try testing.expectEqualStrings("\x1b[27;6;72~", actual);
}
test "legacy: fixterm awkward letters" {
var buf: [128]u8 = undefined;
{