make keyboard modifiers left/right-aware throughout core

This commit is contained in:
Mitchell Hashimoto
2023-08-07 14:33:56 -07:00
parent 4ed21047a7
commit 67cbabd605
9 changed files with 145 additions and 91 deletions

View File

@@ -42,12 +42,24 @@ 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.type == bool) {
if (field.name[0] != '_') {
if (std.mem.eql(u8, part, field.name)) {
// Repeat not allowed
if (@field(result.mods, field.name)) return Error.InvalidFormat;
switch (field.type) {
bool => {
if (@field(result.mods, field.name))
return Error.InvalidFormat;
@field(result.mods, field.name) = true;
},
key.Mods.Side => {
if (@field(result.mods, field.name).pressed())
return Error.InvalidFormat;
@field(result.mods, field.name) = .both;
},
else => @compileError("invalid type"),
}
@field(result.mods, field.name) = true;
continue :loop;
}
}
@@ -336,14 +348,14 @@ test "parse: triggers" {
// single modifier
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.mods = .{ .shift = .both },
.key = .a,
},
.action = .{ .ignore = {} },
}, try parse("shift+a=ignore"));
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .ctrl = true },
.mods = .{ .ctrl = .both },
.key = .a,
},
.action = .{ .ignore = {} },
@@ -352,7 +364,7 @@ test "parse: triggers" {
// multiple modifier
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true, .ctrl = true },
.mods = .{ .shift = .both, .ctrl = .both },
.key = .a,
},
.action = .{ .ignore = {} },
@@ -361,7 +373,7 @@ test "parse: triggers" {
// key can come before modifier
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.mods = .{ .shift = .both },
.key = .a,
},
.action = .{ .ignore = {} },
@@ -370,7 +382,7 @@ test "parse: triggers" {
// unmapped keys
try testing.expectEqual(Binding{
.trigger = .{
.mods = .{ .shift = true },
.mods = .{ .shift = .both },
.key = .a,
.unmapped = true,
},

View File

@@ -5,22 +5,41 @@ 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(u8) {
shift: bool = false,
ctrl: bool = false,
alt: bool = false,
super: bool = false,
pub const Mods = packed struct(Mods.Int) {
pub const Int = u10;
shift: Side = .none,
ctrl: Side = .none,
alt: Side = .none,
super: Side = .none,
caps_lock: bool = false,
num_lock: bool = false,
_padding: u2 = 0,
/// 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;
}
};
// For our own understanding
test {
const testing = std.testing;
try testing.expectEqual(@as(u8, @bitCast(Mods{})), @as(u8, 0b0));
try testing.expectEqual(@as(Int, @bitCast(Mods{})), @as(Int, 0b0));
try testing.expectEqual(
@as(u8, @bitCast(Mods{ .shift = true })),
@as(u8, 0b0000_0001),
@as(Int, @bitCast(Mods{ .shift = .left })),
@as(Int, 0b0000_0001),
);
}
};

View File

@@ -64,7 +64,9 @@ pub const MouseMomentum = enum(u3) {
};
/// The bitmask for mods for scroll events.
pub const ScrollMods = packed struct(u8) {
pub const ScrollMods = packed struct(ScrollMods.Int) {
pub const Int = 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.
@@ -79,10 +81,10 @@ pub const ScrollMods = packed struct(u8) {
// For our own understanding
test {
const testing = std.testing;
try testing.expectEqual(@as(u8, @bitCast(ScrollMods{})), @as(u8, 0b0));
try testing.expectEqual(@as(Int, @bitCast(ScrollMods{})), @as(Int, 0b0));
try testing.expectEqual(
@as(u8, @bitCast(ScrollMods{ .precision = true })),
@as(u8, 0b0000_0001),
@as(Int, @bitCast(ScrollMods{ .precision = true })),
@as(Int, 0b0000_0001),
);
}
};