From 7c287d1afb522d959388b1ba1a8f196223f236c0 Mon Sep 17 00:00:00 2001 From: t Date: Sat, 17 Oct 2026 10:24:20 -0500 Subject: [PATCH 1/7] dvui: the demo opens under the app's windows, the main window themed On fizzy's backend every floating window is now an OS window with the OS's title bar (fizzyedit/fizzy#480-#483, on zig/0.17). The demo was drawn last, so its window opened over the app's own and hid them; it is drawn first now. The main window's content gets the theme's window background, and the header says what the backend does. Co-Authored-By: Claude Opus 5.5 --- dvui/main.zig | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/dvui/main.zig b/dvui/main.zig index ba66263..d387648 100644 --- a/dvui/main.zig +++ b/dvui/main.zig @@ -1,14 +1,13 @@ //! A plain dvui app on fizzy's backend: dvui's own widgets, its demo, and OS windows of its own //! through `dvui.osWindow` — nothing of fizzy the editor, and nothing but dvui in the app's code. //! -//! On fizzy's backend each `dvui.osWindow` is a floating window in the one frame, shown in an OS -//! window of its own that looks just as the floating window does in the main window: dvui's header -//! and close button, no OS title bar. The OS moves it by its header; it resizes itself from its -//! edges, as a floating window does, and its window follows. The backend does all of it +//! On fizzy's backend every floating window that is not modal, `dvui.osWindow`'s and dvui's demo +//! alike, is shown in an OS window of its own: the OS's title bar and buttons in the theme's colour, +//! as on the main window, and the floating window's content below. The OS moves, resizes, zooms and +//! closes it, and keeps it above the main window. The backend does all of it //! (`backend/src/os_windows.zig` in fizzy). On dvui's own SDL3 backend (`-Ddvui-backend=sdl3`) -//! `dvui.osWindow` opens a `dvui.Window` of its own instead, as dvui does anywhere. -//! -//! dvui's demo is a floating window, and stays one: in the main window, as in dvui's own example. +//! `dvui.osWindow` opens a `dvui.Window` of its own instead, and the demo stays in the main window, +//! as dvui does anywhere. const std = @import("std"); const dvui = @import("dvui"); @@ -47,6 +46,9 @@ fn frame() !dvui.App.Result { newWindow(); } mainWindow(); + // dvui's demo first: a window opens over those opened before it, and the demo, centred and much + // the larger, hid the app's own windows opened under it. + dvui.Examples.demo(.lite); for (&windows, 0..) |*slot, i| if (slot.*) |*w| { if (!w.open) { slot.* = null; @@ -54,12 +56,11 @@ fn frame() !dvui.App.Result { } osWindow(w, i); }; - dvui.Examples.demo(.lite); return .ok; } fn mainWindow() void { - var box = dvui.box(@src(), .{}, .{ .expand = .both, .padding = .all(16) }); + var box = dvui.box(@src(), .{}, .{ .expand = .both, .padding = .all(16), .style = .window, .background = true }); defer box.deinit(); dvui.labelNoFmt(@src(), "dvui's own widgets on fizzy's backend.", .{}, .{ .font = .theme(.title) }); dvui.labelNoFmt(@src(), "Each window opened here is a dvui.osWindow.", .{}, .{}); From be6e2b8b99511305f5be07812637c39affc37b66 Mon Sep 17 00:00:00 2001 From: t Date: Sat, 17 Oct 2026 13:17:09 -0500 Subject: [PATCH 2/7] ci: the zig-0.17 branch builds as fizzy's CI builds it The branch's own CI installed Zig 0.16 and failed at build.zig, and on 0.17 its pins (fizzy's 0.16 releases) would fail as well until fizzy's first 0.17 SDK is released. So it runs fizzy's check-examples.sh on fizzy's zig/0.17 with this checkout and example-plugin's zig-0.17 in place of the pins: every shape, the replay app and the dvui app on both backends, on Zig 0.17. Back to building the pins at the merge (ZIG017). Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4e14be..f265fbb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,14 @@ # Builds the fizzy app in every shape on each push and pull request. Fizzy's own CI builds this # repo against each fizzy pull request as well, from a tarball of that tree. +# +# ZIG017: on the zig-0.17 branch the pins here are still the 0.16 releases, until fizzy's first +# 0.17 SDK is released. So this branch is built as fizzy's CI builds it: by fizzy's +# `scripts/check-examples.sh` on its `zig/0.17` branch, with this checkout and example-plugin's +# zig-0.17 branch in place of the pins. Back to building the pins on Zig 0.17 at the merge. name: CI on: push: - branches: [main] + branches: [main, zig-0.17] pull_request: workflow_dispatch: @@ -12,16 +17,24 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + path: examples/example-app + - uses: actions/checkout@v4 + with: + repository: fizzyedit/example-plugin + ref: zig-0.17 + path: examples/example-plugin + - uses: actions/checkout@v4 + with: + repository: fizzyedit/fizzy + ref: zig/0.17 + path: fizzy - uses: mlugg/setup-zig@v2 with: - version: "0.16.0" - - name: Build every shape - run: | - for shape in minimal studio endless; do - echo "::group::$shape" - zig build -Dshape=$shape --summary all - echo "::endgroup::" - done - zig build -Dshape=studio -Dzon-layout=true --summary all - - name: Build the replay app - run: zig build replay --summary all + version: "0.17.0" + use-cache: false + - name: Pre-create Zig cache tmp/ + run: mkdir -p "$ZIG_GLOBAL_CACHE_DIR/tmp" "$ZIG_LOCAL_CACHE_DIR/tmp" + - name: Build every shape, the replay app and the dvui app against fizzy's zig/0.17 + working-directory: fizzy + run: EXAMPLES_DIR="$GITHUB_WORKSPACE/examples" bash scripts/ci-retry.sh bash scripts/check-examples.sh From 77cb026b4f23b1fa76ab27de32a60a4e5df15ec6 Mon Sep 17 00:00:00 2001 From: t Date: Sat, 17 Oct 2026 18:32:00 -0500 Subject: [PATCH 3/7] dvui: only the dvui.osWindows are OS windows; the demo stays in the main window Co-Authored-By: Claude Opus 5.5 --- dvui/main.zig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dvui/main.zig b/dvui/main.zig index d387648..0b340f5 100644 --- a/dvui/main.zig +++ b/dvui/main.zig @@ -1,13 +1,13 @@ //! A plain dvui app on fizzy's backend: dvui's own widgets, its demo, and OS windows of its own //! through `dvui.osWindow` — nothing of fizzy the editor, and nothing but dvui in the app's code. //! -//! On fizzy's backend every floating window that is not modal, `dvui.osWindow`'s and dvui's demo -//! alike, is shown in an OS window of its own: the OS's title bar and buttons in the theme's colour, -//! as on the main window, and the floating window's content below. The OS moves, resizes, zooms and -//! closes it, and keeps it above the main window. The backend does all of it -//! (`backend/src/os_windows.zig` in fizzy). On dvui's own SDL3 backend (`-Ddvui-backend=sdl3`) -//! `dvui.osWindow` opens a `dvui.Window` of its own instead, and the demo stays in the main window, -//! as dvui does anywhere. +//! On fizzy's backend each `dvui.osWindow` is a floating window in the one frame, shown in an OS +//! window of its own: the OS's title bar and buttons in the theme's colour, as on the main window, +//! and the floating window's content below. The OS moves, resizes, zooms and closes it; on macOS it +//! is an ordinary window, with a full screen of its own. The backend does all of it +//! (`backend/src/os_windows.zig` in fizzy). Every other floating window, dvui's demo among them, +//! stays in the main window, as in dvui's own example. On dvui's own SDL3 backend +//! (`-Ddvui-backend=sdl3`) `dvui.osWindow` opens a `dvui.Window` of its own instead. const std = @import("std"); const dvui = @import("dvui"); From 04937f8c8ac8b0f8bedf4611891852feca566909 Mon Sep 17 00:00:00 2001 From: t Date: Sun, 18 Oct 2026 10:52:10 -0500 Subject: [PATCH 4/7] dvui: no OS windows to begin with; one opens when asked for or dragged out Co-Authored-By: Claude Opus 5.5 --- dvui/main.zig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dvui/main.zig b/dvui/main.zig index 0b340f5..12c16e7 100644 --- a/dvui/main.zig +++ b/dvui/main.zig @@ -38,12 +38,11 @@ var made: u32 = 0; var started = false; fn frame() !dvui.App.Result { - // dvui's demo and two OS windows to begin with. + // dvui's demo, in the main window, to begin with. An OS window opens only when one is asked + // for ("New window"), or when a floating window is dragged out of the app's windows. if (!started) { started = true; dvui.Examples.show_demo_window = true; - newWindow(); - newWindow(); } mainWindow(); // dvui's demo first: a window opens over those opened before it, and the demo, centred and much From 161f53a635ffa6cdabb09fbd667ca8f2fb17df62 Mon Sep 17 00:00:00 2001 From: t Date: Sun, 18 Oct 2026 12:02:31 -0500 Subject: [PATCH 5/7] dvui: New window and New OS window, and what the windows are made of "New window" opens an in-app floating window, which on fizzy's backend drags out into an OS window of its own; "New OS window" opens a dvui.osWindow. A dropdown and a transparency slider pick what the windows are made of (opaque, clear, blur, frost, Liquid Glass), the colour the theme's window colour; the main window draws no fill of its own, so the material shows through. Co-Authored-By: Claude Opus 5.5 --- dvui/main.zig | 68 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/dvui/main.zig b/dvui/main.zig index 12c16e7..5bd7639 100644 --- a/dvui/main.zig +++ b/dvui/main.zig @@ -22,8 +22,10 @@ pub const main = dvui.App.main; pub const panic = dvui.App.panic; pub const std_options: std.Options = .{ .logFn = dvui.App.logFn }; -/// An OS window of the app's own. +/// A window of the app's own: an in-app floating window, which can be dragged out into an OS window +/// of its own on fizzy's backend, or a `dvui.osWindow`. const Window = struct { + os: bool, open: bool = true, title_buf: [32:0]u8 = @splat(0), title_len: usize = 0, @@ -33,7 +35,7 @@ const Window = struct { return self.title_buf[0..self.title_len :0]; } }; -var windows: [4]?Window = @splat(null); +var windows: [6]?Window = @splat(null); var made: u32 = 0; var started = false; @@ -53,33 +55,77 @@ fn frame() !dvui.App.Result { slot.* = null; continue; } - osWindow(w, i); + if (w.os) osWindow(w, i) else floatWindow(w, i); }; return .ok; } fn mainWindow() void { - var box = dvui.box(@src(), .{}, .{ .expand = .both, .padding = .all(16), .style = .window, .background = true }); + // No fill of its own: the window's colour is the backend's, under what the window is made of + // (`materialPicker`), the theme's window colour at the transparency asked. + var box = dvui.box(@src(), .{}, .{ .expand = .both, .padding = .all(16) }); defer box.deinit(); dvui.labelNoFmt(@src(), "dvui's own widgets on fizzy's backend.", .{}, .{ .font = .theme(.title) }); - dvui.labelNoFmt(@src(), "Each window opened here is a dvui.osWindow.", .{}, .{}); - if (dvui.button(@src(), "New window", .{}, .{ .margin = .{ .y = 12 } })) newWindow(); + dvui.labelNoFmt(@src(), "A window opens in the app, and drags out into one of its own; an OS window opens as one.", .{}, .{}); + { + var row = dvui.box(@src(), .{ .dir = .horizontal }, .{ .margin = .{ .y = 12 } }); + defer row.deinit(); + if (dvui.button(@src(), "New window", .{}, .{})) newWindow(false); + if (dvui.button(@src(), "New OS window", .{}, .{})) newWindow(true); + } if (!dvui.Examples.show_demo_window) { if (dvui.button(@src(), "Show the dvui demo", .{}, .{})) dvui.Examples.show_demo_window = true; } + if (comptime @hasDecl(dvui.backend, "window_material")) materialPicker(); +} + +/// What the app's windows are made of, on fizzy's backend: opaque, clear, blurred, frosted or +/// Liquid Glass, each falling back to what the OS can show, and how transparent. The colour is the +/// theme's window colour (dvui's theme picker). +fn materialPicker() void { + const B = dvui.backend; + var row = dvui.box(@src(), .{ .dir = .horizontal }, .{ .margin = .{ .y = 12 } }); + defer row.deinit(); + const names = [_][]const u8{ "Opaque", "Clear", "Blur", "Frost", "Liquid Glass" }; + var choice: usize = @backingInt(B.window_material.kind); + if (dvui.dropdown(@src(), &names, .{ .choice = &choice }, .{}, .{ .min_size_content = .{ .w = 140 }, .gravity_y = 0.5 })) { + B.window_material.kind = @fromBackingInt(@as(u8, @intCast(choice))); + // Opaque, the window's colour covers it whole: half, to begin with. + if (B.window_material.kind != .none and B.window_material.opacity >= 1) B.window_material.opacity = 0.5; + } + dvui.labelNoFmt(@src(), "Transparency", .{}, .{ .gravity_y = 0.5, .margin = .{ .x = 12 } }); + var transparency = if (B.window_material.kind == .none) 0 else 1 - B.window_material.opacity; + if (dvui.slider(@src(), .{ .fraction = &transparency }, .{ .min_size_content = .{ .w = 160 }, .gravity_y = 0.5 })) { + // Transparent at all, it is made of something: clear, where it was opaque. + if (B.window_material.kind == .none and transparency > 0) B.window_material.kind = .transparent; + B.window_material.opacity = 1 - transparency; + } } -fn newWindow() void { + +fn newWindow(os: bool) void { const slot = for (&windows) |*slot| { if (slot.* == null) break slot; } else return; made += 1; - slot.* = .{}; + slot.* = .{ .os = os }; const w = &slot.*.?; - const t: []const u8 = std.fmt.bufPrint(&w.title_buf, "Window {d}", .{made}) catch ""; + const t: []const u8 = std.fmt.bufPrint(&w.title_buf, "{s} {d}", .{ if (os) "OS window" else "Window", made }) catch ""; w.title_len = t.len; } +/// An in-app floating window: on fizzy's backend, dragged by its header past the app's windows it +/// tears off into an OS window of its own (its close button, `open_flag`, is what lets it). +fn floatWindow(w: *Window, i: usize) void { + var float = dvui.floatingWindow(@src(), .{ .open_flag = &w.open, .window_avoid = .nudge }, .{ + .id_extra = i, + .min_size_content = .{ .w = 220, .h = 120 }, + }); + defer float.deinit(); + float.dragAreaSet(dvui.windowHeader(w.title(), "", &w.open)); + windowContent(w); +} + fn osWindow(w: *Window, i: usize) void { var os = dvui.osWindow(@src(), .{ .title = w.title(), @@ -87,6 +133,10 @@ fn osWindow(w: *Window, i: usize) void { .min_size = .{ .w = 220, .h = 120 }, }, .{ .id_extra = i, .open_flag = &w.open }); defer os.deinit(); + windowContent(w); +} + +fn windowContent(w: *Window) void { var box = dvui.box(@src(), .{}, .{ .expand = .both, .padding = .all(12) }); defer box.deinit(); dvui.label(@src(), "Clicked {d} times", .{w.count}, .{}); From 0724b34625664c8f1e75731d7b87e6282a85a2d3 Mon Sep 17 00:00:00 2001 From: t Date: Sun, 18 Oct 2026 12:16:11 -0500 Subject: [PATCH 6/7] dvui: the transparency slider keeps its height (and so its knob) Co-Authored-By: Claude Opus 5.5 --- dvui/main.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dvui/main.zig b/dvui/main.zig index 5bd7639..5e3bcb7 100644 --- a/dvui/main.zig +++ b/dvui/main.zig @@ -95,7 +95,7 @@ fn materialPicker() void { } dvui.labelNoFmt(@src(), "Transparency", .{}, .{ .gravity_y = 0.5, .margin = .{ .x = 12 } }); var transparency = if (B.window_material.kind == .none) 0 else 1 - B.window_material.opacity; - if (dvui.slider(@src(), .{ .fraction = &transparency }, .{ .min_size_content = .{ .w = 160 }, .gravity_y = 0.5 })) { + if (dvui.slider(@src(), .{ .fraction = &transparency }, .{ .min_size_content = .{ .w = 160, .h = 20 }, .gravity_y = 0.5 })) { // Transparent at all, it is made of something: clear, where it was opaque. if (B.window_material.kind == .none and transparency > 0) B.window_material.kind = .transparent; B.window_material.opacity = 1 - transparency; From 46fd900e771ad0216bf951884eecc141b1b8a3a9 Mon Sep 17 00:00:00 2001 From: foxnne Date: Sun, 18 Oct 2026 14:38:14 -0500 Subject: [PATCH 7/7] Build on fizzy's Zig 0.17 switch and SDK 0.2.30 fizzy pins its Zig 0.17 switch (fizzyedit/fizzy#575), fizzy_sdk and the shader plugin pin sdk-v0.2.30, hello pins example-plugin's 0.17 branch, and the workflow builds with Zig 0.17.0. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 2 +- build.zig.zon | 12 ++++++------ plugins/shader/build.zig.zon | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4e14be..5853dd6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v4 - uses: mlugg/setup-zig@v2 with: - version: "0.16.0" + version: "0.17.0" - name: Build every shape run: | for shape in minimal studio endless; do diff --git a/build.zig.zon b/build.zig.zon index 9205bef..6ba8f09 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -8,22 +8,22 @@ // by commit; fizzy's CI builds this repo against each of its pull requests, so a change // there that breaks an outside app fails before it lands. .fizzy = .{ - .url = "https://github.com/fizzyedit/fizzy/archive/75fd7f0ed1440432893238f75664e9680a56a123.tar.gz", - .hash = "fizzy-0.2.0-c46aVj4MkABq503RNbfyqugEU7A-BkJreTBFDhNbl6uF", + .url = "git+https://github.com/fizzyedit/fizzy#44ff62a7f757dbeca68bcc63df10967f12867f09", + .hash = "fizzy-0.2.0-c46aVk04ogAB94dagVVhnnXC7aQkakA2xI8itTEu3u2G", }, // The plugins this app bundles beyond fizzy's own: fizzyedit/example-plugin, as any // plugin from its own repo, and this app's own, which also builds alone as a dylib // (`cd plugins/shader && zig build`). .hello = .{ - .url = "https://github.com/fizzyedit/example-plugin/archive/838041afce45.tar.gz", - .hash = "hello-0.1.0-c1Gg4rQXAAA7Ea4vZqD4jAS7eLtXJW3QglYM4HB-17Lw", + .url = "git+https://github.com/fizzyedit/example-plugin#e4694bca51df6b07ae0f34e090919b22ba24da5a", + .hash = "hello-0.1.0-c1Gg4roXAABn7yCeQrlZVv3QJ7mAHsii6gFe1E6R2H7r", }, .shader = .{ .path = "plugins/shader" }, // The plugin SDK alone, for the replay app: its pinned dvui and `tape` / `replay`, with // nothing of fizzy the app. .fizzy_sdk = .{ - .url = "https://github.com/fizzyedit/fizzy/releases/download/sdk-v0.2.20/fizzy-sdk-v0.2.20.tar.gz", - .hash = "fizzy-0.2.20-SGBwY7BcIQAqHKHzaj0vwADkUQNdpiap19SmKZ29Rp0W", + .url = "https://github.com/fizzyedit/fizzy/releases/download/sdk-v0.2.30/fizzy-sdk-v0.2.30.tar.gz", + .hash = "fizzy-0.2.30-SGBwY1QnJwDznUMVnSLATxXgH2e8_Vz7eMwLj9UQ0sVU", }, }, .paths = .{ "build.zig", "build.zig.zon", "shapes", "plugins", "replay", "dvui", "README.md", "LICENSE" }, diff --git a/plugins/shader/build.zig.zon b/plugins/shader/build.zig.zon index 31116d7..c066721 100644 --- a/plugins/shader/build.zig.zon +++ b/plugins/shader/build.zig.zon @@ -7,8 +7,8 @@ .dependencies = .{ .fizzy = .{ // The published SDK: a plugin builds from a clean clone of its own repo. - .url = "https://github.com/fizzyedit/fizzy/releases/download/sdk-v0.2.18/fizzy-sdk-v0.2.18.tar.gz", - .hash = "fizzy-0.2.18-SGBwYzTcHgB679qozyk1xNBTyrOQYoKUNI5lvEX5_v6a", + .url = "https://github.com/fizzyedit/fizzy/releases/download/sdk-v0.2.30/fizzy-sdk-v0.2.30.tar.gz", + .hash = "fizzy-0.2.30-SGBwY1QnJwDznUMVnSLATxXgH2e8_Vz7eMwLj9UQ0sVU", }, }, }