apprt: implement key_sequence action

This commit is contained in:
Mitchell Hashimoto
2024-10-08 06:51:25 -10:00
parent 8d7367fa64
commit 5c1ffbb642
7 changed files with 62 additions and 0 deletions

View File

@ -500,6 +500,12 @@ typedef enum {
GHOSTTY_RENDERER_HEALTH_UNHEALTHY,
} ghostty_action_renderer_health_e;
// apprt.action.KeySequence
typedef struct {
bool active;
ghostty_input_trigger_s trigger;
} ghostty_action_key_sequence_s;
// apprt.Action.Key
typedef enum {
GHOSTTY_ACTION_NEW_WINDOW,
@ -531,6 +537,7 @@ typedef enum {
GHOSTTY_ACTION_OPEN_CONFIG,
GHOSTTY_ACTION_QUIT_TIMER,
GHOSTTY_ACTION_SECURE_INPUT,
GHOSTTY_ACTION_KEY_SEQUENCE,
} ghostty_action_tag_e;
typedef union {
@ -551,6 +558,7 @@ typedef union {
ghostty_action_renderer_health_e renderer_health;
ghostty_action_quit_timer_e quit_timer;
ghostty_action_secure_input_e secure_input;
ghostty_action_key_sequence_s key_sequence;
} ghostty_action_u;
typedef struct {

View File

@ -515,6 +515,8 @@ extension Ghostty {
case GHOSTTY_ACTION_TOGGLE_VISIBILITY:
toggleVisibility(app, target: target)
case GHOSTTY_ACTION_KEY_SEQUENCE:
fallthrough
case GHOSTTY_ACTION_CLOSE_ALL_WINDOWS:
fallthrough
case GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW:

View File

@ -1709,6 +1709,18 @@ fn maybeHandleBinding(
try self.keyboard.queued.append(self.alloc, req);
}
// Start or continue our key sequence
self.rt_app.performAction(
.{ .surface = self },
.key_sequence,
.{ .trigger = entry.key_ptr.* },
) catch |err| {
log.warn(
"failed to notify app of key sequence err={}",
.{err},
);
};
return .consumed;
},
@ -1795,6 +1807,18 @@ fn endKeySequence(
action: KeySequenceQueued,
mem: KeySequenceMemory,
) void {
// Notify apprt key sequence ended
self.rt_app.performAction(
.{ .surface = self },
.key_sequence,
.end,
) catch |err| {
log.warn(
"failed to notify app of key sequence end err={}",
.{err},
);
};
if (self.keyboard.queued.items.len > 0) {
switch (action) {
.flush => for (self.keyboard.queued.items) |write_req| {

View File

@ -1,6 +1,7 @@
const std = @import("std");
const assert = std.debug.assert;
const apprt = @import("../apprt.zig");
const input = @import("../input.zig");
const renderer = @import("../renderer.zig");
const terminal = @import("../terminal/main.zig");
const CoreSurface = @import("../Surface.zig");
@ -173,6 +174,11 @@ pub const Action = union(Key) {
/// system APIs to not log the input, etc.
secure_input: SecureInput,
/// A sequenced key binding has started, continued, or stopped.
/// The UI should show some indication that the user is in a sequenced
/// key mode because other input may be ignored.
key_sequence: KeySequence,
/// Sync with: ghostty_action_tag_e
pub const Key = enum(c_int) {
new_window,
@ -204,6 +210,7 @@ pub const Action = union(Key) {
open_config,
quit_timer,
secure_input,
key_sequence,
};
/// Sync with: ghostty_action_u
@ -411,3 +418,21 @@ pub const DesktopNotification = struct {
};
}
};
pub const KeySequence = union(enum) {
trigger: input.Trigger,
end,
// Sync with: ghostty_action_key_sequence_s
pub const C = extern struct {
active: bool,
trigger: input.Trigger.C,
};
pub fn cval(self: KeySequence) C {
return switch (self) {
.trigger => |t| .{ .active = true, .trigger = t.cval() },
.end => .{ .active = false, .trigger = .{} },
};
}
};

View File

@ -203,6 +203,7 @@ pub const App = struct {
.render_inspector,
.quit_timer,
.secure_input,
.key_sequence,
.desktop_notification,
.mouse_over_link,
.cell_size,

View File

@ -411,6 +411,7 @@ pub fn performAction(
.size_limit,
.cell_size,
.secure_input,
.key_sequence,
.render_inspector,
.renderer_health,
=> log.warn("unimplemented action={}", .{action}),

View File

@ -23,6 +23,7 @@ pub const MousePressureStage = mouse.PressureStage;
pub const ScrollMods = mouse.ScrollMods;
pub const SplitFocusDirection = Binding.Action.SplitFocusDirection;
pub const SplitResizeDirection = Binding.Action.SplitResizeDirection;
pub const Trigger = Binding.Trigger;
// Keymap is only available on macOS right now. We could implement it
// in theory for XKB too on Linux but we don't need it right now.