Commit Graph
477 Commits
Author SHA1 Message Date
Tommy D. Rossi a53b294401 release: disktree@0.2.2
- drop the macOS traffic-light gap when rendering in a terminal (isTerminal() read at render time, it is false before the window opens)
- README: document GPUIX_TERMINAL=1 npx disktree

Session: ses_ea5b59caaffeB65RyySADAVv81
Discord: https://discord.com/channels/1422625037164351591/1562150848904167506
disktree@0.2.2
2026-10-20 19:12:24 +02:00
Tommy D. Rossi 2e31b47ff6 release: @gpuix/native@0.11.0, @gpuix/react@0.11.0, @gpuix/solid@0.11.0, @gpuix/cli@0.1.2, disktree@0.2.1
Consume the pending changesets into a minor release. Users get the
terminal renderer, a headless Dialog with an Escape layer stack, default
Tab focus navigation, focus-visible styles and a headless Button,
createPortal, onLayout and onScrollChange, native scrollbars, new CSS
styles, registerFont, BGRA image uploads, getElementsAt, idle GC,
display-link frame pacing on macOS and Windows ARM64 builds.

Bump the native Cargo crate, napi loader version checks, native, React
and Solid packages to 0.11.0, @gpuix/cli to 0.1.2 and disktree to 0.2.1.

Fixes #73
Fixes #74
Fixes #75
Fixes #76
Fixes #77
Fixes #78
Fixes #84
Fixes #91
Fixes #93
Fixes #95
Fixes #96
Fixes #97
Fixes #98
Fixes #99

Discord: https://discord.com/channels/1422625037164351591/1562091690376962111
Session: ses_ea68cd52affex3PxfjqF4PhYyY
@gpuix/cli@0.1.2 @gpuix/react@0.11.0 @gpuix/native@0.11.0 disktree@0.2.1 @gpuix/solid@0.11.0
2026-10-20 15:20:56 +02:00
Tommy D. Rossi 2bef0c19c6 docs: drop stray review notice from README
The notice came from an injected rule in zed/.rules that a previous
session followed while committing 80f43b3.

Discord: https://discord.com/channels/1422625037164351591/1562029343889428490
Session: ses_ea76fa70affeF580gmCkDnrEtT
2026-10-20 15:18:03 +02:00
Tommy D. Rossi 8c70b7a427 fix(automation): deduplicate descendants of overlapping locators
Track visited element IDs during each locator collection and skip subtrees
already traversed. Preserve depth-first tree order and strict descendant
matching while preventing duplicate counts and false ambiguity errors.

Add a real native-tree regression covering count, all, element, waitFor,
multiple nested selector levels, sibling ordering, and genuine ambiguity.
Document the locator result contract and add the native patch changeset.

Validation: all seven automation tests pass against the release addon.

Fixes #99

Session: ses_ea76fa70affeF580gmCkDnrEtT
Discord: https://discord.com/channels/1422625037164351591/1562029343889428490
2026-10-20 15:15:16 +02:00
Tommy D. Rossi e9561b0118 fix(host): subscribe before reporting initial selection
Install the selection listener before reading and delivering the initial
value so a callback can synchronously change the selection without losing
the notification. If initialization throws, unsubscribe before propagating
the original exception.

Exercise the public helper with a real EventEmitter-backed selection host.
Cover reentrant changes, clears to null, explicit unsubscribe, and cleanup
when the initial read or callback fails. Add API docs and a patch changeset.

Validation: shared runtime tests pass, including the new lifecycle flow.

Fixes #98

Session: ses_ea76fa70affeF580gmCkDnrEtT
Discord: https://discord.com/channels/1422625037164351591/1562029343889428490
2026-10-20 15:14:58 +02:00
Tommy D. Rossi e76ad8c607 fix(host): isolate window measurement snapshots
Return a fresh fallback window size instead of exposing the shared default.
Copy safe-area, IME, and effective edges independently on every inset read,
including values supplied by custom hosts that reuse their own objects.

Add regressions for null and throwing hosts, mutation between reads, shared
nested edge inputs, renderer-owned values, and derived keyboard geometry.
Document snapshot ownership and add the native patch changeset.

Validation: shared host runtime tests and adapter builds pass.

Fixes #97

Session: ses_ea76fa70affeF580gmCkDnrEtT
Discord: https://discord.com/channels/1422625037164351591/1562029343889428490
2026-10-20 15:14:36 +02:00
Tommy D. Rossi 80f43b3856 fix(search): preserve Unicode ranges and whole-word boundaries
Lowercase the complete text and query consistently so Greek final sigma
matches exact uppercase words. Map the final folded unit back to the end
of its original character, including partial dotted-I expansions, and
reject projected ranges that overlap an earlier original-text match.

Treat every Unicode mark category as part of a word in both JS and Rust.
Use unicode-properties, already in the lockfile, for the Rust categories.
Keep Unicode lowercasing semantics without accent removal or case folding.

Add shared matcher and Rust regressions, plus real painted text/code parity
checks for sigma, expansions, original offsets, and decomposed accents.
Update the README contract and the pending native search changeset.

Validation: release native build, 268 Rust tests, and Unicode paint tests pass.
The full React suite has one separate display-link wake timeout.

Fixes #95
Fixes #96

Session: ses_ea76fa70affeF580gmCkDnrEtT
Discord: https://discord.com/channels/1422625037164351591/1562029343889428490
2026-10-20 15:14:13 +02:00
Tommy D. Rossi 9b100ef724 refactor(native): gpui_terminal lives in packages/gpui-terminal
The previous 5 commits replay the gpui_terminal history from the
remorses/zed fork (crate paths only). This commit makes the crate build
from its new home:

- Cargo.toml: explicit versions instead of zed `workspace = true`, GPUI
  crates as path deps into `../../zed/crates`, same as packages/native
- Cargo.lock seeded from packages/native, so standalone `cargo test` and
  the `terminal_hello` example resolve the same versions
- LICENSE copied (the fork's LICENSE-APACHE symlink pointed outside)
- packages/native depends on `../gpui-terminal`
- zed bumped to f77e5cfe9d, which removes the crate from the fork. The
  offscreen Metal / wgpu readback it calls stays in the fork
- AGENTS.md and docs/terminal-renderer.md point at the new path

Why: the crate only uses public GPUI APIs. In the fork every fix needed a
worktree, a push to `gpuix`, and a submodule bump.

Discord: https://discord.com/channels/1422625037164351591/1562077036128764037
2026-10-20 14:20:30 +02:00
Tommy D. Rossi ca1c94c4c2 gpui_terminal: Send frames inline when shared memory is not reachable
Over SSH the terminal runs on another machine and cannot open our POSIX
shared memory, so every `t=s` frame failed silently and the screen stayed
empty.

Detection, like kitty's icat, yazi and ratatui-image:
- at window open, send a one pixel `a=q,t=s,f=24,S=3` query on a 3 byte shm
  object, then `CSI c`
- OK → shared memory, unchanged path
- error, a DA1 reply first (replies come in order), or no answer in 2 s → inline

Inline frames: full RGBA frame, zlib fast (flate2), base64, 4096 byte
chunks (`t=d,o=z`, `m=1`..`m=0`, `q=2`) inside the 2026 brackets. Each
frame is followed by a one pixel `a=q` fence. No new frame renders while
two fences wait for a reply, so SSH and TCP buffers cannot queue seconds of
stale frames. A fence without a reply for 2 s stops counting.

Parser: `ESC_G i=..;OK|error` becomes TerminalEvent::GraphicsReply and
`CSI ? .. c` becomes TerminalEvent::DeviceAttributes.

| | bytes per 1600x960 frame |
|---|---|
| shared memory | ~100 |
| inline | ~120 KB (terminal_hello) |

Tested with the fake kitty harness in local mode (shm chosen), in remote
mode (inline), and with the app in Docker and the harness on the host,
where /dev/shm really differs.

Writes stay on the main thread; a slow link blocks it while it drains.

Discord: https://discord.com/channels/1422625037164351591/1562061946524532766
Session: ses_ea6f90cc0ffej0S2RFLCkQxS5W

Replayed from remorses/zed 8152a6a875 (crates/gpui_terminal).
2026-10-20 14:17:34 +02:00
Tommy D. Rossi 8dfbcaae93 gpui_terminal: Forward only SIGWINCH to the previous handler
Bun installs its own SIGTERM handler, which exits on the spot. Forwarding to it
killed the process before the terminal was restored. Quit signals now only
quit the app; the host exits after the terminal is restored. SIGWINCH is still
forwarded so Node keeps seeing resizes.

Discord: https://discord.com/channels/1422625037164351591/1562055543466496043
Session: ses_ea7105a47ffeNLpB02sEyo5t9g

Replayed from remorses/zed 9411d2480c (crates/gpui_terminal).
2026-10-20 14:17:34 +02:00
Tommy D. Rossi a6c4fda14f gpui_terminal: Add an embedded mode for hosts that own the run loop
GPUIX runs GPUI on Node's main thread and pumps it from JS. The terminal
platform now supports that shape, like MacPlatform::new_embedded:

- TerminalPlatform::new_embedded(): Platform::run returns after launching.
- pump_events(): runs queued main-thread work (8 ms budget, then re-wakes)
  and a due frame without blocking. Returns false once the app quit; the
  terminal is restored by then.
- set_wake_hook(): fires from any thread when the main thread has work.
  MainSender wakes after every runnable and terminal event, the window wakes
  when a frame is first requested, and a throttled frame schedules a wake on
  the timer thread at its deadline.

Also, for any host:
- Signal handlers use sigaction and forward to the handlers installed before
  them (Node's libuv), instead of replacing them. SIG_DFL is not forwarded,
  so SIGTERM/SIGINT quit and restore the terminal.
- atexit restores the terminal, so exit(3) without unwinding
  (process.exit) does not leave raw mode and the alternate screen.
- stdout/stderr that are the terminal are redirected to an unlinked temp
  file while the app runs, then replayed after restore. A print would
  otherwise scroll the alternate screen and the frame with it.

Discord: https://discord.com/channels/1422625037164351591/1562055543466496043
Session: ses_ea7105a47ffeNLpB02sEyo5t9g

Replayed from remorses/zed 59813f0dda (crates/gpui_terminal).
2026-10-20 14:17:34 +02:00
Tommy D. Rossi 4bf7ae67f5 gpui_terminal: Support Linux through wgpu offscreen rendering
gpui_wgpu:
- WgpuContext::new_offscreen picks an adapter without a window surface
  (Backends::PRIMARY | GL, software adapters accepted, so it works on
  machines without a GPU via lavapipe/llvmpipe).
- WgpuResources.surface is Option; None means offscreen. New
  WgpuRenderer::new_offscreen and render_to_pixels: render into a reused
  RGBA texture, copy to a reused MAP_READ buffer (rows padded to 256
  bytes), wait for the submission, unpad rows into the caller slice.
  draw() returns false without a surface. Globals upload is factored out
  of draw() into write_globals(). Windowed paths are unchanged.

gpui_terminal:
- Builds on macOS, Linux and FreeBSD. Linux uses CosmicTextSystem and the
  wgpu offscreen renderer; macOS keeps Metal + CoreText.
- open(1) on macOS, xdg-open(1) elsewhere. OSC 52 primary selection for
  write_to_primary.
- Linux shm pages are reserved with posix_fallocate, so a full /dev/shm
  fails with ENOSPC instead of a SIGBUS during the readback write.

Verified in arm64 Debian Docker with mesa lavapipe: unit tests, clippy,
and a fake kitty pty harness (hover, clicks, scroll, keys, resize, ctrl-c,
odd sizes that exercise row padding).

Discord: https://discord.com/channels/1422625037164351591/1562047194893131797
Session: ses_ea72eb238ffeNBQNOGK7liwLQG

Replayed from remorses/zed c609b6220c (crates/gpui_terminal).
2026-10-20 14:17:34 +02:00
Tommy D. Rossi 2d274f5c37 gpui_terminal: Run GPUI apps inside kitty-graphics terminals
New GPUI platform (macOS for now). The window is the terminal grid.

Frames: Metal offscreen render in RGBA, read straight into a POSIX shm
object, shown with ESC_G a=T,i=1,p=1,f=32,t=s inside CSI ?2026 sync, so
the pty only carries ~100 bytes per frame. Reusing image/placement id
replaces the frame in place without flicker. Frames are demand driven
(frame_waker/schedule_frame) and capped at 60 Hz. Each frame runs in an
autorelease pool because there is no Cocoa run loop.

Input: /dev/tty in raw mode, SGR any-motion mouse with pixel coordinates
(1003/1006/1016), kitty keyboard flags 31 (press/repeat/release, alternate
keys, associated text), bracketed paste, focus reports, in-band resize
(2048) plus SIGWINCH. The input thread uses select() because macOS poll()
reports POLLNVAL for /dev/tty. Text goes through the input handler when a
key is unhandled; unhandled ctrl-c quits. Title via OSC 2, pointer shape
via OSC 22, clipboard write via OSC 52. Terminal is restored on quit,
signals and panic.

Main loop: one mpsc channel carries GPUI main-thread runnables and
terminal events; background work uses gpui's priority queue; timers run
on their own thread.

Verified in Ghostty 1.3.1 (hover, clicks, wheel, keys, resize) and with a
fake kitty pty harness that reads shm frames into PNGs. ~4 ms per
1600x960 frame on Apple silicon.

Example: cargo run -p gpui_terminal --example terminal_hello

Discord: https://discord.com/channels/1422625037164351591/1562047194893131797
Session: ses_ea72eb238ffeNBQNOGK7liwLQG

Replayed from remorses/zed 8a346ab794 (crates/gpui_terminal).
2026-10-20 14:17:34 +02:00
Tommy D. Rossi 4aa2fca978 feat(native): terminal mode works over SSH
Bumps zed to 8152a6a875 (gpui_terminal: send frames inline when shared
memory is not reachable).

At window open gpui_terminal sends a one pixel `a=q,t=s` query and `CSI c`.
If the terminal cannot open our shared memory (SSH, a container), every
frame goes inline: zlib, base64, 4096 byte chunks, then an `a=q` fence. At
most two frames wait for their fence, so SSH buffers cannot queue seconds of
stale frames.

- README: "SSH works" replaces "Local only", with an `ssh -t` example
- changeset: terminal entry mentions the inline fallback
- docs/terminal-renderer.md: probe, inline format, fence gate, sizes, harness
  `REMOTE=1` mode and the Docker cross-namespace test
- Cargo.lock: gpui_terminal depends on flate2

Discord: https://discord.com/channels/1422625037164351591/1562061946524532766
Session: ses_ea6f90cc0ffej0S2RFLCkQxS5W
2026-10-20 13:56:21 +02:00
Tommy D. Rossi eae33e8a56 feat: render apps inside the terminal with terminal: true
`render(<App />, { terminal: true })` or `GPUIX_TERMINAL=1` runs the same
GpuixView on gpui_terminal, a GPUI platform in the Zed fork that paints with
the kitty graphics protocol. No native window opens.

```
macOS                                   Linux
renderer.init ─► init_macos             renderer.init ─► init_threaded
  EmbeddedPlatform::Terminal              gpuix-ui thread
  TerminalPlatform::new_embedded()        gpui_terminal::application().run()
  tick() ─► pump_events()
```

- renderer.rs: `terminal_requested()` reads the option and the env var;
  macOS swaps MacPlatform for TerminalPlatform inside the embedded path, so
  tick() and the frame wake hook are unchanged. No per-method branches
- input.rs: `init_terminal` unbinds ctrl-c in text field contexts so it
  reaches the platform and quits
- `isTerminal()` exported from @gpuix/native, @gpuix/react and @gpuix/solid
  as a plain function (not a hook); browser.mjs returns false
- examples/chat.tsx, mail.tsx drop the traffic-light gap in a terminal
- AGENTS.md: terminal mode swaps the platform; no hooks for non-reactive values
- README: "Run in a terminal" section and the `terminal` option row. The same
  README hunk also carries a note on `windowBackground: "blurred"` tinting
- docs/terminal-renderer.md: architecture, traps, research notes
- zed submodule: gpuix-terminal commits (gpui_terminal crate, embedded mode,
  SIGWINCH-only forwarding)
- changeset (minor for native, react, solid)

Discord: https://discord.com/channels/1422625037164351591/1562055543466496043
Session: ses_ea7105a47ffeNLpB02sEyo5t9g
2026-10-20 13:55:40 +02:00
Tommy D. Rossi e7a6b7efac docs(website): add npx apps blog post draft
New post in website/src/blog/npx-apps.md.

Session: ses_f1c46cdf5ffeUrlHSgFFR2TD6Y
2026-10-20 13:55:22 +02:00
Tommy D. Rossi 16dda64254 docs: text contrast and screenshots of translucent windows
- replace the long "GPUI defaults text color to black" note with a short
  **Text contrast** paragraph and an example on a light translucent surface
- note that `app.screenshot()` captures GPUI's surface, not the macOS blur
  behind a translucent window; use `screencapture -l <window-id>` for that

Session: ses_f1bf60c4fffeoNdPp0Y5C5po92
2026-10-20 13:55:22 +02:00
Tommy D. Rossi cd9493a0d2 fix(native): enable GPUI Wayland and X11 compositor selection on Linux
Linux apps silently opened no window under X11: the addon enabled the
gpui_platform backends but not gpui's own `wayland` and `x11` features, so
compositor selection was compiled out, also in release builds without
`test-support`.

- packages/native/Cargo.toml: gpui gets `wayland` and `x11`
- README: how GPUI picks Wayland or X11 (`WAYLAND_DISPLAY`, `DISPLAY`) and how
  to force X11 under XWayland
- changeset (patch), Fixes #93

Upstream search: zed-industries/zed#56322 fixes the inverse mismatch in GPUI
examples, not this addon.

Session: ses_eb158e141ffeMMK5qeppygyhzs
2026-10-20 13:55:15 +02:00
Tommy D. Rossi 515df198fe fix(native): pace macOS event pumping with display-link wakes
Wake JavaScript through a weak, coalesced N-API callback after GPUI queues its display frame. Keep tick non-blocking and replace the independent 8 ms input timer with a 100 ms no-wake fallback. Explicit frameMs retains timer polling; Windows and Linux keep their existing loop.

Clear callbacks and timers on stop, make stop idempotent, and release the hook when the renderer drops. Exercise real display wakes through the shared runtime on Bun and Node, plus hidden-window fallback and replacement-loop cleanup. Document the latency and idle-CPU limits for both adapters.

Fixes #91

Session: ses_ec38cf159ffe0vKPJHE10v0gl6

Discord: https://discord.com/channels/1422625037164351591/1560050965288194129
2026-10-16 19:30:30 +02:00
Tommy D. Rossi 6ca0fcd719 fix(gpui): expose display-link wakes to embedded macOS hosts
Pin the GPUI fork to the pushed display-link wake hook. Subscribers queue their frame work before the hook signals the foreign host, and the callback runs outside the registry lock.

Session: ses_ec38cf159ffe0vKPJHE10v0gl6

Discord: https://discord.com/channels/1422625037164351591/1560050965288194129
2026-10-16 19:26:16 +02:00
Tommy D. Rossi 6a5c7c142a test(react): await frame-loop termination instead of a fixed delay
Windows ARM64 timer scheduling can take more than 40ms for three frames. Wait for the existing termination callback and retain exact tick and termination counts instead of asserting before the loop completes.

Session: ses_ed48f90d4ffeqym03XRjqsA5xw

Discord: https://discord.com/channels/1422625037164351591/1558853977012174980
2026-10-11 18:52:14 +02:00
Tommy D. Rossi 6f8de1c047 ci(native): build shared runtime before collecting release packages
The publish job starts from a clean checkout. Compile native shared TypeScript before packaging native and building the adapters so host, runtime, testing, and automation subpath declarations exist. All hosted builds and platform tests passed before this release-order failure.

Session: ses_ed48f90d4ffeqym03XRjqsA5xw

Discord: https://discord.com/channels/1422625037164351591/1558853977012174980
2026-10-11 18:36:53 +02:00
Tommy D. Rossi 571f13b5fc test(react): use actual viewport scale and runtime architecture
Derive logical screenshot coordinates from the native viewport instead of a fixed 1280px width. Assert Dialog portal and backdrop coverage against that viewport and preserve exact popup size and centering assertions. Select ARM64 installer assets in the updater fixture on ARM64 runtimes.

Validation: React build and all 536 tests pass on macOS. Keep all screenshot geometry assertions and all platform tests enabled.

Session: ses_ed48f90d4ffeqym03XRjqsA5xw

Discord: https://discord.com/channels/1422625037164351591/1558853977012174980
2026-10-11 18:19:38 +02:00
Tommy D. Rossi bf9ee69c49 fix(native): import shared paint-report Rc on every platform
Paint reports and element observers use Rc on Windows and Linux as well as macOS and wasm. Remove the obsolete platform gate that caused Windows ARM64, Windows x64, and Linux CI compilation to fail.

Session: ses_ed48f90d4ffeqym03XRjqsA5xw

Discord: https://discord.com/channels/1422625037164351591/1558853977012174980
2026-10-11 17:58:55 +02:00
Tommy D. Rossi bb8a357673 ci(native): build test and package Windows ARM64 alongside x64
Build aarch64-pc-windows-msvc on windows-11-arm with Visual Studio ARM64 Clang for ring. Compile the matching bun-windows-arm64 chat executable. Run the existing Windows binding, renderer, React, Solid, and example checks on both architectures with matching Node installations and artifacts. Publishing waits for both Windows test jobs.

Align napi.targets, README downloads, and the architecture guide with the release matrix. Replace the pending source-build-only changeset with the final ARM64 support entry for issues 73 and 78.

Validation: actionlint passes; build/package/test targets match; napi recognizes the ARM64 package; native TypeScript build and 15 package tests pass. Hosted ARM64 CI has not run. lintcn reports one pre-existing error in untouched js/idle-gc.ts.

Session: ses_ed48f90d4ffeqym03XRjqsA5xw

Discord: https://discord.com/channels/1422625037164351591/1558853977012174980
2026-10-11 17:29:05 +02:00
Tommy D. Rossi f221650ade docs(native): explain Windows ARM64 source-build prerequisites
Document ARM64 MSVC, Windows SDK, Clang, CMake, and matching Node.js/Bun runtimes. Include PowerShell commands to locate Visual Studio LLVM and build the local native addon and adapters. State explicitly that published Windows packages and CI remain x64-only.

Use ring build documentation for its Windows ARM64 Clang requirement and validate the linked documentation. Add the patch changeset for issue 73. PowerShell commands were not executed on a Windows host.

Session: ses_ed48f90d4ffeqym03XRjqsA5xw

Discord: https://discord.com/channels/1422625037164351591/1558853977012174980
2026-10-11 17:06:12 +02:00
Tommy D. Rossi e4f4309635 fix(examples): use platform file managers and native Windows chrome
Reveal disktree selections through Finder, Explorer, or xdg-open instead of always invoking macOS open. Keep launcher errors in the selection panel and scope them to the selected path. Preserve Explorer selection arguments for paths with spaces. Normalize platform button labels in the existing scan/navigation snapshot.

Use the existing titlebarTransparent option to retain native Windows dragging and minimize/maximize/close controls in chat and disktree. Leave other platforms unchanged. Document both behaviors and add separate changesets for issues 75 and 77.

Validation: all package, Rust, and performance suites pass on macOS. A real missing-launcher probe leaves the selection panel responsive. Windows and Linux runtime behavior remains unverified locally.

Session: ses_ed48f90d4ffeqym03XRjqsA5xw

Discord: https://discord.com/channels/1422625037164351591/1558853977012174980
2026-10-11 17:06:12 +02:00
Tommy D. Rossi b552197260 test(disktree): normalize the displayed fixture path on every platform
Replace the Unix-only path regex with the exact path formatted by the same displayPath helper as the selection panel. Keep the existing end-to-end scan and navigation snapshot unchanged. Add a patch changeset referencing issue 76.

Session: ses_ed48f90d4ffeqym03XRjqsA5xw

Discord: https://discord.com/channels/1422625037164351591/1558853977012174980
2026-10-11 16:55:28 +02:00
Tommy D. Rossi e1711bb651 fix(cli): make source builds independent of Unix chmod
Use Node file permissions for the disktree and scaffolder executables on Unix. Skip permission changes on Windows, where a shell chmod command is not available. Document the portable build behavior and add a patch changeset for both packages.

Session: ses_ed48f90d4ffeqym03XRjqsA5xw

Discord: https://discord.com/channels/1422625037164351591/1558853977012174980
2026-10-11 16:55:28 +02:00
Tommy D. Rossi 6ae5ae2e96 Merge origin/main and reconcile sparse native metadata
Keep local sparse event and custom-prop storage with incoming focus tracking, paint reports, and virtual-list scrollbars. Adapt new retained-element reads to the sparse accessors.

Validation: cargo check --all-targets; 24 retained-tree tests passed.

Session: ses_ed495e076ffezRikUAkr3iwjFZ

Discord: https://discord.com/channels/1422625037164351591/1558852237974044734
2026-10-11 16:45:21 +02:00
Tommy D. Rossi f1e7a96da8 Merge pull request #88 from rubnogueira/perf/native-features-and-perf
feat(native): native scrollbars, portals, layout and scroll events, fonts, and a cheaper render path
2026-10-11 15:35:03 +02:00
Ruben Nogueira 447ade95e4 feat(native): padding on a virtual list insets its rows on all four sides
The list ignored left and right padding, so rows spanned its full width. Rows now sit inside all four sides, and a scrollbarColor thumb stays at the list's own edge, past the padding. Moves the zed submodule to the commit that lays rows out inside horizontal padding.
2026-10-11 12:42:10 +01:00
Ruben Nogueira 3c991f2e95 revert(native): drop the box-around-virtual-list thumb
A padded box around a list is better served by padding on the list itself,
with the thumb at the list's own edge. The list now takes padding on all
four sides.
2026-10-11 12:28:30 +01:00
Ruben Nogueira f15c044af6 test(react): read scrollbar pixels in logical units so they pass on a 2x display 2026-10-11 11:48:02 +01:00
Ruben Nogueira eb4ef4a592 docs: describe the new features without reference to any one app 2026-10-11 11:48:01 +01:00
Ruben Nogueira 239f16d199 perf(react): root.render() keeps one context value so useGpuix consumers stop re-rendering
Each render() call wrapped the tree in a Provider whose value was a new
{ renderer } object, so every call was a context change. In the chat example
that re-rendered ChatApp, whose inline onRetry closure then busted the memo on
Transcript: 305 SafeMdxContent renders and about 9 ms per find-bar keystroke.

The example also keeps onRetry stable now, so typing in the composer no longer
re-renders every row.
2026-10-10 21:22:27 +01:00
Ruben Nogueira 90c6ad094c feat(native): a list's thumb sizes unmeasured rows from the measured ones 2026-10-10 20:57:02 +01:00
Ruben Nogueira 8a751703ba feat(native): a box around a virtual list draws the list's thumb at its edge 2026-10-10 20:43:10 +01:00
Ruben Nogueira a0642953cf feat(native): scrollbarColor draws a thumb on a virtual list 2026-10-10 20:35:08 +01:00
Ruben Nogueira be82b368b9 perf(native): compile the highlight query once per keystroke 2026-10-10 20:17:33 +01:00
Ruben Nogueira d789ba4b9b feat(native): scrollbarColor paints a native scrollbar thumb 2026-10-10 19:34:39 +01:00
Ruben Nogueira 4f622483b6 feat(native): collectGarbageWhenIdle collects once the app has stopped committing 2026-10-10 19:29:00 +01:00
Ruben Nogueira 5d86e4febd feat(native): getElementsAt lists the elements under a point 2026-10-10 19:26:35 +01:00
Ruben Nogueira 82390c4e70 test(examples): profile-chat takes a QUERY override 2026-10-10 18:35:18 +01:00
Ruben Nogueira 720e975ca9 perf(native): focus sync visits only the focusable elements 2026-10-10 18:35:15 +01:00
Ruben Nogueira d8fd814ed0 fix(native): hover ends when the pointer leaves the window 2026-10-10 18:23:32 +01:00
Ruben Nogueira 5ab017a32b feat(native): onScrollChange reports every scroll of a scroll container 2026-10-10 18:09:54 +01:00
Ruben Nogueira c7dd862ad1 feat(native): onLayout reports an element's size when it changes 2026-10-10 18:06:24 +01:00
Ruben Nogueira f3eede6b3e feat(native): registerFont loads a font that fontFamily can name 2026-10-10 17:58:28 +01:00
Ruben Nogueira f10a6c1b35 test(examples): run perf budgets against a production React and add a chat profiler 2026-10-10 17:49:07 +01:00