From 22296b377a9336114c56a92fe82653b63328a646 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 7 Aug 2023 17:06:40 -0700 Subject: [PATCH] Revert "Merge pull request #244 from mitchellh/alt-as-esc" This reverts commit c139279d479682c17f63d9b57c2d56608d09d16a, reversing changes made to 4ed21047a734d7c586debe0026e3b6ea90ed1622. We do want to do this but this broke bindings. --- include/ghostty.h | 16 ++-- macos/Sources/Ghostty/SurfaceView.swift | 14 +--- src/Surface.zig | 20 ++--- src/apprt/embedded.zig | 6 +- src/apprt/glfw.zig | 15 +--- src/apprt/gtk.zig | 8 +- src/config.zig | 102 +++++++++++------------- src/input/Binding.zig | 65 +++------------ src/input/key.zig | 52 +++--------- src/input/mouse.zig | 10 +-- 10 files changed, 98 insertions(+), 210 deletions(-) diff --git a/include/ghostty.h b/include/ghostty.h index 1c7d18d37..5b75ea1ad 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -72,16 +72,12 @@ typedef int ghostty_input_scroll_mods_t; typedef enum { GHOSTTY_MODS_NONE = 0, - GHOSTTY_MODS_LEFT_SHIFT = 1 << 0, - GHOSTTY_MODS_RIGHT_SHIFT = 1 << 1, - GHOSTTY_MODS_LEFT_CTRL = 1 << 2, - GHOSTTY_MODS_RIGHT_CTRL = 1 << 3, - GHOSTTY_MODS_LEFT_ALT = 1 << 4, - GHOSTTY_MODS_RIGHT_ALT = 1 << 5, - GHOSTTY_MODS_LEFT_SUPER = 1 << 6, - GHOSTTY_MODS_RIGHT_SUPER = 1 << 7, - GHOSTTY_MODS_CAPS = 1 << 8, - GHOSTTY_MODS_NUM = 1 << 9, + GHOSTTY_MODS_SHIFT = 1 << 0, + GHOSTTY_MODS_CTRL = 1 << 1, + GHOSTTY_MODS_ALT = 1 << 2, + GHOSTTY_MODS_SUPER = 1 << 3, + GHOSTTY_MODS_CAPS = 1 << 4, + GHOSTTY_MODS_NUM = 1 << 5, } ghostty_input_mods_e; typedef enum { diff --git a/macos/Sources/Ghostty/SurfaceView.swift b/macos/Sources/Ghostty/SurfaceView.swift index 03e5f333f..2bb9c5e8d 100644 --- a/macos/Sources/Ghostty/SurfaceView.swift +++ b/macos/Sources/Ghostty/SurfaceView.swift @@ -491,16 +491,10 @@ extension Ghostty { private static func translateFlags(_ flags: NSEvent.ModifierFlags) -> ghostty_input_mods_e { var mods: UInt32 = GHOSTTY_MODS_NONE.rawValue - - let rawFlags = flags.rawValue - if (rawFlags & UInt(NX_DEVICELSHIFTKEYMASK) != 0) { mods |= GHOSTTY_MODS_LEFT_SHIFT.rawValue } - if (rawFlags & UInt(NX_DEVICERSHIFTKEYMASK) != 0) { mods |= GHOSTTY_MODS_RIGHT_SHIFT.rawValue } - if (rawFlags & UInt(NX_DEVICELCTLKEYMASK) != 0) { mods |= GHOSTTY_MODS_LEFT_CTRL.rawValue } - if (rawFlags & UInt(NX_DEVICERCTLKEYMASK) != 0) { mods |= GHOSTTY_MODS_RIGHT_CTRL.rawValue } - if (rawFlags & UInt(NX_DEVICELALTKEYMASK) != 0) { mods |= GHOSTTY_MODS_LEFT_ALT.rawValue } - if (rawFlags & UInt(NX_DEVICERALTKEYMASK) != 0) { mods |= GHOSTTY_MODS_RIGHT_ALT.rawValue } - if (rawFlags & UInt(NX_DEVICELCMDKEYMASK) != 0) { mods |= GHOSTTY_MODS_LEFT_SUPER.rawValue } - if (rawFlags & UInt(NX_DEVICERCMDKEYMASK) != 0) { mods |= GHOSTTY_MODS_RIGHT_SUPER.rawValue } + if (flags.contains(.shift)) { mods |= GHOSTTY_MODS_SHIFT.rawValue } + if (flags.contains(.control)) { mods |= GHOSTTY_MODS_CTRL.rawValue } + if (flags.contains(.option)) { mods |= GHOSTTY_MODS_ALT.rawValue } + if (flags.contains(.command)) { mods |= GHOSTTY_MODS_SUPER.rawValue } if (flags.contains(.capsLock)) { mods |= GHOSTTY_MODS_CAPS.rawValue } return ghostty_input_mods_e(mods) diff --git a/src/Surface.zig b/src/Surface.zig index 25cfdfec8..bf8bd3649 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -981,12 +981,12 @@ pub fn keyCallback( // Handle non-printables const char: u8 = char: { - const mods_int: input.Mods.Int = @bitCast(mods); - const ctrl_only: input.Mods.Int = @bitCast(input.Mods{ .ctrl = .both }); + const mods_int: u8 = @bitCast(mods); + const ctrl_only: u8 = @bitCast(input.Mods{ .ctrl = true }); // If we're only pressing control, check if this is a character // we convert to a non-printable. - if (mods_int & ctrl_only > 0) { + if (mods_int == ctrl_only) { const val: u8 = switch (key) { .left_bracket => 0x1B, .backslash => 0x1C, @@ -1324,9 +1324,9 @@ fn mouseReport( // X10 doesn't have modifiers if (self.io.terminal.modes.mouse_event != .x10) { - if (mods.shift.pressed()) acc += 4; - if (mods.super.pressed()) acc += 8; - if (mods.ctrl.pressed()) acc += 16; + if (mods.shift) acc += 4; + if (mods.super) acc += 8; + if (mods.ctrl) acc += 16; } // Motion adds another bit @@ -1478,13 +1478,13 @@ pub fn mouseButtonCallback( // Always record our latest mouse state self.mouse.click_state[@intCast(@intFromEnum(button))] = action; - self.mouse.mods = mods; + self.mouse.mods = @bitCast(mods); // Shift-click continues the previous mouse state if we have a selection. // cursorPosCallback will also do a mouse report so we don't need to do any // of the logic below. if (button == .left and action == .press) { - if (mods.shift.pressed() and self.mouse.left_click_count > 0) { + if (mods.shift and self.mouse.left_click_count > 0) { // Checking for selection requires the renderer state mutex which // sucks but this should be pretty rare of an event so it won't // cause a ton of contention. @@ -1508,7 +1508,7 @@ pub fn mouseButtonCallback( // Report mouse events if enabled if (self.io.terminal.modes.mouse_event != .none) report: { // Shift overrides mouse "grabbing" in the window, taken from Kitty. - if (mods.shift.pressed()) break :report; + if (mods.shift) break :report; // In any other mouse button scenario without shift pressed we // clear the selection since the underlying application can handle @@ -1634,7 +1634,7 @@ pub fn cursorPosCallback( // Do a mouse report if (self.io.terminal.modes.mouse_event != .none) report: { // Shift overrides mouse "grabbing" in the window, taken from Kitty. - if (self.mouse.mods.shift.pressed()) break :report; + if (self.mouse.mods.shift) break :report; // We use the first mouse button we find pressed in order to report // since the spec (afaict) does not say... diff --git a/src/apprt/embedded.zig b/src/apprt/embedded.zig index 53f6b2d76..e793360c6 100644 --- a/src/apprt/embedded.zig +++ b/src/apprt/embedded.zig @@ -508,7 +508,7 @@ pub const CAPI = struct { action, key, unmapped_key, - @bitCast(@as(input.Mods.Int, @truncate(@as(c_uint, @bitCast(mods))))), + @bitCast(@as(u8, @truncate(@as(c_uint, @bitCast(mods))))), ); } @@ -527,7 +527,7 @@ pub const CAPI = struct { surface.mouseButtonCallback( action, button, - @bitCast(@as(input.Mods.Int, @truncate(@as(c_uint, @bitCast(mods))))), + @bitCast(@as(u8, @truncate(@as(c_uint, @bitCast(mods))))), ); } @@ -545,7 +545,7 @@ pub const CAPI = struct { surface.scrollCallback( x, y, - @bitCast(@as(input.ScrollMods.Int, @truncate(@as(c_uint, @bitCast(scroll_mods))))), + @bitCast(@as(u8, @truncate(@as(c_uint, @bitCast(scroll_mods))))), ); } diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index c3cb6d683..4863e5511 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -564,7 +564,7 @@ pub const Surface = struct { defer tracy.end(); // Convert our glfw types into our input types - const mods = convertMods(glfw_mods); + const mods: input.Mods = @bitCast(glfw_mods); const action: input.Action = switch (glfw_action) { .release => .release, .press => .press, @@ -784,7 +784,7 @@ pub const Surface = struct { const core_win = window.getUserPointer(CoreSurface) orelse return; // Convert glfw button to input button - const mods = convertMods(glfw_mods); + const mods: input.Mods = @bitCast(glfw_mods); const button: input.MouseButton = switch (glfw_button) { .left => .left, .right => .right, @@ -806,15 +806,4 @@ pub const Surface = struct { return; }; } - - fn convertMods(mods: glfw.Mods) input.Mods { - return .{ - .shift = if (mods.shift) .both else .none, - .ctrl = if (mods.control) .both else .none, - .alt = if (mods.alt) .both else .none, - .super = if (mods.super) .both else .none, - .caps_lock = mods.caps_lock, - .num_lock = mods.num_lock, - }; - } }; diff --git a/src/apprt/gtk.zig b/src/apprt/gtk.zig index 4c3471979..2871e7f06 100644 --- a/src/apprt/gtk.zig +++ b/src/apprt/gtk.zig @@ -1230,10 +1230,10 @@ fn translateMouseButton(button: c.guint) input.MouseButton { fn translateMods(state: c.GdkModifierType) input.Mods { var mods: input.Mods = .{}; - if (state & c.GDK_SHIFT_MASK != 0) mods.shift = .both; - if (state & c.GDK_CONTROL_MASK != 0) mods.ctrl = .both; - if (state & c.GDK_ALT_MASK != 0) mods.alt = .both; - if (state & c.GDK_SUPER_MASK != 0) mods.super = .both; + if (state & c.GDK_SHIFT_MASK != 0) mods.shift = true; + if (state & c.GDK_CONTROL_MASK != 0) mods.ctrl = true; + if (state & c.GDK_ALT_MASK != 0) mods.alt = true; + if (state & c.GDK_SUPER_MASK != 0) mods.super = true; // Lock is dependent on the X settings but we just assume caps lock. if (state & c.GDK_LOCK_MASK != 0) mods.caps_lock = true; diff --git a/src/config.zig b/src/config.zig index ef56f3d42..e812cbec8 100644 --- a/src/config.zig +++ b/src/config.zig @@ -3,7 +3,6 @@ const std = @import("std"); const builtin = @import("builtin"); const Allocator = std.mem.Allocator; const ArenaAllocator = std.heap.ArenaAllocator; -const apprt = @import("apprt.zig"); const inputpkg = @import("input.zig"); const terminal = @import("terminal/main.zig"); const internal_os = @import("os/main.zig"); @@ -301,7 +300,7 @@ pub const Config = struct { // Add our default keybindings try result.keybind.set.put( alloc, - .{ .key = .space, .mods = .{ .super = .both, .alt = .both, .ctrl = .both } }, + .{ .key = .space, .mods = .{ .super = true, .alt = true, .ctrl = true } }, .{ .reload_config = {} }, ); @@ -309,9 +308,9 @@ pub const Config = struct { // On macOS we default to super but Linux ctrl+shift since // ctrl+c is to kill the process. const mods: inputpkg.Mods = if (builtin.target.isDarwin()) - .{ .super = .both } + .{ .super = true } else - .{ .ctrl = .both, .shift = .both }; + .{ .ctrl = true, .shift = true }; try result.keybind.set.put( alloc, @@ -394,13 +393,13 @@ pub const Config = struct { // Dev Mode try result.keybind.set.put( alloc, - .{ .key = .down, .mods = .{ .shift = .both, .super = .both } }, + .{ .key = .down, .mods = .{ .shift = true, .super = true } }, .{ .toggle_dev_mode = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .j, .mods = ctrlOrSuper(.{ .shift = .both }) }, + .{ .key = .j, .mods = ctrlOrSuper(.{ .shift = true }) }, .{ .write_scrollback_file = {} }, ); @@ -408,89 +407,89 @@ pub const Config = struct { if (comptime !builtin.target.isDarwin()) { try result.keybind.set.put( alloc, - .{ .key = .n, .mods = .{ .ctrl = .both, .shift = .both } }, + .{ .key = .n, .mods = .{ .ctrl = true, .shift = true } }, .{ .new_window = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .w, .mods = .{ .ctrl = .both, .shift = .both } }, + .{ .key = .w, .mods = .{ .ctrl = true, .shift = true } }, .{ .close_surface = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .q, .mods = .{ .ctrl = .both, .shift = .both } }, + .{ .key = .q, .mods = .{ .ctrl = true, .shift = true } }, .{ .quit = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .f4, .mods = .{ .alt = .both } }, + .{ .key = .f4, .mods = .{ .alt = true } }, .{ .close_window = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .t, .mods = .{ .ctrl = .both, .shift = .both } }, + .{ .key = .t, .mods = .{ .ctrl = true, .shift = true } }, .{ .new_tab = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .left, .mods = .{ .ctrl = .both, .shift = .both } }, + .{ .key = .left, .mods = .{ .ctrl = true, .shift = true } }, .{ .previous_tab = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .right, .mods = .{ .ctrl = .both, .shift = .both } }, + .{ .key = .right, .mods = .{ .ctrl = true, .shift = true } }, .{ .next_tab = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .o, .mods = .{ .ctrl = .both, .shift = .both } }, + .{ .key = .o, .mods = .{ .ctrl = true, .shift = true } }, .{ .new_split = .right }, ); try result.keybind.set.put( alloc, - .{ .key = .e, .mods = .{ .ctrl = .both, .shift = .both } }, + .{ .key = .e, .mods = .{ .ctrl = true, .shift = true } }, .{ .new_split = .down }, ); try result.keybind.set.put( alloc, - .{ .key = .left_bracket, .mods = .{ .ctrl = .both, .super = .both } }, + .{ .key = .left_bracket, .mods = .{ .ctrl = true, .super = true } }, .{ .goto_split = .previous }, ); try result.keybind.set.put( alloc, - .{ .key = .right_bracket, .mods = .{ .ctrl = .both, .super = .both } }, + .{ .key = .right_bracket, .mods = .{ .ctrl = true, .super = true } }, .{ .goto_split = .next }, ); try result.keybind.set.put( alloc, - .{ .key = .up, .mods = .{ .ctrl = .both, .alt = .both } }, + .{ .key = .up, .mods = .{ .ctrl = true, .alt = true } }, .{ .goto_split = .top }, ); try result.keybind.set.put( alloc, - .{ .key = .down, .mods = .{ .ctrl = .both, .alt = .both } }, + .{ .key = .down, .mods = .{ .ctrl = true, .alt = true } }, .{ .goto_split = .bottom }, ); try result.keybind.set.put( alloc, - .{ .key = .left, .mods = .{ .ctrl = .both, .alt = .both } }, + .{ .key = .left, .mods = .{ .ctrl = true, .alt = true } }, .{ .goto_split = .left }, ); try result.keybind.set.put( alloc, - .{ .key = .right, .mods = .{ .ctrl = .both, .alt = .both } }, + .{ .key = .right, .mods = .{ .ctrl = true, .alt = true } }, .{ .goto_split = .right }, ); // Semantic prompts try result.keybind.set.put( alloc, - .{ .key = .page_up, .mods = .{ .shift = .both } }, + .{ .key = .page_up, .mods = .{ .shift = true } }, .{ .jump_to_prompt = -1 }, ); try result.keybind.set.put( alloc, - .{ .key = .page_down, .mods = .{ .shift = .both } }, + .{ .key = .page_down, .mods = .{ .shift = true } }, .{ .jump_to_prompt = 1 }, ); } @@ -503,9 +502,9 @@ pub const Config = struct { // On macOS we default to super but everywhere else // is alt. const mods: inputpkg.Mods = if (builtin.target.isDarwin()) - .{ .super = .both } + .{ .super = true } else - .{ .alt = .both }; + .{ .alt = true }; try result.keybind.set.put( alloc, @@ -526,97 +525,97 @@ pub const Config = struct { if (comptime builtin.target.isDarwin()) { try result.keybind.set.put( alloc, - .{ .key = .q, .mods = .{ .super = .both } }, + .{ .key = .q, .mods = .{ .super = true } }, .{ .quit = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .k, .mods = .{ .super = .both } }, + .{ .key = .k, .mods = .{ .super = true } }, .{ .clear_screen = {} }, ); // Semantic prompts try result.keybind.set.put( alloc, - .{ .key = .up, .mods = .{ .super = .both, .shift = .both } }, + .{ .key = .up, .mods = .{ .super = true, .shift = true } }, .{ .jump_to_prompt = -1 }, ); try result.keybind.set.put( alloc, - .{ .key = .down, .mods = .{ .super = .both, .shift = .both } }, + .{ .key = .down, .mods = .{ .super = true, .shift = true } }, .{ .jump_to_prompt = 1 }, ); // Mac windowing try result.keybind.set.put( alloc, - .{ .key = .n, .mods = .{ .super = .both } }, + .{ .key = .n, .mods = .{ .super = true } }, .{ .new_window = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .w, .mods = .{ .super = .both } }, + .{ .key = .w, .mods = .{ .super = true } }, .{ .close_surface = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .w, .mods = .{ .super = .both, .shift = .both } }, + .{ .key = .w, .mods = .{ .super = true, .shift = true } }, .{ .close_window = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .t, .mods = .{ .super = .both } }, + .{ .key = .t, .mods = .{ .super = true } }, .{ .new_tab = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .left_bracket, .mods = .{ .super = .both, .shift = .both } }, + .{ .key = .left_bracket, .mods = .{ .super = true, .shift = true } }, .{ .previous_tab = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .right_bracket, .mods = .{ .super = .both, .shift = .both } }, + .{ .key = .right_bracket, .mods = .{ .super = true, .shift = true } }, .{ .next_tab = {} }, ); try result.keybind.set.put( alloc, - .{ .key = .d, .mods = .{ .super = .both } }, + .{ .key = .d, .mods = .{ .super = true } }, .{ .new_split = .right }, ); try result.keybind.set.put( alloc, - .{ .key = .d, .mods = .{ .super = .both, .shift = .both } }, + .{ .key = .d, .mods = .{ .super = true, .shift = true } }, .{ .new_split = .down }, ); try result.keybind.set.put( alloc, - .{ .key = .left_bracket, .mods = .{ .super = .both } }, + .{ .key = .left_bracket, .mods = .{ .super = true } }, .{ .goto_split = .previous }, ); try result.keybind.set.put( alloc, - .{ .key = .right_bracket, .mods = .{ .super = .both } }, + .{ .key = .right_bracket, .mods = .{ .super = true } }, .{ .goto_split = .next }, ); try result.keybind.set.put( alloc, - .{ .key = .up, .mods = .{ .super = .both, .alt = .both } }, + .{ .key = .up, .mods = .{ .super = true, .alt = true } }, .{ .goto_split = .top }, ); try result.keybind.set.put( alloc, - .{ .key = .down, .mods = .{ .super = .both, .alt = .both } }, + .{ .key = .down, .mods = .{ .super = true, .alt = true } }, .{ .goto_split = .bottom }, ); try result.keybind.set.put( alloc, - .{ .key = .left, .mods = .{ .super = .both, .alt = .both } }, + .{ .key = .left, .mods = .{ .super = true, .alt = true } }, .{ .goto_split = .left }, ); try result.keybind.set.put( alloc, - .{ .key = .right, .mods = .{ .super = .both, .alt = .both } }, + .{ .key = .right, .mods = .{ .super = true, .alt = true } }, .{ .goto_split = .right }, ); } @@ -631,9 +630,9 @@ pub const Config = struct { fn ctrlOrSuper(mods: inputpkg.Mods) inputpkg.Mods { var copy = mods; if (comptime builtin.target.isDarwin()) { - copy.super = .both; + copy.super = true; } else { - copy.ctrl = .both; + copy.ctrl = true; } return copy; @@ -1207,18 +1206,7 @@ pub const Keybinds = struct { }; errdefer if (copy) |v| alloc.free(v); - const binding = binding: { - var binding = try inputpkg.Binding.parse(value); - - // Unless we're on native macOS, we don't allow directional - // keys, so we just remap them to "both". - if (comptime !(builtin.target.isDarwin() and apprt.runtime == apprt.embedded)) { - binding.trigger.mods = binding.trigger.mods.removeDirection(); - } - - break :binding binding; - }; - + const binding = try inputpkg.Binding.parse(value); switch (binding.action) { .unbind => self.set.remove(binding.trigger), else => try self.set.put(alloc, binding.trigger, binding.action), diff --git a/src/input/Binding.zig b/src/input/Binding.zig index c4090b804..4dec02d6f 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -3,7 +3,6 @@ const Binding = @This(); const std = @import("std"); -const builtin = @import("builtin"); const Allocator = std.mem.Allocator; const assert = std.debug.assert; const key = @import("key.zig"); @@ -43,44 +42,12 @@ pub fn parse(input: []const u8) !Binding { // Check if its a modifier const modsInfo = @typeInfo(key.Mods).Struct; inline for (modsInfo.fields) |field| { - if (field.name[0] != '_') { - if (std.mem.endsWith(u8, part, field.name)) { - // Parse the directional modifier if it exists - const side: key.Mods.Side = side: { - if (std.mem.eql(u8, part, field.name)) - break :side .both; - if (std.mem.eql(u8, part, "left_" ++ field.name)) - break :side .left; - if (std.mem.eql(u8, part, "right_" ++ field.name)) - break :side .right; - - return Error.InvalidFormat; - }; - - switch (field.type) { - bool => { - // Can only be set once - if (@field(result.mods, field.name)) - return Error.InvalidFormat; - - // Can not be directional - if (side != .both) - return Error.InvalidFormat; - - @field(result.mods, field.name) = true; - }, - - key.Mods.Side => { - // Can only be set once - if (@field(result.mods, field.name).pressed()) - return Error.InvalidFormat; - - @field(result.mods, field.name) = side; - }, - - else => @compileError("invalid type"), - } + if (field.type == bool) { + if (std.mem.eql(u8, part, field.name)) { + // Repeat not allowed + if (@field(result.mods, field.name)) return Error.InvalidFormat; + @field(result.mods, field.name) = true; continue :loop; } } @@ -369,32 +336,23 @@ test "parse: triggers" { // single modifier try testing.expectEqual(Binding{ .trigger = .{ - .mods = .{ .shift = .both }, + .mods = .{ .shift = true }, .key = .a, }, .action = .{ .ignore = {} }, }, try parse("shift+a=ignore")); try testing.expectEqual(Binding{ .trigger = .{ - .mods = .{ .ctrl = .both }, + .mods = .{ .ctrl = true }, .key = .a, }, .action = .{ .ignore = {} }, }, try parse("ctrl+a=ignore")); - // directional modifier - try testing.expectEqual(Binding{ - .trigger = .{ - .mods = .{ .shift = .left }, - .key = .a, - }, - .action = .{ .ignore = {} }, - }, try parse("left_shift+a=ignore")); - // multiple modifier try testing.expectEqual(Binding{ .trigger = .{ - .mods = .{ .shift = .both, .ctrl = .both }, + .mods = .{ .shift = true, .ctrl = true }, .key = .a, }, .action = .{ .ignore = {} }, @@ -403,7 +361,7 @@ test "parse: triggers" { // key can come before modifier try testing.expectEqual(Binding{ .trigger = .{ - .mods = .{ .shift = .both }, + .mods = .{ .shift = true }, .key = .a, }, .action = .{ .ignore = {} }, @@ -412,7 +370,7 @@ test "parse: triggers" { // unmapped keys try testing.expectEqual(Binding{ .trigger = .{ - .mods = .{ .shift = .both }, + .mods = .{ .shift = true }, .key = .a, .unmapped = true, }, @@ -425,9 +383,6 @@ test "parse: triggers" { // repeated control try testing.expectError(Error.InvalidFormat, parse("shift+shift+a=ignore")); - // conflicting sides - try testing.expectError(Error.InvalidFormat, parse("left_shift+right_shift+a=ignore")); - // multiple character try testing.expectError(Error.InvalidFormat, parse("a+b=ignore")); } diff --git a/src/input/key.zig b/src/input/key.zig index 681b934fc..f7a8a244a 100644 --- a/src/input/key.zig +++ b/src/input/key.zig @@ -5,54 +5,22 @@ const Allocator = std.mem.Allocator; /// GLFW representation, but we use this generically. /// /// IMPORTANT: Any changes here update include/ghostty.h -pub const Mods = packed struct(Mods.Int) { - pub const Int = u10; - - shift: Side = .none, - ctrl: Side = .none, - alt: Side = .none, - super: Side = .none, +pub const Mods = packed struct(u8) { + shift: bool = false, + ctrl: bool = false, + alt: bool = false, + super: bool = false, caps_lock: bool = false, num_lock: bool = false, - - /// Keeps track of left/right press. A packed struct makes it easy - /// to set as a bitmask and then check the individual values. - pub const Side = enum(u2) { - none = 0, - left = 1, - right = 2, - - /// Note that while this should only be set for BOTH being set, - /// this is semantically used to mean "any" for the purposes of - /// keybindings. We do not allow keybindings to map to "both". - both = 3, - - /// Returns true if the key is pressed at all. - pub fn pressed(self: Side) bool { - return @intFromEnum(self) != 0; - } - }; - - /// Return the identical mods but with all directional configuration - /// removed and all of it set to "both". - pub fn removeDirection(self: Mods) Mods { - return Mods{ - .shift = if (self.shift.pressed()) .both else .none, - .ctrl = if (self.ctrl.pressed()) .both else .none, - .alt = if (self.alt.pressed()) .both else .none, - .super = if (self.super.pressed()) .both else .none, - .caps_lock = self.caps_lock, - .num_lock = self.num_lock, - }; - } + _padding: u2 = 0, // For our own understanding test { const testing = std.testing; - try testing.expectEqual(@as(Int, @bitCast(Mods{})), @as(Int, 0b0)); + try testing.expectEqual(@as(u8, @bitCast(Mods{})), @as(u8, 0b0)); try testing.expectEqual( - @as(Int, @bitCast(Mods{ .shift = .left })), - @as(Int, 0b0000_0001), + @as(u8, @bitCast(Mods{ .shift = true })), + @as(u8, 0b0000_0001), ); } }; @@ -131,7 +99,7 @@ pub const Key = enum(c_int) { equal, left_bracket, // [ right_bracket, // ] - backslash, // \ + backslash, // / // control up, diff --git a/src/input/mouse.zig b/src/input/mouse.zig index df4fe8db3..2233c4494 100644 --- a/src/input/mouse.zig +++ b/src/input/mouse.zig @@ -64,9 +64,7 @@ pub const MouseMomentum = enum(u3) { }; /// The bitmask for mods for scroll events. -pub const ScrollMods = packed struct(ScrollMods.Int) { - pub const Int = u8; - +pub const ScrollMods = packed struct(u8) { /// True if this is a high-precision scroll event. For example, Apple /// devices such as Magic Mouse, trackpads, etc. are high-precision /// and send very detailed scroll events. @@ -81,10 +79,10 @@ pub const ScrollMods = packed struct(ScrollMods.Int) { // For our own understanding test { const testing = std.testing; - try testing.expectEqual(@as(Int, @bitCast(ScrollMods{})), @as(Int, 0b0)); + try testing.expectEqual(@as(u8, @bitCast(ScrollMods{})), @as(u8, 0b0)); try testing.expectEqual( - @as(Int, @bitCast(ScrollMods{ .precision = true })), - @as(Int, 0b0000_0001), + @as(u8, @bitCast(ScrollMods{ .precision = true })), + @as(u8, 0b0000_0001), ); } };