Skip to content

sdk: release 0.2.18, a plugin's glass over its picture and native - #228

Merged
foxnne merged 10 commits into
mainfrom
ccr-7f00e3d0-sjpshu
Oct 8, 2026
Merged

foxnne merged 10 commits into
mainfrom
ccr-7f00e3d0-sjpshu

Conversation

@foxnne

@foxnne foxnne commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #226

What changes

Two pieces pixi's dropper magnifier (fizzyedit/pixi#3) needs to be a clear liquid orb over its zoom, with no frost and strong refraction: native Liquid Glass on macOS, the app's glass everywhere else. And the SDK release that ships them, so the orb can be tried against main as soon as this merges.

core.native_glass.offered

  • The app publishes each frame whether the OS draws glass declared outside a view drag (publishOffered, from Popout.beginFrame's nativeGlass()).
  • A plugin that sees it declares its glass with native_glass.add. Fizzy's overlay of Liquid Glass already stays up while any glass is declared.
  • Pixi declares a clear piece (frost = 0, the lens alone) over a zoom it draws in the window, so the OS's lens refracts the window beneath.
  • Off macOS 26, or with native glass off, offered() is false.

LiquidField.drawPicture / pictureMargin / lens, and glass_look.forLens

  • The app's glass as a lens over a picture the plugin drew. The middle is the picture as it is, with no frost, colour or lift; the rim bends and lights it.
  • It reads no capture, so the middle stays pixel-exact.
  • On the web, where no look is published, it is the earlier glass. pictureMargin says how far past the shapes the picture should reach for that glass's rim, at the strongest shape lens.

Tried and dropped: pixi tried the drop zones' frosted glass with its zoom laid over it. On a Mac it read as a thick grey border or a flat rim.

Merged with main (#234–#236, #239, #240).

SDK impact

  • None
  • Core-only or additive: reaches plugins at the next SDK release
  • Fingerprint moved: recorded in sdk/src/version.zig, sdk_version untouched, PR labelled sdk
  • SDK release: bumps sdk_version, lists the sdk PRs since the last sdk-v* tag

sdk_version goes 0.2.17 → 0.2.18 (ef95301). Since sdk-v0.2.17 this release carries:

The fingerprint has not moved, so installed plugins keep loading. Merging tags sdk-v0.2.18 and, per #240, asks the store plugins to repin.

Verified

  • zig test core/gfx/glass_look.zig: 13 pass.
  • zig fmt --check and zig ast-check on the changed files.
  • tests/integration.zig compiles drawPicture and checks pictureMargin.
  • CI: Linux, macOS, Windows, integration and the Windows cross-build on this head.
  • macOS: pixi's orb tried locally against this branch by the maintainer, who approved it.
  • Windows:
  • Linux:
  • Web:

Follow-ups

  • pixi#3 repinned to sdk-v0.2.18 once it's tagged.
  • The orb pinching off pixi's sample button and merging with it (the plan's next step for this consumer).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Euk6iCavQdW7MG5FN2vvFw

claude added 2 commits October 8, 2026 12:45
…r pixi's dropper magnifier

The first plugin consumer in the native windows plan (#226) is pixi's colour dropper magnifier
as liquid glass. Its glass shows pixi's own pixel-exact zoom, not what lies behind it, so it
reads nothing from the frame:

- `LiquidField.drawPicture(picture, covered)` queues the field over a texture the caller drew
  (`dvui.deferRender`, at full alpha, as every glass is), and returns false where there is no
  glass program, so the caller can draw a fallback. `pictureMargin` is how far past the shapes
  the picture should reach for the earlier glass, whose rim pulls from just outside (the web,
  where no look is published).
- `LiquidField.lens` and `glass_look.forLens`: the slider's in-app look with no frost, colour
  or lift, so the middle is the picture as it is and a colour picked through it is the colour
  under it. Only the edge's band bends and is lit, following the slider. Tested beside the other
  looks.

No SDK ABI change: `LiquidField` crosses no boundary. pixi picks it up from the next SDK
release, and builds against SDKs without it (it checks `@hasDecl`).

Checked: `zig test core/gfx/glass_look.zig` (13 pass), `zig fmt`, `zig ast-check`. The full
build was not run: dependency downloads are blocked in the environment this was written in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Euk6iCavQdW7MG5FN2vvFw
…ins that build core in

No change to the plugin boundary: the shape fingerprint is 0.2.17's, so every installed plugin
keeps loading. A plugin that builds `core` into itself (pixi) picks these up by repinning to
0.2.18:

- `LiquidField.drawPicture` and `glass_look.forLens`: glass over a picture the plugin drew,
  for pixi's colour dropper magnifier;
- the glass on one slider since 0.2.17 (#227: `glass_look`, Apple's lens in the in-app glass,
  `core.native_glass`), and the pop-out window pieces of #223 and #224.

Merging this to main tags sdk-v0.2.18 and publishes its tarball (`sdk-tag.yml`).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Euk6iCavQdW7MG5FN2vvFw
…Margin checked

Nothing in fizzy calls `drawPicture` (pixi's dropper magnifier does), and Zig compiles only what
is called, so a green CI said nothing about it. This test takes its address, which compiles it,
and checks that the picture reaches as far past the shape as the earlier glass's rim pulls from,
and further at a stronger refraction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Euk6iCavQdW7MG5FN2vvFw
…p zones' glass

Tried on a Mac with pixi's branch, the dropper's orb read as a zoomed picture with a bent edge,
nothing like the drop zones. The lens over a picture stripped what makes the app's glass look
like glass: the frost, the window's colour and the lift. Pixi's orb now uses the drop zones'
own glass over the canvas (`dialogs.carriedField`, already in the SDK) and carries its zoom
over it, as a drop zone carries its icon. So `drawPicture`, `pictureMargin`, `lens`,
`glass_look.forLens` and their tests have no caller, and go.

This PR is now the SDK bump alone. It ships the one-slider glass of #227 to plugins that build
`core` in, so pixi's orb matches the host's drop zones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Euk6iCavQdW7MG5FN2vvFw
@foxnne foxnne changed the title sdk 0.2.18: glass over a picture of the caller's own (LiquidField.drawPicture), for pixi's dropper magnifier sdk 0.2.18: the one-slider glass reaches plugins that build core in (for pixi's dropper magnifier) Oct 8, 2026
foxnne added a commit that referenced this pull request Oct 8, 2026
## What changes

**Fixes the macOS failure in #234's CI:** `LocalFs` "a read lands
through pump" failed with `error.NeverLanded`. #234 itself changes only
`ci.yml`, and the same test passed on macOS in #234's previous run and
in #228's.

**Cause.** The read runs on the `Io`'s thread pool, and the test pumped
and yielded **200,000 times** before giving up. When the read thread is
waiting on the disk, not the CPU, each yield returns at once. I measured
the full budget:

| Condition | 200,000 yields take |
|---|---|
| Idle M-series Mac | **20 ms** |
| Background priority | 125 ms |
| CPU saturated | 1.2–54 s (each yield hands the core away) |

So a runner whose disk took more than about 20–50 ms to answer failed
the test. Loading the CPU makes the test *more* tolerant, which is why
my reproduction attempts under load all passed: 0/80 runs of the test
binary and 0/15 warm `zig build test` runs at background priority.

**Reproduced directly:** with the read delayed by 100 ms, the old test
fails with exactly CI's error (`NeverLanded` at `LocalFs.zig:393`), and
the new one passes.

**Now:**
- **`LocalFs` "a read lands through pump"** pumps until the read lands
or 10 s pass on `std.Io.Clock.boot`, and stops the moment it lands, so
it's no slower when things are fast. It also keeps the read's error. The
old sink dropped it, so a read that *failed* also showed up as "never
landed". A future failure will now say which of the two it was.
- **The same count-of-yields wait** was in three `core/work.zig`
thread-mode tests (100,000 yields, about 10 ms) and in FileTable's
"rename onto a mount" test. They now wait on the clock the same way,
written inline at each site.

## SDK impact

- [x] None. Tests only.

## Verified

- [x] **macOS (local):** `zig build test` passes 71/71 steps and 491/492
tests (the one skip is the existing `lsp-uri` one). The file-table tests
pass 43/43 and the work tests 4/4.
- [x] **The read delayed 100 ms:** the old test fails with
`NeverLanded`; the new one passes. The delay was temporary and is not in
this diff.
- [ ] Linux, Windows: this PR's CI.

## Follow-ups

- #234's macOS failure was this flake. Re-running its failed job, or
merging this first, should turn it green.
- `core/FileTable.zig` on `main` already fails `zig fmt --check`. I left
it alone to keep this diff to the tests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…d, for pixi's dropper magnifier

Fizzy's overlay of the OS's Liquid Glass (macOS 26, floats as windows, native glass on) showed
only a view drag's glass. Pixi's dropper magnifier wants the same glass as the drop zones, so the
app now publishes each frame whether the OS draws glass declared outside a drag
(`core.native_glass.publishOffered` / `offered`). A plugin that sees it declares its glass with
`native_glass.add`, and marks what goes over it with `core.screens.markCarried`. The overlay
already stays while any glass is declared and takes carried layers over its glass, so it shows
them as it shows the drag's drops and their icons. The app's windows draw neither. Off macOS 26
nothing is offered, and plugins draw the app's glass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Euk6iCavQdW7MG5FN2vvFw
@foxnne foxnne changed the title sdk 0.2.18: the one-slider glass reaches plugins that build core in (for pixi's dropper magnifier) sdk 0.2.18: a plugin's glass is the OS's outside a drag (native_glass.offered), for pixi's dropper magnifier Oct 8, 2026
…om, refracting hard

The dropper's orb in the drop zones' frosted glass, with the zoom laid over it, showed only a rim
of glass: flat on the web, and with nothing refracting under the native glass. The user wants it
the other way: no frost and a lot of refraction, a liquid orb over the zoom. So the glass goes
over the picture again.
- In the app's glass that is `drawPicture`, a lens over the plugin's own picture, its middle
  exact, its rim bending it. It is restored from b66d241.
- Natively the plugin declares a clear piece (`frost = 0`) over a zoom it draws in the window,
  and the OS's lens refracts the window beneath.

`pictureMargin` now reckons with a shape's lens past 1, which the orb uses to bend harder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Euk6iCavQdW7MG5FN2vvFw
@foxnne foxnne changed the title sdk 0.2.18: a plugin's glass is the OS's outside a drag (native_glass.offered), for pixi's dropper magnifier sdk 0.2.18: a plugin's glass over its own picture and as the OS's outside a drag, for pixi's dropper orb Oct 8, 2026
claude added 2 commits October 8, 2026 15:26
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Euk6iCavQdW7MG5FN2vvFw
CONTRIBUTING.md (merged with main) has a feature PR leave `sdk_version` alone: only an
`sdk: release 0.2.N` PR bumps it. This PR's core changes reach pixi at that release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Euk6iCavQdW7MG5FN2vvFw
@foxnne foxnne changed the title sdk 0.2.18: a plugin's glass over its own picture and as the OS's outside a drag, for pixi's dropper orb core: a plugin's glass over its own picture, native outside a drag Oct 8, 2026
foxnne added a commit that referenced this pull request Oct 8, 2026
## What changes

**Publishing a new SDK release now asks each store plugin to repin
itself.** Until now, five plugin repos were repinned by hand after every
SDK release.

After `sdk-tag.yml` publishes a new `sdk-v*` release, a new step sends
`fizzy-sdk-release` (with the version) to every `fizzyedit` plugin in
the store registry. It finds them through `fizzyedit/plugins`'
`registry/*.json` homepages, so a new plugin needs no edit here. Today
that's atlas, drive, ghostty, pixi and zig.

Each plugin's `sdk-repin.yml` then runs `plugin-build-action`'s
`repin.yml`, which builds the plugin against the new SDK and opens a PR
**only when the plugin needs a release**: its fingerprint moved, or it
no longer builds (as a draft). Nothing tags a plugin.
`CONTRIBUTING.md`'s release-train section now says what follows a
release.

**The pieces:**
- fizzyedit/plugin-build-action#1: `repin.yml` + `repin_zon.py`, to be
tagged `v6`
- fizzyedit/pixi#4, fizzyedit/atlas#2, fizzyedit/zig#2,
fizzyedit/ghostty#1, fizzyedit/drive#1: each plugin's `sdk-repin.yml`
- this PR: the trigger

## Setup (yours)

1. Merge fizzyedit/plugin-build-action#1, then tag `v6` on its merge
commit.
2. Merge the five plugin PRs, and in each plugin repo allow Actions to
open PRs:
   ```sh
for r in pixi atlas zig ghostty drive; do gh api -X PUT
repos/fizzyedit/$r/actions/permissions/workflow -f
default_workflow_permissions=read -F
can_approve_pull_request_reviews=true; done
   ```
3. Create a fine-grained token: owner `fizzyedit`, those five repos (or
all), **Contents: read and write**. `repository_dispatch` needs that.
Store it as this repo's `PLUGIN_DISPATCH_TOKEN`:
   ```sh
   gh secret set PLUGIN_DISPATCH_TOKEN --repo fizzyedit/fizzy
   ```
4. Merge this.

Without the token the step warns and the SDK release is otherwise
unaffected, so the order doesn't matter for safety.

## SDK impact

- [x] None. Workflow and docs only; no `sdk_version` change, so merging
publishes nothing.

## Verified

- [x] The step, extracted from the YAML, run with `gh` stubbed for the
dispatch calls only. The registry reads were real.
- It found atlas, drive, ghostty, pixi and zig, and asked each one to
repin.
  - With no token it emits one warning and exits 0.
  - With an unreadable registry it emits one warning and exits 0.
- [x] `sdk-tag.yml` parses. The step runs only when the tag step
publishes (`steps.tag.outputs.publish`), so a push that leaves the
version alone dispatches nothing.
- [ ] Live: the next SDK release (#228's 0.2.18, if it merges first) is
the end-to-end test. Before then, any plugin can be checked by hand with
`gh workflow run sdk-repin.yml --repo fizzyedit/atlas`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
claude added 2 commits October 8, 2026 15:47
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Euk6iCavQdW7MG5FN2vvFw
The user wants this PR to carry the release, so the orb can be tried on main as soon as it
merges: `sdk_version` 0.2.17 → 0.2.18 again. It ships `LiquidField.drawPicture`,
`native_glass.offered` and the unreleased core changes since `sdk-v0.2.17` (#223, #224, #227) to
plugins that build `core` in. The fingerprint has not moved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Euk6iCavQdW7MG5FN2vvFw
@foxnne foxnne changed the title core: a plugin's glass over its own picture, native outside a drag sdk: release 0.2.18, a plugin's glass over its picture and native Oct 8, 2026
@foxnne
foxnne marked this pull request as ready for review October 8, 2026 15:56
@foxnne
foxnne merged commit ac8d58d into main Oct 8, 2026
11 checks passed
@foxnne
foxnne deleted the ccr-7f00e3d0-sjpshu branch October 8, 2026 16:01
foxnne added a commit that referenced this pull request Oct 8, 2026
)

Part of #236 (`docs/WINDOWS_LINUX_GLASS_PLAN.md`, step 0; no plan issue)

## What changes

On Linux (Vulkan) and Windows (D3D12) the in-window glass — dialogs,
menus, a drag's drops — now draws Apple's lens and follows the one
window-opacity slider (`glass_look`), as it already does on macOS. The
SPIR-V and DXIL embedded in `LiquidField` were last compiled in #206;
the HLSL changed in #227, so those two platforms kept drawing the
earlier glass whatever `publishLook` said.

- **The HLSL needed nothing.** Apart from each language's declarations
it is `liquid_glass.glsl` and `liquid_glass.metal` line for line, with
three deliberate, documented differences (the loop form, samples at
level 0, the dither taking `uv`). `LiquidField.sample` agrees with them
on the field.
- **Compiled with the commands at the top of the HLSL**, by
SDL_shadercross with the DXC it vendors
(libsdl-org/DirectXShaderCompiler at 2c84a1c5) — the toolchain #206
used: it compiles #206's HLSL to #206's SPIR-V and DXIL byte for byte.
The DXIL is signed (validator 1.9, as before) and passes `dxv`; the
SPIR-V passes `spirv-val`; the interface is unchanged (two samplers, one
uniform buffer, colour at location 0, uv at 1). That DXC wants clang on
Linux: built with GCC 13 it corrupts its heap compiling DXIL.
- `publishLook`'s comment says every form of the program draws the lens
now, and that the web publishes none (`Editor.zig` passes null on wasm).
- Step 0 of `docs/WINDOWS_LINUX_GLASS_PLAN.md` and the "still to do" in
`docs/NATIVE_WINDOWS_PLAN.md`'s materials library are marked done.

## SDK impact

- [ ] None
- [x] Core-only or additive: reaches plugins at the next SDK release —
the programs are embedded in `core`. 0.2.18 (#228,
`LiquidField.drawPicture` for pixi's dropper magnifier) shipped without
them, so the magnifier's lens shows on Vulkan/D3D12 from the next
release.
- [ ] Fingerprint moved: recorded in `sdk/src/version.zig`,
`sdk_version` untouched, PR labelled `sdk`
- [ ] SDK release: bumps `sdk_version`, lists the `sdk` PRs since the
last `sdk-v*` tag

## Verified

Not yet seen in the app: the cloud session this was built in could not
build fizzy (its network policy denies gitlab.freedesktop.org and
sndio.org, which sdl_zig fetches from). What was checked instead (and CI
on fb422e9 builds the app and passes its tests on macOS, Windows and
Linux, the headless integration tests on Linux, and the Windows
cross-build of fizzy's backend — that shows the new programs embed and
link, not how they draw):

- [ ] macOS: unchanged (Metal source untouched).
- [ ] Windows: `core`, with `LiquidField` and the new DXIL embedded,
compiles for x86_64-windows-gnu; the DXIL validates (`dxv`). **Not run
on D3D12** — wants a Windows machine (WARP is enough).
- [ ] Linux: the new SPIR-V drawn through SDL_GPU on lavapipe, as
`GpuRenderer` draws a program (frost at sampler 0, sharp at 1, the punch
and add passes), with `pack` + `applyLook` uniforms and the look from
`glass_look.inApp` at window opacity 0, 0.35, 0.7, 1 — a dialog
(`forText`) and three drops beside a carried card (`forDrops`), over an
opaque and a translucent window. Within 1/255 of `liquid_glass.glsl`
(built with glslang) at every pixel of every case; with no look
published, identical to the old SPIR-V; with one published, the old
SPIR-V was off by up to 204/255. `core` compiles and its check runs on
x86_64-linux. **Not seen in the app.**
- [ ] Web: unchanged (GLSL untouched; the web publishes no look).

## Follow-ups

- See it in the app on Linux and Windows (a dialog, and a drag's drops,
at a few window opacities).
- The next SDK release carries these to plugins that build `core` in.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01Vci2bBhv2EH5QxygzWxmx8

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants