Repository navigation
core: tabs show the hand, and a tapped item is left unlit - #563
Merged
Merged
Conversation
foxnne
marked this pull request as ready for review
October 18, 2026 16:58
foxnne
enabled auto-merge (squash)
October 18, 2026 17:03
foxnne
force-pushed
the
core/pointer-seam
branch
from
October 18, 2026 17:16
5fecb59 to
9a92429
Compare
One answer per frame to "what kind of pointer is this, and does a resize handle claim the cursor here", from dvui (foxnne/dvui-dev fizzy-sdk-0.2.30-6): - `dvui.pointerKind()` (`.touch` or `.mouse`) is the window's, set as the backend adds events, so the app and every plugin dylib or wasm side module read the same answer. After a touch with no finger down, dvui puts the frame's `.position` event off every window: a lifted finger hovers nothing. - `dvui.cursorSetPriority`: the highest asked in a frame wins. Splits and a float's bottom-right corner ask at `.resize`, the view drag at `.drag`. Presses are routed as before. Its first users: panel tabs, rail icons (`core.widgets.Tabs`) and document tabs show the hand, held too (`Tabs.handCursor`); a split's arrow still wins beside its sash. The native backend gives only fingers on the screen a touch button, one per finger (`backend/src/touch_slots.zig`): a macOS trackpad's fingers, a pen's and SDL's mouse touches no longer reach dvui as `touch0` presses, and fingers the window never hears lift (focus lost, background, close) are released. Fixes #547 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
foxnne
force-pushed
the
core/pointer-seam
branch
from
October 18, 2026 17:16
9a92429 to
4c8af49
Compare
This was referenced Oct 18, 2026
foxnne
added a commit
that referenced
this pull request
Oct 18, 2026
Part of fizzyedit/plans#27 (option A, the corner). ## What changes A report from the phone web build: a focused chip in a place's top-right corner sat under the place's corner button. The draw-order half was #540. This is the trigger half: the button came up whenever the pointer was within 64pt of the corner. On touch the last touch *is* the pointer, so tapping a control in that corner put the button on top of it. - **A filled place always shows its corner:** a piece of glass filling the card's top-right corner (option A in the prototypes). Its top and right edges are the card's, its outer corner is the card's own curve, and its inner corner is rounded. It carries the button's grid as a small glyph. Its frost is read once (`witness`), since what is under it is the card's own padding. - A glass shape's corner is held to half its side, so the piece is at least twice the card's radius wide. That way its outer curve is always the card's, at any corner roundness. - **Only the corner brings the button up, and the corner turns into it.** - The piece of glass becomes the button: one glass id, its rect and corners eased from the corner's to the button's circle by the button's fade, and back as it goes. - With a mouse: the pointer on the corner, then anywhere on the button while it is up. It stays down under a modal, keeping #535's rule. - With a finger: a tap on the corner brings the button up and goes no further, so the place never sees it. A second tap opens the picker, and holding the button lifts the view as before. It goes after 3s (a `dvui.timer` wakes the frame), or at the next touch anywhere else. - The finger's target is 44pt, centred on the card's outer corner, so half of it lies in the gutter. - **Any material, not only glass.** The piece and the morph draw through `core.dialogs.glassBubbles`, which now takes per-corner `radii` (each held to half the shorter side; the frosted-pane and plain-fill fallbacks take the same corners). Where there is no glass program or no blur, it is frosted, a transparent tint or an opaque fill, in the same shape, as plans#27's material says once that lands. - **Empty places are unchanged:** the hatch and the button, always. Prototypes: https://claude.ai/artifact/MotGphK5UyeH9sQ6NHeYZk (option A). The piece's inner corner is rounded to half its side (the most a shape's corner can be), not a full quarter-circle, so it reads as the corner filled with glass rather than a quarter disc. ## 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 26: - `scripts/check-fmt.sh`, `zig build` and `zig build check-web` all pass. - `zig build test`: 105/105 steps. - `zig build test-integration`: 54/54 steps, 594/594 tests. - On screen: a sandbox fizzy (`--profile`), captured at rest. The corner piece shows in the explorer, the main view and the panel, its outer curve on each card's, with the glyph. - Not seen: the morph into the button on hover, a tap, the 3s hide, or the non-glass materials (those need plans#27's material, #549). The hover and tap need input I didn't drive, since no tape here hovers a corner. - [ ] Windows: - [ ] Linux: - [ ] Web: `check-web` only. **The phone flow (tap, tap, hide) is what this is for, and needs seeing on a phone.** ## Follow-ups - Once #563 merges, the corner reads `dvui.pointerKind() == .touch` in place of its own `_chooser_touch` flag, in a small PR of its own. - Cost not measured: every filled place now draws its corner glass each frame it draws, with its frost read once (`witness`). That is one small pane draw per place. - The hint beside the button on a first tap ("Tap to arrange · hold to move", in the prototypes) is not drawn here. - Option C, the button docked in a tab strip. - A demo tape that hovers and taps the corner, so this is covered by a test. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 18, 2026
foxnne
added a commit
that referenced
this pull request
Oct 18, 2026
Part of fizzyedit/plans#5 (`plans/ZIG_0_17_PLAN.md`, step 2): fizzy, its backend and its bundled plugins move to Zig 0.17. Every piece was reviewed as its own PR into `zig/0.17`, and this PR lands that branch. `main` is already merged in (through #555), so it carries no conflicts. ## What changes **The move to 0.17** (`minimum_zig_version = "0.17.0"` everywhere), as reviewed in: - #437: the switch, scaffolded with marked stand-ins - #438: the build's custom steps become helper programs - #448: release packaging on 0.17, with Velopack 1.2.161 (+ #452's zon arenas) - #488: settings and command schemas read 0.17's `@typeInfo`, with a test that the SDK fingerprint hashes the same facts as on 0.16 - #489: per-pointer capture through `captureMouseGet` - #494: the Windows traps in `docs/PITFALLS.md` - #496: `blitData` without an `extern struct` `@bitCast` - #498: `fizzy.plugin.installBeside`, for a plugin's helper program - #505: the 0.16 inflate workaround goes; the docs say 0.17 - #561: review fixes. A settings payload with pointers is a compile error, and build reads go through `b.root`. - #573: the plugin install helper compiles once, in Debug - the catch-ups with `main` (#486, #503, #558, #574, and the last merge here), each with `scripts/zig-0.17/rewrite.sh` re-run. That script is deleted in the last commit. Most of the diff is mechanical: `zig fmt`'s upgrades (`@backingInt`, `std.lang`, …) and one-answer renames. The hand migrations are the build (configure/make split, no custom steps), the zon arenas, `@typeInfo`, translate-c for `@cImport`, and the `@bitCast` audit. A high-effort review of the whole `main`…`zig/0.17` diff found five things; the three correctness ones are fixed in #561, and one efficiency one in #573. **Also on the branch, merged there by the maintainer:** the windowing work. - #480–#483: plain dvui apps on macOS - #492, #501, #504, #510: OS windows for floating windows, full screen, pointer routing - #546: window materials **Forks:** dvui-dev at its `zig-0.17` head `1b29a16`, which carries fizzy-dev's patches on upstream's 0.17 `main`, including #540, #544 and #563's dvui commits. Also assetpack, md4zig, sdl_zig and zig-objc on their `zig-0.17` branches, and velopack-zig `3d553b7` (tagged `fizzy-zig0.17`). ## Measured macOS arm64, under load from other sessions, each step alternated between the two. 0.16 is `main` #509; 0.17 is `zig/0.17` with #561. | | Zig 0.16 | Zig 0.17 | |---|---|---| | App, cold Debug build | 94.4 s | 78.6 s | | App, warm no-op rebuild | 0.7 s | 0.4 s | | `test-integration` (compile + run) | 108.9 s | 90.4 s | | App, ReleaseFast build | 142.8 s | 131.5 s | | Image plugin, cold standalone build | 11.6 s | 14.0 s (with #573) | | Startup, Debug (median of 5) | 565 ms | 466 ms | | Startup, ReleaseFast (median of 5) | 175 ms | 177 ms | | Text, ReleaseFast, µs/frame: idle / mid / scroll / typing | 305 / 424 / 435 / 403 | 240 / 306 / 286 / 290 | | Markdown, ReleaseFast, 4 docs, median of 5, µs/frame: idle top / mid / scroll / resize | 1177 / 1735 / 2104 / 1319 | 1270 / 1699 / 1833 / 1192 | The one slowdown is markdown idle at the top of a document, +8%. The rest of the plugin build's gap is dvui's own translate-c on 0.17. ## The plan's gate - **ZLS:** no 0.17 release yet (latest 0.16.0). zigtools/zls#3270 is on ZLS's master. Completions across `fizzy_sdk` from a plugin are not checked. - **Minimum OS:** 0.17 needs Darwin 15+ (OS X 10.11); fizzy's macOS minimum is 11.0, so no change. Windows 10+ and Linux 5.10+ are not stated by fizzy. - **Debug leak reports:** still print (`DebugAllocator`, deprecated, unchanged). The move to `SafeAllocator` is a follow-up with its own Debug frame-time check. - **Velopack:** packaging proven by a test release on macOS (signed and notarized), Windows and Linux. An update in place was not tested. - **Every target builds:** in CI. Windows and Linux were not run by hand on the VMs. ## SDK impact - [x] Fingerprint moved (`0x5f9c818a6972efd4`, recorded in `sdk/src/version.zig`); `sdk_version` untouched. `sdk: release 0.2.30` follows this at once. Plugins need Zig 0.17 to build against it: there's no overlap window. - Plugin authors see `minimum_zig_version = "0.17.0"` and `fizzy.plugin.installBeside`. A settings payload holding pointers other than a string is now a compile error. `docs/PLUGINS.md` says 0.17.0. ## Right after this merges 1. fizzyedit/example-app#8 and fizzyedit/example-plugin#13 merge. Then a one-line PR points `scripts/check-examples.sh` back at `main` (it pins the examples' `zig-0.17` branches until then, so `main`'s CI is never red). 2. `sdk: release 0.2.30`. 3. The store plugins' 0.17 PRs repin and release: fizzyedit/pixi#51, zig#15, atlas#16, drive#13, ghostty#14, agent#23, chat#16. ## Verified - [x] macOS (arm64, Zig 0.17.0), on this tree: - `scripts/check-fmt.sh` - `zig build`: 71/71 - `zig build test`: 109/109 steps, 637/638 (1 skipped) - `zig build check-tests-reached`: 998 tests in 122 files - `zig build check-web`: 42/42 - `zig build test-sdk-version`: 35/35 - `zig build test-integration`: 78/78 steps, 608/608 - [x] All seven store plugins built against `zig/0.17`'s `sdk/` and loaded together in a 0.17 fizzy (Debug, sandbox profile). - [ ] Windows, Linux, the example repos: CI. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
foxnne
added a commit
that referenced
this pull request
Oct 18, 2026
## What changes `sdk_version` goes from 0.2.29 to 0.2.30. Merging this tags `sdk-v0.2.30` and publishes its tarball. **Why now:** this is the first SDK on Zig 0.17 (#575, `plans/ZIG_0_17_PLAN.md` step 2), and the plan has the release follow the switch at once. A 0.17 fizzy refuses every plugin built against 0.2.29, and fizzyed.it/testapp is built from `main`, so the store plugins can't trail by days. Their 0.17 PRs are ready and only need this tarball to repin. ## 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` - [x] SDK release: bumps `sdk_version`, lists the `sdk` PRs since the last `sdk-v*` tag **`sdk` PRs since `sdk-v0.2.29`:** - **#575: Zig 0.17.** Plugins need `minimum_zig_version = "0.17.0"` and Zig 0.17 to build; there's no overlap window with 0.16. Also new: - `fizzy.plugin.installBeside`, for a helper program a plugin ships. - A settings payload holding pointers other than a string is a compile error. - The dev-install helper compiles once, in Debug. - **#536:** a plugin can replace a command it names, and gets it back on unload. - **#538:** a command may answer in a later frame. - **#540, #544:** dvui's front-to-back blocks (render order of floats, glass and focus rings). - **#563:** `dvui.pointerKind()` and `cursorSetPriority`; tabs show the hand, and a tapped item is left unlit. The fingerprint is `0x5f9c818a6972efd4`. ## Verified - [x] macOS (arm64, Zig 0.17.0): - On this head, `zig build test-sdk-version` passes, and `scripts/pack-sdk.sh` packs `fizzy-sdk-v0.2.30.tar.gz`. - All seven store plugins build against this `sdk/` by path with no further changes: pixi, zig, atlas, drive, ghostty, agent and chat (their 0.17 PRs below). All seven loaded together in a 0.17 fizzy earlier on the branch. - [ ] Windows, Linux: CI. ## Follow-ups - The repin automation opens `sdk: repin to fizzy SDK 0.2.30` PRs. The store plugins' own 0.17 PRs carry the port and only need the pin moved: - fizzyedit/pixi#51, fizzyedit/zig#15, fizzyedit/atlas#16 - fizzyedit/drive#13, fizzyedit/ghostty#14, fizzyedit/agent#23, fizzyedit/chat#16 I'll repin those branches to `sdk-v0.2.30` and close the bot's duplicates. - fizzyedit/example-plugin#13 repins to 0.2.30. Then fizzyedit/example-app#8 pins it, `sdk-v0.2.30` and fizzy's switch commit. Then `scripts/check-examples.sh` points back at `main`. - fizzyedit/plugin-build-action's default `zig-version` is still 0.16.0; every plugin passes its own. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
foxnne
added a commit
that referenced
this pull request
Oct 18, 2026
Part of fizzyedit/plans#27 (the corner). Follows #555. ## What changes The corner #555 put on every filled place looked wrong on `main` (seen by the user): "doesn't look like a bubble filling the top right corner, it's got sharp edges, doesn't cover the corner area, and has a weird single corner cut". **The cause:** `cornerButton` runs inside the place's *content* clip, the card inset by its padding (8 pt). The resting piece and its morph into the button were drawn under that clip, so their top and right 8 pt were cut off. The piece sat inset from the card's edge, and its outer curve, the card's own, never showed. The ring beside it already drew under the card's rect (`clipSet(rs.r)`) for the same reason. #555's screenshot showed the cut, and it was misread as the shape. **The corner is now what the user asked for after seeing the options:** a small round bubble that "moves behind/under the region's rounded corner, peeking out". - **The bubble:** 16 pt round, its centre halfway round the card's top-right curve, so half lies over the card and half peeks past the curve. - **Square cards:** with no curve, its centre is the corner point itself. - **Clipping:** it is drawn, and morphed into the button, under the card's rect outset by half the bubble, not the content clip. It is kept whole inside the window, for a card that runs to the window's edge. - **Hover:** the pointer target is the bubble plus 8 pt round it (`CornerPiece.hit`). The finger's target is unchanged: 44 pt, centred on the card's outer corner. - **Glyph:** centred in the bubble, smaller. - **Why not a flush piece:** a shape with the card's top and right edges can't be small. Its outer corner has to match the card's radius (24 pt), and a glass corner is held to half its side, so it would be at least 48 pt across. Prototype by the session working on the history transport (it measured the clip), taken over, checked and finished here. ## 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: - **Gates:** `scripts/check-fmt.sh`, `zig build`, `zig build check-web` all pass. `zig build test`: 107/107 steps. `zig build test-integration`: 54/54 steps, 605/605 tests. - **On screen** (sandbox fizzy, `--profile`, captured): - default rounding: the bubble on the main view's and the panel's curve, peeking out; - `corner_roundness = 0`: the bubble whole, centred on the square corner at the window's edge; - hovered, by the prototype's author: the bubble turning into the button. - **Explorer:** the explorer has no card of its own, so its bubble sits on the place's corner over the window's chrome. It marks the place, but reads more detached than on a card. - **Not seen:** a tap on a touchscreen. - **Unchanged by this PR, not re-checked:** the empty-place path (hatch and button), which this doesn't touch (`resting` is false there); and the 44 pt touch target. - [ ] Windows: - [ ] Linux: - [ ] Web: `check-web` only ## Follow-ups - The corner reads `dvui.pointerKind()` once #563 merges (it already has a follow-up note on #555). - Whether the explorer, which has no card, should have a corner at all, or one placed differently. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
3 of 5 tasks
foxnne
added a commit
that referenced
this pull request
Oct 19, 2026
Fixes #568 ## What changes On the web, an Apple Pencil is now the mouse, not a finger. iPad Safari sends a pencil as a `TouchEvent` whose touch has `touchType === "stylus"`, and `web/web.js` turned every touch into a dvui touch button, so `dvui.pointerKind()` said `.touch` while drawing with a pencil: nothing stayed hovered after a lift, and canvases panned as they do for a finger. Now a stylus touch goes in as mouse motion to its position (in drawing-buffer pixels, as `mousemove` does) followed by a left-button press or release, with the event's modifiers. It takes no touch slot. dvui then reports `.mouse`, the same answer native gives once SDL's pen touches are excluded (#563, `backend/src/touch_slots.zig`). Fingers, and touches with no `touchType` (browsers other than Safari), are unchanged. `touchcancel` now ends a touch the way `touchend` does. It had no handler, so a touch the system took (a gesture, an alert) left its button held. A pencil's held mouse button would be worse, because it keeps dragging until the next press. The change is in fizzy's own web backend, not dvui-dev: fizzy builds dvui in `custom` mode and links `web/web.js` + `src/backend/WebBackend.zig` (`docs/DEPENDENCIES.md`), so no dvui commit and no repin are needed. **Considered and dropped:** moving to Pointer Events and `pointerType` (`"pen"`/`"touch"`/ `"mouse"`). That would also cover Android styluses and pencil hover, but it replaces all of the mouse and touch input paths (capture, the compatibility mouse events, the on-screen-keyboard `oskCheck` that iOS only allows inside a touch handler) for a pencil fix. Worth doing as its own change if Android stylus support is wanted. ## SDK impact - [x] None ## Verified - [x] A Node harness (not in the repo; fizzy has no JS test setup) loads `web/web.js`, runs `Dvui.run` with a stub canvas and wasm exports, and fires fake touch events at the handlers. A stylus start/move/end sends mouse motion at pixel coordinates, then a left press or release with the modifiers; a stylus takes no touch slot; a cancelled stylus releases the button. Finger and no-`touchType` touches still send touch press/motion/release at normalised coordinates; a cancelled finger releases its touch button. On `main`'s `web.js` the stylus cases fail (they send touch events). - [x] `zig build`, `zig build test`, `zig build test-integration`, `zig build check-web`, `zig build test-sdk-version`, `zig build check-tests-reached` on macOS, and `scripts/check-examples.sh` with `EXAMPLES_DIR` (example-app `zig-0.17`, example-plugin `main`: example-plugin has no `zig-0.17` branch any more, so the script's default clone fails on `main`). `scripts/check-fmt.sh` flags only `backend/src/platform/win32_titlebar.zig`, which is unformatted on `main` too (`main`'s Format job fails since #463); this PR touches no Zig. - [ ] Web, by hand: on an iPad with an Apple Pencil in Safari, open this branch's build (`zig build web`, `scripts/serve-web.sh`, the Mac's address on :8765). Tap a tab or tree row with the pencil and lift: it stays lit (it went dark before). In a pixi canvas, a pencil stroke draws rather than pans. A finger tap on a tab still leaves it unlit. - [ ] macOS / Windows / Linux: not affected (web only). ## Follow-ups - Pointer Events (`pointerType`) for Android styluses and pencil hover, if wanted. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.
Fixes #547. Serves #555 (plans#27), whose corner button needs to tell touch from mouse.
What changes
core.widgets.Tabs) and document tabs show the hand under a mouse.touch0presses at the finger's position on the pad. They are mouse input only, as they already were through SDL's mouse events.SDL_HINT_PEN_TOUCH_EVENTSis on by default, so every pen stroke reached dvui as bothtouch0and a left press, andpointerKindflipped with each stroke.For plugins:
dvui.pointerKind()(.touchor.mouse) anddvui.cursorSetPriority(cursor, .normal | .resize | .drag), both from dvui-dev. #555 should readdvui.pointerKind() == .touch.Design: the pointer kind and cursor priority seam
Two questions every hover look and cursor needs answered once a frame: is this pointer a finger or a mouse, and does a resize handle claim the cursor here.
Pointer kind: from the event source, or inferred by fizzy?
Windowsetspointer_kindas the backend adds events: a touch button (touch0..touch9, fromaddEventPointeroraddEventTouchMotion) is.touch; mouse motion, a mouse button or the wheel is.mouse. Read withdvui.pointerKind(). The window is the one every plugin dylib and wasm side module already draws into, so they all read the same answer, with no frame key and no module global. dvui also keeps which touch buttons are down: after a touch with none down, the frame's.positionevent goes off every window and to no widget. A lifted finger hovers nothing, so dvui's buttons, menu rows, tooltips andcore.widgets.hoveredall stop showing hover after a tap without a check of their own.The backend decides what a touch is. SDL reports a macOS trackpad's fingers as touches (
SDL_TOUCH_DEVICE_INDIRECT_*, at the pad's normalized point), and fizzy's backend passed them on astouch0presses at that point mapped into the window. Nothing in fizzy or the store plugins read them as anything else: every touch consumer (CanvasWidget,Tabs,ContextWidget,viz, pixi, atlas) reads touch buttons as fingers on the screen. So the backend gives onlySDL_TOUCH_DEVICE_DIRECTfingers a touch button, one per finger (touch_slots.zig), and the trackpad stays the mouse it already is.core.input, scanning each frame's events for touch buttons). This is what core: tabs and rail icons show a hover look #542 tried. State in a module is per image (each dylib and wasm side module has its own), a per-frame key needs a frame id that is unique on every backend, and a hover look in a dvui widget (a menu row) would still need dvui changed. Putting it onHostinstead would add an SDK seam for something dvui already sees.Cursor: priority in dvui, or ordering in fizzy?
dvui.cursorSetPriority(cursor, priority)(chosen). The highest asked in a frame wins, and between equals the first.cursorSetis.normal, as before. A resize handle asks at.resize(fizzy'sSplit, float edges; dvui'sPanedWidget,GridWidgetcolumns and floating window edges), and the carried view at.drag. A tab's.handcan't take a split's arrow, whichever is drawn first, and which widget takes a press doesn't change.For #555 (plans#27): the read is
dvui.pointerKind() == .touch. It replaces the corner's_chooser_touchbool. A finger that lifted leaves no.positionhit, so the corner's mouse-hover reveal won't fire after a tap.The pieces
fizzy-dev, tagfizzy-sdk-0.2.30-6,docs/DEPENDENCIES.mditems 11 to 13):e04bcccWindow: the pointer kind, and a lifted finger hovers nothing20e56f1cursorSet: a priority, so a resize handle's cursor wins40e664cFloatingWindowWidget: edges ask for their arrow at normal prioritybackend/src/touch_slots.zigis std-only and unit-tested.touch0, andFINGER_CANCELEDwas dropped.deviceOfturns away SDL's mouse and pen touch ids.releaseAllfrees every held slot. The backend sends their releases on focus loss,WILL_ENTER_BACKGROUNDand window close.FINGER_DOWN.core.widgets.Tabs.handCursor: the hand under the pointer, and while the tab is held.Split.graband the float's bottom-right corner ask at.resize. That corner takes its press before the float's children do. The float's edges stay at.normal, because the children inside the edge band take the press there first, and a.resizearrow would show over a press that goes to a child. dvui'sFloatingWindowWidgetis the same (dvui-dev40e664c).Layout.init's view-drag cursor asks at.drag.The cursor priority doesn't change routing. The split's band still sends a press to the tab: inside a split's reach, over the edge of the tab drawn before it, the split's arrow shows but a press goes to the tab, as before this PR (a test pins this). That mismatch existed before this PR. Changing it means changing routing, which #542 showed has costs, so it's a follow-up.
SDK impact
sdk/src/version.zig,sdk_versionuntouched, PR labelledsdksdk_version, lists thesdkPRs since the lastsdk-v*tagThe dvui pin moves from
fizzy-sdk-0.2.30-4tofizzy-sdk-0.2.30-6, becauseWindowgainedpointer_kind,touches_downandcursor_priority. The fingerprint is now0x35bac8377071cd23, on top of #538's. For plugin authors:dvui.pointerKind()anddvui.cursorSetPriorityare new.cursorSetbehaves as before.Verified
scripts/check-fmt.sh,zig build,zig build test(107/107 steps, 635 passed, 1 skipped),zig build test-integration(54/54 steps, 601/601),zig build check-web,zig build test-sdk-version,zig build check-tests-reached,scripts/check-examples.sh(all 8 ok).zig build test -Dbackend=testing, 268/268. New tests:core/widgets/Tabs.zig, dvui testing backend, underfizzy-sizing-tests):Splitset back to plaincursorSet, this one fails with "expected .arrow_w_e, found .hand".backend-touch-slots-tests):check-webonly. The phone tap that leaves no hover look needs seeing on a phone.Follow-ups
core/widgets/CanvasWidget.zig(last_input_was_touch) andcore/viz/viz.zig(touch_pointer) could readdvui.pointerKind()instead.app/store/PluginStore.zigsays "last cursorSet call wins". It is the first, so its.arrowoverride never takes effect. A comment-only fix would leave the code wrong, and the real fix (asking for the card's cursor before its text) belongs to the store, so it's left for that.🤖 Generated with Claude Code