Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions backend/src/GpuRenderer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,10 @@ fn acquireSwapchain(self: *GpuRenderer) !bool {
return false;
}
const cmd = try self.ensureCmd();
// No pass may be open while a drawable is acquired, the uploads' copy pass included. An app
// drawing its frame straight into the window (any dvui app; fizzy draws into a target first)
// had one open from the frame's uploads, and SDL asserted on every frame.
self.endCopy();
var tex: ?*c.SDL_GPUTexture = null;
var w: u32 = 0;
var h: u32 = 0;
Expand Down
10 changes: 5 additions & 5 deletions backend/src/platform/menu.zig
Original file line number Diff line number Diff line change
Expand Up @@ -105,31 +105,31 @@ fn selector(name: [*:0]const u8) ?*anyopaque {
return FizzyGetSelector(name);
}

export fn FizzyMenuActivated(section: c_int, tag: c_int, from_key: bool) void {
pub export fn FizzyMenuActivated(section: c_int, tag: c_int, from_key: bool) void {
if (section < 0 or section > 2 or tag < 0) return;
if (section == 0) pending_from_key.store(from_key, .release);
pending_tag[@intCast(section)].store(tag, .release);
}

export fn FizzyMenuEnabled(section: c_int, tag: c_int) callconv(.c) bool {
pub export fn FizzyMenuEnabled(section: c_int, tag: c_int) callconv(.c) bool {
const h = hooks orelse return true;
if (h.input_blocked(h.ctx)) return false;
if (section < 0 or section > 2 or tag < 0) return true;
return h.enabled(h.ctx, .{ .section = @enumFromInt(section), .tag = @intCast(tag) });
}

export fn FizzyMenuTitle(section: c_int, tag: c_int) callconv(.c) ?[*:0]const u8 {
pub export fn FizzyMenuTitle(section: c_int, tag: c_int) callconv(.c) ?[*:0]const u8 {
const h = hooks orelse return null;
if (section < 0 or section > 2 or tag < 0) return null;
return h.title(h.ctx, .{ .section = @enumFromInt(section), .tag = @intCast(tag) });
}

export fn FizzyMenuInputBlocked() callconv(.c) bool {
pub export fn FizzyMenuInputBlocked() callconv(.c) bool {
const h = hooks orelse return false;
return h.input_blocked(h.ctx);
}

export fn FizzyMenuAbout() callconv(.c) void {
pub export fn FizzyMenuAbout() callconv(.c) void {
pending_about.store(true, .release);
}

Expand Down
13 changes: 13 additions & 0 deletions backend/src/platform/root.zig
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,16 @@ pub const geometry = @import("geometry.zig");
pub const macos_monitor = @import("macos_monitor.zig");
pub const window_layout = @import("window_layout.zig");
pub const menu = @import("menu.zig");

comptime {
// The menu bar's Objective-C (`macos/menu_target.m`) calls these back, and it is compiled into
// every app on macOS (`addPlatformObjC`), so they are kept whether or not the app ever reaches
// `menu` — a plain dvui app with no menu bar of its own failed to link without them.
if (@import("builtin").os.tag == .macos) {
_ = &menu.FizzyMenuActivated;
_ = &menu.FizzyMenuEnabled;
_ = &menu.FizzyMenuTitle;
_ = &menu.FizzyMenuInputBlocked;
_ = &menu.FizzyMenuAbout;
}
}
32 changes: 32 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,35 @@ pub fn buildApp(fizzy_dep: *std.Build.Dependency, plugins: []const BundledPlugin
opts.app_plugins = plugins;
try @import("build/app.zig").construct(fizzy_dep.builder, d.target, d.optimize, opts, d.cfg);
}

/// What a dvui app of its own builds on (`addDvui`): fizzy's backend, with OS windows besides the
/// main one, or dvui's own SDL3 backend, with the main window only.
pub const NativeBackend = @import("build/exe.zig").NativeBackend;

/// A plain dvui app — dvui's widgets and `dvui.App`, nothing of fizzy the editor — on `backend`:
/// `root_module` gets `dvui` (fizzy's pin), its `backend`, and `viewports_none`, so the same code
/// builds on either backend:
///
/// ```zig
/// const backend = @import("backend");
/// const viewports = if (@hasDecl(backend, "viewports")) backend.viewports else @import("viewports_none");
/// ```
///
/// On fizzy's backend it also gets `platform` (the window's chrome and state), and on macOS the
/// backend's Objective-C, compiled into it. Give `root_module` its target and optimize mode first.
pub fn addDvui(fizzy_dep: *std.Build.Dependency, root_module: *std.Build.Module, backend: NativeBackend) !void {
const b = fizzy_dep.builder;
const exe = @import("build/exe.zig");
const target = root_module.resolved_target orelse @panic("fizzy.addDvui: give the root module its target first");
const optimize = root_module.optimize orelse .Debug;
const macos_sdl_paths = try @import("build/common.zig").macosSdlPathsForExplicitTarget(b, target);
const native = exe.nativeDvui(b, backend, target, optimize, .off, macos_sdl_paths);
root_module.addImport("dvui", native.dvui);
root_module.addImport("backend", native.backend);
const backend_dep = exe.backendDependency(b);
root_module.addImport("viewports_none", @import("fizzy_backend").viewportsNoneModule(backend_dep, native.dvui));
if (backend == .fizzy) {
root_module.addImport("platform", exe.platformModule(b, native, target, optimize, macos_sdl_paths));
@import("fizzy_backend").addPlatformObjC(backend_dep, root_module, exe.backendOptions(target, optimize, macos_sdl_paths));
}
}
53 changes: 33 additions & 20 deletions build/exe.zig
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,42 @@ pub fn defaultNativeBackend(target: std.Build.ResolvedTarget) NativeBackend {
}

/// dvui as the executable links it, and the backend under it.
const NativeDvui = struct {
pub const NativeDvui = struct {
dep: *std.Build.Dependency,
dvui: *std.Build.Module,
backend: *std.Build.Module,
};

/// dvui on the native backend asked for: fizzy's (`fizzyNativeDvui`), or dvui's own SDL3 backend.
/// The executable's, and a dvui app's of its own (`fizzy.addDvui`, in `build.zig`).
pub fn nativeDvui(
b: *std.Build,
native_backend: NativeBackend,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
accesskit: dvui.AccesskitOptions,
macos_sdl_paths: ?MacosSdlPaths,
) NativeDvui {
return switch (native_backend) {
.fizzy => fizzyNativeDvui(b, target, optimize, accesskit, macos_sdl_paths),
.sdl3 => blk: {
const dep = if (macos_sdl_paths) |p|
sdk.dvuiDependency(b, .{
.target = target,
.optimize = optimize,
.backend = .sdl3,
.accesskit = accesskit,
.system_include_path = p.include,
.system_framework_path = p.framework,
.library_path = p.lib,
})
else
sdk.dvuiDependency(b, .{ .target = target, .optimize = optimize, .backend = .sdl3, .accesskit = accesskit });
break :blk .{ .dep = dep, .dvui = dep.module("dvui_sdl3"), .backend = dep.module("sdl3") };
},
};
}

/// dvui in its `custom` mode with fizzy's backend linked under it — as `build/web.zig` does for
/// the web. Every option is the one dvui's own `sdl3` mode sets, so dvui's shape, and with it
/// the plugin ABI fingerprint, is the same either way.
Expand Down Expand Up @@ -139,7 +169,7 @@ pub fn backendOptions(target: std.Build.ResolvedTarget, optimize: std.builtin.Op

/// Window and platform pieces for apps on either SDL3 backend (the backend package's
/// `platform`). Fizzy's own backend imports it as well.
fn platformModule(
pub fn platformModule(
b: *std.Build,
native: NativeDvui,
target: std.Build.ResolvedTarget,
Expand Down Expand Up @@ -175,24 +205,7 @@ pub fn addFizzyExecutableForTarget(
/// `bundled_plugins` module under its plugin id.
app_plugins: []const sdk.BundledPlugin,
) !FizzyExecutable {
const native: NativeDvui = switch (native_backend) {
.fizzy => fizzyNativeDvui(b, resolved_target, optimize, accesskit, macos_sdl_paths),
.sdl3 => blk: {
const dep = if (macos_sdl_paths) |p|
sdk.dvuiDependency(b, .{
.target = resolved_target,
.optimize = optimize,
.backend = .sdl3,
.accesskit = accesskit,
.system_include_path = p.include,
.system_framework_path = p.framework,
.library_path = p.lib,
})
else
sdk.dvuiDependency(b, .{ .target = resolved_target, .optimize = optimize, .backend = .sdl3, .accesskit = accesskit });
break :blk .{ .dep = dep, .dvui = dep.module("dvui_sdl3"), .backend = dep.module("sdl3") };
},
};
const native = nativeDvui(b, native_backend, resolved_target, optimize, accesskit, macos_sdl_paths);
const dvui_dep = native.dep;
const dvui_mod = native.dvui;

Expand Down
Loading