core: more actions

This commit is contained in:
Mitchell Hashimoto
2024-09-26 09:37:24 -07:00
parent 26cba70b69
commit 1e010b8e08
6 changed files with 85 additions and 68 deletions

View File

@ -3663,35 +3663,27 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
v,
),
.new_tab => {
if (@hasDecl(apprt.Surface, "newTab")) {
try self.rt_surface.newTab();
} else log.warn("runtime doesn't implement newTab", .{});
},
.new_tab => try self.rt_app.performAction(
.{ .surface = self },
.new_tab,
{},
),
.previous_tab => {
if (@hasDecl(apprt.Surface, "gotoTab")) {
self.rt_surface.gotoTab(.previous);
} else log.warn("runtime doesn't implement gotoTab", .{});
},
.next_tab => {
if (@hasDecl(apprt.Surface, "gotoTab")) {
self.rt_surface.gotoTab(.next);
} else log.warn("runtime doesn't implement gotoTab", .{});
},
.last_tab => {
if (@hasDecl(apprt.Surface, "gotoTab")) {
self.rt_surface.gotoTab(.last);
} else log.warn("runtime doesn't implement gotoTab", .{});
},
.goto_tab => |n| {
if (@hasDecl(apprt.Surface, "gotoTab")) {
self.rt_surface.gotoTab(@enumFromInt(n));
} else log.warn("runtime doesn't implement gotoTab", .{});
inline .previous_tab,
.next_tab,
.last_tab,
.goto_tab,
=> |v, tag| try self.rt_app.performAction(
.{ .surface = self },
.goto_tab,
switch (tag) {
.previous_tab => .previous,
.next_tab => .next,
.last_tab => .last,
.goto_tab => @enumFromInt(v),
else => comptime unreachable,
},
),
.new_split => |direction| {
if (@hasDecl(apprt.Surface, "newSplit")) {

View File

@ -12,9 +12,9 @@ const std = @import("std");
const builtin = @import("builtin");
const build_config = @import("build_config.zig");
const action = @import("apprt/action.zig");
const structs = @import("apprt/structs.zig");
pub const action = @import("apprt/action.zig");
pub const glfw = @import("apprt/glfw.zig");
pub const gtk = @import("apprt/gtk.zig");
pub const none = @import("apprt/none.zig");

View File

@ -16,6 +16,15 @@ pub const Action = union(enum) {
/// as font size should be inherited.
new_window,
/// Open a new tab. If the target is a surface it should be opened in
/// the same window as the surface. If the target is the app then
/// the tab should be opened in a new window.
new_tab,
/// Jump to a specific tab. Must handle the scenario that the tab
/// value is invalid.
goto_tab: GotoTab,
/// Close all open windows.
close_all_windows,
@ -58,3 +67,13 @@ pub const Target = union(enum) {
app,
surface: *CoreSurface,
};
/// The tab to jump to. This is non-exhaustive so that integer values represent
/// the index (zero-based) of the tab to jump to. Negative values are special
/// values.
pub const GotoTab = enum(c_int) {
previous = -1,
next = -2,
last = -3,
_,
};

View File

@ -83,7 +83,8 @@ pub const App = struct {
/// views then this can be null.
new_split: ?*const fn (SurfaceUD, apprt.SplitDirection, apprt.Surface.Options) callconv(.C) void = null,
/// New tab with options.
/// New tab with options. The surface may be null if there is no target
/// surface in which case the apprt is expected to create a new window.
new_tab: ?*const fn (SurfaceUD, apprt.Surface.Options) callconv(.C) void = null,
/// New window with options. The surface may be null if there is no
@ -109,7 +110,7 @@ pub const App = struct {
toggle_split_zoom: ?*const fn (SurfaceUD) callconv(.C) void = null,
/// Goto tab
goto_tab: ?*const fn (SurfaceUD, apprt.GotoTab) callconv(.C) void = null,
goto_tab: ?*const fn (SurfaceUD, apprt.action.GotoTab) callconv(.C) void = null,
/// Toggle fullscreen for current window.
toggle_fullscreen: ?*const fn (SurfaceUD, configpkg.NonNativeFullscreen) callconv(.C) void = null,
@ -506,9 +507,36 @@ pub const App = struct {
func(null, .{});
}
fn newTab(self: *const App, target: apprt.Target) void {
const func = self.opts.new_tab orelse {
log.info("runtime embedder does not support new_tab", .{});
return;
};
switch (target) {
.app => func(null, .{}),
.surface => |v| func(
v.rt_surface.userdata,
v.rt_surface.newSurfaceOptions(),
),
}
}
fn gotoTab(self: *App, target: apprt.Target, tab: apprt.action.GotoTab) void {
const func = self.opts.goto_tab orelse {
log.info("runtime embedder does not support goto_tab", .{});
return;
};
switch (target) {
.app => {},
.surface => |v| func(v.rt_surface.userdata, tab),
}
}
fn setPasswordInput(self: *App, target: apprt.Target, v: bool) void {
const func = self.opts.set_password_input orelse {
log.info("runtime embedder does not set_password_input", .{});
log.info("runtime embedder does not support set_password_input", .{});
return;
};
@ -531,8 +559,9 @@ pub const App = struct {
.surface => |v| v,
}),
.new_tab => self.newTab(target),
.goto_tab => self.gotoTab(target, value),
.open_config => try configpkg.edit.open(self.core_app.alloc),
.secure_input => self.setPasswordInput(target, value),
// Unimplemented
@ -1099,15 +1128,6 @@ pub const Surface = struct {
};
}
pub fn gotoTab(self: *Surface, tab: apprt.GotoTab) void {
const func = self.app.opts.goto_tab orelse {
log.info("runtime embedder does not goto_tab", .{});
return;
};
func(self.userdata, tab);
}
pub fn toggleFullscreen(self: *Surface, nonNativeFullscreen: configpkg.NonNativeFullscreen) void {
const func = self.app.opts.toggle_fullscreen orelse {
log.info("runtime embedder does not toggle_fullscreen", .{});
@ -1126,16 +1146,6 @@ pub const Surface = struct {
func();
}
pub fn newTab(self: *const Surface) !void {
const func = self.app.opts.new_tab orelse {
log.info("runtime embedder does not support new_tab", .{});
return;
};
const options = self.newSurfaceOptions();
func(self.userdata, options);
}
fn newWindow(self: *const Surface) !void {
const func = self.app.opts.new_window orelse {
log.info("runtime embedder does not support new_window", .{});

View File

@ -142,10 +142,16 @@ pub const App = struct {
.surface => |v| v,
}),
.new_tab => try self.newTab(switch (target) {
.app => null,
.surface => |v| v,
}),
.open_config => try configpkg.edit.open(self.app.alloc),
// Unimplemented
.close_all_windows,
.goto_tab,
.quit_timer,
.secure_input,
=> log.info("unimplemented action={}", .{action}),
@ -216,12 +222,17 @@ pub const App = struct {
}
/// Create a new tab in the parent surface.
fn newTab(self: *App, parent: *CoreSurface) !void {
fn newTab(self: *App, parent_: ?*CoreSurface) !void {
if (!Darwin.enabled) {
log.warn("tabbing is not supported on this platform", .{});
return;
}
const parent = parent_ orelse {
_ = try self.newSurface(null);
return;
};
// Create the new window
const window = try self.newSurface(parent);
@ -540,11 +551,6 @@ pub const Surface = struct {
}
}
/// Create a new tab in the window containing this surface.
pub fn newTab(self: *Surface) !void {
try self.app.newTab(&self.core_surface);
}
/// Checks if the glfw window is in fullscreen.
pub fn isFullscreen(self: *Surface) bool {
return self.window.getMonitor() != null;

View File

@ -62,16 +62,6 @@ pub const DesktopNotification = struct {
body: []const u8,
};
/// The tab to jump to. This is non-exhaustive so that integer values represent
/// the index (zero-based) of the tab to jump to. Negative values are special
/// values.
pub const GotoTab = enum(c_int) {
previous = -1,
next = -2,
last = -3,
_,
};
// This is made extern (c_int) to make interop easier with our embedded
// runtime. The small size cost doesn't make a difference in our union.
pub const SplitDirection = enum(c_int) {