From da165fc3cf6f8ef514f8f7b52c5bdb080509aa74 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 20 Oct 2025 14:41:35 -0700 Subject: [PATCH] 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. --- src/input/key_encode.zig | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/input/key_encode.zig b/src/input/key_encode.zig index fa641c1aa..f411deb19 100644 --- a/src/input/key_encode.zig +++ b/src/input/key_encode.zig @@ -77,7 +77,7 @@ pub fn encode( event: key.KeyEvent, opts: Options, ) std.Io.Writer.Error!void { - // log.warn("KEYENCODER self={}", .{self.*}); + //std.log.warn("KEYENCODER event={} opts={}", .{ event, opts }); return if (opts.kitty_flags.int() != 0) try kitty( writer, event, @@ -411,6 +411,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 = event.mods.binding(); + // This copies xterm's `ModifyOtherKeys` function that returns // whether modify other keys should be encoded for the given // input. @@ -420,7 +424,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; @@ -435,7 +439,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 writer.print( "\x1B[27;{};{}~", .{ code, codepoint }, @@ -1970,6 +1974,20 @@ test "legacy: ctrl+shift+char with modify other state 2" { try testing.expectEqualStrings("\x1b[27;6;72~", writer.buffered()); } +test "legacy: ctrl+shift+char with modify other state 2 and consumed mods" { + var buf: [128]u8 = undefined; + var writer: std.Io.Writer = .fixed(&buf); + try legacy(&writer, .{ + .key = .key_h, + .mods = .{ .ctrl = true, .shift = true }, + .consumed_mods = .{ .shift = true }, + .utf8 = "H", + }, .{ + .modify_other_keys_state_2 = true, + }); + try testing.expectEqualStrings("\x1b[27;6;72~", writer.buffered()); +} + test "legacy: fixterm awkward letters" { var buf: [128]u8 = undefined; {