mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
core: enable key sequence handling, including dumping invalid
This commit is contained in:
@ -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);
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user