Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ea83962
zig: the 0.17 switch, scaffolded with marked stand-ins (#437)
foxnne Oct 16, 2026
9a22df2
zig: the build's custom steps become helper programs (#438)
foxnne Oct 16, 2026
2491f4e
zig: release packaging on 0.17, with Velopack 1.2.161 (#448)
foxnne Oct 16, 2026
b18213c
backend: no crash quitting a plain dvui app on macOS (#480)
foxnne Oct 17, 2026
a59ff14
backend: a plain dvui app's floating windows open as OS windows (#481)
foxnne Oct 17, 2026
67cc6ea
macos: a plain dvui app's windows take fizzy's window shape (#482)
foxnne Oct 17, 2026
78a5019
macos: child windows stay above the main window (#483)
foxnne Oct 17, 2026
46ddcd8
zig/0.17: merge main (40 commits, to #469)
foxnne Oct 17, 2026
6d94889
zig/0.17: merge main (40 commits, to #469) (#486)
foxnne Oct 17, 2026
28766fa
zig: settings and command schemas read 0.17's @typeInfo (#488)
foxnne Oct 17, 2026
b45233a
zig: a lifted view keeps its drag through dvui's captureMouseGet (#489)
foxnne Oct 17, 2026
a1feb78
docs: the Windows traps of the Zig 0.17 move (#494)
foxnne Oct 18, 2026
300d797
core: a transparent blit reads its pixels as bytes on Zig 0.17 (#496)
foxnne Oct 18, 2026
1b6ad2c
sdk: a plugin can install a program beside itself (#498)
foxnne Oct 18, 2026
0be3e64
zig/0.17: record #486's merge of main as a parent
foxnne Oct 18, 2026
47a0c1e
zig/0.17: merge main (6 commits, to #490)
foxnne Oct 18, 2026
87ae2ae
zig: what 0.16 needed goes with the move (#505)
foxnne Oct 18, 2026
3513b9f
macos: a plain dvui app's OS windows are ordinary document windows (#…
foxnne Oct 18, 2026
eb452e8
backend: OS windows for the floating windows that ask, or all by choi…
foxnne Oct 18, 2026
7336d4a
macos: a float's full screen at the display's rate, clear and rounded…
foxnne Oct 18, 2026
2dc6fc4
macos: the pointer reaches the window it is over, not one behind it (…
foxnne Oct 18, 2026
4eca7f6
core: one window material, and the kinds each backend can show
foxnne Oct 18, 2026
d2128cb
app: every glass draws in the window material
foxnne Oct 18, 2026
9f5fc85
backend: a floating window dragged past the app's windows tears off (…
foxnne Oct 18, 2026
9e8e530
zig/0.17: merge main (22 commits, to #509) (#558)
foxnne Oct 18, 2026
e118432
zig/0.17: merge into backend/window-materials (to #558)
foxnne Oct 18, 2026
18c1631
Merge backend/window-materials into app/glass-material
foxnne Oct 18, 2026
54014c7
zig: settings own only strings, and builds read through b.root (#561)
foxnne Oct 18, 2026
39574be
core: one window material, and the kinds each backend can show (#546)
foxnne Oct 18, 2026
0b0f9e0
Merge zig/0.17 into app/glass-material
foxnne Oct 18, 2026
ae5e719
backend: plain dvui app windows made of the window material (#565)
foxnne Oct 18, 2026
9d9dbee
Merge main into app/glass-material
foxnne Oct 18, 2026
e17b4ce
macos: a window's glass bevel follows a live resize (#576)
foxnne Oct 18, 2026
d6732b6
backend: fizzy's in-app glass is the backend's, core re-exports it
foxnne Oct 18, 2026
2aa641c
main: merge into backend/glass-module
foxnne Oct 18, 2026
27eae42
backend: a plain dvui app's frame draws through FrameTarget
foxnne Oct 18, 2026
441be69
main: merge into backend/plain-frame-target
foxnne Oct 18, 2026
46c95e6
main: merge into backend/plain-frame-target
foxnne Oct 18, 2026
bafe379
main: merge into backend/plain-frame-target
foxnne Oct 19, 2026
296c07a
main: merge into backend/plain-frame-target
foxnne Oct 19, 2026
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
6 changes: 6 additions & 0 deletions backend/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ how an app wires it).
(`core.FrameTarget`, `core.widgets.BlurBackdrop`, …) and takes the backend's instance over the
same dvui (`core_module.addImports`); it depends on dvui and `glass_look` only. Its profiler
scopes reach `core.profile` through `glass/prof.zig`, which the profiler hands its scopes to.
- **A plain dvui app's frame draws into a texture** (`plainFrameBegin`/`plainFrameEnd` in
`SDLBackend.zig`, a `glass.FrameTarget`), so glass drawn over it can read what is under it.
Fizzy wraps its own frame (`src/Entry.zig`), so the backend's wrap is only for an app that
does not dress its windows (`platform.window.app_dresses_windows`): never both. It sits inside
`os_windows`' `beforeFrame`/`afterFrame`, whose pictures bind their own targets and give this
one back; anything that draws into the main window's frame goes before `plainFrameEnd`.
- **dvui is the caller's.** It is never pinned here; the backend compiles against the app's dvui.
- **SDL is patched here,** not in a fork: `patches/sdl/*.patch`, applied by zig-patch. How to
change, add or bump them is `docs/DEPENDENCIES.md` ("SDL", "Bumping"). Touching a patch or this
Expand Down
4 changes: 4 additions & 0 deletions backend/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ pub fn backendModule(dep: *std.Build.Dependency, dvui_mod: *std.Build.Module, op
m.addCSourceFile(.{ .file = b.path("src/macos_monitor.m") });
}
m.addImport("glass_look", glassLookModule(dep));
// A plain dvui app's frame is drawn through the glass's frame target (`plainFrameBegin`). The
// same module as the app's `core` takes (`glassModule`, one per dvui); it imports dvui, never
// the backend.
m.addImport("glass", glassModule(dep, dvui_mod));
dvui_mod.addImport("backend", m);
backend_modules.put(b.allocator, dvui_mod, m) catch @panic("OOM");
return m;
Expand Down
59 changes: 54 additions & 5 deletions backend/src/SDLBackend.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ pub const viewports = @import("viewports.zig");
pub const os_windows = @import("os_windows.zig");
/// What this backend keeps count of as it runs (`health`).
pub const Health = @import("Health.zig");
/// Fizzy's in-app glass (`src/glass/`): here for `FrameTarget`, a plain dvui app's frame drawn
/// into a texture (`plainFrameBegin`).
pub const glass = @import("glass");

/// What an app gets from its window beyond drawing into it: native dialogs, files the OS hands
/// over, trackpad gestures, the window's chrome and state (`platform/`).
Expand Down Expand Up @@ -97,11 +100,17 @@ sdl_quit: bool = true,
clear_window_on_begin: bool = false,
/// See `mainPicture`.
main_picture: ?viewport_map.Rect = null,
/// The backend lays the main window's frame down where its picture is (`mainPicture`), the app
/// drawing straight to the window: a plain dvui app's, whose picture is also below the title bar
/// (`platform.macos_monitor.titlebarStrip`). Fizzy draws to a target and lays it down itself
/// (`core.gfx.FrameTarget`), and keeps its content clear of the traffic lights itself.
/// The main window's frame goes down where its picture is (`mainPicture`): a plain dvui app's,
/// whose picture is also below the title bar (`platform.macos_monitor.titlebarStrip`). Its frame
/// target lays it there (`plain_frame`, `pictureInWindow`); the backend moves what is drawn
/// straight to the window there itself only on a frame the target did not bind. Fizzy draws to a
/// target of its own, lays it down itself, and keeps its content clear of the traffic lights.
places_main_picture: bool = false,
/// A plain dvui app's frame, drawn into a texture and laid down on the window at its end
/// (`plainFrameBegin`), as fizzy draws its own (`src/Entry.zig`).
plain_frame: glass.FrameTarget = .{},
/// Whether `glass.FrameTarget.init` has run for `plain_frame`.
plain_frame_ready: bool = false,
/// A plain dvui app's main window's size its shadow was last taken at, and the frames it is taken
/// again for: clear over its backdrop (`platform.window.nativeTitleBar`), AppKit shapes the shadow
/// — and the outline that comes with it — from what is drawn, as a float's window has it
Expand Down Expand Up @@ -1146,6 +1155,40 @@ fn dressPlainWindows(self: *SDLBackend) void {
for (&self.viewport_slots) |*slot| if (slot.*) |*v| if (v.native) plainGlass(v.window, material.opacity, colors[0]);
}

/// A plain dvui app's frame from here to `plainFrameEnd` draws into a texture the window's size
/// (`glass.FrameTarget`), laid down on the window at the end, as fizzy's own frame is
/// (`src/Entry.zig`). So that what is drawn over the frame — a floating window in the window's
/// material, a frost under it — can read back what is under it from a texture the GPU holds
/// (`glass.BlurBackdrop`), rather than read the window back through the CPU. Costs a full-window
/// textured quad a frame; on Metal it also defers acquiring the drawable to the end of the frame.
/// Not for fizzy, which wraps its frame itself (`platform.window.app_dresses_windows`); and
/// nothing on a backend without render targets.
///
/// Around the app's frame function, inside `os_windows`' `beforeFrame` and `afterFrame`: the
/// floating windows in OS windows of their own are taken out of the frame into their windows'
/// pictures there (`viewports.Picture` binds its own target and gives this one back), so they
/// never reach this one; what stays in the main window is drawn into it by `plainFrameEnd`.
fn plainFrameBegin(self: *SDLBackend) void {
if (platform.window.app_dresses_windows) return;
if (!self.plain_frame_ready) {
glass.FrameTarget.init();
self.plain_frame_ready = true;
}
self.plain_frame.begin();
// The target lays the frame down at the main window's picture itself (`pictureInWindow`):
// not moved there a second time on its way into the window (`begin`, `places_main_picture`).
if (self.plain_frame.bound) self.gpu.window_offset = .{ 0, 0 };
}

/// The end of a plain dvui app's frame (`plainFrameBegin`): before `Window.end`, after everything
/// the frame draws into the main window. dvui's deferred subwindows — floating windows, dialogs,
/// toasts — render into the target here (`FrameTarget.end` runs `Window.endRendering`, which
/// `Window.end` then skips), and the target is drawn on the window.
fn plainFrameEnd(self: *SDLBackend) void {
if (platform.window.app_dresses_windows) return;
self.plain_frame.end();
}

/// `window`'s Liquid Glass this frame, as fizzy's own windows have it (`Editor.windowGlassLook`):
/// what `glass_look` says at `opacity`, in the window's colour, its clearing bevel by its size.
/// Nothing where the window stands on no glass.
Expand Down Expand Up @@ -3839,11 +3882,13 @@ pub fn main(main_init: std.process.Init) !u8 {
try back.addAllEvents(&win);

// As `appIterate`: the floating windows in OS windows of their own, and a plain dvui app's
// main window dressed.
// main window dressed, its frame drawn into a texture (`plainFrameBegin`).
os_windows.beforeFrame();
back.plainFrameBegin();
const res = try app.frameFn();
os_windows.afterFrame();
if (!platform.window.app_dresses_windows) back.dressPlainWindows();
back.plainFrameEnd();

var end_micros = try win.end(.{});
Health.current.frameEnd(c.SDL_GetTicksNS());
Expand Down Expand Up @@ -4094,6 +4139,9 @@ fn appIterate(_: ?*anyopaque) callconv(.c) c.SDL_AppResult {

const app = dvui.App.get() orelse unreachable;
os_windows.beforeFrame();
// A plain dvui app's frame into a texture, laid down on the window before `Window.end`
// (`plainFrameBegin`).
appState.back.plainFrameBegin();
var res = app.frameFn() catch |err| {
log.err("dvui.App.frameFn failed: {any}", .{err});
return c.SDL_APP_FAILURE;
Expand All @@ -4104,6 +4152,7 @@ fn appIterate(_: ?*anyopaque) callconv(.c) c.SDL_AppResult {
if (!platform.window.app_dresses_windows) appState.back.dressPlainWindows();

live_resize_trace.overlay();
appState.back.plainFrameEnd();

var end_micros = appState.win.end(.{ .manage_backend = false }) catch |err| {
log.err("dvui.Window.end failed: {any}", .{err});
Expand Down
Loading