mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
input: Kitty encodes alternate keys
This commit is contained in:
@ -51,10 +51,22 @@ fn kitty(
|
||||
|
||||
// Find the entry for this key in the kitty table.
|
||||
const entry_: ?KittyEntry = entry: {
|
||||
// Functional or predefined keys
|
||||
for (kitty_entries) |entry| {
|
||||
if (entry.key == self.event.key) break :entry entry;
|
||||
}
|
||||
|
||||
// Otherwise, we use our unicode codepoint from UTF8. We
|
||||
// always use the unshifted value.
|
||||
if (self.event.unshifted_codepoint > 0) {
|
||||
break :entry .{
|
||||
.key = self.event.key,
|
||||
.code = self.event.unshifted_codepoint,
|
||||
.final = 'u',
|
||||
.modifier = false,
|
||||
};
|
||||
}
|
||||
|
||||
break :entry null;
|
||||
};
|
||||
|
||||
@ -119,6 +131,16 @@ fn kitty(
|
||||
};
|
||||
}
|
||||
|
||||
if (self.kitty_flags.report_alternates) alternates: {
|
||||
const view = try std.unicode.Utf8View.init(self.event.utf8);
|
||||
var it = view.iterator();
|
||||
const cp = it.nextCodepoint() orelse break :alternates;
|
||||
if (it.nextCodepoint() != null) break :alternates;
|
||||
if (cp != seq.key) {
|
||||
seq.alternates = &.{cp};
|
||||
}
|
||||
}
|
||||
|
||||
if (self.kitty_flags.report_associated) {
|
||||
seq.text = self.event.utf8;
|
||||
}
|
||||
@ -521,11 +543,11 @@ const KittyMods = packed struct(u8) {
|
||||
///
|
||||
/// CSI unicode-key-code:alternate-key-codes ; modifiers:event-type ; text-as-codepoints u
|
||||
const KittySequence = struct {
|
||||
key: u16,
|
||||
key: u21,
|
||||
final: u8,
|
||||
mods: KittyMods = .{},
|
||||
event: Event = .none,
|
||||
alternates: []const u16 = &.{},
|
||||
alternates: []const u21 = &.{},
|
||||
text: []const u8 = "",
|
||||
|
||||
/// Values for the event code (see "event-type" in above comment).
|
||||
@ -777,6 +799,47 @@ test "kitty: composing with modifier" {
|
||||
try testing.expectEqualStrings("\x1b[57441;2u", actual);
|
||||
}
|
||||
|
||||
test "kitty: shift+a on US keyboard" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var enc: KeyEncoder = .{
|
||||
.event = .{
|
||||
.key = .a,
|
||||
.mods = .{ .shift = true },
|
||||
.utf8 = "A",
|
||||
.unshifted_codepoint = 97, // lowercase A
|
||||
},
|
||||
.kitty_flags = .{
|
||||
.disambiguate = true,
|
||||
.report_alternates = true,
|
||||
},
|
||||
};
|
||||
|
||||
const actual = try enc.kitty(&buf);
|
||||
try testing.expectEqualStrings("\x1b[97:65;2u", actual);
|
||||
}
|
||||
|
||||
test "kitty: matching unshifted codepoint" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var enc: KeyEncoder = .{
|
||||
.event = .{
|
||||
.key = .a,
|
||||
.mods = .{ .shift = true },
|
||||
.utf8 = "A",
|
||||
.unshifted_codepoint = 65,
|
||||
},
|
||||
.kitty_flags = .{
|
||||
.disambiguate = true,
|
||||
.report_alternates = true,
|
||||
},
|
||||
};
|
||||
|
||||
// WARNING: This is not a valid encoding. This is a hypothetical encoding
|
||||
// just to test that our logic is correct around matching unshifted
|
||||
// codepoints.
|
||||
const actual = try enc.kitty(&buf);
|
||||
try testing.expectEqualStrings("\x1b[65;2u", actual);
|
||||
}
|
||||
|
||||
test "legacy: ctrl+alt+c" {
|
||||
var buf: [128]u8 = undefined;
|
||||
var enc: KeyEncoder = .{
|
||||
|
@ -6,7 +6,7 @@ const key = @import("key.zig");
|
||||
/// for a given key.
|
||||
pub const Entry = struct {
|
||||
key: key.Key,
|
||||
code: u16,
|
||||
code: u21,
|
||||
final: u8,
|
||||
modifier: bool,
|
||||
};
|
||||
@ -28,7 +28,7 @@ pub const entries: []const Entry = entries: {
|
||||
/// Raw entry is the tuple form of an entry for easy human management.
|
||||
/// This should never be used in a real program so it is not pub. For
|
||||
/// real programs, use `entries` which has properly typed, structured data.
|
||||
const RawEntry = struct { key.Key, u16, u8, bool };
|
||||
const RawEntry = struct { key.Key, u21, u8, bool };
|
||||
|
||||
/// The raw data for how to map keys to Kitty data. Based on the information:
|
||||
/// https://sw.kovidgoyal.net/kitty/keyboard-protocol/#functional-key-definitions
|
||||
|
Reference in New Issue
Block a user