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, v,
), ),
.new_tab => { .new_tab => try self.rt_app.performAction(
if (@hasDecl(apprt.Surface, "newTab")) { .{ .surface = self },
try self.rt_surface.newTab(); .new_tab,
} else log.warn("runtime doesn't implement newTab", .{}); {},
}, ),
.previous_tab => { inline .previous_tab,
if (@hasDecl(apprt.Surface, "gotoTab")) { .next_tab,
self.rt_surface.gotoTab(.previous); .last_tab,
} else log.warn("runtime doesn't implement gotoTab", .{}); .goto_tab,
}, => |v, tag| try self.rt_app.performAction(
.{ .surface = self },
.next_tab => { .goto_tab,
if (@hasDecl(apprt.Surface, "gotoTab")) { switch (tag) {
self.rt_surface.gotoTab(.next); .previous_tab => .previous,
} else log.warn("runtime doesn't implement gotoTab", .{}); .next_tab => .next,
}, .last_tab => .last,
.goto_tab => @enumFromInt(v),
.last_tab => { else => comptime unreachable,
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", .{});
}, },
),
.new_split => |direction| { .new_split => |direction| {
if (@hasDecl(apprt.Surface, "newSplit")) { if (@hasDecl(apprt.Surface, "newSplit")) {

View File

@ -12,9 +12,9 @@ const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const build_config = @import("build_config.zig"); const build_config = @import("build_config.zig");
const action = @import("apprt/action.zig");
const structs = @import("apprt/structs.zig"); const structs = @import("apprt/structs.zig");
pub const action = @import("apprt/action.zig");
pub const glfw = @import("apprt/glfw.zig"); pub const glfw = @import("apprt/glfw.zig");
pub const gtk = @import("apprt/gtk.zig"); pub const gtk = @import("apprt/gtk.zig");
pub const none = @import("apprt/none.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. /// as font size should be inherited.
new_window, 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 open windows.
close_all_windows, close_all_windows,
@ -58,3 +67,13 @@ pub const Target = union(enum) {
app, app,
surface: *CoreSurface, 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. /// views then this can be null.
new_split: ?*const fn (SurfaceUD, apprt.SplitDirection, apprt.Surface.Options) callconv(.C) void = 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_tab: ?*const fn (SurfaceUD, apprt.Surface.Options) callconv(.C) void = null,
/// New window with options. The surface may be null if there is no /// 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, toggle_split_zoom: ?*const fn (SurfaceUD) callconv(.C) void = null,
/// Goto tab /// 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 for current window.
toggle_fullscreen: ?*const fn (SurfaceUD, configpkg.NonNativeFullscreen) callconv(.C) void = null, toggle_fullscreen: ?*const fn (SurfaceUD, configpkg.NonNativeFullscreen) callconv(.C) void = null,
@ -506,9 +507,36 @@ pub const App = struct {
func(null, .{}); 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 { fn setPasswordInput(self: *App, target: apprt.Target, v: bool) void {
const func = self.opts.set_password_input orelse { 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; return;
}; };
@ -531,8 +559,9 @@ pub const App = struct {
.surface => |v| v, .surface => |v| v,
}), }),
.new_tab => self.newTab(target),
.goto_tab => self.gotoTab(target, value),
.open_config => try configpkg.edit.open(self.core_app.alloc), .open_config => try configpkg.edit.open(self.core_app.alloc),
.secure_input => self.setPasswordInput(target, value), .secure_input => self.setPasswordInput(target, value),
// Unimplemented // 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 { pub fn toggleFullscreen(self: *Surface, nonNativeFullscreen: configpkg.NonNativeFullscreen) void {
const func = self.app.opts.toggle_fullscreen orelse { const func = self.app.opts.toggle_fullscreen orelse {
log.info("runtime embedder does not toggle_fullscreen", .{}); log.info("runtime embedder does not toggle_fullscreen", .{});
@ -1126,16 +1146,6 @@ pub const Surface = struct {
func(); 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 { fn newWindow(self: *const Surface) !void {
const func = self.app.opts.new_window orelse { const func = self.app.opts.new_window orelse {
log.info("runtime embedder does not support new_window", .{}); log.info("runtime embedder does not support new_window", .{});

View File

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

View File

@ -62,16 +62,6 @@ pub const DesktopNotification = struct {
body: []const u8, 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 // 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. // runtime. The small size cost doesn't make a difference in our union.
pub const SplitDirection = enum(c_int) { pub const SplitDirection = enum(c_int) {