Repository navigation
core: glass that merges with its place's edge, and stays inside it - #583
Merged
Merged
Conversation
foxnne
force-pushed
the
core/glass-edge
branch
3 times, most recently
from
October 18, 2026 20:44
1ed44f5 to
1afd3ae
Compare
`LiquidField.edge`: a place's outline (rect and corner radii). Its outside is one more shape the field's shapes run into, so a shape near the outline joins the edge by a neck, metaball-like, and the outline cuts the glass's coverage, so none of it crosses. The rim and bend come from the joined shape, so there is no rim along the cut. The edge takes the program's last shape slot, flagged 2, so the uniforms keep their layout. `glassBubbles` takes it as `.edge`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
foxnne
force-pushed
the
core/glass-edge
branch
from
October 18, 2026 21:04
1afd3ae to
8844748
Compare
foxnne
force-pushed
the
core/glass-edge
branch
from
October 18, 2026 21:35
902883b to
d0703ad
Compare
2 of 8 tasks
foxnne
added a commit
that referenced
this pull request
Oct 19, 2026
Fixes the flaky step check in the integration tour test ("Integration
tests (Linux)" on #583, 2026-10-18: `.added` where
`.joined` was expected).
## What changes
Typing in a document with unsaved changes stays one undo step, however
long you type. Before, the crash checkpoint split it every few seconds.
**The cause wasn't a join window.** The text plugin joins keystrokes by
run of operation (VSCode's rule), with no timer. What cut the run was
the crash checkpoint (`src/editor/Checkpoint.zig`). It runs on the wall
clock, at least 3 s after the last checkpoint and once there has been
input, and captures every dirty document through
`KeptDocuments.capture`. For the unsaved bytes, that calls
`documentBytes`, which goes `documentSnapshot` → `Document.savedBytes`,
and `savedBytes` called `history.closeGroup()` as though the save had
happened. On a slow runner, a checkpoint landed between the test's two
keystrokes. Reproduced locally with a 4 s sleep between them (gives the
CI failure exactly); a 1.5 s sleep doesn't, because it stays inside the
checkpoint's spacing.
**The fix:** `savedBytes` still remembers which edit the bytes stand
for, but no longer closes the group. `written` (the `documentWritten`
hook, which only a real save reports: `DocumentIo` and the web download)
makes the undo stop, while the written state is still the top step. The
synchronous `save` path is unchanged.
One behavior moves: a keystroke typed while a save's write is in flight
(milliseconds, off-thread) now joins the step the save captured. The
document stays dirty, which is correct because that step is newer than
the file, but undo goes past the saved state instead of stopping on it.
Before, the snapshot closed the group up front.
**The test** doesn't touch the clock. It takes a checkpoint's capture
itself (`KeptDocuments.capture`) between "a" and "b" and still expects
`.joined`, so it covers the bug however long a frame takes. A new check
covers the save side: type, save through the host's path
(`documentBytes` + `documentWritten`), type, undo. That should give back
the saved text, clean. Each check fails when its half of the fix is
removed (verified by reverting `savedBytes`, and separately by dropping
the `closeGroup` in `written`).
## SDK impact
- [x] 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
## Verified
- [x] macOS: `zig build test-integration` (the tour test with the new
checks; it fails with either half of the fix reverted), plus `zig
build`, `test`, `check-web`, `test-sdk-version`, `scripts/check-fmt.sh`
- [ ] Windows:
- [ ] Linux: CI
- [ ] Web: `check-web` builds; not run
## Follow-ups
The root of this is the host using the save's snapshot for things that
aren't saves: the crash checkpoint, a restart or plugin reload
(`KeptDocuments`), and Tracks' share export. This PR fixes the undo
split inside the text plugin. Two problems stay, and want a host-side
seam (bytes as a save would write them, without a save's bookkeeping):
- With format-on-save on (off by default), a checkpoint runs the
formatter on a dirty document while it is being edited
(`documentSnapshot` formats before taking the bytes).
- A checkpoint taken while a save is in flight overwrites
`serialized_op_id`. If an edit came between the two, the save lands and
marks the document clean at an edit newer than what was written.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
foxnne
force-pushed
the
core/glass-edge
branch
from
October 19, 2026 14:07
d055c03 to
a55d15c
Compare
This was referenced Oct 19, 2026
foxnne
force-pushed
the
core/glass-edge
branch
from
October 19, 2026 15:00
a55d15c to
e1a838a
Compare
…rom the top right `LiquidField.Edge.cut` cuts glass by its place's outline with a bevel and lens band of its own along the cut, rather than joining the place's outside: a piece of glass laid in a corner, bending the border and ring it lies along. `light_across` turns a drop's rim light a quarter, for glass whose edges that show face across the usual light (a place's top-right or bottom-right corner). Both reach `core.dialogs.glassBubbles` as options.
foxnne
force-pushed
the
core/glass-edge
branch
2 times, most recently
from
October 19, 2026 15:03
e1a838a to
8dcf15b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of fizzyedit/plans#29 (the liquid edge, step 2 in the comment that revised it).
What changes
Glass can belong to a place and merge with that place's edge. This is the primitive behind controls that come out of a viewport's edge, metaball-like, without crossing it.
LiquidField.edge: a place's outline, its rect and corner radii (rounded or square). The outside of the place is one more shape in the field. A shape near the outline runs into it through the field's smooth minimum, so it joins the edge by a neck. The outline then cuts the glass's coverage, so none of it crosses.EDGE_GAP), so nothing shows along the edge, only the necks where shapes come near it.LiquidFieldnever set it. A field with an edge holds one shape fewer.glassBubbles(..., .{ .edge = ... })passes it on. Without the glass program, the bubbles are cut to the edge's rect.LiquidField.sample, the CPU mirror, does the same, line for line with the HLSL.The compiled forms (SPIR-V, DXIL, Metal, GLSL) come from CI's
Shadersjob and are committed in a second commit here.SDK impact
sdk/src/version.zig,sdk_versionuntouched, PR labelledsdksdk_version, lists thesdkPRs since the lastsdk-v*tagVerified
zig build,zig build check-web,zig build test-sdk-versionall pass.zig build test: 109/109 steps.zig build test-integration: 78/78 steps, 609/609 tests, including a new test againstLiquidField.sample: a drop near the edge joins it by a neck; there's no glass along the edge away from it; a drop pushed past the edge is cut there, round a curved corner too; and a field with an edge holds one shape fewer.check-webonlyFollow-ups
🤖 Generated with Claude Code