input: leaf_chained tagged union value

This commit is contained in:
Mitchell Hashimoto
2025-12-22 09:13:05 -08:00
parent 3877ead071
commit 42c21eb16b
6 changed files with 184 additions and 35 deletions

View File

@@ -357,15 +357,17 @@ pub fn keyEvent(
// Get the keybind entry for this event. We don't support key sequences
// so we can look directly in the top-level set.
const entry = rt_app.config.keybind.set.getEvent(event) orelse return false;
const leaf: input.Binding.Set.Leaf = switch (entry.value_ptr.*) {
const leaf: input.Binding.Set.GenericLeaf = switch (entry.value_ptr.*) {
// Sequences aren't supported. Our configuration parser verifies
// this for global keybinds but we may still get an entry for
// a non-global keybind.
.leader => return false,
// Leaf entries are good
.leaf => |leaf| leaf,
inline .leaf, .leaf_chained => |leaf| leaf.generic(),
};
const actions: []const input.Binding.Action = leaf.actionsSlice();
assert(actions.len > 0);
// If we aren't focused, then we only process global keybinds.
if (!self.focused and !leaf.flags.global) return false;
@@ -373,13 +375,7 @@ pub fn keyEvent(
// Global keybinds are done using performAll so that they
// can target all surfaces too.
if (leaf.flags.global) {
self.performAllAction(rt_app, leaf.action) catch |err| {
log.warn("error performing global keybind action action={s} err={}", .{
@tagName(leaf.action),
err,
});
};
self.performAllChainedAction(rt_app, actions);
return true;
}
@@ -389,14 +385,20 @@ pub fn keyEvent(
// If we are focused, then we process keybinds only if they are
// app-scoped. Otherwise, we do nothing. Surface-scoped should
// be processed by Surface.keyEvent.
const app_action = leaf.action.scoped(.app) orelse return false;
self.performAction(rt_app, app_action) catch |err| {
log.warn("error performing app keybind action action={s} err={}", .{
@tagName(app_action),
err,
});
};
// be processed by Surface.keyEvent. For chained actions, all
// actions must be app-scoped.
for (actions) |action| if (action.scoped(.app) == null) return false;
for (actions) |action| {
self.performAction(
rt_app,
action.scoped(.app).?,
) catch |err| {
log.warn("error performing app keybind action action={s} err={}", .{
@tagName(action),
err,
});
};
}
return true;
}
@@ -454,6 +456,23 @@ pub fn performAction(
}
}
/// Performs a chained action. We will continue executing each action
/// even if there is a failure in a prior action.
pub fn performAllChainedAction(
self: *App,
rt_app: *apprt.App,
actions: []const input.Binding.Action,
) void {
for (actions) |action| {
self.performAllAction(rt_app, action) catch |err| {
log.warn("error performing chained action action={s} err={}", .{
@tagName(action),
err,
});
};
}
}
/// Perform an app-wide binding action. If the action is surface-specific
/// then it will be performed on all surfaces. To perform only app-scoped
/// actions, use performAction.