core: enable key sequence handling, including dumping invalid

This commit is contained in:
Mitchell Hashimoto
2024-08-19 12:10:31 -07:00
parent 3a952de272
commit 4ce7a88dee
2 changed files with 45 additions and 6 deletions

View File

@ -209,6 +209,14 @@ pub const Keyboard = struct {
/// a combination to be handled by different bindings before the release /// a combination to be handled by different bindings before the release
/// of the prior (namely since you can't bind modifier-only). /// of the prior (namely since you can't bind modifier-only).
last_trigger: ?u64 = null, last_trigger: ?u64 = null,
/// The queued keys when we're in the middle of a sequenced binding.
/// These are flushed when the sequence is completed and unconsumed or
/// invalid.
///
/// This is naturally bounded due to the configuration maximum
/// length of a sequence.
queued: std.ArrayListUnmanaged(termio.Message.WriteReq) = .{},
}; };
/// The configuration that a surface has, this is copied from the main /// The configuration that a surface has, this is copied from the main
@ -625,6 +633,10 @@ pub fn deinit(self: *Surface) void {
self.alloc.destroy(v); self.alloc.destroy(v);
} }
// Clean up our keyboard state
for (self.keyboard.queued.items) |req| req.deinit();
self.keyboard.queued.deinit(self.alloc);
// Clean up our font grid // Clean up our font grid
self.app.font_grid_set.deref(self.font_grid_key); self.app.font_grid_set.deref(self.font_grid_key);
@ -1521,17 +1533,36 @@ fn maybeHandleBinding(
// No entry found. If we're not looking at the root set of the // No entry found. If we're not looking at the root set of the
// bindings we need to encode everything up to this point and // bindings we need to encode everything up to this point and
// send to the pty. // send to the pty.
if (self.keyboard.bindings != null) @panic("TODO"); if (self.keyboard.bindings != null) {
// Reset to the root set
self.keyboard.bindings = null;
// Encode everything up to this point
for (self.keyboard.queued.items) |write_req| {
self.io.queueMessage(switch (write_req) {
.small => |v| .{ .write_small = v },
.stable => |v| .{ .write_stable = v },
.alloc => |v| .{ .write_alloc = v },
}, .unlocked);
}
self.keyboard.queued.clearRetainingCapacity();
}
return null; return null;
}; };
// Determine if this entry has an action or if its a leader key. // Determine if this entry has an action or if its a leader key.
const action: input.Binding.Action, const consumed: bool = switch (entry) { const action: input.Binding.Action, const consumed: bool = switch (entry) {
.leader => { .leader => |set| {
// TODO // Setup the next set we'll look at.
log.warn("sequenced keybinds are not supported yet", .{}); self.keyboard.bindings = set;
return null;
// Store this event so that we can drain and encode on invalid
if (try self.encodeKey(event, insp_ev)) |req| {
try self.keyboard.queued.append(self.alloc, req);
}
return .consumed;
}, },
.action => |v| .{ v, true }, .action => |v| .{ v, true },
@ -1543,6 +1574,14 @@ fn maybeHandleBinding(
// perform an action (below) // perform an action (below)
self.keyboard.last_trigger = null; self.keyboard.last_trigger = null;
// An action also always resets the binding set.
self.keyboard.bindings = null;
if (self.keyboard.queued.items.len > 0) {
// TODO: unconsumed
for (self.keyboard.queued.items) |req| req.deinit();
self.keyboard.queued.clearRetainingCapacity();
}
// Attempt to perform the action // Attempt to perform the action
log.debug("key event binding consumed={} action={}", .{ consumed, action }); log.debug("key event binding consumed={} action={}", .{ consumed, action });
const performed = try self.performBindingAction(action); const performed = try self.performBindingAction(action);

View File

@ -179,7 +179,7 @@ pub fn MessageData(comptime Elem: type, comptime small_size: comptime_int) type
pub fn deinit(self: Self) void { pub fn deinit(self: Self) void {
switch (self) { switch (self) {
.small, .stable => {}, .small, .stable => {},
.alloc => |v| v.alloc.free(v.alloc.data), .alloc => |v| v.alloc.free(v.data),
} }
} }