From 13603c51a922392e925fd5f8bd2f0221ac438dbb Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 25 Sep 2024 11:01:35 -0700 Subject: [PATCH] apprt: begin transition to making actions an enum and not use hasDecl --- src/App.zig | 22 ++++++++++------------ src/apprt.zig | 6 ++++++ src/apprt/action.zig | 29 +++++++++++++++++++++++++++++ src/apprt/glfw.zig | 22 +++++++++++++++++----- 4 files changed, 62 insertions(+), 17 deletions(-) create mode 100644 src/apprt/action.zig diff --git a/src/App.zig b/src/App.zig index d93e00a2a..65153127a 100644 --- a/src/App.zig +++ b/src/App.zig @@ -241,19 +241,17 @@ fn redrawInspector(self: *App, rt_app: *apprt.App, surface: *apprt.Surface) !voi /// Create a new window pub fn newWindow(self: *App, rt_app: *apprt.App, msg: Message.NewWindow) !void { - if (!@hasDecl(apprt.App, "newWindow")) { - log.warn("newWindow is not supported by this runtime", .{}); - return; - } + const target: apprt.Target = target: { + const parent = msg.parent orelse break :target .app; + if (self.hasSurface(parent)) break :target .{ .surface = parent }; + break :target .app; + }; - const parent = if (msg.parent) |parent| parent: { - break :parent if (self.hasSurface(parent)) - parent - else - null; - } else null; - - try rt_app.newWindow(parent); + try rt_app.performAction( + target, + .new_window, + {}, + ); } /// Start quitting diff --git a/src/apprt.zig b/src/apprt.zig index 491f1b8b5..f6952c9ec 100644 --- a/src/apprt.zig +++ b/src/apprt.zig @@ -12,6 +12,7 @@ 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 glfw = @import("apprt/glfw.zig"); @@ -21,6 +22,9 @@ pub const browser = @import("apprt/browser.zig"); pub const embedded = @import("apprt/embedded.zig"); pub const surface = @import("apprt/surface.zig"); +pub const Action = action.Action; +pub const Target = action.Target; + pub const ContentScale = structs.ContentScale; pub const Clipboard = structs.Clipboard; pub const ClipboardRequest = structs.ClipboardRequest; @@ -84,4 +88,6 @@ pub const Runtime = enum { test { _ = Runtime; _ = runtime; + _ = action; + _ = structs; } diff --git a/src/apprt/action.zig b/src/apprt/action.zig new file mode 100644 index 000000000..38b318109 --- /dev/null +++ b/src/apprt/action.zig @@ -0,0 +1,29 @@ +const std = @import("std"); +const assert = std.debug.assert; +const CoreSurface = @import("../Surface.zig"); + +/// The possible actions an apprt has to react to. +pub const Action = union(enum) { + new_window, + + /// The enum of keys in the tagged union. + pub const Key = @typeInfo(Action).Union.tag_type.?; + + /// Returns the value type for the given key. + pub fn Value(comptime key: Key) type { + inline for (@typeInfo(Action).Union.fields) |field| { + const field_key = @field(Key, field.name); + if (field_key == key) return field.type; + } + + unreachable; + } +}; + +/// The target for an action. This is generally the thing that had focus +/// while the action was made but the concept of "focus" is not guaranteed +/// since actions can also be triggered by timers, scripts, etc. +pub const Target = union(enum) { + app, + surface: *CoreSurface, +}; diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index 57cb257b4..e5405eb32 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -127,6 +127,23 @@ pub const App = struct { glfw.postEmptyEvent(); } + /// Perform a given action. + pub fn performAction( + self: *App, + target: apprt.Target, + comptime action: apprt.Action.Key, + value: apprt.Action.Value(action), + ) !void { + _ = value; + + switch (action) { + .new_window => _ = try self.newSurface(switch (target) { + .app => null, + .surface => |v| v, + }), + } + } + /// Open the configuration in the system editor. pub fn openConfig(self: *App) !void { try configpkg.edit.open(self.app.alloc); @@ -195,11 +212,6 @@ pub const App = struct { win.setMonitor(monitor, 0, 0, video_mode.getWidth(), video_mode.getHeight(), 0); } - /// Create a new window for the app. - pub fn newWindow(self: *App, parent_: ?*CoreSurface) !void { - _ = try self.newSurface(parent_); - } - /// Create a new tab in the parent surface. fn newTab(self: *App, parent: *CoreSurface) !void { if (!Darwin.enabled) {