mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-09-14 18:01:58 +00:00
input: encode ctrl keys with modifyOtherKeys 2 (#14144)
#7425 Control-modified characters use xterm's MOK2 encoding. I incorrectly believed previously that MOK2 ctrl chars were still encoded as C0 bytes. This is wrong. I'm going to do a more in depth audit if possible with every possible key combination against xterm to see where we diverge but this fixes this for now without regressing any tests. Background: https://invisible-island.net/xterm/modified-keys.html
This commit is contained in:
@@ -379,42 +379,10 @@ fn legacy(
|
||||
return try writer.writeAll(sequence);
|
||||
}
|
||||
|
||||
// If we match a control sequence, we output that directly. For
|
||||
// ctrlSeq we have to use all mods because we want it to only
|
||||
// match ctrl+<char>.
|
||||
if (ctrlSeq(
|
||||
event.key,
|
||||
event.utf8,
|
||||
event.unshifted_codepoint,
|
||||
all_mods,
|
||||
)) |char| {
|
||||
// C0 sequences support alt-as-esc prefixing.
|
||||
if (binding_mods.alt) {
|
||||
try writer.writeByte(0x1B);
|
||||
try writer.writeByte(char);
|
||||
return;
|
||||
}
|
||||
|
||||
try writer.writeByte(char);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have no UTF8 text then the only possibility is the
|
||||
// alt-prefix handling of unshifted codepoints... so we process that.
|
||||
const utf8 = event.utf8;
|
||||
if (utf8.len == 0) {
|
||||
if (try legacyAltPrefix(
|
||||
event,
|
||||
binding_mods,
|
||||
all_mods,
|
||||
opts,
|
||||
)) |byte| try writer.print("\x1B{c}", .{byte});
|
||||
return;
|
||||
}
|
||||
|
||||
// In modify other keys state 2, we send the CSI 27 sequence
|
||||
// for any char with a modifier. Ctrl sequences like Ctrl+a
|
||||
// are already handled above.
|
||||
// for any char with a modifier. This must happen before converting
|
||||
// Ctrl+<char> to a C0 byte because mode 2 encodes those keys, too.
|
||||
const utf8 = event.utf8;
|
||||
if (opts.modify_other_keys_state_2) modify_other: {
|
||||
const view = std.unicode.Utf8View.init(utf8) catch {
|
||||
// Assume invalid UTF-8 means we no UTF-8.
|
||||
@@ -476,6 +444,38 @@ fn legacy(
|
||||
}
|
||||
}
|
||||
|
||||
// If we match a control sequence, we output that directly. For
|
||||
// ctrlSeq we have to use all mods because we want it to only
|
||||
// match ctrl+<char>.
|
||||
if (ctrlSeq(
|
||||
event.key,
|
||||
event.utf8,
|
||||
event.unshifted_codepoint,
|
||||
all_mods,
|
||||
)) |char| {
|
||||
// C0 sequences support alt-as-esc prefixing.
|
||||
if (binding_mods.alt) {
|
||||
try writer.writeByte(0x1B);
|
||||
try writer.writeByte(char);
|
||||
return;
|
||||
}
|
||||
|
||||
try writer.writeByte(char);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have no UTF8 text then the only possibility is the
|
||||
// alt-prefix handling of unshifted codepoints... so we process that.
|
||||
if (utf8.len == 0) {
|
||||
if (try legacyAltPrefix(
|
||||
event,
|
||||
binding_mods,
|
||||
all_mods,
|
||||
opts,
|
||||
)) |byte| try writer.print("\x1B{c}", .{byte});
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's see if we should apply fixterms to this codepoint.
|
||||
// At this stage of key processing, we only need to apply fixterms
|
||||
// to unicode codepoints if we have ctrl set.
|
||||
@@ -2219,6 +2219,30 @@ test "legacy: ctrl+shift+char with modify other state 2" {
|
||||
try testing.expectEqualStrings("\x1b[27;6;72~", writer.buffered());
|
||||
}
|
||||
|
||||
test "legacy: ctrl+char with modify other state 2" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
try legacy(&writer, .{
|
||||
.key = .key_p,
|
||||
.mods = .{ .ctrl = true },
|
||||
.utf8 = "p",
|
||||
}, .{
|
||||
.modify_other_keys_state_2 = true,
|
||||
});
|
||||
try testing.expectEqualStrings("\x1b[27;5;112~", writer.buffered());
|
||||
}
|
||||
|
||||
test "legacy: ctrl+char without modify other state 2" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var writer: std.Io.Writer = .fixed(&buf);
|
||||
try legacy(&writer, .{
|
||||
.key = .key_p,
|
||||
.mods = .{ .ctrl = true },
|
||||
.utf8 = "p",
|
||||
}, .{});
|
||||
try testing.expectEqualStrings("\x10", 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);
|
||||
|
||||
Reference in New Issue
Block a user