input: CSIu should send full codepoint

Related to #1802

CSIu format sends a unicode codepoint but we were just sending the first
byte of the utf8 sequence, which is very much not right. This fixes that
by parsing the utf-8.

It isn't defined what to do if the utf-8 sequence is invalid or has
multiple codepoints so we just skip CSIu encoding in that case.
This commit is contained in:
Mitchell Hashimoto
2024-06-02 14:36:42 -07:00
parent 1551c27578
commit 1fae17d1ef

View File

@ -358,15 +358,21 @@ fn legacy(
// Let's see if we should apply fixterms to this codepoint. // Let's see if we should apply fixterms to this codepoint.
// At this stage of key processing, we only need to apply fixterms // At this stage of key processing, we only need to apply fixterms
// to unicode codepoints if we have ctrl set. // to unicode codepoints if we have ctrl set.
if (self.event.mods.ctrl) { if (self.event.mods.ctrl) csiu: {
// Important: we want to use the original mods here, not the // Important: we want to use the original mods here, not the
// effective mods. The fixterms spec states the shifted chars // effective mods. The fixterms spec states the shifted chars
// should be sent uppercase but Kitty changes that behavior // should be sent uppercase but Kitty changes that behavior
// so we'll send all the mods. // so we'll send all the mods.
const csi_u_mods, const char = mods: { const csi_u_mods, const char = mods: {
var char: u21 = @intCast(utf8[0]);
var mods = CsiUMods.fromInput(self.event.mods); var mods = CsiUMods.fromInput(self.event.mods);
// Get our codepoint. If we have more than one codepoint this
// can't be valid CSIu.
const view = std.unicode.Utf8View.init(self.event.utf8) catch break :csiu;
var it = view.iterator();
var char = it.nextCodepoint() orelse break :csiu;
if (it.nextCodepoint() != null) break :csiu;
// If our character is A to Z and we have shift set, then // If our character is A to Z and we have shift set, then
// we lowercase it. This is a Kitty-specific behavior that // we lowercase it. This is a Kitty-specific behavior that
// we choose to follow and diverge from the fixterms spec. // we choose to follow and diverge from the fixterms spec.
@ -2113,6 +2119,21 @@ test "legacy: right_shift+tab" {
try testing.expectEqualStrings("\x1b[Z", actual); try testing.expectEqualStrings("\x1b[Z", actual);
} }
test "legacy: hu layout ctrl+ő sends proper codepoint" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .left_bracket,
.physical_key = .left_bracket,
.mods = .{ .ctrl = true },
.utf8 = "ő",
.unshifted_codepoint = 337,
},
};
const actual = try enc.legacy(&buf);
try testing.expectEqualStrings("[337;5u", actual[1..]);
}
test "ctrlseq: normal ctrl c" { test "ctrlseq: normal ctrl c" {
const seq = ctrlSeq("c", 'c', .{ .ctrl = true }); const seq = ctrlSeq("c", 'c', .{ .ctrl = true });
try testing.expectEqual(@as(u8, 0x03), seq.?); try testing.expectEqual(@as(u8, 0x03), seq.?);