input: remove translated

This commit is contained in:
Mitchell Hashimoto
2025-05-08 08:47:21 -07:00
parent 91d15c89bc
commit a3462dd2bd
9 changed files with 481 additions and 570 deletions

3
NOTES.md Normal file
View File

@ -0,0 +1,3 @@
- key backwards compatibility, e.g. `grave_accent`
- `physical:` backwards compatibility?

View File

@ -4343,12 +4343,12 @@ pub const Keybinds = struct {
// keybinds for opening and reloading config
try self.set.put(
alloc,
.{ .key = .{ .translated = .comma }, .mods = inputpkg.ctrlOrSuper(.{ .shift = true }) },
.{ .key = .{ .unicode = ',' }, .mods = inputpkg.ctrlOrSuper(.{ .shift = true }) },
.{ .reload_config = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .comma }, .mods = inputpkg.ctrlOrSuper(.{}) },
.{ .key = .{ .unicode = ',' }, .mods = inputpkg.ctrlOrSuper(.{}) },
.{ .open_config = {} },
);
@ -4362,12 +4362,12 @@ pub const Keybinds = struct {
if (!builtin.target.os.tag.isDarwin()) {
try self.set.put(
alloc,
.{ .key = .{ .translated = .insert }, .mods = .{ .ctrl = true } },
.{ .key = .{ .physical = .insert }, .mods = .{ .ctrl = true } },
.{ .copy_to_clipboard = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .insert }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .insert }, .mods = .{ .shift = true } },
.{ .paste_from_clipboard = {} },
);
}
@ -4381,12 +4381,12 @@ pub const Keybinds = struct {
try self.set.put(
alloc,
.{ .key = .{ .translated = .c }, .mods = mods },
.{ .key = .{ .unicode = 'c' }, .mods = mods },
.{ .copy_to_clipboard = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .v }, .mods = mods },
.{ .key = .{ .unicode = 'v' }, .mods = mods },
.{ .paste_from_clipboard = {} },
);
}
@ -4397,84 +4397,84 @@ pub const Keybinds = struct {
// set the expected keybind for the menu.
try self.set.put(
alloc,
.{ .key = .{ .translated = .plus }, .mods = inputpkg.ctrlOrSuper(.{}) },
.{ .key = .{ .unicode = '+' }, .mods = inputpkg.ctrlOrSuper(.{}) },
.{ .increase_font_size = 1 },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .equal }, .mods = inputpkg.ctrlOrSuper(.{}) },
.{ .key = .{ .physical = .equal }, .mods = inputpkg.ctrlOrSuper(.{}) },
.{ .increase_font_size = 1 },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .minus }, .mods = inputpkg.ctrlOrSuper(.{}) },
.{ .key = .{ .physical = .minus }, .mods = inputpkg.ctrlOrSuper(.{}) },
.{ .decrease_font_size = 1 },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .zero }, .mods = inputpkg.ctrlOrSuper(.{}) },
.{ .key = .{ .physical = .digit_0 }, .mods = inputpkg.ctrlOrSuper(.{}) },
.{ .reset_font_size = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .j }, .mods = inputpkg.ctrlOrSuper(.{ .shift = true }) },
.{ .key = .{ .unicode = 'j' }, .mods = inputpkg.ctrlOrSuper(.{ .shift = true }) },
.{ .write_screen_file = .paste },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .j }, .mods = inputpkg.ctrlOrSuper(.{ .shift = true, .alt = true }) },
.{ .key = .{ .unicode = 'j' }, .mods = inputpkg.ctrlOrSuper(.{ .shift = true, .alt = true }) },
.{ .write_screen_file = .open },
);
// Expand Selection
try self.set.putFlags(
alloc,
.{ .key = .{ .translated = .left }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .arrow_left }, .mods = .{ .shift = true } },
.{ .adjust_selection = .left },
.{ .performable = true },
);
try self.set.putFlags(
alloc,
.{ .key = .{ .translated = .right }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .arrow_right }, .mods = .{ .shift = true } },
.{ .adjust_selection = .right },
.{ .performable = true },
);
try self.set.putFlags(
alloc,
.{ .key = .{ .translated = .up }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .arrow_up }, .mods = .{ .shift = true } },
.{ .adjust_selection = .up },
.{ .performable = true },
);
try self.set.putFlags(
alloc,
.{ .key = .{ .translated = .down }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .arrow_down }, .mods = .{ .shift = true } },
.{ .adjust_selection = .down },
.{ .performable = true },
);
try self.set.putFlags(
alloc,
.{ .key = .{ .translated = .page_up }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .page_up }, .mods = .{ .shift = true } },
.{ .adjust_selection = .page_up },
.{ .performable = true },
);
try self.set.putFlags(
alloc,
.{ .key = .{ .translated = .page_down }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .page_down }, .mods = .{ .shift = true } },
.{ .adjust_selection = .page_down },
.{ .performable = true },
);
try self.set.putFlags(
alloc,
.{ .key = .{ .translated = .home }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .home }, .mods = .{ .shift = true } },
.{ .adjust_selection = .home },
.{ .performable = true },
);
try self.set.putFlags(
alloc,
.{ .key = .{ .translated = .end }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .end }, .mods = .{ .shift = true } },
.{ .adjust_selection = .end },
.{ .performable = true },
);
@ -4482,12 +4482,12 @@ pub const Keybinds = struct {
// Tabs common to all platforms
try self.set.put(
alloc,
.{ .key = .{ .translated = .tab }, .mods = .{ .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .tab }, .mods = .{ .ctrl = true, .shift = true } },
.{ .previous_tab = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .tab }, .mods = .{ .ctrl = true } },
.{ .key = .{ .physical = .tab }, .mods = .{ .ctrl = true } },
.{ .next_tab = {} },
);
@ -4495,174 +4495,174 @@ pub const Keybinds = struct {
if (comptime !builtin.target.os.tag.isDarwin()) {
try self.set.put(
alloc,
.{ .key = .{ .translated = .n }, .mods = .{ .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .n }, .mods = .{ .ctrl = true, .shift = true } },
.{ .new_window = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .w }, .mods = .{ .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .w }, .mods = .{ .ctrl = true, .shift = true } },
.{ .close_surface = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .q }, .mods = .{ .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .q }, .mods = .{ .ctrl = true, .shift = true } },
.{ .quit = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .f4 }, .mods = .{ .alt = true } },
.{ .key = .{ .physical = .f4 }, .mods = .{ .alt = true } },
.{ .close_window = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .t }, .mods = .{ .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .t }, .mods = .{ .ctrl = true, .shift = true } },
.{ .new_tab = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .w }, .mods = .{ .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .w }, .mods = .{ .ctrl = true, .shift = true } },
.{ .close_tab = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .left }, .mods = .{ .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .left }, .mods = .{ .ctrl = true, .shift = true } },
.{ .previous_tab = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .right }, .mods = .{ .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .right }, .mods = .{ .ctrl = true, .shift = true } },
.{ .next_tab = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .page_up }, .mods = .{ .ctrl = true } },
.{ .key = .{ .physical = .page_up }, .mods = .{ .ctrl = true } },
.{ .previous_tab = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .page_down }, .mods = .{ .ctrl = true } },
.{ .key = .{ .physical = .page_down }, .mods = .{ .ctrl = true } },
.{ .next_tab = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .o }, .mods = .{ .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .o }, .mods = .{ .ctrl = true, .shift = true } },
.{ .new_split = .right },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .e }, .mods = .{ .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .e }, .mods = .{ .ctrl = true, .shift = true } },
.{ .new_split = .down },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .left_bracket }, .mods = .{ .ctrl = true, .super = true } },
.{ .key = .{ .physical = .bracket_left }, .mods = .{ .ctrl = true, .super = true } },
.{ .goto_split = .previous },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .right_bracket }, .mods = .{ .ctrl = true, .super = true } },
.{ .key = .{ .physical = .bracket_right }, .mods = .{ .ctrl = true, .super = true } },
.{ .goto_split = .next },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .up }, .mods = .{ .ctrl = true, .alt = true } },
.{ .key = .{ .physical = .up }, .mods = .{ .ctrl = true, .alt = true } },
.{ .goto_split = .up },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .down }, .mods = .{ .ctrl = true, .alt = true } },
.{ .key = .{ .physical = .down }, .mods = .{ .ctrl = true, .alt = true } },
.{ .goto_split = .down },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .left }, .mods = .{ .ctrl = true, .alt = true } },
.{ .key = .{ .physical = .left }, .mods = .{ .ctrl = true, .alt = true } },
.{ .goto_split = .left },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .right }, .mods = .{ .ctrl = true, .alt = true } },
.{ .key = .{ .physical = .right }, .mods = .{ .ctrl = true, .alt = true } },
.{ .goto_split = .right },
);
// Resizing splits
try self.set.put(
alloc,
.{ .key = .{ .translated = .up }, .mods = .{ .super = true, .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .up }, .mods = .{ .super = true, .ctrl = true, .shift = true } },
.{ .resize_split = .{ .up, 10 } },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .down }, .mods = .{ .super = true, .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .down }, .mods = .{ .super = true, .ctrl = true, .shift = true } },
.{ .resize_split = .{ .down, 10 } },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .left }, .mods = .{ .super = true, .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .left }, .mods = .{ .super = true, .ctrl = true, .shift = true } },
.{ .resize_split = .{ .left, 10 } },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .right }, .mods = .{ .super = true, .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .right }, .mods = .{ .super = true, .ctrl = true, .shift = true } },
.{ .resize_split = .{ .right, 10 } },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .plus }, .mods = .{ .super = true, .ctrl = true, .shift = true } },
.{ .key = .{ .physical = .plus }, .mods = .{ .super = true, .ctrl = true, .shift = true } },
.{ .equalize_splits = {} },
);
// Viewport scrolling
try self.set.put(
alloc,
.{ .key = .{ .translated = .home }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .home }, .mods = .{ .shift = true } },
.{ .scroll_to_top = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .end }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .end }, .mods = .{ .shift = true } },
.{ .scroll_to_bottom = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .page_up }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .page_up }, .mods = .{ .shift = true } },
.{ .scroll_page_up = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .page_down }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .page_down }, .mods = .{ .shift = true } },
.{ .scroll_page_down = {} },
);
// Semantic prompts
try self.set.put(
alloc,
.{ .key = .{ .translated = .page_up }, .mods = .{ .shift = true, .ctrl = true } },
.{ .key = .{ .physical = .page_up }, .mods = .{ .shift = true, .ctrl = true } },
.{ .jump_to_prompt = -1 },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .page_down }, .mods = .{ .shift = true, .ctrl = true } },
.{ .key = .{ .physical = .page_down }, .mods = .{ .shift = true, .ctrl = true } },
.{ .jump_to_prompt = 1 },
);
// Inspector, matching Chromium
try self.set.put(
alloc,
.{ .key = .{ .translated = .i }, .mods = .{ .shift = true, .ctrl = true } },
.{ .key = .{ .physical = .i }, .mods = .{ .shift = true, .ctrl = true } },
.{ .inspector = .toggle },
);
// Terminal
try self.set.put(
alloc,
.{ .key = .{ .translated = .a }, .mods = .{ .shift = true, .ctrl = true } },
.{ .key = .{ .physical = .a }, .mods = .{ .shift = true, .ctrl = true } },
.{ .select_all = {} },
);
// Selection clipboard paste
try self.set.put(
alloc,
.{ .key = .{ .translated = .insert }, .mods = .{ .shift = true } },
.{ .key = .{ .physical = .insert }, .mods = .{ .shift = true } },
.{ .paste_from_selection = {} },
);
}
@ -4675,23 +4675,14 @@ pub const Keybinds = struct {
.{ .alt = true };
// Cmd+N for goto tab N
const start = @intFromEnum(inputpkg.Key.one);
const end = @intFromEnum(inputpkg.Key.eight);
var i: usize = start;
const start: u21 = '1';
const end: u21 = '8';
var i: u21 = start;
while (i <= end) : (i += 1) {
try self.set.put(
alloc,
.{
// On macOS, we use the physical key for tab changing so
// that this works across all keyboard layouts. This may
// want to be true on other platforms as well but this
// is definitely true on macOS so we just do it here for
// now (#817)
.key = if (comptime builtin.target.os.tag.isDarwin())
.{ .physical = @enumFromInt(i) }
else
.{ .translated = @enumFromInt(i) },
.key = .{ .unicode = i },
.mods = mods,
},
.{ .goto_tab = (i - start) + 1 },
@ -4700,10 +4691,7 @@ pub const Keybinds = struct {
try self.set.put(
alloc,
.{
.key = if (comptime builtin.target.os.tag.isDarwin())
.{ .physical = .nine }
else
.{ .translated = .nine },
.key = .{ .unicode = '9' },
.mods = mods,
},
.{ .last_tab = {} },
@ -4713,14 +4701,14 @@ pub const Keybinds = struct {
// Toggle fullscreen
try self.set.put(
alloc,
.{ .key = .{ .translated = .enter }, .mods = inputpkg.ctrlOrSuper(.{}) },
.{ .key = .{ .physical = .enter }, .mods = inputpkg.ctrlOrSuper(.{}) },
.{ .toggle_fullscreen = {} },
);
// Toggle zoom a split
try self.set.put(
alloc,
.{ .key = .{ .translated = .enter }, .mods = inputpkg.ctrlOrSuper(.{ .shift = true }) },
.{ .key = .{ .physical = .enter }, .mods = inputpkg.ctrlOrSuper(.{ .shift = true }) },
.{ .toggle_split_zoom = {} },
);
@ -4728,199 +4716,199 @@ pub const Keybinds = struct {
if (comptime builtin.target.os.tag.isDarwin()) {
try self.set.put(
alloc,
.{ .key = .{ .translated = .q }, .mods = .{ .super = true } },
.{ .key = .{ .unicode = 'q' }, .mods = .{ .super = true } },
.{ .quit = {} },
);
try self.set.putFlags(
alloc,
.{ .key = .{ .translated = .k }, .mods = .{ .super = true } },
.{ .key = .{ .unicode = 'k' }, .mods = .{ .super = true } },
.{ .clear_screen = {} },
.{ .performable = true },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .a }, .mods = .{ .super = true } },
.{ .key = .{ .unicode = 'a' }, .mods = .{ .super = true } },
.{ .select_all = {} },
);
// Viewport scrolling
try self.set.put(
alloc,
.{ .key = .{ .translated = .home }, .mods = .{ .super = true } },
.{ .key = .{ .physical = .home }, .mods = .{ .super = true } },
.{ .scroll_to_top = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .end }, .mods = .{ .super = true } },
.{ .key = .{ .physical = .end }, .mods = .{ .super = true } },
.{ .scroll_to_bottom = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .page_up }, .mods = .{ .super = true } },
.{ .key = .{ .physical = .page_up }, .mods = .{ .super = true } },
.{ .scroll_page_up = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .page_down }, .mods = .{ .super = true } },
.{ .key = .{ .physical = .page_down }, .mods = .{ .super = true } },
.{ .scroll_page_down = {} },
);
// Semantic prompts
try self.set.put(
alloc,
.{ .key = .{ .translated = .up }, .mods = .{ .super = true, .shift = true } },
.{ .key = .{ .physical = .arrow_up }, .mods = .{ .super = true, .shift = true } },
.{ .jump_to_prompt = -1 },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .down }, .mods = .{ .super = true, .shift = true } },
.{ .key = .{ .physical = .arrow_down }, .mods = .{ .super = true, .shift = true } },
.{ .jump_to_prompt = 1 },
);
// Mac windowing
try self.set.put(
alloc,
.{ .key = .{ .translated = .n }, .mods = .{ .super = true } },
.{ .key = .{ .unicode = 'n' }, .mods = .{ .super = true } },
.{ .new_window = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .w }, .mods = .{ .super = true } },
.{ .key = .{ .unicode = 'w' }, .mods = .{ .super = true } },
.{ .close_surface = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .w }, .mods = .{ .super = true, .alt = true } },
.{ .key = .{ .unicode = 'w' }, .mods = .{ .super = true, .alt = true } },
.{ .close_tab = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .w }, .mods = .{ .super = true, .shift = true } },
.{ .key = .{ .unicode = 'w' }, .mods = .{ .super = true, .shift = true } },
.{ .close_window = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .w }, .mods = .{ .super = true, .shift = true, .alt = true } },
.{ .key = .{ .unicode = 'w' }, .mods = .{ .super = true, .shift = true, .alt = true } },
.{ .close_all_windows = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .t }, .mods = .{ .super = true } },
.{ .key = .{ .unicode = 't' }, .mods = .{ .super = true } },
.{ .new_tab = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .left_bracket }, .mods = .{ .super = true, .shift = true } },
.{ .key = .{ .physical = .bracket_left }, .mods = .{ .super = true, .shift = true } },
.{ .previous_tab = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .right_bracket }, .mods = .{ .super = true, .shift = true } },
.{ .key = .{ .physical = .bracket_right }, .mods = .{ .super = true, .shift = true } },
.{ .next_tab = {} },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .d }, .mods = .{ .super = true } },
.{ .key = .{ .unicode = 'd' }, .mods = .{ .super = true } },
.{ .new_split = .right },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .d }, .mods = .{ .super = true, .shift = true } },
.{ .key = .{ .unicode = 'd' }, .mods = .{ .super = true, .shift = true } },
.{ .new_split = .down },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .left_bracket }, .mods = .{ .super = true } },
.{ .key = .{ .physical = .bracket_left }, .mods = .{ .super = true } },
.{ .goto_split = .previous },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .right_bracket }, .mods = .{ .super = true } },
.{ .key = .{ .physical = .bracket_right }, .mods = .{ .super = true } },
.{ .goto_split = .next },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .up }, .mods = .{ .super = true, .alt = true } },
.{ .key = .{ .physical = .arrow_up }, .mods = .{ .super = true, .alt = true } },
.{ .goto_split = .up },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .down }, .mods = .{ .super = true, .alt = true } },
.{ .key = .{ .physical = .arrow_down }, .mods = .{ .super = true, .alt = true } },
.{ .goto_split = .down },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .left }, .mods = .{ .super = true, .alt = true } },
.{ .key = .{ .physical = .arrow_left }, .mods = .{ .super = true, .alt = true } },
.{ .goto_split = .left },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .right }, .mods = .{ .super = true, .alt = true } },
.{ .key = .{ .physical = .arrow_right }, .mods = .{ .super = true, .alt = true } },
.{ .goto_split = .right },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .up }, .mods = .{ .super = true, .ctrl = true } },
.{ .key = .{ .physical = .arrow_up }, .mods = .{ .super = true, .ctrl = true } },
.{ .resize_split = .{ .up, 10 } },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .down }, .mods = .{ .super = true, .ctrl = true } },
.{ .key = .{ .physical = .arrow_down }, .mods = .{ .super = true, .ctrl = true } },
.{ .resize_split = .{ .down, 10 } },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .left }, .mods = .{ .super = true, .ctrl = true } },
.{ .key = .{ .physical = .arrow_left }, .mods = .{ .super = true, .ctrl = true } },
.{ .resize_split = .{ .left, 10 } },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .right }, .mods = .{ .super = true, .ctrl = true } },
.{ .key = .{ .physical = .arrow_right }, .mods = .{ .super = true, .ctrl = true } },
.{ .resize_split = .{ .right, 10 } },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .equal }, .mods = .{ .super = true, .ctrl = true } },
.{ .key = .{ .physical = .equal }, .mods = .{ .super = true, .ctrl = true } },
.{ .equalize_splits = {} },
);
// Jump to prompt, matches Terminal.app
try self.set.put(
alloc,
.{ .key = .{ .translated = .up }, .mods = .{ .super = true } },
.{ .key = .{ .physical = .arrow_up }, .mods = .{ .super = true } },
.{ .jump_to_prompt = -1 },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .down }, .mods = .{ .super = true } },
.{ .key = .{ .physical = .arrow_down }, .mods = .{ .super = true } },
.{ .jump_to_prompt = 1 },
);
// Toggle command palette, matches VSCode
try self.set.put(
alloc,
.{ .key = .{ .translated = .p }, .mods = .{ .super = true, .shift = true } },
.{ .key = .{ .unicode = 'p' }, .mods = .{ .super = true, .shift = true } },
.{ .toggle_command_palette = {} },
);
// Inspector, matching Chromium
try self.set.put(
alloc,
.{ .key = .{ .translated = .i }, .mods = .{ .alt = true, .super = true } },
.{ .key = .{ .unicode = 'i' }, .mods = .{ .alt = true, .super = true } },
.{ .inspector = .toggle },
);
// Alternate keybind, common to Mac programs
try self.set.put(
alloc,
.{ .key = .{ .translated = .f }, .mods = .{ .super = true, .ctrl = true } },
.{ .key = .{ .unicode = 'f' }, .mods = .{ .super = true, .ctrl = true } },
.{ .toggle_fullscreen = {} },
);
// Selection clipboard paste, matches Terminal.app
try self.set.put(
alloc,
.{ .key = .{ .translated = .v }, .mods = .{ .super = true, .shift = true } },
.{ .key = .{ .unicode = 'v' }, .mods = .{ .super = true, .shift = true } },
.{ .paste_from_selection = {} },
);
@ -4931,27 +4919,27 @@ pub const Keybinds = struct {
// the keybinds to `unbind`.
try self.set.put(
alloc,
.{ .key = .{ .translated = .right }, .mods = .{ .super = true } },
.{ .key = .{ .physical = .arrow_right }, .mods = .{ .super = true } },
.{ .text = "\\x05" },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .left }, .mods = .{ .super = true } },
.{ .key = .{ .physical = .arrow_left }, .mods = .{ .super = true } },
.{ .text = "\\x01" },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .backspace }, .mods = .{ .super = true } },
.{ .key = .{ .physical = .backspace }, .mods = .{ .super = true } },
.{ .text = "\\x15" },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .left }, .mods = .{ .alt = true } },
.{ .key = .{ .physical = .arrow_left }, .mods = .{ .alt = true } },
.{ .esc = "b" },
);
try self.set.put(
alloc,
.{ .key = .{ .translated = .right }, .mods = .{ .alt = true } },
.{ .key = .{ .physical = .arrow_right }, .mods = .{ .alt = true } },
.{ .esc = "f" },
);
}
@ -5138,8 +5126,8 @@ pub const Keybinds = struct {
// Note they turn into translated keys because they match
// their ASCII mapping.
const want =
\\keybind = ctrl+z>two=goto_tab:2
\\keybind = ctrl+z>one=goto_tab:1
\\keybind = ctrl+z>2=goto_tab:2
\\keybind = ctrl+z>1=goto_tab:1
\\
;
try std.testing.expectEqualStrings(want, buf.items);
@ -5163,8 +5151,8 @@ pub const Keybinds = struct {
// NB: This does not currently retain the order of the keybinds.
const want =
\\a = ctrl+a>ctrl+b>w=close_window
\\a = ctrl+a>ctrl+b>n=new_window
\\a = ctrl+a>ctrl+b>w=close_window
\\a = ctrl+a>ctrl+c>t=new_tab
\\a = ctrl+b>ctrl+d>a=previous_tab
\\

View File

@ -99,9 +99,12 @@ pub const Parser = struct {
if (flags.performable) return Error.InvalidFormat;
flags.performable = true;
} else {
// If we don't recognize the prefix then we're done.
// There are trigger-specific prefixes like "physical:" so
// this lets us fall into that.
// If we don't recognize the prefix then we're done. We
// let any unknown prefix fallthrough to trigger-specific
// parsing in case there are trigger-specific prefixes
// (none currently but historically there was `physical:`
// at one point). Breaking here lets us always implement new
// prefixes.
break;
}
@ -202,14 +205,12 @@ pub fn lessThan(_: void, lhs: Binding, rhs: Binding) bool {
const lhs_key: c_int = blk: {
switch (lhs.trigger.key) {
.translated => break :blk @intFromEnum(lhs.trigger.key.translated),
.physical => break :blk @intFromEnum(lhs.trigger.key.physical),
.unicode => break :blk @intCast(lhs.trigger.key.unicode),
}
};
const rhs_key: c_int = blk: {
switch (rhs.trigger.key) {
.translated => break :blk @intFromEnum(rhs.trigger.key.translated),
.physical => break :blk @intFromEnum(rhs.trigger.key.physical),
.unicode => break :blk @intCast(rhs.trigger.key.unicode),
}
@ -1065,18 +1066,12 @@ pub const Action = union(enum) {
/// This must be kept in sync with include/ghostty.h ghostty_input_trigger_s
pub const Trigger = struct {
/// The key that has to be pressed for a binding to take action.
key: Trigger.Key = .{ .translated = .invalid },
key: Trigger.Key = .{ .physical = .unidentified },
/// The key modifiers that must be active for this to match.
mods: key.Mods = .{},
pub const Key = union(C.Tag) {
/// key is the translated version of a key. This is the key that
/// a logical keyboard layout at the OS level would translate the
/// physical key to. For example if you use a US hardware keyboard
/// but have a Dvorak layout, the key would be the Dvorak key.
translated: key.Key,
/// key is the "physical" version. This is the same as mapped for
/// standard US keyboard layouts. For non-US keyboard layouts, this
/// is used to bind to a physical key location rather than a translated
@ -1091,18 +1086,16 @@ pub const Trigger = struct {
/// The extern struct used for triggers in the C API.
pub const C = extern struct {
tag: Tag = .translated,
key: C.Key = .{ .translated = .invalid },
tag: Tag = .physical,
key: C.Key = .{ .physical = .unidentified },
mods: key.Mods = .{},
pub const Tag = enum(c_int) {
translated,
physical,
unicode,
};
pub const Key = extern union {
translated: key.Key,
physical: key.Key,
unicode: u32,
};
@ -1150,24 +1143,16 @@ pub const Trigger = struct {
}
}
// If the key starts with "physical" then this is an physical key.
const physical_prefix = "physical:";
const physical = std.mem.startsWith(u8, part, physical_prefix);
const key_part = if (physical) part[physical_prefix.len..] else part;
// Check if its a key
const keysInfo = @typeInfo(key.Key).@"enum";
inline for (keysInfo.fields) |field| {
if (!std.mem.eql(u8, field.name, "invalid")) {
if (std.mem.eql(u8, key_part, field.name)) {
if (!std.mem.eql(u8, field.name, "unidentified")) {
if (std.mem.eql(u8, part, field.name)) {
// Repeat not allowed
if (!result.isKeyUnset()) return Error.InvalidFormat;
const keyval = @field(key.Key, field.name);
result.key = if (physical)
.{ .physical = keyval }
else
.{ .translated = keyval };
result.key = .{ .physical = keyval };
continue :loop;
}
}
@ -1177,21 +1162,13 @@ pub const Trigger = struct {
// character then we can use that as a key.
if (result.isKeyUnset()) unicode: {
// Invalid UTF8 drops to invalid format
const view = std.unicode.Utf8View.init(key_part) catch break :unicode;
const view = std.unicode.Utf8View.init(part) catch break :unicode;
var it = view.iterator();
// No codepoints or multiple codepoints drops to invalid format
const cp = it.nextCodepoint() orelse break :unicode;
if (it.nextCodepoint() != null) break :unicode;
// If this is ASCII and we have a translated key, set that.
if (std.math.cast(u8, cp)) |ascii| {
if (key.Key.fromASCII(ascii)) |k| {
result.key = .{ .translated = k };
continue :loop;
}
}
result.key = .{ .unicode = cp };
continue :loop;
}
@ -1205,7 +1182,7 @@ pub const Trigger = struct {
/// Returns true if this trigger has no key set.
pub fn isKeyUnset(self: Trigger) bool {
return switch (self.key) {
.translated => |v| v == .invalid,
.physical => |v| v == .unidentified,
else => false,
};
}
@ -1228,7 +1205,6 @@ pub const Trigger = struct {
return .{
.tag = self.key,
.key = switch (self.key) {
.translated => |v| .{ .translated = v },
.physical => |v| .{ .physical = v },
.unicode => |v| .{ .unicode = @intCast(v) },
},
@ -1254,8 +1230,7 @@ pub const Trigger = struct {
// Key
switch (self.key) {
.translated => |k| try writer.print("{s}", .{@tagName(k)}),
.physical => |k| try writer.print("physical:{s}", .{@tagName(k)}),
.physical => |k| try writer.print("{s}", .{@tagName(k)}),
.unicode => |c| try writer.print("{u}", .{c}),
}
}
@ -1620,13 +1595,10 @@ pub const Set = struct {
pub fn getEvent(self: *const Set, event: KeyEvent) ?Entry {
var trigger: Trigger = .{
.mods = event.mods.binding(),
.key = .{ .translated = event.key },
.key = .{ .physical = event.physical_key },
};
if (self.get(trigger)) |v| return v;
trigger.key = .{ .physical = event.physical_key };
if (self.get(trigger)) |v| return v;
if (event.unshifted_codepoint > 0) {
trigger.key = .{ .unicode = event.unshifted_codepoint };
if (self.get(trigger)) |v| return v;
@ -1637,19 +1609,7 @@ pub const Set = struct {
/// Remove a binding for a given trigger.
pub fn remove(self: *Set, alloc: Allocator, t: Trigger) void {
// Remove whatever this trigger is
self.removeExact(alloc, t);
// If we have a physical we remove translated and vice versa.
const alternate: Trigger.Key = switch (t.key) {
.unicode => return,
.translated => |k| .{ .physical = k },
.physical => |k| .{ .translated = k },
};
var alt_t: Trigger = t;
alt_t.key = alternate;
self.removeExact(alloc, alt_t);
}
fn removeExact(self: *Set, alloc: Allocator, t: Trigger) void {
@ -1750,37 +1710,24 @@ test "parse: triggers" {
// single character
try testing.expectEqual(
Binding{
.trigger = .{ .key = .{ .translated = .a } },
.trigger = .{ .key = .{ .unicode = 'a' } },
.action = .{ .ignore = {} },
},
try parseSingle("a=ignore"),
);
// unicode keys that map to translated
try testing.expectEqual(Binding{
.trigger = .{ .key = .{ .translated = .one } },
.action = .{ .ignore = {} },
}, try parseSingle("1=ignore"));
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .super = true },
.key = .{ .translated = .period },
},
.action = .{ .ignore = {} },
}, try parseSingle("cmd+.=ignore"));
// single modifier
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
}, try parseSingle("shift+a=ignore"));
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .ctrl = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
}, try parseSingle("ctrl+a=ignore"));
@ -1789,7 +1736,7 @@ test "parse: triggers" {
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true, .ctrl = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
}, try parseSingle("shift+ctrl+a=ignore"));
@ -1798,7 +1745,7 @@ test "parse: triggers" {
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
}, try parseSingle("a+shift=ignore"));
@ -1807,10 +1754,10 @@ test "parse: triggers" {
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.key = .{ .physical = .a },
.key = .{ .physical = .key_a },
},
.action = .{ .ignore = {} },
}, try parseSingle("shift+physical:a=ignore"));
}, try parseSingle("shift+key_a=ignore"));
// unicode keys
try testing.expectEqual(Binding{
@ -1825,7 +1772,7 @@ test "parse: triggers" {
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
.flags = .{ .consumed = false },
@ -1835,17 +1782,17 @@ test "parse: triggers" {
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.key = .{ .physical = .a },
.key = .{ .physical = .key_a },
},
.action = .{ .ignore = {} },
.flags = .{ .consumed = false },
}, try parseSingle("unconsumed:physical:a+shift=ignore"));
}, try parseSingle("unconsumed:key_a+shift=ignore"));
// performable keys
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
.flags = .{ .performable = true },
@ -1868,7 +1815,7 @@ test "parse: global triggers" {
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
.flags = .{ .global = true },
@ -1878,17 +1825,17 @@ test "parse: global triggers" {
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.key = .{ .physical = .a },
.key = .{ .physical = .key_a },
},
.action = .{ .ignore = {} },
.flags = .{ .global = true },
}, try parseSingle("global:physical:a+shift=ignore"));
}, try parseSingle("global:key_a+shift=ignore"));
// global unconsumed keys
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
.flags = .{
@ -1911,7 +1858,7 @@ test "parse: all triggers" {
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
.flags = .{ .all = true },
@ -1921,17 +1868,17 @@ test "parse: all triggers" {
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.key = .{ .physical = .a },
.key = .{ .physical = .key_a },
},
.action = .{ .ignore = {} },
.flags = .{ .all = true },
}, try parseSingle("all:physical:a+shift=ignore"));
}, try parseSingle("all:key_a+shift=ignore"));
// all unconsumed keys
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
.flags = .{
@ -1953,14 +1900,14 @@ test "parse: modifier aliases" {
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .super = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
}, try parseSingle("cmd+a=ignore"));
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .super = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
}, try parseSingle("command+a=ignore"));
@ -1968,14 +1915,14 @@ test "parse: modifier aliases" {
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .alt = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
}, try parseSingle("opt+a=ignore"));
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .alt = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
}, try parseSingle("option+a=ignore"));
@ -1983,7 +1930,7 @@ test "parse: modifier aliases" {
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .ctrl = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
}, try parseSingle("control+a=ignore"));
@ -2002,7 +1949,7 @@ test "parse: action no parameters" {
// no parameters
try testing.expectEqual(
Binding{
.trigger = .{ .key = .{ .translated = .a } },
.trigger = .{ .key = .{ .unicode = 'a' } },
.action = .{ .ignore = {} },
},
try parseSingle("a=ignore"),
@ -2108,15 +2055,15 @@ test "sequence iterator" {
// single character
{
var it: SequenceIterator = .{ .input = "a" };
try testing.expectEqual(Trigger{ .key = .{ .translated = .a } }, (try it.next()).?);
try testing.expectEqual(Trigger{ .key = .{ .unicode = 'a' } }, (try it.next()).?);
try testing.expect(try it.next() == null);
}
// multi character
{
var it: SequenceIterator = .{ .input = "a>b" };
try testing.expectEqual(Trigger{ .key = .{ .translated = .a } }, (try it.next()).?);
try testing.expectEqual(Trigger{ .key = .{ .translated = .b } }, (try it.next()).?);
try testing.expectEqual(Trigger{ .key = .{ .unicode = 'a' } }, (try it.next()).?);
try testing.expectEqual(Trigger{ .key = .{ .unicode = 'b' } }, (try it.next()).?);
try testing.expect(try it.next() == null);
}
@ -2135,7 +2082,7 @@ test "sequence iterator" {
// empty ending sequence
{
var it: SequenceIterator = .{ .input = "a>" };
try testing.expectEqual(Trigger{ .key = .{ .translated = .a } }, (try it.next()).?);
try testing.expectEqual(Trigger{ .key = .{ .unicode = 'a' } }, (try it.next()).?);
try testing.expectError(Error.InvalidFormat, it.next());
}
}
@ -2149,7 +2096,7 @@ test "parse: sequences" {
try testing.expectEqual(Parser.Elem{ .binding = .{
.trigger = .{
.mods = .{ .ctrl = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
},
.action = .{ .ignore = {} },
} }, (try p.next()).?);
@ -2160,11 +2107,11 @@ test "parse: sequences" {
{
var p = try Parser.init("a>b=ignore");
try testing.expectEqual(Parser.Elem{ .leader = .{
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
} }, (try p.next()).?);
try testing.expectEqual(Parser.Elem{ .binding = .{
.trigger = .{
.key = .{ .translated = .b },
.key = .{ .unicode = 'b' },
},
.action = .{ .ignore = {} },
} }, (try p.next()).?);
@ -2183,7 +2130,7 @@ test "set: parseAndPut typical binding" {
// Creates forward mapping
{
const action = s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.*.leaf;
const action = s.get(.{ .key = .{ .unicode = 'a' } }).?.value_ptr.*.leaf;
try testing.expect(action.action == .new_window);
try testing.expectEqual(Flags{}, action.flags);
}
@ -2191,7 +2138,7 @@ test "set: parseAndPut typical binding" {
// Creates reverse mapping
{
const trigger = s.getTrigger(.{ .new_window = {} }).?;
try testing.expect(trigger.key.translated == .a);
try testing.expect(trigger.key.unicode == 'a');
}
}
@ -2206,7 +2153,7 @@ test "set: parseAndPut unconsumed binding" {
// Creates forward mapping
{
const trigger: Trigger = .{ .key = .{ .translated = .a } };
const trigger: Trigger = .{ .key = .{ .unicode = 'a' } };
const action = s.get(trigger).?.value_ptr.*.leaf;
try testing.expect(action.action == .new_window);
try testing.expectEqual(Flags{ .consumed = false }, action.flags);
@ -2215,7 +2162,7 @@ test "set: parseAndPut unconsumed binding" {
// Creates reverse mapping
{
const trigger = s.getTrigger(.{ .new_window = {} }).?;
try testing.expect(trigger.key.translated == .a);
try testing.expect(trigger.key.unicode == 'a');
}
}
@ -2231,25 +2178,7 @@ test "set: parseAndPut removed binding" {
// Creates forward mapping
{
const trigger: Trigger = .{ .key = .{ .translated = .a } };
try testing.expect(s.get(trigger) == null);
}
try testing.expect(s.getTrigger(.{ .new_window = {} }) == null);
}
test "set: parseAndPut removed physical binding" {
const testing = std.testing;
const alloc = testing.allocator;
var s: Set = .{};
defer s.deinit(alloc);
try s.parseAndPut(alloc, "physical:a=new_window");
try s.parseAndPut(alloc, "a=unbind");
// Creates forward mapping
{
const trigger: Trigger = .{ .key = .{ .physical = .a } };
const trigger: Trigger = .{ .key = .{ .unicode = 'a' } };
try testing.expect(s.get(trigger) == null);
}
try testing.expect(s.getTrigger(.{ .new_window = {} }) == null);
@ -2265,13 +2194,13 @@ test "set: parseAndPut sequence" {
try s.parseAndPut(alloc, "a>b=new_window");
var current: *Set = &s;
{
const t: Trigger = .{ .key = .{ .translated = .a } };
const t: Trigger = .{ .key = .{ .unicode = 'a' } };
const e = current.get(t).?.value_ptr.*;
try testing.expect(e == .leader);
current = e.leader;
}
{
const t: Trigger = .{ .key = .{ .translated = .b } };
const t: Trigger = .{ .key = .{ .unicode = 'b' } };
const e = current.get(t).?.value_ptr.*;
try testing.expect(e == .leaf);
try testing.expect(e.leaf.action == .new_window);
@ -2290,20 +2219,20 @@ test "set: parseAndPut sequence with two actions" {
try s.parseAndPut(alloc, "a>c=new_tab");
var current: *Set = &s;
{
const t: Trigger = .{ .key = .{ .translated = .a } };
const t: Trigger = .{ .key = .{ .unicode = 'a' } };
const e = current.get(t).?.value_ptr.*;
try testing.expect(e == .leader);
current = e.leader;
}
{
const t: Trigger = .{ .key = .{ .translated = .b } };
const t: Trigger = .{ .key = .{ .unicode = 'b' } };
const e = current.get(t).?.value_ptr.*;
try testing.expect(e == .leaf);
try testing.expect(e.leaf.action == .new_window);
try testing.expectEqual(Flags{}, e.leaf.flags);
}
{
const t: Trigger = .{ .key = .{ .translated = .c } };
const t: Trigger = .{ .key = .{ .unicode = 'c' } };
const e = current.get(t).?.value_ptr.*;
try testing.expect(e == .leaf);
try testing.expect(e.leaf.action == .new_tab);
@ -2322,13 +2251,13 @@ test "set: parseAndPut overwrite sequence" {
try s.parseAndPut(alloc, "a>b=new_window");
var current: *Set = &s;
{
const t: Trigger = .{ .key = .{ .translated = .a } };
const t: Trigger = .{ .key = .{ .unicode = 'a' } };
const e = current.get(t).?.value_ptr.*;
try testing.expect(e == .leader);
current = e.leader;
}
{
const t: Trigger = .{ .key = .{ .translated = .b } };
const t: Trigger = .{ .key = .{ .unicode = 'b' } };
const e = current.get(t).?.value_ptr.*;
try testing.expect(e == .leaf);
try testing.expect(e.leaf.action == .new_window);
@ -2347,13 +2276,13 @@ test "set: parseAndPut overwrite leader" {
try s.parseAndPut(alloc, "a>b=new_window");
var current: *Set = &s;
{
const t: Trigger = .{ .key = .{ .translated = .a } };
const t: Trigger = .{ .key = .{ .unicode = 'a' } };
const e = current.get(t).?.value_ptr.*;
try testing.expect(e == .leader);
current = e.leader;
}
{
const t: Trigger = .{ .key = .{ .translated = .b } };
const t: Trigger = .{ .key = .{ .unicode = 'b' } };
const e = current.get(t).?.value_ptr.*;
try testing.expect(e == .leaf);
try testing.expect(e.leaf.action == .new_window);
@ -2372,7 +2301,7 @@ test "set: parseAndPut unbind sequence unbinds leader" {
try s.parseAndPut(alloc, "a>b=unbind");
var current: *Set = &s;
{
const t: Trigger = .{ .key = .{ .translated = .a } };
const t: Trigger = .{ .key = .{ .unicode = 'a' } };
try testing.expect(current.get(t) == null);
}
}
@ -2387,7 +2316,7 @@ test "set: parseAndPut unbind sequence unbinds leader if not set" {
try s.parseAndPut(alloc, "a>b=unbind");
var current: *Set = &s;
{
const t: Trigger = .{ .key = .{ .translated = .a } };
const t: Trigger = .{ .key = .{ .unicode = 'a' } };
try testing.expect(current.get(t) == null);
}
}
@ -2405,7 +2334,7 @@ test "set: parseAndPut sequence preserves reverse mapping" {
// Creates reverse mapping
{
const trigger = s.getTrigger(.{ .new_window = {} }).?;
try testing.expect(trigger.key.translated == .a);
try testing.expect(trigger.key.unicode == 'a');
}
}
@ -2419,13 +2348,13 @@ test "set: put overwrites sequence" {
try s.parseAndPut(alloc, "ctrl+a>b=new_window");
try s.put(alloc, .{
.mods = .{ .ctrl = true },
.key = .{ .translated = .a },
.key = .{ .unicode = 'a' },
}, .{ .new_window = {} });
// Creates reverse mapping
{
const trigger = s.getTrigger(.{ .new_window = {} }).?;
try testing.expect(trigger.key.translated == .a);
try testing.expect(trigger.key.unicode == 'a');
}
}
@ -2436,24 +2365,24 @@ test "set: maintains reverse mapping" {
var s: Set = .{};
defer s.deinit(alloc);
try s.put(alloc, .{ .key = .{ .translated = .a } }, .{ .new_window = {} });
try s.put(alloc, .{ .key = .{ .unicode = 'a' } }, .{ .new_window = {} });
{
const trigger = s.getTrigger(.{ .new_window = {} }).?;
try testing.expect(trigger.key.translated == .a);
try testing.expect(trigger.key.unicode == 'a');
}
// should be most recent
try s.put(alloc, .{ .key = .{ .translated = .b } }, .{ .new_window = {} });
try s.put(alloc, .{ .key = .{ .unicode = 'b' } }, .{ .new_window = {} });
{
const trigger = s.getTrigger(.{ .new_window = {} }).?;
try testing.expect(trigger.key.translated == .b);
try testing.expect(trigger.key.unicode == 'b');
}
// removal should replace
s.remove(alloc, .{ .key = .{ .translated = .b } });
s.remove(alloc, .{ .key = .{ .unicode = 'b' } });
{
const trigger = s.getTrigger(.{ .new_window = {} }).?;
try testing.expect(trigger.key.translated == .a);
try testing.expect(trigger.key.unicode == 'a');
}
}
@ -2464,29 +2393,29 @@ test "set: performable is not part of reverse mappings" {
var s: Set = .{};
defer s.deinit(alloc);
try s.put(alloc, .{ .key = .{ .translated = .a } }, .{ .new_window = {} });
try s.put(alloc, .{ .key = .{ .unicode = 'a' } }, .{ .new_window = {} });
{
const trigger = s.getTrigger(.{ .new_window = {} }).?;
try testing.expect(trigger.key.translated == .a);
try testing.expect(trigger.key.unicode == 'a');
}
// trigger should be non-performable
try s.putFlags(
alloc,
.{ .key = .{ .translated = .b } },
.{ .key = .{ .unicode = 'b' } },
.{ .new_window = {} },
.{ .performable = true },
);
{
const trigger = s.getTrigger(.{ .new_window = {} }).?;
try testing.expect(trigger.key.translated == .a);
try testing.expect(trigger.key.unicode == 'a');
}
// removal of performable should do nothing
s.remove(alloc, .{ .key = .{ .translated = .b } });
s.remove(alloc, .{ .key = .{ .unicode = 'b' } });
{
const trigger = s.getTrigger(.{ .new_window = {} }).?;
try testing.expect(trigger.key.translated == .a);
try testing.expect(trigger.key.unicode == 'a');
}
}
@ -2497,14 +2426,14 @@ test "set: overriding a mapping updates reverse" {
var s: Set = .{};
defer s.deinit(alloc);
try s.put(alloc, .{ .key = .{ .translated = .a } }, .{ .new_window = {} });
try s.put(alloc, .{ .key = .{ .unicode = 'a' } }, .{ .new_window = {} });
{
const trigger = s.getTrigger(.{ .new_window = {} }).?;
try testing.expect(trigger.key.translated == .a);
try testing.expect(trigger.key.unicode == 'a');
}
// should be most recent
try s.put(alloc, .{ .key = .{ .translated = .a } }, .{ .new_tab = {} });
try s.put(alloc, .{ .key = .{ .unicode = 'a' } }, .{ .new_tab = {} });
{
const trigger = s.getTrigger(.{ .new_window = {} });
try testing.expect(trigger == null);
@ -2518,22 +2447,22 @@ test "set: consumed state" {
var s: Set = .{};
defer s.deinit(alloc);
try s.put(alloc, .{ .key = .{ .translated = .a } }, .{ .new_window = {} });
try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.* == .leaf);
try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.*.leaf.flags.consumed);
try s.put(alloc, .{ .key = .{ .unicode = 'a' } }, .{ .new_window = {} });
try testing.expect(s.get(.{ .key = .{ .unicode = 'a' } }).?.value_ptr.* == .leaf);
try testing.expect(s.get(.{ .key = .{ .unicode = 'a' } }).?.value_ptr.*.leaf.flags.consumed);
try s.putFlags(
alloc,
.{ .key = .{ .translated = .a } },
.{ .key = .{ .unicode = 'a' } },
.{ .new_window = {} },
.{ .consumed = false },
);
try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.* == .leaf);
try testing.expect(!s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.*.leaf.flags.consumed);
try testing.expect(s.get(.{ .key = .{ .unicode = 'a' } }).?.value_ptr.* == .leaf);
try testing.expect(!s.get(.{ .key = .{ .unicode = 'a' } }).?.value_ptr.*.leaf.flags.consumed);
try s.put(alloc, .{ .key = .{ .translated = .a } }, .{ .new_window = {} });
try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.* == .leaf);
try testing.expect(s.get(.{ .key = .{ .translated = .a } }).?.value_ptr.*.leaf.flags.consumed);
try s.put(alloc, .{ .key = .{ .unicode = 'a' } }, .{ .new_window = {} });
try testing.expect(s.get(.{ .key = .{ .unicode = 'a' } }).?.value_ptr.* == .leaf);
try testing.expect(s.get(.{ .key = .{ .unicode = 'a' } }).?.value_ptr.*.leaf.flags.consumed);
}
test "Action: clone" {

View File

@ -1082,7 +1082,7 @@ test "kitty: plain text" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .a,
.key = .key_a,
.mods = .{},
.utf8 = "abcd",
},
@ -1098,7 +1098,7 @@ test "kitty: repeat with just disambiguate" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .a,
.key = .key_a,
.action = .repeat,
.mods = .{},
.utf8 = "a",
@ -1222,7 +1222,7 @@ test "kitty: enter with all flags" {
test "kitty: ctrl with all flags" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{ .key = .left_control, .mods = .{ .ctrl = true }, .utf8 = "" },
.event = .{ .key = .control_left, .mods = .{ .ctrl = true }, .utf8 = "" },
.kitty_flags = .{
.disambiguate = true,
.report_events = true,
@ -1240,7 +1240,7 @@ test "kitty: ctrl release with ctrl mod set" {
var enc: KeyEncoder = .{
.event = .{
.action = .release,
.key = .left_control,
.key = .control_left,
.mods = .{ .ctrl = true },
.utf8 = "",
},
@ -1272,7 +1272,7 @@ test "kitty: composing with no modifier" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .a,
.key = .key_a,
.mods = .{ .shift = true },
.composing = true,
},
@ -1287,7 +1287,7 @@ test "kitty: composing with modifier" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .left_shift,
.key = .shift_left,
.mods = .{ .shift = true },
.composing = true,
},
@ -1302,7 +1302,7 @@ test "kitty: shift+a on US keyboard" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .a,
.key = .key_a,
.mods = .{ .shift = true },
.utf8 = "A",
.unshifted_codepoint = 97, // lowercase A
@ -1321,7 +1321,7 @@ test "kitty: matching unshifted codepoint" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .a,
.key = .key_a,
.mods = .{ .shift = true },
.utf8 = "A",
.unshifted_codepoint = 65,
@ -1344,7 +1344,7 @@ test "kitty: report alternates with caps" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .j,
.key = .key_j,
.mods = .{ .caps_lock = true },
.utf8 = "J",
.unshifted_codepoint = 106,
@ -1450,7 +1450,7 @@ test "kitty: report alternates with hu layout release" {
var enc: KeyEncoder = .{
.event = .{
.action = .release,
.key = .left_bracket,
.key = .bracket_left,
.mods = .{ .ctrl = true },
.utf8 = "",
.unshifted_codepoint = 337,
@ -1473,7 +1473,7 @@ test "kitty: up arrow with utf8" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .up,
.key = .arrow_up,
.mods = .{},
.utf8 = &.{30},
},
@ -1505,7 +1505,7 @@ test "kitty: left shift" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .left_shift,
.key = .shift_left,
.mods = .{},
.utf8 = "",
},
@ -1521,7 +1521,7 @@ test "kitty: left shift with report all" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .left_shift,
.key = .shift_left,
.mods = .{},
.utf8 = "",
},
@ -1539,7 +1539,7 @@ test "kitty: report associated with alt text on macOS with option" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .w,
.key = .key_w,
.mods = .{ .alt = true },
.utf8 = "",
.unshifted_codepoint = 119,
@ -1565,7 +1565,7 @@ test "kitty: report associated with alt text on macOS with alt" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .w,
.key = .key_w,
.mods = .{ .alt = true },
.utf8 = "",
.unshifted_codepoint = 119,
@ -1588,7 +1588,7 @@ test "kitty: report associated with alt text on macOS with alt" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .w,
.key = .key_w,
.mods = .{},
.utf8 = "",
.unshifted_codepoint = 119,
@ -1611,7 +1611,7 @@ test "kitty: report associated with modifiers" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .j,
.key = .key_j,
.mods = .{ .ctrl = true },
.utf8 = "j",
.unshifted_codepoint = 106,
@ -1632,7 +1632,7 @@ test "kitty: report associated" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .j,
.key = .key_j,
.mods = .{ .shift = true },
.utf8 = "J",
.unshifted_codepoint = 106,
@ -1654,7 +1654,7 @@ test "kitty: report associated on release" {
var enc: KeyEncoder = .{
.event = .{
.action = .release,
.key = .j,
.key = .key_j,
.mods = .{ .shift = true },
.utf8 = "J",
.unshifted_codepoint = 106,
@ -1713,7 +1713,7 @@ test "kitty: enter with utf8 (dead key state)" {
test "kitty: keypad number" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{ .key = .kp_1, .mods = .{}, .utf8 = "1" },
.event = .{ .key = .numpad_1, .mods = .{}, .utf8 = "1" },
.kitty_flags = .{
.disambiguate = true,
.report_events = true,
@ -1807,7 +1807,7 @@ test "legacy: ctrl+alt+c" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .c,
.key = .key_c,
.mods = .{ .ctrl = true, .alt = true },
.utf8 = "c",
},
@ -1821,7 +1821,7 @@ test "legacy: alt+c" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .c,
.key = .key_c,
.utf8 = "c",
.mods = .{ .alt = true },
},
@ -1837,7 +1837,7 @@ test "legacy: alt+e only unshifted" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .e,
.key = .key_e,
.unshifted_codepoint = 'e',
.mods = .{ .alt = true },
},
@ -1855,7 +1855,7 @@ test "legacy: alt+x macos" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .c,
.key = .key_c,
.utf8 = "",
.unshifted_codepoint = 'c',
.mods = .{ .alt = true },
@ -1891,7 +1891,7 @@ test "legacy: alt+ф" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .f,
.key = .key_f,
.utf8 = "ф",
.mods = .{ .alt = true },
},
@ -1906,7 +1906,7 @@ test "legacy: ctrl+c" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .c,
.key = .key_c,
.mods = .{ .ctrl = true },
.utf8 = "c",
},
@ -1947,7 +1947,7 @@ test "legacy: ctrl+shift+char with modify other state 2" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .h,
.key = .key_h,
.mods = .{ .ctrl = true, .shift = true },
.utf8 = "H",
},
@ -1962,7 +1962,7 @@ test "legacy: fixterm awkward letters" {
var buf: [128]u8 = undefined;
{
var enc: KeyEncoder = .{ .event = .{
.key = .i,
.key = .key_i,
.mods = .{ .ctrl = true },
.utf8 = "i",
} };
@ -1971,7 +1971,7 @@ test "legacy: fixterm awkward letters" {
}
{
var enc: KeyEncoder = .{ .event = .{
.key = .m,
.key = .key_m,
.mods = .{ .ctrl = true },
.utf8 = "m",
} };
@ -1980,7 +1980,7 @@ test "legacy: fixterm awkward letters" {
}
{
var enc: KeyEncoder = .{ .event = .{
.key = .left_bracket,
.key = .bracket_left,
.mods = .{ .ctrl = true },
.utf8 = "[",
} };
@ -1989,7 +1989,7 @@ test "legacy: fixterm awkward letters" {
}
{
var enc: KeyEncoder = .{ .event = .{
.key = .two,
.key = .digit_2,
.mods = .{ .ctrl = true, .shift = true },
.utf8 = "@",
.unshifted_codepoint = '2',
@ -2005,7 +2005,7 @@ test "legacy: ctrl+shift+letter ascii" {
var buf: [128]u8 = undefined;
{
var enc: KeyEncoder = .{ .event = .{
.key = .m,
.key = .key_m,
.mods = .{ .ctrl = true, .shift = true },
.utf8 = "M",
.unshifted_codepoint = 'm',
@ -2019,7 +2019,7 @@ test "legacy: shift+function key should use all mods" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .up,
.key = .arrow_up,
.mods = .{ .shift = true },
.consumed_mods = .{ .shift = true },
},
@ -2033,7 +2033,7 @@ test "legacy: keypad enter" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .kp_enter,
.key = .numpad_enter,
.mods = .{},
.consumed_mods = .{},
},
@ -2047,7 +2047,7 @@ test "legacy: keypad 1" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .kp_1,
.key = .numpad_1,
.mods = .{},
.consumed_mods = .{},
.utf8 = "1",
@ -2062,7 +2062,7 @@ test "legacy: keypad 1 with application keypad" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .kp_1,
.key = .numpad_1,
.mods = .{},
.consumed_mods = .{},
.utf8 = "1",
@ -2078,7 +2078,7 @@ test "legacy: keypad 1 with application keypad and numlock" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .kp_1,
.key = .numpad_1,
.mods = .{ .num_lock = true },
.consumed_mods = .{},
.utf8 = "1",
@ -2094,7 +2094,7 @@ test "legacy: keypad 1 with application keypad and numlock ignore" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .kp_1,
.key = .numpad_1,
.mods = .{ .num_lock = false },
.consumed_mods = .{},
.utf8 = "1",
@ -2189,8 +2189,8 @@ test "legacy: hu layout ctrl+ő sends proper codepoint" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .left_bracket,
.physical_key = .left_bracket,
.key = .bracket_left,
.physical_key = .bracket_left,
.mods = .{ .ctrl = true },
.utf8 = "ő",
.unshifted_codepoint = 337,
@ -2207,7 +2207,7 @@ test "legacy: super-only on macOS with text" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .b,
.key = .key_b,
.utf8 = "b",
.mods = .{ .super = true },
},
@ -2223,7 +2223,7 @@ test "legacy: super and other mods on macOS with text" {
var buf: [128]u8 = undefined;
var enc: KeyEncoder = .{
.event = .{
.key = .b,
.key = .key_b,
.utf8 = "B",
.mods = .{ .super = true, .shift = true },
},
@ -2234,50 +2234,50 @@ test "legacy: super and other mods on macOS with text" {
}
test "ctrlseq: normal ctrl c" {
const seq = ctrlSeq(.invalid, "c", 'c', .{ .ctrl = true });
const seq = ctrlSeq(.unidentified, "c", 'c', .{ .ctrl = true });
try testing.expectEqual(@as(u8, 0x03), seq.?);
}
test "ctrlseq: normal ctrl c, right control" {
const seq = ctrlSeq(.invalid, "c", 'c', .{ .ctrl = true, .sides = .{ .ctrl = .right } });
const seq = ctrlSeq(.unidentified, "c", 'c', .{ .ctrl = true, .sides = .{ .ctrl = .right } });
try testing.expectEqual(@as(u8, 0x03), seq.?);
}
test "ctrlseq: alt should be allowed" {
const seq = ctrlSeq(.invalid, "c", 'c', .{ .alt = true, .ctrl = true });
const seq = ctrlSeq(.unidentified, "c", 'c', .{ .alt = true, .ctrl = true });
try testing.expectEqual(@as(u8, 0x03), seq.?);
}
test "ctrlseq: no ctrl does nothing" {
try testing.expect(ctrlSeq(.invalid, "c", 'c', .{}) == null);
try testing.expect(ctrlSeq(.unidentified, "c", 'c', .{}) == null);
}
test "ctrlseq: shifted non-character" {
const seq = ctrlSeq(.invalid, "_", '-', .{ .ctrl = true, .shift = true });
const seq = ctrlSeq(.unidentified, "_", '-', .{ .ctrl = true, .shift = true });
try testing.expectEqual(@as(u8, 0x1F), seq.?);
}
test "ctrlseq: caps ascii letter" {
const seq = ctrlSeq(.invalid, "C", 'c', .{ .ctrl = true, .caps_lock = true });
const seq = ctrlSeq(.unidentified, "C", 'c', .{ .ctrl = true, .caps_lock = true });
try testing.expectEqual(@as(u8, 0x03), seq.?);
}
test "ctrlseq: shift does not generate ctrl seq" {
try testing.expect(ctrlSeq(.invalid, "C", 'c', .{ .shift = true }) == null);
try testing.expect(ctrlSeq(.invalid, "C", 'c', .{ .shift = true, .ctrl = true }) == null);
try testing.expect(ctrlSeq(.unidentified, "C", 'c', .{ .shift = true }) == null);
try testing.expect(ctrlSeq(.unidentified, "C", 'c', .{ .shift = true, .ctrl = true }) == null);
}
test "ctrlseq: russian ctrl c" {
const seq = ctrlSeq(.c, "с", 0x0441, .{ .ctrl = true });
const seq = ctrlSeq(.key_c, "с", 0x0441, .{ .ctrl = true });
try testing.expectEqual(@as(u8, 0x03), seq.?);
}
test "ctrlseq: russian shifted ctrl c" {
const seq = ctrlSeq(.c, "с", 0x0441, .{ .ctrl = true, .shift = true });
const seq = ctrlSeq(.key_c, "с", 0x0441, .{ .ctrl = true, .shift = true });
try testing.expect(seq == null);
}
test "ctrlseq: russian alt ctrl c" {
const seq = ctrlSeq(.c, "с", 0x0441, .{ .ctrl = true, .alt = true });
const seq = ctrlSeq(.key_c, "с", 0x0441, .{ .ctrl = true, .alt = true });
try testing.expectEqual(@as(u8, 0x03), seq.?);
}

View File

@ -75,10 +75,10 @@ pub const KeyEntryArray = std.EnumArray(key.Key, []const Entry);
pub const keys = keys: {
var result = KeyEntryArray.initFill(&.{});
result.set(.up, pcStyle("\x1b[1;{}A") ++ cursorKey("\x1b[A", "\x1bOA"));
result.set(.down, pcStyle("\x1b[1;{}B") ++ cursorKey("\x1b[B", "\x1bOB"));
result.set(.right, pcStyle("\x1b[1;{}C") ++ cursorKey("\x1b[C", "\x1bOC"));
result.set(.left, pcStyle("\x1b[1;{}D") ++ cursorKey("\x1b[D", "\x1bOD"));
result.set(.arrow_up, pcStyle("\x1b[1;{}A") ++ cursorKey("\x1b[A", "\x1bOA"));
result.set(.arrow_down, pcStyle("\x1b[1;{}B") ++ cursorKey("\x1b[B", "\x1bOB"));
result.set(.arrow_right, pcStyle("\x1b[1;{}C") ++ cursorKey("\x1b[C", "\x1bOC"));
result.set(.arrow_left, pcStyle("\x1b[1;{}D") ++ cursorKey("\x1b[D", "\x1bOD"));
result.set(.home, pcStyle("\x1b[1;{}H") ++ cursorKey("\x1b[H", "\x1bOH"));
result.set(.end, pcStyle("\x1b[1;{}F") ++ cursorKey("\x1b[F", "\x1bOF"));
result.set(.insert, pcStyle("\x1b[2;{}~") ++ .{Entry{ .sequence = "\x1B[2~" }});
@ -101,33 +101,33 @@ pub const keys = keys: {
result.set(.f12, pcStyle("\x1b[24;{}~") ++ .{Entry{ .sequence = "\x1B[24~" }});
// Keypad keys
result.set(.kp_0, kpKeys("p"));
result.set(.kp_1, kpKeys("q"));
result.set(.kp_2, kpKeys("r"));
result.set(.kp_3, kpKeys("s"));
result.set(.kp_4, kpKeys("t"));
result.set(.kp_5, kpKeys("u"));
result.set(.kp_6, kpKeys("v"));
result.set(.kp_7, kpKeys("w"));
result.set(.kp_8, kpKeys("x"));
result.set(.kp_9, kpKeys("y"));
result.set(.kp_decimal, kpKeys("n"));
result.set(.kp_divide, kpKeys("o"));
result.set(.kp_multiply, kpKeys("j"));
result.set(.kp_subtract, kpKeys("m"));
result.set(.kp_add, kpKeys("k"));
result.set(.kp_enter, kpKeys("M") ++ .{Entry{ .sequence = "\r" }});
result.set(.kp_up, pcStyle("\x1b[1;{}A") ++ cursorKey("\x1b[A", "\x1bOA"));
result.set(.kp_down, pcStyle("\x1b[1;{}B") ++ cursorKey("\x1b[B", "\x1bOB"));
result.set(.kp_right, pcStyle("\x1b[1;{}C") ++ cursorKey("\x1b[C", "\x1bOC"));
result.set(.kp_left, pcStyle("\x1b[1;{}D") ++ cursorKey("\x1b[D", "\x1bOD"));
result.set(.kp_begin, pcStyle("\x1b[1;{}E") ++ cursorKey("\x1b[E", "\x1bOE"));
result.set(.kp_home, pcStyle("\x1b[1;{}H") ++ cursorKey("\x1b[H", "\x1bOH"));
result.set(.kp_end, pcStyle("\x1b[1;{}F") ++ cursorKey("\x1b[F", "\x1bOF"));
result.set(.kp_insert, pcStyle("\x1b[2;{}~") ++ .{Entry{ .sequence = "\x1B[2~" }});
result.set(.kp_delete, pcStyle("\x1b[3;{}~") ++ .{Entry{ .sequence = "\x1B[3~" }});
result.set(.kp_page_up, pcStyle("\x1b[5;{}~") ++ .{Entry{ .sequence = "\x1B[5~" }});
result.set(.kp_page_down, pcStyle("\x1b[6;{}~") ++ .{Entry{ .sequence = "\x1B[6~" }});
result.set(.numpad_0, kpKeys("p"));
result.set(.numpad_1, kpKeys("q"));
result.set(.numpad_2, kpKeys("r"));
result.set(.numpad_3, kpKeys("s"));
result.set(.numpad_4, kpKeys("t"));
result.set(.numpad_5, kpKeys("u"));
result.set(.numpad_6, kpKeys("v"));
result.set(.numpad_7, kpKeys("w"));
result.set(.numpad_8, kpKeys("x"));
result.set(.numpad_9, kpKeys("y"));
result.set(.numpad_decimal, kpKeys("n"));
result.set(.numpad_divide, kpKeys("o"));
result.set(.numpad_multiply, kpKeys("j"));
result.set(.numpad_subtract, kpKeys("m"));
result.set(.numpad_add, kpKeys("k"));
result.set(.numpad_enter, kpKeys("M") ++ .{Entry{ .sequence = "\r" }});
result.set(.numpad_up, pcStyle("\x1b[1;{}A") ++ cursorKey("\x1b[A", "\x1bOA"));
result.set(.numpad_down, pcStyle("\x1b[1;{}B") ++ cursorKey("\x1b[B", "\x1bOB"));
result.set(.numpad_right, pcStyle("\x1b[1;{}C") ++ cursorKey("\x1b[C", "\x1bOC"));
result.set(.numpad_left, pcStyle("\x1b[1;{}D") ++ cursorKey("\x1b[D", "\x1bOD"));
result.set(.numpad_begin, pcStyle("\x1b[1;{}E") ++ cursorKey("\x1b[E", "\x1bOE"));
result.set(.numpad_home, pcStyle("\x1b[1;{}H") ++ cursorKey("\x1b[H", "\x1bOH"));
result.set(.numpad_end, pcStyle("\x1b[1;{}F") ++ cursorKey("\x1b[F", "\x1bOF"));
result.set(.numpad_insert, pcStyle("\x1b[2;{}~") ++ .{Entry{ .sequence = "\x1B[2~" }});
result.set(.numpad_delete, pcStyle("\x1b[3;{}~") ++ .{Entry{ .sequence = "\x1B[3~" }});
result.set(.numpad_page_up, pcStyle("\x1b[5;{}~") ++ .{Entry{ .sequence = "\x1B[5~" }});
result.set(.numpad_page_down, pcStyle("\x1b[6;{}~") ++ .{Entry{ .sequence = "\x1B[6~" }});
result.set(.backspace, &.{
// Modify Keys Normal

View File

@ -21,7 +21,7 @@ pub const KeyEvent = struct {
/// the "i" physical key will be reported as "c". The physical
/// key is the key that was physically pressed on the keyboard.
key: Key,
physical_key: Key = .invalid,
physical_key: Key = .unidentified,
/// Mods are the modifiers that are pressed.
mods: Mods = .{},
@ -391,6 +391,25 @@ pub const Key = enum(c_int) {
numpad_paren_right,
numpad_subtract,
// > For numpads that provide keys not listed here, a code value string
// > should be created by starting with "Numpad" and appending an
// > appropriate description of the key.
//
// These numpad entries are distinguished by various encoding protocols
// (legacy and Kitty) so we support them here in case the apprt can
// produce them.
numpad_up,
numpad_down,
numpad_right,
numpad_left,
numpad_begin,
numpad_home,
numpad_end,
numpad_insert,
numpad_delete,
numpad_page_up,
numpad_page_down,
// "Function Section" § 3.5
escape,
f1,
@ -405,6 +424,19 @@ pub const Key = enum(c_int) {
f10,
f11,
f12,
f13,
f14,
f15,
f16,
f17,
f18,
f19,
f20,
f21,
f22,
f23,
f24,
f25,
@"fn",
fn_lock,
print_screen,
@ -437,87 +469,61 @@ pub const Key = enum(c_int) {
// Backwards compatibility for Ghostty 1.1.x and earlier, we don't
// want to force people to rewrite their configs.
pub const a = .key_a;
pub const b = .key_b;
pub const c = .key_c;
pub const d = .key_d;
pub const e = .key_e;
pub const f = .key_f;
pub const g = .key_g;
pub const h = .key_h;
pub const i = .key_i;
pub const j = .key_j;
pub const k = .key_k;
pub const l = .key_l;
pub const m = .key_m;
pub const n = .key_n;
pub const o = .key_o;
pub const p = .key_p;
pub const q = .key_q;
pub const r = .key_r;
pub const s = .key_s;
pub const t = .key_t;
pub const u = .key_u;
pub const v = .key_v;
pub const w = .key_w;
pub const x = .key_x;
pub const y = .key_y;
pub const z = .key_z;
pub const zero = .digit_0;
pub const one = .digit_1;
pub const two = .digit_2;
pub const three = .digit_3;
pub const four = .digit_4;
pub const five = .digit_5;
pub const six = .digit_6;
pub const seven = .digit_7;
pub const eight = .digit_8;
pub const nine = .digit_9;
pub const apostrophe = .quote;
pub const grave_accent = .backquote;
pub const left_bracket = .bracket_left;
pub const right_bracket = .bracket_right;
pub const up = .arrow_up;
pub const down = .arrow_down;
pub const left = .arrow_left;
pub const right = .arrow_right;
pub const kp_0 = .numpad_0;
pub const kp_1 = .numpad_1;
pub const kp_2 = .numpad_2;
pub const kp_3 = .numpad_3;
pub const kp_4 = .numpad_4;
pub const kp_5 = .numpad_5;
pub const kp_6 = .numpad_6;
pub const kp_7 = .numpad_7;
pub const kp_8 = .numpad_8;
pub const kp_9 = .numpad_9;
pub const kp_decimal = .numpad_decimal;
pub const kp_divide = .numpad_divide;
pub const kp_multiply = .numpad_multiply;
pub const kp_subtract = .numpad_subtract;
pub const kp_add = .numpad_add;
pub const kp_enter = .numpad_enter;
pub const kp_equal = .numpad_equal;
pub const kp_separator = .numpad_separator;
pub const kp_left = .numpad_left;
pub const kp_right = .numpad_right;
pub const kp_up = .numpad_up;
pub const kp_down = .numpad_down;
pub const kp_page_up = .numpad_page_up;
pub const kp_page_down = .numpad_page_down;
pub const kp_home = .numpad_home;
pub const kp_end = .numpad_end;
pub const kp_insert = .numpad_insert;
pub const kp_delete = .numpad_delete;
pub const kp_begin = .numpad_begin;
pub const left_shift = .shift_left;
pub const right_shift = .shift_right;
pub const left_control = .control_left;
pub const right_control = .control_right;
pub const left_alt = .alt_left;
pub const right_alt = .alt_right;
pub const left_super = .meta_left;
pub const right_super = .meta_right;
// pub const zero = .digit_0;
// pub const one = .digit_1;
// pub const two = .digit_2;
// pub const three = .digit_3;
// pub const four = .digit_4;
// pub const five = .digit_5;
// pub const six = .digit_6;
// pub const seven = .digit_7;
// pub const eight = .digit_8;
// pub const nine = .digit_9;
// pub const apostrophe = .quote;
// pub const grave_accent = .backquote;
// pub const left_bracket = .bracket_left;
// pub const right_bracket = .bracket_right;
// pub const up = .arrow_up;
// pub const down = .arrow_down;
// pub const left = .arrow_left;
// pub const right = .arrow_right;
// pub const kp_0 = .numpad_0;
// pub const kp_1 = .numpad_1;
// pub const kp_2 = .numpad_2;
// pub const kp_3 = .numpad_3;
// pub const kp_4 = .numpad_4;
// pub const kp_5 = .numpad_5;
// pub const kp_6 = .numpad_6;
// pub const kp_7 = .numpad_7;
// pub const kp_8 = .numpad_8;
// pub const kp_9 = .numpad_9;
// pub const kp_decimal = .numpad_decimal;
// pub const kp_divide = .numpad_divide;
// pub const kp_multiply = .numpad_multiply;
// pub const kp_subtract = .numpad_subtract;
// pub const kp_add = .numpad_add;
// pub const kp_enter = .numpad_enter;
// pub const kp_equal = .numpad_equal;
// pub const kp_separator = .numpad_separator;
// pub const kp_left = .numpad_left;
// pub const kp_right = .numpad_right;
// pub const kp_up = .numpad_up;
// pub const kp_down = .numpad_down;
// pub const kp_page_up = .numpad_page_up;
// pub const kp_page_down = .numpad_page_down;
// pub const kp_home = .numpad_home;
// pub const kp_end = .numpad_end;
// pub const kp_insert = .numpad_insert;
// pub const kp_delete = .numpad_delete;
// pub const kp_begin = .numpad_begin;
// pub const left_shift = .shift_left;
// pub const right_shift = .shift_right;
// pub const left_control = .control_left;
// pub const right_control = .control_right;
// pub const left_alt = .alt_left;
// pub const right_alt = .alt_right;
// pub const left_super = .meta_left;
// pub const right_super = .meta_right;
/// Converts an ASCII character to a key, if possible. This returns
/// null if the character is unknown.
@ -586,7 +592,7 @@ pub const Key = enum(c_int) {
return switch (self) {
inline else => |tag| {
const name = @tagName(tag);
const result = comptime std.mem.startsWith(u8, name, "kp_");
const result = comptime std.mem.startsWith(u8, name, "numpad_");
return result;
},
};
@ -763,107 +769,106 @@ pub const Key = enum(c_int) {
/// or ctrl.
pub fn ctrlOrSuper(self: Key) bool {
if (comptime builtin.target.os.tag.isDarwin()) {
return self == .left_super or self == .right_super;
return self == .meta_left or self == .meta_right;
}
return self == .left_control or self == .right_control;
return self == .control_left or self == .control_right;
}
/// true if this key is either left or right shift.
pub fn leftOrRightShift(self: Key) bool {
return self == .left_shift or self == .right_shift;
return self == .shift_left or self == .shift_right;
}
/// true if this key is either left or right alt.
pub fn leftOrRightAlt(self: Key) bool {
return self == .left_alt or self == .right_alt;
return self == .alt_left or self == .alt_right;
}
test "fromASCII should not return keypad keys" {
const testing = std.testing;
try testing.expect(Key.fromASCII('0').? == .zero);
try testing.expect(Key.fromASCII('0').? == .digit_0);
try testing.expect(Key.fromASCII('*') == null);
}
test "keypad keys" {
const testing = std.testing;
try testing.expect(Key.kp_0.keypad());
try testing.expect(!Key.one.keypad());
try testing.expect(Key.numpad_0.keypad());
try testing.expect(!Key.digit_1.keypad());
}
const codepoint_map: []const struct { u21, Key } = &.{
.{ 'a', .a },
.{ 'b', .b },
.{ 'c', .c },
.{ 'd', .d },
.{ 'e', .e },
.{ 'f', .f },
.{ 'g', .g },
.{ 'h', .h },
.{ 'i', .i },
.{ 'j', .j },
.{ 'k', .k },
.{ 'l', .l },
.{ 'm', .m },
.{ 'n', .n },
.{ 'o', .o },
.{ 'p', .p },
.{ 'q', .q },
.{ 'r', .r },
.{ 's', .s },
.{ 't', .t },
.{ 'u', .u },
.{ 'v', .v },
.{ 'w', .w },
.{ 'x', .x },
.{ 'y', .y },
.{ 'z', .z },
.{ '0', .zero },
.{ '1', .one },
.{ '2', .two },
.{ '3', .three },
.{ '4', .four },
.{ '5', .five },
.{ '6', .six },
.{ '7', .seven },
.{ '8', .eight },
.{ '9', .nine },
.{ 'a', .key_a },
.{ 'b', .key_b },
.{ 'c', .key_c },
.{ 'd', .key_d },
.{ 'e', .key_e },
.{ 'f', .key_f },
.{ 'g', .key_g },
.{ 'h', .key_h },
.{ 'i', .key_i },
.{ 'j', .key_j },
.{ 'k', .key_k },
.{ 'l', .key_l },
.{ 'm', .key_m },
.{ 'n', .key_n },
.{ 'o', .key_o },
.{ 'p', .key_p },
.{ 'q', .key_q },
.{ 'r', .key_r },
.{ 's', .key_s },
.{ 't', .key_t },
.{ 'u', .key_u },
.{ 'v', .key_v },
.{ 'w', .key_w },
.{ 'x', .key_x },
.{ 'y', .key_y },
.{ 'z', .key_z },
.{ '0', .digit_0 },
.{ '1', .digit_1 },
.{ '2', .digit_2 },
.{ '3', .digit_3 },
.{ '4', .digit_4 },
.{ '5', .digit_5 },
.{ '6', .digit_6 },
.{ '7', .digit_7 },
.{ '8', .digit_8 },
.{ '9', .digit_9 },
.{ ';', .semicolon },
.{ ' ', .space },
.{ '\'', .apostrophe },
.{ '\'', .quote },
.{ ',', .comma },
.{ '`', .grave_accent },
.{ '`', .backquote },
.{ '.', .period },
.{ '/', .slash },
.{ '-', .minus },
.{ '+', .plus },
.{ '=', .equal },
.{ '[', .left_bracket },
.{ ']', .right_bracket },
.{ '[', .bracket_left },
.{ ']', .bracket_right },
.{ '\\', .backslash },
// Control characters
.{ '\t', .tab },
// Keypad entries. We just assume keypad with the kp_ prefix
// Keypad entries. We just assume keypad with the numpad_ prefix
// so that has some special meaning. These must also always be last,
// so that our `fromASCII` function doesn't accidentally map them
// over normal numerics and other keys.
.{ '0', .kp_0 },
.{ '1', .kp_1 },
.{ '2', .kp_2 },
.{ '3', .kp_3 },
.{ '4', .kp_4 },
.{ '5', .kp_5 },
.{ '6', .kp_6 },
.{ '7', .kp_7 },
.{ '8', .kp_8 },
.{ '9', .kp_9 },
.{ '.', .kp_decimal },
.{ '/', .kp_divide },
.{ '*', .kp_multiply },
.{ '-', .kp_subtract },
.{ '+', .kp_add },
.{ '=', .kp_equal },
.{ '0', .numpad_0 },
.{ '1', .numpad_1 },
.{ '2', .numpad_2 },
.{ '3', .numpad_3 },
.{ '4', .numpad_4 },
.{ '5', .numpad_5 },
.{ '6', .numpad_6 },
.{ '7', .numpad_7 },
.{ '8', .numpad_8 },
.{ '9', .numpad_9 },
.{ '.', .numpad_decimal },
.{ '/', .numpad_divide },
.{ '*', .numpad_multiply },
.{ '-', .numpad_subtract },
.{ '+', .numpad_add },
.{ '=', .numpad_equal },
};
};

View File

@ -49,10 +49,10 @@ const raw_entries: []const RawEntry = &.{
.{ .backspace, 127, 'u', false },
.{ .insert, 2, '~', false },
.{ .delete, 3, '~', false },
.{ .left, 1, 'D', false },
.{ .right, 1, 'C', false },
.{ .up, 1, 'A', false },
.{ .down, 1, 'B', false },
.{ .arrow_left, 1, 'D', false },
.{ .arrow_right, 1, 'C', false },
.{ .arrow_up, 1, 'A', false },
.{ .arrow_down, 1, 'B', false },
.{ .page_up, 5, '~', false },
.{ .page_down, 6, '~', false },
.{ .home, 1, 'H', false },
@ -89,46 +89,32 @@ const raw_entries: []const RawEntry = &.{
.{ .f24, 57387, 'u', false },
.{ .f25, 57388, 'u', false },
.{ .kp_0, 57399, 'u', false },
.{ .kp_1, 57400, 'u', false },
.{ .kp_2, 57401, 'u', false },
.{ .kp_3, 57402, 'u', false },
.{ .kp_4, 57403, 'u', false },
.{ .kp_5, 57404, 'u', false },
.{ .kp_6, 57405, 'u', false },
.{ .kp_7, 57406, 'u', false },
.{ .kp_8, 57407, 'u', false },
.{ .kp_9, 57408, 'u', false },
.{ .kp_decimal, 57409, 'u', false },
.{ .kp_divide, 57410, 'u', false },
.{ .kp_multiply, 57411, 'u', false },
.{ .kp_subtract, 57412, 'u', false },
.{ .kp_add, 57413, 'u', false },
.{ .kp_enter, 57414, 'u', false },
.{ .kp_equal, 57415, 'u', false },
.{ .kp_separator, 57416, 'u', false },
.{ .kp_left, 57417, 'u', false },
.{ .kp_right, 57418, 'u', false },
.{ .kp_up, 57419, 'u', false },
.{ .kp_down, 57420, 'u', false },
.{ .kp_page_up, 57421, 'u', false },
.{ .kp_page_down, 57422, 'u', false },
.{ .kp_home, 57423, 'u', false },
.{ .kp_end, 57424, 'u', false },
.{ .kp_insert, 57425, 'u', false },
.{ .kp_delete, 57426, 'u', false },
.{ .kp_begin, 57427, 'u', false },
.{ .numpad_0, 57399, 'u', false },
.{ .numpad_1, 57400, 'u', false },
.{ .numpad_2, 57401, 'u', false },
.{ .numpad_3, 57402, 'u', false },
.{ .numpad_4, 57403, 'u', false },
.{ .numpad_5, 57404, 'u', false },
.{ .numpad_6, 57405, 'u', false },
.{ .numpad_7, 57406, 'u', false },
.{ .numpad_8, 57407, 'u', false },
.{ .numpad_9, 57408, 'u', false },
.{ .numpad_decimal, 57409, 'u', false },
.{ .numpad_divide, 57410, 'u', false },
.{ .numpad_multiply, 57411, 'u', false },
.{ .numpad_subtract, 57412, 'u', false },
.{ .numpad_add, 57413, 'u', false },
.{ .numpad_enter, 57414, 'u', false },
.{ .numpad_equal, 57415, 'u', false },
// TODO: media keys
.{ .left_shift, 57441, 'u', true },
.{ .right_shift, 57447, 'u', true },
.{ .left_control, 57442, 'u', true },
.{ .right_control, 57448, 'u', true },
.{ .left_super, 57444, 'u', true },
.{ .right_super, 57450, 'u', true },
.{ .left_alt, 57443, 'u', true },
.{ .right_alt, 57449, 'u', true },
.{ .shift_left, 57441, 'u', true },
.{ .shift_right, 57447, 'u', true },
.{ .control_left, 57442, 'u', true },
.{ .control_right, 57448, 'u', true },
.{ .meta_left, 57444, 'u', true },
.{ .meta_right, 57450, 'u', true },
.{ .alt_left, 57443, 'u', true },
.{ .alt_right, 57449, 'u', true },
};
test {

View File

@ -56,7 +56,7 @@ pub const Event = struct {
// Write our key. If we have an invalid key we attempt to write
// the utf8 associated with it if we have it to handle non-ascii.
try writer.writeAll(switch (self.event.key) {
.invalid => if (self.event.utf8.len > 0) self.event.utf8 else @tagName(.invalid),
.unidentified => if (self.event.utf8.len > 0) self.event.utf8 else @tagName(self.event.key),
else => @tagName(self.event.key),
});
@ -227,9 +227,9 @@ test "event string" {
const testing = std.testing;
const alloc = testing.allocator;
var event = try Event.init(alloc, .{ .key = .a });
var event = try Event.init(alloc, .{ .key = .key_a });
defer event.deinit(alloc);
var buf: [1024]u8 = undefined;
try testing.expectEqualStrings("Press: a", try event.label(&buf));
try testing.expectEqualStrings("Press: key_a", try event.label(&buf));
}

View File

@ -132,7 +132,7 @@ test "keyToMouseShape" {
{
// No specific key pressed
const m: SurfaceMouse = .{
.physical_key = .invalid,
.physical_key = .unidentified,
.mouse_event = .none,
.mouse_shape = .progress,
.mods = .{},
@ -148,7 +148,7 @@ test "keyToMouseShape" {
// Over a link. NOTE: This tests that we don't touch the inbound state,
// not necessarily if we're over a link.
const m: SurfaceMouse = .{
.physical_key = .left_shift,
.physical_key = .shift_left,
.mouse_event = .none,
.mouse_shape = .progress,
.mods = .{},
@ -163,7 +163,7 @@ test "keyToMouseShape" {
{
// Mouse is currently hidden
const m: SurfaceMouse = .{
.physical_key = .left_shift,
.physical_key = .shift_left,
.mouse_event = .none,
.mouse_shape = .progress,
.mods = .{},
@ -178,7 +178,7 @@ test "keyToMouseShape" {
{
// default, no mods (mouse tracking)
const m: SurfaceMouse = .{
.physical_key = .left_shift,
.physical_key = .shift_left,
.mouse_event = .x10,
.mouse_shape = .default,
.mods = .{},
@ -194,7 +194,7 @@ test "keyToMouseShape" {
{
// default -> crosshair (mouse tracking)
const m: SurfaceMouse = .{
.physical_key = .left_alt,
.physical_key = .alt_left,
.mouse_event = .x10,
.mouse_shape = .default,
.mods = .{ .ctrl = true, .super = true, .alt = true, .shift = true },
@ -210,7 +210,7 @@ test "keyToMouseShape" {
{
// default -> text (mouse tracking)
const m: SurfaceMouse = .{
.physical_key = .left_shift,
.physical_key = .shift_left,
.mouse_event = .x10,
.mouse_shape = .default,
.mods = .{ .shift = true },
@ -226,7 +226,7 @@ test "keyToMouseShape" {
{
// crosshair -> text (mouse tracking)
const m: SurfaceMouse = .{
.physical_key = .left_alt,
.physical_key = .alt_left,
.mouse_event = .x10,
.mouse_shape = .crosshair,
.mods = .{ .shift = true },
@ -242,7 +242,7 @@ test "keyToMouseShape" {
{
// crosshair -> default (mouse tracking)
const m: SurfaceMouse = .{
.physical_key = .left_alt,
.physical_key = .alt_left,
.mouse_event = .x10,
.mouse_shape = .crosshair,
.mods = .{},
@ -258,7 +258,7 @@ test "keyToMouseShape" {
{
// text -> crosshair (mouse tracking)
const m: SurfaceMouse = .{
.physical_key = .left_alt,
.physical_key = .alt_left,
.mouse_event = .x10,
.mouse_shape = .text,
.mods = .{ .ctrl = true, .super = true, .alt = true, .shift = true },
@ -274,7 +274,7 @@ test "keyToMouseShape" {
{
// text -> default (mouse tracking)
const m: SurfaceMouse = .{
.physical_key = .left_shift,
.physical_key = .shift_left,
.mouse_event = .x10,
.mouse_shape = .text,
.mods = .{},
@ -290,7 +290,7 @@ test "keyToMouseShape" {
{
// text, no mods (no mouse tracking)
const m: SurfaceMouse = .{
.physical_key = .left_shift,
.physical_key = .shift_left,
.mouse_event = .none,
.mouse_shape = .text,
.mods = .{},
@ -306,7 +306,7 @@ test "keyToMouseShape" {
{
// text -> crosshair (no mouse tracking)
const m: SurfaceMouse = .{
.physical_key = .left_alt,
.physical_key = .alt_left,
.mouse_event = .none,
.mouse_shape = .text,
.mods = .{ .ctrl = true, .super = true, .alt = true },
@ -322,7 +322,7 @@ test "keyToMouseShape" {
{
// crosshair -> text (no mouse tracking)
const m: SurfaceMouse = .{
.physical_key = .left_alt,
.physical_key = .alt_left,
.mouse_event = .none,
.mouse_shape = .crosshair,
.mods = .{},