core: performAction now returns a bool

This is to facilitate the `performable:` prefix on keybinds that are
implemented using app runtime actions.
This commit is contained in:
Jeffrey C. Ollie
2025-02-08 15:56:29 -06:00
committed by Mitchell Hashimoto
parent 66442cd469
commit 4ad749607a
5 changed files with 79 additions and 70 deletions

View File

@ -161,7 +161,7 @@ pub fn updateConfig(self: *App, rt_app: *apprt.App, config: *const Config) !void
const applied: *const configpkg.Config = if (applied_) |*c| c else config; const applied: *const configpkg.Config = if (applied_) |*c| c else config;
// Notify the apprt that the app has changed configuration. // Notify the apprt that the app has changed configuration.
try rt_app.performAction( _ = try rt_app.performAction(
.app, .app,
.config_change, .config_change,
.{ .config = applied }, .{ .config = applied },
@ -180,7 +180,7 @@ pub fn addSurface(
// Since we have non-zero surfaces, we can cancel the quit timer. // Since we have non-zero surfaces, we can cancel the quit timer.
// It is up to the apprt if there is a quit timer at all and if it // It is up to the apprt if there is a quit timer at all and if it
// should be canceled. // should be canceled.
rt_surface.app.performAction( _ = rt_surface.app.performAction(
.app, .app,
.quit_timer, .quit_timer,
.stop, .stop,
@ -214,7 +214,7 @@ pub fn deleteSurface(self: *App, rt_surface: *apprt.Surface) void {
// If we have no surfaces, we can start the quit timer. It is up to the // If we have no surfaces, we can start the quit timer. It is up to the
// apprt to determine if this is necessary. // apprt to determine if this is necessary.
if (self.surfaces.items.len == 0) rt_surface.app.performAction( if (self.surfaces.items.len == 0) _ = rt_surface.app.performAction(
.app, .app,
.quit_timer, .quit_timer,
.start, .start,
@ -294,7 +294,7 @@ pub fn newWindow(self: *App, rt_app: *apprt.App, msg: Message.NewWindow) !void {
break :target .app; break :target .app;
}; };
try rt_app.performAction( _ = try rt_app.performAction(
target, target,
.new_window, .new_window,
{}, {},
@ -419,7 +419,7 @@ pub fn colorSchemeEvent(
// Request our configuration be reloaded because the new scheme may // Request our configuration be reloaded because the new scheme may
// impact the colors of the app. // impact the colors of the app.
try rt_app.performAction( _ = try rt_app.performAction(
.app, .app,
.reload_config, .reload_config,
.{ .soft = true }, .{ .soft = true },
@ -437,13 +437,13 @@ pub fn performAction(
switch (action) { switch (action) {
.unbind => unreachable, .unbind => unreachable,
.ignore => {}, .ignore => {},
.quit => try rt_app.performAction(.app, .quit, {}), .quit => _ = try rt_app.performAction(.app, .quit, {}),
.new_window => try self.newWindow(rt_app, .{ .parent = null }), .new_window => _ = try self.newWindow(rt_app, .{ .parent = null }),
.open_config => try rt_app.performAction(.app, .open_config, {}), .open_config => _ = try rt_app.performAction(.app, .open_config, {}),
.reload_config => try rt_app.performAction(.app, .reload_config, .{}), .reload_config => _ = try rt_app.performAction(.app, .reload_config, .{}),
.close_all_windows => try rt_app.performAction(.app, .close_all_windows, {}), .close_all_windows => _ = try rt_app.performAction(.app, .close_all_windows, {}),
.toggle_quick_terminal => try rt_app.performAction(.app, .toggle_quick_terminal, {}), .toggle_quick_terminal => _ = try rt_app.performAction(.app, .toggle_quick_terminal, {}),
.toggle_visibility => try rt_app.performAction(.app, .toggle_visibility, {}), .toggle_visibility => _ = try rt_app.performAction(.app, .toggle_visibility, {}),
} }
} }

View File

@ -569,7 +569,7 @@ pub fn init(
errdefer self.io.deinit(); errdefer self.io.deinit();
// Report initial cell size on surface creation // Report initial cell size on surface creation
try rt_app.performAction( _ = try rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.cell_size, .cell_size,
.{ .width = size.cell.width, .height = size.cell.height }, .{ .width = size.cell.width, .height = size.cell.height },
@ -581,7 +581,7 @@ pub fn init(
const min_window_width_cells: u32 = 10; const min_window_width_cells: u32 = 10;
const min_window_height_cells: u32 = 4; const min_window_height_cells: u32 = 4;
try rt_app.performAction( _ = try rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.size_limit, .size_limit,
.{ .{
@ -645,7 +645,7 @@ pub fn init(
size.padding.top + size.padding.top +
size.padding.bottom; size.padding.bottom;
rt_app.performAction( _ = rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.initial_size, .initial_size,
.{ .width = final_width, .height = final_height }, .{ .width = final_width, .height = final_height },
@ -657,7 +657,7 @@ pub fn init(
} }
if (config.title) |title| { if (config.title) |title| {
try rt_app.performAction( _ = try rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.set_title, .set_title,
.{ .title = title }, .{ .title = title },
@ -678,7 +678,7 @@ pub fn init(
break :xdg; break :xdg;
}; };
defer alloc.free(title); defer alloc.free(title);
try rt_app.performAction( _ = try rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.set_title, .set_title,
.{ .title = title }, .{ .title = title },
@ -831,7 +831,7 @@ pub fn handleMessage(self: *Surface, msg: Message) !void {
// We know that our title should end in 0. // We know that our title should end in 0.
const slice = std.mem.sliceTo(@as([*:0]const u8, @ptrCast(v)), 0); const slice = std.mem.sliceTo(@as([*:0]const u8, @ptrCast(v)), 0);
log.debug("changing title \"{s}\"", .{slice}); log.debug("changing title \"{s}\"", .{slice});
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.set_title, .set_title,
.{ .title = slice }, .{ .title = slice },
@ -867,7 +867,7 @@ pub fn handleMessage(self: *Surface, msg: Message) !void {
.color_change => |change| { .color_change => |change| {
// Notify our apprt, but don't send a mode 2031 DSR report // Notify our apprt, but don't send a mode 2031 DSR report
// because VT sequences were used to change the color. // because VT sequences were used to change the color.
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.color_change, .color_change,
.{ .{
@ -886,7 +886,7 @@ pub fn handleMessage(self: *Surface, msg: Message) !void {
.set_mouse_shape => |shape| { .set_mouse_shape => |shape| {
log.debug("changing mouse shape: {}", .{shape}); log.debug("changing mouse shape: {}", .{shape});
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.mouse_shape, .mouse_shape,
shape, shape,
@ -918,7 +918,7 @@ pub fn handleMessage(self: *Surface, msg: Message) !void {
const str = try self.alloc.dupeZ(u8, w.slice()); const str = try self.alloc.dupeZ(u8, w.slice());
defer self.alloc.free(str); defer self.alloc.free(str);
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.pwd, .pwd,
.{ .pwd = str }, .{ .pwd = str },
@ -969,7 +969,7 @@ fn passwordInput(self: *Surface, v: bool) !void {
} }
// Notify our apprt so it can do whatever it wants. // Notify our apprt so it can do whatever it wants.
self.rt_app.performAction( _ = self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.secure_input, .secure_input,
if (v) .on else .off, if (v) .on else .off,
@ -1058,7 +1058,7 @@ fn mouseRefreshLinks(
self.renderer_state.mouse.point = pos_vp; self.renderer_state.mouse.point = pos_vp;
self.mouse.over_link = true; self.mouse.over_link = true;
self.renderer_state.terminal.screen.dirty.hyperlink_hover = true; self.renderer_state.terminal.screen.dirty.hyperlink_hover = true;
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.mouse_shape, .mouse_shape,
.pointer, .pointer,
@ -1071,7 +1071,7 @@ fn mouseRefreshLinks(
.trim = false, .trim = false,
}); });
defer self.alloc.free(str); defer self.alloc.free(str);
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.mouse_over_link, .mouse_over_link,
.{ .url = str }, .{ .url = str },
@ -1085,7 +1085,7 @@ fn mouseRefreshLinks(
log.warn("failed to get URI for OSC8 hyperlink", .{}); log.warn("failed to get URI for OSC8 hyperlink", .{});
break :link; break :link;
}; };
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.mouse_over_link, .mouse_over_link,
.{ .url = uri }, .{ .url = uri },
@ -1095,12 +1095,12 @@ fn mouseRefreshLinks(
try self.queueRender(); try self.queueRender();
} else if (over_link) { } else if (over_link) {
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.mouse_shape, .mouse_shape,
self.io.terminal.mouse_shape, self.io.terminal.mouse_shape,
); );
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.mouse_over_link, .mouse_over_link,
.{ .url = "" }, .{ .url = "" },
@ -1112,7 +1112,7 @@ fn mouseRefreshLinks(
/// Called when our renderer health state changes. /// Called when our renderer health state changes.
fn updateRendererHealth(self: *Surface, health: renderer.Health) void { fn updateRendererHealth(self: *Surface, health: renderer.Health) void {
log.warn("renderer health status change status={}", .{health}); log.warn("renderer health status change status={}", .{health});
self.rt_app.performAction( _ = self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.renderer_health, .renderer_health,
health, health,
@ -1124,7 +1124,7 @@ fn updateRendererHealth(self: *Surface, health: renderer.Health) void {
/// This should be called anytime `config_conditional_state` changes /// This should be called anytime `config_conditional_state` changes
/// so that the apprt can reload the configuration. /// so that the apprt can reload the configuration.
fn notifyConfigConditionalState(self: *Surface) void { fn notifyConfigConditionalState(self: *Surface) void {
self.rt_app.performAction( _ = self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.reload_config, .reload_config,
.{ .soft = true }, .{ .soft = true },
@ -1204,14 +1204,14 @@ pub fn updateConfig(
// If we have a title set then we update our window to have the // If we have a title set then we update our window to have the
// newly configured title. // newly configured title.
if (config.title) |title| try self.rt_app.performAction( if (config.title) |title| _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.set_title, .set_title,
.{ .title = title }, .{ .title = title },
); );
// Notify the window // Notify the window
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.config_change, .config_change,
.{ .config = config }, .{ .config = config },
@ -1478,7 +1478,7 @@ fn setCellSize(self: *Surface, size: renderer.CellSize) !void {
self.io.queueMessage(.{ .resize = self.size }, .unlocked); self.io.queueMessage(.{ .resize = self.size }, .unlocked);
// Notify the window // Notify the window
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.cell_size, .cell_size,
.{ .width = size.width, .height = size.height }, .{ .width = size.width, .height = size.height },
@ -1774,12 +1774,12 @@ pub fn keyCallback(
}; };
} else if (self.io.terminal.flags.mouse_event != .none and !self.mouse.mods.shift) { } else if (self.io.terminal.flags.mouse_event != .none and !self.mouse.mods.shift) {
// If we have mouse reports on and we don't have shift pressed, we reset state // If we have mouse reports on and we don't have shift pressed, we reset state
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.mouse_shape, .mouse_shape,
self.io.terminal.mouse_shape, self.io.terminal.mouse_shape,
); );
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.mouse_over_link, .mouse_over_link,
.{ .url = "" }, .{ .url = "" },
@ -1797,7 +1797,7 @@ pub fn keyCallback(
.mods = self.mouse.mods, .mods = self.mouse.mods,
.over_link = self.mouse.over_link, .over_link = self.mouse.over_link,
.hidden = self.mouse.hidden, .hidden = self.mouse.hidden,
}).keyToMouseShape()) |shape| try self.rt_app.performAction( }).keyToMouseShape()) |shape| _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.mouse_shape, .mouse_shape,
shape, shape,
@ -1922,7 +1922,7 @@ fn maybeHandleBinding(
} }
// Start or continue our key sequence // Start or continue our key sequence
self.rt_app.performAction( _ = self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.key_sequence, .key_sequence,
.{ .trigger = entry.key_ptr.* }, .{ .trigger = entry.key_ptr.* },
@ -2031,7 +2031,7 @@ fn endKeySequence(
mem: KeySequenceMemory, mem: KeySequenceMemory,
) void { ) void {
// Notify apprt key sequence ended // Notify apprt key sequence ended
self.rt_app.performAction( _ = self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.key_sequence, .key_sequence,
.end, .end,
@ -3367,12 +3367,12 @@ pub fn cursorPosCallback(
self.mouse.link_point = null; self.mouse.link_point = null;
if (self.mouse.over_link) { if (self.mouse.over_link) {
self.mouse.over_link = false; self.mouse.over_link = false;
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.mouse_shape, .mouse_shape,
self.io.terminal.mouse_shape, self.io.terminal.mouse_shape,
); );
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.mouse_over_link, .mouse_over_link,
.{ .url = "" }, .{ .url = "" },
@ -3798,7 +3798,7 @@ fn scrollToBottom(self: *Surface) !void {
fn hideMouse(self: *Surface) void { fn hideMouse(self: *Surface) void {
if (self.mouse.hidden) return; if (self.mouse.hidden) return;
self.mouse.hidden = true; self.mouse.hidden = true;
self.rt_app.performAction( _ = self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.mouse_visibility, .mouse_visibility,
.hidden, .hidden,
@ -3810,7 +3810,7 @@ fn hideMouse(self: *Surface) void {
fn showMouse(self: *Surface) void { fn showMouse(self: *Surface) void {
if (!self.mouse.hidden) return; if (!self.mouse.hidden) return;
self.mouse.hidden = false; self.mouse.hidden = false;
self.rt_app.performAction( _ = self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.mouse_visibility, .mouse_visibility,
.visible, .visible,
@ -4101,13 +4101,13 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
v, v,
), ),
.new_tab => try self.rt_app.performAction( .new_tab => return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.new_tab, .new_tab,
{}, {},
), ),
.close_tab => try self.rt_app.performAction( .close_tab => return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.close_tab, .close_tab,
{}, {},
@ -4117,7 +4117,7 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
.next_tab, .next_tab,
.last_tab, .last_tab,
.goto_tab, .goto_tab,
=> |v, tag| try self.rt_app.performAction( => |v, tag| return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.goto_tab, .goto_tab,
switch (tag) { switch (tag) {
@ -4129,13 +4129,13 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
}, },
), ),
.move_tab => |position| try self.rt_app.performAction( .move_tab => |position| return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.move_tab, .move_tab,
.{ .amount = position }, .{ .amount = position },
), ),
.new_split => |direction| try self.rt_app.performAction( .new_split => |direction| return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.new_split, .new_split,
switch (direction) { switch (direction) {
@ -4150,7 +4150,7 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
}, },
), ),
.goto_split => |direction| try self.rt_app.performAction( .goto_split => |direction| return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.goto_split, .goto_split,
switch (direction) { switch (direction) {
@ -4161,7 +4161,7 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
}, },
), ),
.resize_split => |value| try self.rt_app.performAction( .resize_split => |value| return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.resize_split, .resize_split,
.{ .{
@ -4175,25 +4175,25 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
}, },
), ),
.equalize_splits => try self.rt_app.performAction( .equalize_splits => return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.equalize_splits, .equalize_splits,
{}, {},
), ),
.toggle_split_zoom => try self.rt_app.performAction( .toggle_split_zoom => return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.toggle_split_zoom, .toggle_split_zoom,
{}, {},
), ),
.toggle_maximize => try self.rt_app.performAction( .toggle_maximize => return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.toggle_maximize, .toggle_maximize,
{}, {},
), ),
.toggle_fullscreen => try self.rt_app.performAction( .toggle_fullscreen => return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.toggle_fullscreen, .toggle_fullscreen,
switch (self.config.macos_non_native_fullscreen) { switch (self.config.macos_non_native_fullscreen) {
@ -4203,19 +4203,19 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
}, },
), ),
.toggle_window_decorations => try self.rt_app.performAction( .toggle_window_decorations => return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.toggle_window_decorations, .toggle_window_decorations,
{}, {},
), ),
.toggle_tab_overview => try self.rt_app.performAction( .toggle_tab_overview => return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.toggle_tab_overview, .toggle_tab_overview,
{}, {},
), ),
.toggle_secure_input => try self.rt_app.performAction( .toggle_secure_input => return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.secure_input, .secure_input,
.toggle, .toggle,
@ -4229,7 +4229,7 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
} }
}, },
.inspector => |mode| try self.rt_app.performAction( .inspector => |mode| return try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.inspector, .inspector,
switch (mode) { switch (mode) {
@ -4676,7 +4676,7 @@ fn showDesktopNotification(self: *Surface, title: [:0]const u8, body: [:0]const
self.app.last_notification_time = now; self.app.last_notification_time = now;
self.app.last_notification_digest = new_digest; self.app.last_notification_digest = new_digest;
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.desktop_notification, .desktop_notification,
.{ .{
@ -4696,7 +4696,7 @@ fn crashThreadState(self: *Surface) crash.sentry.ThreadState {
/// Tell the surface to present itself to the user. This may involve raising the /// Tell the surface to present itself to the user. This may involve raising the
/// window and switching tabs. /// window and switching tabs.
fn presentSurface(self: *Surface) !void { fn presentSurface(self: *Surface) !void {
try self.rt_app.performAction( _ = try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.present_terminal, .present_terminal,
{}, {},

View File

@ -478,13 +478,14 @@ pub const App = struct {
surface.queueInspectorRender(); surface.queueInspectorRender();
} }
/// Perform a given action. /// Perform a given action. Returns `true` if the action was able to be
/// performed, `false` otherwise.
pub fn performAction( pub fn performAction(
self: *App, self: *App,
target: apprt.Target, target: apprt.Target,
comptime action: apprt.Action.Key, comptime action: apprt.Action.Key,
value: apprt.Action.Value(action), value: apprt.Action.Value(action),
) !void { ) !bool {
// Special case certain actions before they are sent to the // Special case certain actions before they are sent to the
// embedded apprt. // embedded apprt.
self.performPreAction(target, action, value); self.performPreAction(target, action, value);
@ -499,6 +500,8 @@ pub const App = struct {
target.cval(), target.cval(),
@unionInit(apprt.Action, @tagName(action), value).cval(), @unionInit(apprt.Action, @tagName(action), value).cval(),
); );
return true;
} }
fn performPreAction( fn performPreAction(
@ -1006,7 +1009,7 @@ pub const Surface = struct {
} }
fn queueInspectorRender(self: *Surface) void { fn queueInspectorRender(self: *Surface) void {
self.app.performAction( _ = self.app.performAction(
.{ .surface = &self.core_surface }, .{ .surface = &self.core_surface },
.render_inspector, .render_inspector,
{}, {},
@ -1457,7 +1460,7 @@ pub const CAPI = struct {
/// Open the configuration. /// Open the configuration.
export fn ghostty_app_open_config(v: *App) void { export fn ghostty_app_open_config(v: *App) void {
v.performAction(.app, .open_config, {}) catch |err| { _ = v.performAction(.app, .open_config, {}) catch |err| {
log.err("error reloading config err={}", .{err}); log.err("error reloading config err={}", .{err});
return; return;
}; };
@ -1800,7 +1803,7 @@ pub const CAPI = struct {
/// Request that the surface split in the given direction. /// Request that the surface split in the given direction.
export fn ghostty_surface_split(ptr: *Surface, direction: apprt.action.SplitDirection) void { export fn ghostty_surface_split(ptr: *Surface, direction: apprt.action.SplitDirection) void {
ptr.app.performAction( _ = ptr.app.performAction(
.{ .surface = &ptr.core_surface }, .{ .surface = &ptr.core_surface },
.new_split, .new_split,
direction, direction,
@ -1815,7 +1818,7 @@ pub const CAPI = struct {
ptr: *Surface, ptr: *Surface,
direction: apprt.action.GotoSplit, direction: apprt.action.GotoSplit,
) void { ) void {
ptr.app.performAction( _ = ptr.app.performAction(
.{ .surface = &ptr.core_surface }, .{ .surface = &ptr.core_surface },
.goto_split, .goto_split,
direction, direction,
@ -1834,7 +1837,7 @@ pub const CAPI = struct {
direction: apprt.action.ResizeSplit.Direction, direction: apprt.action.ResizeSplit.Direction,
amount: u16, amount: u16,
) void { ) void {
ptr.app.performAction( _ = ptr.app.performAction(
.{ .surface = &ptr.core_surface }, .{ .surface = &ptr.core_surface },
.resize_split, .resize_split,
.{ .direction = direction, .amount = amount }, .{ .direction = direction, .amount = amount },
@ -1846,7 +1849,7 @@ pub const CAPI = struct {
/// Equalize the size of all splits in the current window. /// Equalize the size of all splits in the current window.
export fn ghostty_surface_split_equalize(ptr: *Surface) void { export fn ghostty_surface_split_equalize(ptr: *Surface) void {
ptr.app.performAction( _ = ptr.app.performAction(
.{ .surface = &ptr.core_surface }, .{ .surface = &ptr.core_surface },
.equalize_splits, .equalize_splits,
{}, {},

View File

@ -147,13 +147,14 @@ pub const App = struct {
glfw.postEmptyEvent(); glfw.postEmptyEvent();
} }
/// Perform a given action. /// Perform a given action. Returns `true` if the action was able to be
/// performed, `false` otherwise.
pub fn performAction( pub fn performAction(
self: *App, self: *App,
target: apprt.Target, target: apprt.Target,
comptime action: apprt.Action.Key, comptime action: apprt.Action.Key,
value: apprt.Action.Value(action), value: apprt.Action.Value(action),
) !void { ) !bool {
switch (action) { switch (action) {
.quit => self.quit = true, .quit => self.quit = true,
@ -240,6 +241,8 @@ pub const App = struct {
.toggle_maximize, .toggle_maximize,
=> log.info("unimplemented action={}", .{action}), => log.info("unimplemented action={}", .{action}),
} }
return true;
} }
/// Reload the configuration. This should return the new configuration. /// Reload the configuration. This should return the new configuration.

View File

@ -507,13 +507,14 @@ pub fn terminate(self: *App) void {
self.config.deinit(); self.config.deinit();
} }
/// Perform a given action. /// Perform a given action. Returns `true` if the action was able to be
/// performed, `false` otherwise.
pub fn performAction( pub fn performAction(
self: *App, self: *App,
target: apprt.Target, target: apprt.Target,
comptime action: apprt.Action.Key, comptime action: apprt.Action.Key,
value: apprt.Action.Value(action), value: apprt.Action.Value(action),
) !void { ) !bool {
switch (action) { switch (action) {
.quit => self.quit(), .quit => self.quit(),
.new_window => _ = try self.newWindow(switch (target) { .new_window => _ = try self.newWindow(switch (target) {
@ -561,6 +562,8 @@ pub fn performAction(
.color_change, .color_change,
=> log.warn("unimplemented action={}", .{action}), => log.warn("unimplemented action={}", .{action}),
} }
return true;
} }
fn newTab(_: *App, target: apprt.Target) !void { fn newTab(_: *App, target: apprt.Target) !void {