Don't encode option as alt in modify other keys 2 (#9406)
There have been frequent reports of key encoding issues in vim and tmux with version 1.2.3 on macOS: #9340, #9361, #9401, https://discord.com/channels/1005603569187160125/1432413679806320772. I think I found the culprit: the option modifier is always passed as alt to the core, regardless of `macos-option-as-alt`. Since #9289, this means that a key event where option was used (as option) for translation is encoded as if it also has the alt modifier. For example, consider the many European keyboard layouts where option+8 sends `[`. If `macos-option-as-alt = true`, Ghostty correctly intercepts the option and encodes option+8 as alt+8 instead (that is, `^[[27;3;56~`). But if `macos-option-as-alt = false`, Ghostty first allows option to be used for translation, obtaining `[`, and then encodes the key event as alt+[ (that is, `^[[27;3;91~`), rather than just `[`. Tweaking the test case from #9289, here's a quick way to see this: set `macos-option-as-alt = left`, run ``` printf '\033[>4;2m' cat ``` choose a European keyboard layout (e.g., Norwegian), and hit both left-option+8 and right-option+8. The former inserts `^[[27;3;56~` in all well-behaved terminals. The latter inserts `[` in other terminals, but `^[[27;3;91~` in Ghostty. Basically, while modify other keys 2 does require encoding consumed modifiers, the option key is not one of the supported modifiers, and should not be included (as alt or anything else) when `macos-option-as-alt = false`. This PR removes alts that were actually options when using modify other keys 2.pull/9407/head
parent
a4d54dca1c
commit
e70ca0b9b5
|
|
@ -412,8 +412,20 @@ fn legacy(
|
|||
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();
|
||||
// super, alt unless it is actually option).
|
||||
const mods = mods: {
|
||||
var mods_binding = event.mods.binding();
|
||||
if (comptime builtin.target.os.tag.isDarwin()) alt: {
|
||||
switch (opts.macos_option_as_alt) {
|
||||
.false => {},
|
||||
.true => break :alt,
|
||||
.left => if (event.mods.sides.alt == .left) break :alt,
|
||||
.right => if (event.mods.sides.alt == .right) break :alt,
|
||||
}
|
||||
mods_binding.alt = false;
|
||||
}
|
||||
break :mods mods_binding;
|
||||
};
|
||||
|
||||
// This copies xterm's `ModifyOtherKeys` function that returns
|
||||
// whether modify other keys should be encoded for the given
|
||||
|
|
@ -1988,6 +2000,37 @@ test "legacy: ctrl+shift+char with modify other state 2 and consumed mods" {
|
|||
try testing.expectEqualStrings("\x1b[27;6;72~", writer.buffered());
|
||||
}
|
||||
|
||||
test "legacy: alt+digit with modify other state 2" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
try legacy(&writer, .{
|
||||
.key = .digit_8,
|
||||
.mods = .{ .alt = true },
|
||||
.consumed_mods = .{},
|
||||
.utf8 = "8",
|
||||
}, .{
|
||||
.modify_other_keys_state_2 = true,
|
||||
.macos_option_as_alt = .true,
|
||||
});
|
||||
try testing.expectEqualStrings("\x1b[27;3;56~", writer.buffered());
|
||||
}
|
||||
|
||||
test "legacy: alt+digit with modify other state 2 and macos-option-as-alt = false" {
|
||||
if (comptime builtin.os.tag != .macos) return error.SkipZigTest;
|
||||
var buf: [128]u8 = undefined;
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
try legacy(&writer, .{
|
||||
.key = .digit_8,
|
||||
.mods = .{ .alt = true },
|
||||
.consumed_mods = .{ .alt = true },
|
||||
.utf8 = "[", // common translation of option+8 with European keyboard layouts
|
||||
}, .{
|
||||
.modify_other_keys_state_2 = true,
|
||||
.macos_option_as_alt = .false,
|
||||
});
|
||||
try testing.expectEqualStrings("[", writer.buffered());
|
||||
}
|
||||
|
||||
test "legacy: fixterm awkward letters" {
|
||||
var buf: [128]u8 = undefined;
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue