GPUI Box GitHub

GPUI Box compatibility

0.1.x matrix

GPUI Box owns its framework and package compatibility. There is one package and type universe: applications use Cargo package gpui-box as Rust crate gpui, and gpui-box-kit as gpui_kit. Zed crates must not be mixed into that graph.

GPUI Box cohortFramework originRustStatus
0.1.xfiltered bootstrap fran0220/zed@0b9c8dc932b65cba2dc87464148984e93f60ae18; official baseline a6a23c7b80a5cefa0487b7856335be89ace7e483; PlatformView fork overlay through b46bf740a55c53612b14120f5dfbb7ceec4632611.97, edition 20240.1.2 public release

The SHAs identify imported source provenance, not Cargo Git dependencies. scripts/sync-zed/state.json records the deterministic filtered bootstrap tip, the official baseline cursor, and its exact integration merge. It separately records the exact bootstrap-rooted fork overlay that supplies native PlatformView hosting. Offline release verification checks both retained vendor refs, every recorded source trailer and parent, their unique bootstrap merge base, and both integration merges against the release commit's first-parent history. It does not contact either historical source repository.

Platform evidence and limits

Window::paint_mark / record_paint_since freeze a balanced, contiguous range while the subtree is live. Marks may be inside ancestor paint layers: capture owns balanced copies of their ordering scopes. The range must not close an inherited layer or leave a newly opened layer unclosed. Take the mark before painting the child and finish capture before leaving its ancestor scope. paint_recording and paint_recording_with_offset replay only owned GPUI paint, never element callbacks or input/focus/IME, accessibility, hosted-view, or Kit semantic registration. Current ambient uniform transform/opacity replaces its captured counterpart; local subtree effects remain frozen. Offsets are current-local logical pixels, transformed once. Capture-visible rectangular/rounded clipping moves with the picture and intersects the current ancestor clip; replay cannot expose clipped/culled content or reflow text. Zero/nonfinite capture opacity is refused.

WGPU, Metal, Direct3D, and deterministic test atlases implement allocation leases. Image eviction waits only for referenced allocations; reset invalidates leases before resource identities can be reused. Both replay and renderer submission check validity, including reset after replay. Window, display scale, capture-frame identity and capture-time atlas revision are checked. Unsupported atlases refuse sprite capture. Glass, platform surfaces/views, and frames with deferred draws refuse capture rather than disappearing from a recording; position-dependent edge fade refuses replay. Callers drop recordings on completion, reinsertion, reduced motion, or refusal. This is not arbitrary content retirement: composited historical backdrop capture remains missing.

Native atlas leases retain Send + Sync release callbacks so GPU submission completion may drop them on another thread. Wasm leases and callbacks remain thread-confined, matching browser GPU resources without an unsafe Send wrapper. The browser-gallery release build exercises this WGPU path; checking the Kit library for wasm alone does not. Native tests verify cross-thread final release.

Capture bookkeeping does not rescan earlier cards. Marks copy only the active layer depth; capture validates/clones only its operation range. Atlas retention uses one expected-constant-time reverse-index lookup per sprite reference, with index memory proportional to allocated tiles. Referenced frame leases are found by a binary search in paint-order ranges, then only intersecting leases are visited. Path vertices, distinct clip ancestors, and the existing bounds tree reconstruction still cost work proportional to the captured content and its geometry; this is not a constant-cost snapshot or an arbitrary-rendering linear-time guarantee. Counter regressions cover 1,024 cards with an 8,192-op unrelated prefix and 3,072 tile references in both 64- and 8,192-tile atlases.

Linux tests and dynamic offscreen frames cover text/card/image removal, reinsertion, ambient opacity/scale, clipping and reduced motion. macOS/Windows native execution remains pending; source changes are not platform acceptance.

Inline deferred prepaint (including sticky content) preserves logical AccessKit ancestors, source child order, synthetic children, and ancestor-based active descendant focus independently of paint priority. Frame-local child reservations attach to finalized ancestors without duplicate platform nodes. Generic deferred overlays retain window-root accessibility parentage; inline callers opt in with Deferred::preserve_accessibility or Window::defer_draw_with_accessibility. Popover and hover-card surfaces remain window siblings of their triggers. While accessibility is active, visual view caches are rebuilt each frame: their prepaint/paint ranges do not contain replayable accessibility trees. Linux builder and sticky/nested-deferred integration tests cover these shared invariants; browser smoke checks TreeGrid ancestry on WebGL2 and WebGPU. Native macOS and Windows adapter validation remains the on-demand Platforms lane; the shared change does not alter clipping, transforms, hit testing, or paint.

Windows native-view clips are independent child-local regions as well as a host union; clipping never changes full layout dimensions. Empty frames hide and empty the host, including subsequent move/resize synchronization. Saved caller regions remain owned copies throughout restoration retries. If the OS refuses teardown, GPUI hides and disowns the popup rather than destroying a caller child. Explicit teardown can retry; final destruction deliberately retains stranded controllers and the hidden popup (an exceptional resource leak, not permission to destroy caller-owned windows). Native regression command: cargo test -p gpui-box-windows platform_view --lib. These HWND tests require Windows; Linux headless images do not prove them.

Pointer cancellation is a distinct PlatformInput::MouseCancelled event, not a synthetic mouse-up: it cannot click or drop. Window broadcasts it regardless of propagation, resets framework text/press/drag state, and releases capture. Custom gesture listeners must discard pending state on MouseCancelEvent. The legacy Window::capture_pointer retains its any-up policy; button-specific capture_pointer_for_button and on_mouse_down_with_pointer_capture release only on the matching button or cancellation. Framework text selection uses the button-specific API and framework drag/drop remains left-button-owned. Web reconciles the complete buttons snapshot on intermediate pointer moves, and cancels only the active pointer on pointercancel, lostpointercapture, or window blur. Normal final up followed by capture loss is idempotent. Primary pen pointer compatibility is retained. Touch contacts use the distinct portable multi-contact path described below rather than duplicate mouse events. Windows retains OS capture until no mouse buttons remain, and delivers capture loss separately after normal up dispatch. Shared regressions run with cargo test -p gpui-box --lib pointer_; real browser cancellation and native Windows device chords still require platform execution evidence.

Linux gate executes both cargo test --workspace and cargo test --workspace --all-features, not only an all-feature compile. Both Windows and macOS Platforms/Release native lanes execute cargo test --workspace --all-features --locked --exclude gpui-box-media; media lifecycle tests remain a separate invocation with their existing host restrictions. These commands are required evidence, not a claim that an unrun platform has passed.

PlatformCurrent repository contractValidation command/evidenceLimits
macOSFramework, kit, Metal, native action context menus, clipped and paint-ordered native views, native AVFoundation audio/video playback, and deterministic headless catalogOn demand: the dispatched Platforms workflow runs native media load/control/replacement/teardown tests, the remaining all-feature platform tests and clippy, performance check, and cargo run -p xtask -- headless check on Metal; real-window review remains separatePlayback supports operating-system codecs and unprotected sources; no DRM, track selection, capture, or application network policy; real-window accessibility and context-menu presentation need a logged-in host
WindowsFramework/kit, native action context menus, paint-ordered custom caption controls and native drag/resize behavior, re-entrant native frame-request deferral, clipped and paint-ordered native views, native Media Foundation audio/video playback, and deterministic WGPU/WARP headless catalogOn demand: the dispatched Platforms workflow runs native UIA editing/focus/character/caret/form-description/menu-action smoke, native media replacement/teardown/COM/MF-lifetime and truthful no-backend tests on its audio-less hosted runner, the all-feature clippy, performance check, the Direct3D release-shader compile, and cargo run -p xtask -- headless check on WARP; release acceptance additionally exercises real-window caption controls and borders plus media load/control/end/restart on an equipped Windows host; Windows baselines existPlayback supports operating-system codecs and unprotected sources; native frame capture is not implemented
LinuxWayland/X11 framework code, the all-feature native check, and the deterministic llvmpipe headless catalogEvery commit: cargo run -p xtask -- gate full on the orb runs the all-feature tests and clippy, rustdoc, the structural performance budgets, and headless check against snapshots/headless/linuxApplication context menus use Kit's in-window fallback; native media service reports no-backend; AT-SPI and native behavior claims remain capability-scoped
Browser/WASMStable, single-threaded browser gallery, hosted compose surface, and lazy catalog embeds using the same Rust scenesEvery commit: gate runs web check (wasm32 compile, warnings denied); web smoke drives the real Chromium gallery/site session when the browser gallery changes, and the visual command remains available for scoped reviewApplication context menus use Kit's in-window fallback; native media service reports no-backend; no threaded COOP/COEP claim and no screen-reader announcement coverage

All four rows are mandatory surfaces, in two lanes recorded by compatibility.toml's gate_lane: authority (Linux and browser) runs in xtask gate at every commit on the orb, on-demand (macOS and Windows) is the dispatched Platforms workflow. No GitHub workflow builds on push. A release may claim only results recorded for its commit, which for the on-demand lane means a Platforms run of that commit; the commands do not erase the explicit limitations in the final column. Accessibility capability details remain in accessibility.md, and visual mechanics in screenshot-testing.md.

Native mobile source is experimental and not an additional validated row. gpui-box-android provides an API33+ arm64 Vulkan Activity/JNI host, and gpui-box-ios provides a UIKit/WGPU host with caller-supplied fonts. Portable host checks exercise Rust types and local contracts, not Java/APK compilation, Xcode linking, native frame presentation, keyboard behavior or accessibility. See the Android backend contract and iOS native procedure for explicit limits, SDK/device requirements and executable acceptance procedures.

Mobile browser tests run with npm --prefix examples/browser-gallery run mobile after xtask web build. gate full, web smoke and web gate build the gallery and run this suite. They exercise Chromium touch delivery, keyless input/composition, lifecycle, CSS/backing-size consistency and residual inset fixtures. They do not establish Android Chrome or iOS Safari keyboard activation, autofill, native selection, screen-reader or device lifecycle behavior. The exact boundary is documented in the browser mobile contract.

Checked App::try_* and Window::try_* operations preserve unsupported, unavailable and refused outcomes before native dispatch. An accepted request does not prove an OS transition completed. Mobile backends default to denial unless they implement the operation. WGPU explicit detach/destroy drains native resources before handle invalidation; device loss reports unconfirmed completion while still releasing resources. Native teardown and recreation must be tested on each platform before claiming lifecycle acceptance.

Accessibility action listeners are frame-local and registered only while the window's AccessKit adapter is active for that frame. Adapter activation forces a redraw before actions can be delivered, so inactive rendering does not add unreachable handlers and active action behavior is unchanged.

Every native row also runs cargo run -p xtask -- performance check. The command enforces per-window structural budgets over 10,000-item List, DataGrid, TreeGrid, CodeView, LogStream, and AgentDocument fixtures and writes target/performance/report.json. The browser build compiles the same fixed counters; its renderer-specific timing lane remains separate from the structural gate. See performance-testing.md.

Live frame timing has the same per-window boundary. FrameTiming retains draw work for benchmark consumers; FrameSubmissionTiming pairs the latest newly drawn frame with the synchronous platform submission call, the first observed invalidating input, and the number of coalesced top-level inputs. FrameTimingMonitor retains a bounded history of those submitted frames and does not create a refresh loop. Reference-counted trace leases keep concurrent diagnostic and benchmark consumers independent. Submission completion means the platform draw call returned, not that a compositor or display reported a presented or dropped frame. The budget metric remains draw-only.

Client-drawn desktop titlebars share one framework contract. Nested Client areas override an enclosing Drag strip, caption controls preserve their platform identities, and Window::request_close follows the same vetoable close path as native chrome. A native hit-test request carries its own current position into the rendered-frame lookup instead of borrowing the previous pointer event. Windows therefore maps maximize to HTMAXBUTTON on entry for Snap Layout; macOS keeps native traffic lights; Linux reports the same requests to its compositor-backed window implementation; browser builds expose no desktop caption controls.

Transient notifications remain viewport-pinned, but a host can declare edges already occupied by its own chrome through ToastLayer::reserved_edges. StatusBar::height exposes the matching shared strip height, so applications do not copy framework geometry to keep persistent notifications clear.

Inline sticky subtrees retain ordinary layout while GPUI translates their prepaint, hit testing, accessibility bounds, and paint together against the active content mask. Overflow containers can reveal a focused descendant with physical edge insets reserved for those overlays. DataGrid and TreeGrid use that contract for a single horizontal header/body/summary viewport and a direction-aware frozen leading group; their virtualized vertical handle remains independent.

Measured Reveal subtrees retain a stable natural primary-axis extent while contributing caller-supplied progress to ordinary layout. The same content mask governs paint and pointer delivery, and role-bearing bounds are intersected with the active mask before AccessKit publication; a fully shut subtree is not prepainted or published. Reveal owns no timer, easing, or component policy. Kit's Accordion and Collapsible resolve semantic Resize motion and pass only the resulting progress into this framework primitive.

Stateful springs also have one framework authority. SpringConfig analytically advances position and velocity for fixed and steadily moving targets, and AnimationExt::with_spring keeps that state under a stable element id so a retarget does not restart from rest. A first mount starts at the target unless the builder supplies from; pause retains velocity, stop discards it, complete lands at the target, cancel returns to the initial value, and reduced motion lands immediately. Finite eased values may exceed 0–1, so an underdamped spring's overshoot is preserved. Kit retains the token, semantic-role, visual settle, transition, presence, and FLIP policy above this scalar primitive.

Raw touch has one portable framework path. Every contact carries a stable TouchId; native pointer indices are not identities. Single contact tap, axis-locked scrolling/fling and claimed drag/long press remain compatible. The first two unclaimed contacts promote to pinch, cancelling an existing scroll. Pinch uses raw centroid and incremental span ratios, never predictions. Coincident contacts retain the last nonzero scale baseline. Additional contacts drain without becoming taps after the owner ends.

During paint, Window::on_touch_pan registers a stable window-unique owner ID. An initial Started offer carries direction after slop. Later unconsumed live scroll can offer Started with is_scroll_handoff; rejected offers have no terminal event. Inspect touch_start_position for hit testing and use position - start_position for travel: handoff rebases the latter to residual movement only. prevent_default acquires and stops bubbling. Only the owner receives later phases. A captured manipulation retains reversal and never silently transfers back to scrolling. Frames with arbitration listeners use raw scrolling positions so consumed plus residual equals actual travel.

Window::on_touch_pinch similarly captures an owner, even when the centroid crosses into another view. Registering pinch and pan with the same ID permits that owner's pan to cancel and promote to pinch; other claimed manipulations retain ownership. Keep captured listeners registered until their terminal phase, or call cancel_touch_input before removal. Inactive platform status automatically cancels contacts, pending timers and already-released momentum. This is exclusive arbitration for these primitives, not a rotation recognizer or an arbitrary simultaneous-gesture graph. Shared tests are not native device integration evidence. Platform-provided trackpad pinch remains separate.

Window::insets reports safe-area and IME edge avoidance in logical pixels relative to the current content viewport. A resized viewport must not also subtract the keyboard's full height; only residual overlap is reported. effective() takes a per-edge maximum. Floating/split keyboard geometry is not invented as full-width padding. Backend inset changes invalidate the window. Text input hints and fallible actions flow through EntityInputHandler, InputHandler and PlatformInputHandler; native text positions/ranges use UTF-16 offsets and unsupported geometry is unavailable, not approximated. Keyboard focus/options notifications follow the installed accepting handler. Backends defer input-handler queries until these notifications return to avoid reentering a borrowed core window. Autofill hints do not promise SMS access, validation, or successful autofill.

Application-provided native context menus use the framework's existing Menu/MenuItem action tree rather than a platform-specific component model. macOS maps it to NSMenu; Windows maps it to HMENU and TrackPopupMenuEx. Both run their blocking tracking loop only after GPUI's current borrow has yielded, then dispatch the selected action through the focus context captured at open time. The explicit unsupported result keeps Linux, browser, headless, and other platforms on Kit's accessible in-window ContextMenu; ContextMenuPresentation::InWindow also lets a host force that portable rendering on a native-capable platform.

Window::show_context_menu returns an awaitable NativeMenuSession, not a bare task. Retain id() for Window::cancel_context_menu(id) and revision checks, and retain effect_owner() for asynchronous component callbacks. Re-enter the captured owner with App::with_effect_owner; focus is not effect authority. Framework command dispatch checks the latest application revision and enters the captured owner independently.

Cancellation immediately invalidates commands, including already queued selection, but Ok(true) only acknowledges the request. Completion confirms tracking has exited. Cancelled, Dismissed, and Unavailable are distinct; receiver loss/window destruction is unavailable, never a fake dismissal. NativeMenuError::NotSupported is the only automatic fallback case. CancellationFailed preserves the invalidated session for an explicit retry; components must report refusal rather than pretending the native UI closed. Cancel before changing a presented action snapshot. Each replacement gets a fresh identity, and stale identities cannot cancel another owner's menu.

macOS cancels the tracked NSMenu with cancelTracking; AppKit supplies no refusal return value, so loop completion remains the closure evidence. Tracking is scheduled on the main NSRunLoop in common modes after the GCD foreground task returns; entering the blocking menu from the serial main dispatch queue would starve the very continuations needed to cancel it. Windows guards thread-wide EndMenu by session and HWND. Both backends wait for the previous tracking loop before starting a replacement, including queued replacement chains and cross-window presentations, and invalidate on teardown. Windows preserves menu-loop notifications so its existing WM_ENTERMENULOOP timer drains foreground tasks inside TrackPopupMenuEx. TPM_RETURNCMD still keeps command dispatch under the revision session; TPM_NONOTIFY would suppress the entry notification needed to install the modal timer. The shared deterministic lifecycle tests run on Linux. Actual native tracking, replacement and cancellation need macOS/Windows execution; a Linux test pass does not establish that native behavior. No renderer or baseline changes are part of this primitive.

On a logged-in macOS/Windows desktop, run:

cargo run --locked -p gpui-box-platform --features test-support --example native_menu_smoke

This smoke opens actual OS menus and observes the backend inside NSMenu/TrackPopupMenuEx before cancelling. It checks completed cancellation, same-window and cross-window replacement, stale/wrong-owner cancellation, destruction of a stale owner without closing the new menu, destruction during active tracking, and successful presentation after teardown. The observation API is test-support-only; simulated/queued menus cannot supply that evidence. Every replacement must really enter native tracking, and every cancelled session must complete with the specified outcome. An independent 45-second watchdog fails on a blocked modal loop or shutdown, reporting the last phase. Unsupported capability is a failure, not a skipped test or Kit fallback. Capture both output streams as target/native-menu-smoke.log in each native Platforms lane. Exit zero plus the final native-menu-smoke: PASS line is required. Linux compilation/shared tests do not validate this smoke; native execution must be recorded separately. This lifecycle smoke does not inject OS selection/escape input or establish native command-selection accessibility; queued stale-command and effect-owner invariants retain their shared tests.

Actual Platforms run 34396298822 at 02468534 failed this smoke on both macOS and Windows: each watchdog expired at cancel active native menu, before observing tracking. The scheduling and notification corrections above are candidates awaiting a new native run, not established native parity. The smoke also exercises queued replacement cancellation before invocation to guard the new run-loop scheduling gap; all actual-tracking, cancellation, stale-owner and teardown assertions remain.

Native child views sit between GPUI's base and deferred-overlay scene planes. Text on the opaque base plane retains platform subpixel rendering; text in the transparent overlay plane uses grayscale antialiasing because RGB subpixel coverage cannot carry meaningful alpha through native composition. Dialogs, menus, prompts, drag previews, and tooltips therefore keep visible glyphs above native surfaces without weakening ordinary document text. Cache reuse includes the owning plane, and Direct3D converts any retained RGB coverage that still crosses the split into one alpha-writing mask as the renderer's final invariant. Direct3D path and backdrop passes restore the plane that invoked them after using their scratch targets, so subsequent overlay batches cannot leak into the opaque base scene.

Renderer-backed linear, elliptical radial, and conic gradients accept two through eight ordered color stops for both quads and filled paths. Radial centres and radii are normalized to the painted bounds; conic gradients start at the caller's CSS-oriented angle and proceed clockwise. Metal, Direct3D, WGPU, and browser WebGL derive the same geometry and select the same adjacent stop interval before applying sRGB or Oklab interpolation. Their dithering also follows one contract: a screen-pixel-anchored unsigned integer hash produces the two triangular samples, so GPU families and shader compilers cannot choose different transcendental approximations for the noise. Color conversion and edge rasterization remain renderer-specific, which is why each renderer retains its own baseline rather than claiming identical bytes across platforms.

A rounded sprite's antialiasing ramp is a property of its own geometry rather than of its neighbours. Metal, Direct3D, WGPU, and WebGL all size the polychrome sprite's corner mask from the analytic gradient of the same signed distance field the mask uses, mapped to device pixels through the sprite's own transform. That is the width a conforming fwidth reports for the smooth parts of the field, and it is defined everywhere the field is — including along the shared edge of the two triangles a sprite rectangle is drawn as, where a screen-space derivative depends on how a backend reconstructs a helper invocation and llvmpipe returns hundreds of pixels. Monochrome sprites, glyphs, SVG masks, shadows, and quads never consumed that derivative; their coverage is unchanged.

Scroll-edge fading uses those same painted bounds rather than treating every primitive as one atomic mark. Solid quads and filled paths crossing one active edge carry a per-pixel linear alpha ramp; a path's stops are normalized to the clipped bounds consumed by every path shader. Shadows, monochrome SVGs, polychrome images, and sprite instances expose uniform alpha, so primitives larger than the band sample at the center of the portion inside the fade region. Atomic primitives no larger than the band, including glyphs, retain nearest-edge fading so they disappear before clipping can slice them.

Read-only StyledText selection is a framework primitive rather than a Kit gesture. A window-owned coordinator joins separately mounted participants in caller-declared reading order, while stable business keys keep a selection on the same content across reordering and re-virtualization. Selection scopes isolate overlays from the page behind them. A copy crossing virtualized rows contains only mounted text and reports complete: false; GPUI never invents content it did not lay out. Pointer capture, grapheme-safe reverse drags, Copy, Select All, and AccessKit selection continue to use the shaped text geometry of each participant. A host that needs a complete copy of unmounted content still uses the component's whole-value copy intent.

EditBuffer is the shared editable-value authority for TextInput, TextArea, and later rich editors. It owns grapheme-safe selection, replacement and marked-composition transactions, grouped undo/redo, single-/multi-line normalization, byte and grapheme limits, and UTF-8/UTF-16 conversion. Secret controls permanently refuse history. EditableTextLayout is the corresponding shaped-geometry authority: the same wrapped and bidirectional lines that paint answer byte/point hit tests, visual-row ranges, selection fragments, aligned caret and hit geometry, platform range bounds, and reveal scrolling. TextInput and TextArea both consume it. EditableStyleRuns<S> keeps grapheme-safe, complete, normalized caller-owned style coverage across source replacement. Theme and document policy remain outside these framework primitives. Kit's storage-neutral RichTextDocument now supplies stable block identity, composite inline marks and links, paragraph/list metadata, and typed edit intents. A caller-owned RichTextEditSession applies those intents and owns composition and undo transactions without parsing or persisting a file format. RichTextEditor projects the session through the same shaped geometry, including selection, caret, IME, clipboard, diagnostics, links, lists, alignment, and a token-backed toolbar. All three editors capture the exact shaped cells during prepaint and publish AccessKit per-grapheme positions, widths, and run bounds from that current-frame geometry; they do not run a second accessibility layout.

Role-bearing elements can declare aria_labelled_by, aria_described_by, or their inverse aria_labels and aria_describes forms. GPUI resolves the referenced element id after ordinary and deferred prepaint in the active window. A missing, duplicate, or removed endpoint produces no relationship for that frame; no stale AccessKit node id is retained. Kit's NodeSpec::labels and NodeSpec::describes project through this native relation path as well as remaining visible in deterministic semantic snapshots. Because native adapters do not consume the references uniformly, resolution also derives an absent scalar label or description from the related node text. Explicit scalar values still win and the references remain present.

InteractiveElement::on_focus_resolved runs after the element's subtree has prepainted and receives the exact handle GPUI resolved during layout. An explicit track_focus handle remains authoritative; tab_index elements use their stable framework-generated handle; and non-focusable elements receive no handle. Kit semantic diagnostics read focus through this observer, while AccessKit continues to use the same existing handle and node projection.

ScrollTarget gives overflowing containers, uniform lists, and measured variable-height lists one offset, extent, viewport, and mutation contract. Kit scrollbars bind to that target instead of wrapping a virtualized list in a second scrolling container. A measured list freezes its reported extent while the thumb is dragged, so newly measured rows cannot move the thumb away from the pointer.

Window::paint_sprite_batch samples half-open physical-pixel rectangles from one RenderImage frame and retains one atlas upload for all instances. Each instance carries logical destination bounds, a center-relative transform, rounded and source-alpha masking, tint/opacity, and normal, additive, or screen compositing. Metal, Direct3D, WGPU, and WebGL apply the same transformed clip and scene-culling contract; hardware blend state is selected per contiguous paint-ordered batch. Invalid frame, source, destination, transform, or opacity facts reject the whole call before any instance is painted. The primitive adds no hit testing or accessibility nodes, and it does not claim subtree-wide offscreen masks or blends. RenderImage::from_rgba is the public procedural pixel boundary and hides the renderer's internal channel order.

Window::paint_particle_batch is a deterministic CPU sampler above that same sprite ABI. One or more ParticleEmitters use integer seed lanes and absolute elapsed time, so sampling order and dropped frames do not alter birth times, positions, dimensions, rotation, or opacity. A call admits at most 4,096 declared slots and validates every emitter and atlas source before scene insertion. It performs no compute-shader simulation and creates no per-particle element. Kit's EffectParticles is the policy-owned adapter: it maps EffectPlan recipes to emitter topology, semantic theme colors and a built-in procedural alpha atlas; reinforces tiny semantic marks toward the active text tone for standard-surface contrast; mirrors directional traces under RTL; schedules only while an animated recipe is live; and uses a fixed smaller constellation for quality, budget, or reduced-motion fallbacks. Platform renderers require no new particle pipeline because the final submission is one ordinary sprite batch.

CinematicEffect is platform-neutral and available in every Kit build. It maps the same semantic plans to Box-owned cinematic slots, timelines, poster samples, directional RTL behavior, and particle fallback. The optional gpui-box-kit/dotlottie feature links the crates.io rasterlottie 0.2 adapter and accepts only host-resolved archive bytes. Before decoding, Box enforces hard and host-tightenable limits for encoded size, entries, per-entry and total expansion, compression ratio, canvas area, frame rate/count/duration, animation count, state-machine count, embedded-image count, source dimensions, and aggregate image target pixels; rejects traversal, duplicate paths, symlinks, and encryption; inspects embedded image headers before full decoding; and rebuilds a bounded stored archive from fully read entries. The adapter returns deterministic RGBA samples and exposes no third-party type. A build without the feature and any preparation/rendering failure remain truthful runtime-unavailable or typed-error states and render the policy-owned fallback. Reduced motion chooses the recipe's deterministic poster and owns no frame timeline.

PathBuilder::stroke_trim keeps an ordered normalized interval of the measured source path before Lyon expands the stroke. dash_offset advances and wraps a validated dash pattern against that same measurement, so trim, phase, joins, caps, transforms, clipping, and gradient paint remain one path contract. Empty and all-zero dash arrays are solid strokes; negative or non-finite lengths and invalid trim intervals are rejected at construction. Motion systems sample the two numeric parameters and rebuild one path rather than approximating a trace with one element per segment.

Read-only StyledText selection is a framework primitive rather than a Kit gesture. Its stable element id retains transient anchor/focus state; pointer capture continues reverse drags outside the element; grapheme-safe Copy and Select All share the focused dispatch path; and AccessKit receives bidi-split text runs, word starts, per-grapheme bounds, and stale-revision-safe selection actions. Selection is scoped to one shaped value. A host that needs one drag to span independently mounted or virtualized values still needs a future document-selection coordinator rather than inferring bytes from row indexes. HighlightStyle::background_radius paints each line or wrap fragment as its own rounded quad, preserving range-highlight geometry without changing shaping, wrapping, hit testing, or accessibility bounds.

Font fallback is also an explicit framework contract. Styled::font_fallbacks inherits an ordered family chain; offscreen Cosmic shaping splits grapheme-safe runs by registered-font coverage, macOS resolves registered family names, and DirectWrite searches the application collection before the system collection. Kit registers Geist plus Noto Sans Arabic and Noto Sans Hebrew and applies the two Noto families to its type styles. Mixed RTL script output therefore does not depend on fonts installed by a downstream host. Locale-specific copy, number/date formatting, and language policy remain host-owned.

Grayscale glyph compositing shares one shader contract on Metal, Direct3D, and WGPU: a tintable coverage mask in the sprite atlas, reshaped by apply_contrast_and_gamma_correction before the hardware blend. The parameters are per platform. DirectWrite and Cosmic coverage takes the DirectWrite / Windows Terminal curve (default γ = 1.8, grayscale contrast 1.0). Core Text coverage takes identity parameters (TextGammaParams::identity): Core Graphics bakes its gamma handling into the mask and the macOS text system already dilates strokes per foreground luminance to match AppleFontSmoothing, so a second reshape thickens and smudges glyphs. The mask remains reusable across colors, so this is not destination-aware Core Text or AppKit font smoothing. macOS windows still report no subpixel support; subpixel mode stays a Windows / WGPU path. The macOS swapchain layer is tagged kCGColorSpaceSRGB, so the window server color-matches it like AppKit content instead of scanning untagged pixels out in the display's native gamut.

Browser checks are:

rustup target add wasm32-unknown-unknown
cargo run -p xtask -- web check
cargo run -p xtask -- web build
cargo run -p xtask -- web smoke
cargo run -p xtask -- web visual check button input dialog node-graph

The browser host is not a DOM rewrite. The marketing home, the component catalog, and the docs remain selectable, indexable HTML and retain committed captures as fallbacks; the live GPUI scene is a lazy enhancement shown in both themes on the home specimen, while /compose/ is the complete interactive surface. The pinned Playwright smoke covers forced WebGL2, forced WebGPU, automatic fallback, catalog embedding, static deep links, and the compose route. Its AccessKit adapter mirrors roles, focus, actions, values, and canvas-scaled bounds into semantic DOM, but the JSON semantic snapshot is only a testing/debug surface.

Focus visibility

focus_visible styling is placed by focus provenance, not by input history. Window::focus_from_pointer is the move a pointer press makes and is the only one that suppresses the styling; Window::focus, tab stops, focus traps, and accessibility focus actions all leave it visible, so a dialog that moves focus to its own action still says so. Window::focus_is_visible reads the current answer. Window::last_input_was_keyboard is unchanged and still governs hover suppression, which is about the pointer's position rather than focus.

Behaviour is platform-independent: it is decided in Window from dispatched events, so macOS, Windows, Linux, and the browser host agree without any platform reporting a focus modality of its own.

Backdrop glass is one material contract across Metal, Direct3D, and WGPU. GlassMaterial::blur_radius controls scattering only: zero performs no gaussian passes but still snapshots and composites clear refraction. A positive radius derives a blurred source for both the interior and refracted rim; the sharp paint-order snapshot is retained only for explicit edge-mask restoration. GlassMaterial::clear() replaces the historical zero-argument frosted() constructor; GlassMaterial::frosted(radius) names an actual frost. The material also carries saturation, a straight-alpha colour wash, transmission gain, additive optical lift, and hairline width. All renderers apply Rec. 709 saturation to the sampled interior and refracted rim, clamp negative channels, multiply transmission gain, source-over the material colour wash, then add optical lift and edge light. Clear/frosted constructors default to saturation 1 and transparent wash. Metal generates its packed material layout from Rust; Direct3D and WGPU map it to aligned uniform registers. The browser shares WGPU, not a separate glass implementation. Native Windows and Linux validation of this extension is still required in their lanes.

Wash sanitization preserves RGB rather than collapsing it to a black/white pole; each channel is clamped independently and non-finite channels become zero. This reuses the existing three renderer colour paths without an ABI change. Kit composes Glass::tint and GlassGroup::tint into that wash before the optical rim, including fused bridges. Frosted keeps its existing fill. Untinted Regular protects body-text contrast by default; protect_text_contrast(false) preserves the configured material and makes foreground legibility caller-owned. It is an explicit policy, not evidence that an unprotected native-like control meets a body-text contrast target.

The independently authored tools/liquid-glass-reference harness records public SwiftUI compositor output and validates source, image and timing identities separately from GPUI candidate renders. Static trial selection reports training, held-out size, cross-appearance and Clear-invariance scores; neither a score nor native capture certifies GPUI equivalence to Apple's private renderer. Native surface resizing and synthetic AppKit event receipt are distinct from cross-view morphs and physical input.

Glass uses a shared elliptical height field: thickness (zero follows the bounded bevel) times the signed refraction multiplier determines height and its derivative. Positive refraction makes a convex cap; negative makes a depression of the same maximum depth. BackdropGlass::optical_bevel bounds the profile width by positive corner radii and half-extents without changing the silhouette. Analytic rounded-rect and polynomial smooth-min derivatives retain their magnitude through the union; only the final 3D normal is normalized. Medial-axis ties choose an incident face rather than inventing a bisector.

Metal, HLSL and WGSL use Snell refraction with refractive_index in 1..=2.5. RGB indices are 1 + (index - 1) * (1 - dispersion, 1, 1 + dispersion). Index 1 is exactly undisplaced and has no Fresnel reflection. Rays intersect an effective optical background plane at local height plus backdrop_depth; there is no 45%-of-bevel displacement cap. The CPU sampling bound follows (maximum height + backdrop depth) * sqrt(maximum channel index² - 1), plus one bilinear texel and Gaussian support. Content masks restrict output, not the source information needed by a visible refracted pixel.

The same normal reflects the incident view ray into an analytic directional environment. Schlick Fresnel blends reflection with transmission; specular is its strength, no longer an independent additive highlight. Wash, gain, lift and hairline remain explicit artistic controls, so the entire material is not an energy-conserving physical volume. This is single-interface, screen-space optics: backdrop_depth is distance in the refracted medium, not a second-interface air gap. There is no scene-depth recovery, hidden geometry, real external environment reflection, multiple internal reflection, or caustic transport. Blur remains a spatially uniform scattering model. It is not Apple's private Liquid Glass renderer.

The glass-optics exhibit isolates index, thickness, plane distance, dispersion, Fresnel and scattering over a ruled fixture and includes a fused height field. Existing Glass/GlassGroup press response changes this height and normal together; pointer tracking changes the analytic light direction. Foreground layout stays logical, while pressable content scales around its surface center using the framework's paired prepaint/paint transform. Descendant hitboxes, IME geometry and accessibility bounds follow the displayed transform. The surface outline remains fixed. Reduced motion suppresses foreground scale. Metal pixel regressions check the inner diagonal against adjacent face pixels, retain the real arc highlight, and bound text-stroke variance at a blurred rim against the flat interior. Blur-zero Clear remains sharp. These tests do not substitute for the Linux/WGPU and Windows/HLSL native validation lanes.

Metal uses its platform gaussian when scattering is nonzero. Direct3D and WGPU split wide gaussians into bounded passes and both degrade an over-budget blur to the sharp source without dropping refraction or a requested luminance probe. The browser uses the same WGPU path, including clear optics and bounded scattering. Every backend retains full-size scratch textures and unchanged viewport coordinates, but snapshot, blur, and composite work is clipped to the integral visible surface plus three standard deviations of support for each Gaussian pass and the maximum refracted and dispersed sampling reach. WGPU evaluates each Gaussian weight once into a GPU-resident 65-entry texture and reuses bind groups whose texture roles and uniform slot are unchanged; blur fragments no longer evaluate an exponential for every tap. Metal publishes luminance probes from command-buffer completion handlers, so a query returns the most recently completed frame without waiting for the GPU and may remain one additional frame behind when completion is late.

Window::backdrop_statistics exposes encoded RGB mean and encoded Rec.709 luminance mean, minimum, maximum and population variance from the same five optical-source samples. These are not exhaustive backdrop extrema or linear light measurements. Alpha is ignored, not used to unpremultiply or weight RGB. Statistics share the lease and completion freshness of the scalar reading; existing WGPU polling and Direct3D staging mapping can wait for completion. Kit retains the last completed reading while a newer one is unavailable. Ring shadow strength responds to mean darkness or twice the sampled standard deviation, whichever is larger; sampled busyness cannot describe unsampled content. Appearance hysteresis still uses the mean and only eligible compact non-Clear controls may flip.

Window::with_rounded_content_mask explicitly scopes descendants in both prepaint and paint using logical window coordinates. Rounded chains constrain pointer input and primitive writes, including retained and deferred rendering, without narrowing the rectangular optical source capture. AccessKit receives only the conservative enclosing rectangle intersection. This does not change Style overflow behavior or add rounded clipping to external native child views. Linux tests exercise storage and integer-texture clip transport on a software GPU; the latter is not a browser GL runtime test. The portable rounded-clip pixel test, four glass-reference tests and seven Metal renderer tests also passed on an exact source snapshot on macOS 27 build 26A5416b, M4 Pro, SDK26.2; compatibility.toml records its SHA-256 identity. This does not exercise CVPixelBuffer pixels or native Direct3D, certify a native full catalog, or validate subsequent visual-scale changes.

Window::without_content_masks clears inherited rectangular and rounded masks, restoring them after its scope without resetting transforms or logical ownership. Deferred::unclipped opts in; default deferred clipping stays inherited. Kit window overlays, popover helpers and toast layers use this explicit escape. Their inner masks still apply. Later exact-source scale/frame tests and the current release's platform evidence are recorded separately in compatibility.toml; earlier clipping evidence is not reused as scale proof.

Independently, the scene admits at most 16 backdrop-glass surfaces per frame. Valid surfaces past that paint their caller-supplied ordinary-fill fallback and stay in cached paint ranges so a later paint-order change can admit them. Rejected surfaces never issue luminance probes. Ordinary Liquid and Lens paint no source-over fill while admitted; Kit supplies effect.glassAlpha as their over-budget fallback. Frosted and the explicitly adaptive readability policy already carry that fill. Adaptive surfaces begin with the safe tint and release it after the first non-opposing probe reading, so first paint and renderers without probe delivery do not expose content over an unknown backdrop.

Native external data drag and drop

macOS and Windows preserve the existing ExternalPaths contract for real filesystem paths and additionally expose pathless native data as ExternalDrop. Both platforms identify encoded images, UTF-8 text, URLs, and promised or virtual files during hover without reading item content. Content is read only after drop through a caller-supplied per-item byte limit; virtual names are sanitized, and URLs are never fetched by GPUI. macOS uses dragging pasteboards and file-promise receivers. Windows uses OLE IDataObject, including PNG/DIB, Unicode text, URL, and FileGroupDescriptorW/FileContents (IStream or HGLOBAL). A source that also exposes a real path remains a path drop to avoid duplicate delivery.

Linux keeps its existing real-path drag support and does not yet publish the new pathless payload. Web has no native desktop drag bridge in this cohort.

Framework development contract

GPUI Box is the sole framework and platform development authority. Changes are implemented, tested, documented, and released directly from this repository; Zed is neither a dependency, synchronization source, nor future compatibility target. scripts/sync-zed is an offline verifier for immutable historical attribution only. Its source list, filtered refs, and receipts are never advanced or rewritten. A deliberate future source port must receive a new, independent provenance record rather than reopening the retired import lane.

Editable layout ownership and lazy source geometry

EditableTextLayout::painted_lines() now yields (Arc<WrappedLine>, Pixels) instead of (&WrappedLine, Pixels). Ordinary .paint(...) calls continue to work through dereferencing; callers storing a borrowed line must instead retain the returned Arc. This is a source-level API change, recorded in the generated developer index. Dense and lazy layouts share the same iterator.

EditableTextLayout::unwrapped retains a persistent document and shapes only painted or explicitly queried hard lines. bounds_for_range still computes exact logical geometry, including offscreen ranges. Selection rendering must use painted_bounds_for_range to avoid shaping an entire selected document. text_width is the maximum measured line width, not a measurement of unseen lines. shaping_work counts actual submitted UTF-8 bytes and hard lines.

TextArea's new document() returns a persistent indexed snapshot; snapshot() and value() retain their contiguous compatibility contracts. This preserves caller behavior but does not eliminate their document-wide cost. See docs/coverage.md for the remaining large-file paths.

The optional Kit syntax feature adds Editor::syntax(EditorSyntax::json()) or EditorSyntax::new(language, query) for caller-selected grammars compatible with Tree-sitter 0.25.10. Consecutive TextAreaEdit events incrementally update the retained tree using UTF-8 byte columns; skipped revisions reparse. Explicit EditorHighlights for the current revision override parser colors. Parsing is synchronous, with no process or filesystem access; error nodes are reported through EditorEvent::Parsed, not silently converted to language diagnostics. EditorParseWork counts borrowed input bytes offered and requests, including repeated reads, and records whether a prior tree was reused. It does not measure the parser's internal allocations or claim constant-time parsing. The editor scene includes a JSON fixture when this feature is enabled.

Native browser host evidence

The independent gpui-box-webview package uses Wry 0.57.0 with the installed native browser engines. Linux X11/XWayland uses WebKitGTK 4.1 and GTK3; fresh orbs and the release Linux gate install libwebkit2gtk-4.1-dev. Root and headless workspaces continue to use the same local GPUI framework packages; Kit/headless do not acquire a browser-engine dependency.

Linux native smoke has exercised full CSS layout, actual browser viewport, script IPC/evaluation, HTTP navigation, back/forward/reload and native connection-refused errors. X11 attachment tests separately cover clipping, native pointer bounds, stacking and lifecycle. Windows GNU cross-compilation passes; macOS compilation and both platforms' interactive browser validation remain required. This is not native Wayland parity. See webview.md for the XWayland product route, unsupported composition operations, permission policy constraints and exact reproduction commands.

Editable viewport browsing

TextArea/Editor wheel and touchpad input can leave the caret offscreen. Only editing and explicit selection/navigation reveal it again. Read-only areas remain scrollable; disabled areas do not install a wheel handler. Consumption uses Window::consume_scroll_delta, including independent axes, partial-edge remainders and native line units, without swallowing overshoot. The no-wrap horizontal extent retains the maximum width measured since the last set_value, rather than shrinking when a shorter row enters the viewport. This deliberately permits trailing blank space after shortening the widest line; it avoids a horizontal jump while browsing and never pre-shapes unseen lines to discover their widths.

Accessible text publication segments words once globally and indexes their grapheme positions once, retaining word starts across visual, bidi, and 255-grapheme run boundaries. Bidi direction scans stop at the run limit. Publication still builds a full-document accessibility tree and copies its source snapshot: this removes quadratic segmentation, not all linear costs. The platform-independent tests include mixed Unicode and 1,000/10,000-row JSON fixtures with a byte-visit budget. Native accessibility adapter behavior is unchanged; macOS and Windows execution remains a separate validation lane.

TextArea and Editor expose primary-first selections/set_selections, painted select_rectangle, and atomic original-document range replacements. Overlaps and duplicate carets merge; invalid batch boundaries are refused before edits. Alt-click toggles a caret; Alt-Shift-drag selects painted columns and clamps short rows to their ends. Navigation and typing operate on every selection; one multicursor edit is one undo step. IME uses only the primary selection, clears secondary carets during composition, and restores the previous set on undo. Accessibility selection continues to describe the primary native caret. Final-glyph hit testing now chooses the nearest start/end caret, including multibyte single-glyph lines, instead of always choosing end-of-line.

A11ySubtreeBuilder::retain_child retains unchanged synthetic leaves only while they remain connected across active frames. A removed or inactive-frame leaf must be fully published before reuse; unchanged ids do not imply a live platform node. AccessibleTextCache uses this contract for TextArea logical runs. It rebuilds text segmentation on revision, row, or direction changes; scrolling refreshes current and former viewport geometry, retaining offscreen text payloads. Debug accessibility dumps accumulate incremental updates into the complete tree rather than exposing only the latest delta.

This bounds text-run payload publication on scroll, not every frame operation: parent child-id lists and live-id bookkeeping still scale with run count, and a text revision still invalidates the logical cache. Compatibility whole-value events and semantic values remain separate allocation work. Platform-independent tests cover complete 1,000/10,000-row content, distant select-all endpoints, bounded viewport cell queries, removal/reattachment and mid-frame deactivation.

Source migration: TextAreaEvent::Change and EditorEvent::Changed now carry gpui::EditSnapshot, not SharedString. Read slices or indexed line/UTF-16 positions without a full copy; call snapshot.text() explicitly for the old contiguous value. String signal bindings and MentionInput's existing string event retain their compatibility conversion at the subscribing consumer. Internal Editor forwarding does not flatten the snapshot.

EditSnapshot::difference_from computes a scalar-aligned single replacement using borrowed chunks. Its compared_bytes and shared_bytes report actual comparison and identity-skipped work; inserted.len() is the copied payload. The regression edits a 100,000-row persistent snapshot, compares under 8 KiB, and leaves both contiguous caches empty. Independent equal snapshots can still require full comparison, and separated multicursor changes can span unchanged text in the single-delta compatibility representation. This is not a claim that rendering or new-revision accessibility publication is bounded.

Editor language services are opt-in via language_services(true). Ctrl-Space, F12, Ctrl-K Ctrl-I and Ctrl-. emit completion, definition, hover and code-action requests carrying persistent snapshots and exact UTF-8 byte coordinates. Callers publish AsyncValue replies against the request id; stale revisions, duplicate identities, split-grapheme edits and overlapping batches are refused. Completion and local code-action replacements use one shared undo transaction. Definition targets and external code actions emit events; Kit never opens a file, launches a server or executes a host command. Refresh errors retain the last verified visible result but do not permit its acceptance. Navigation, blur and text revision changes invalidate outstanding responses; an open completion requests a new revision after typing. Diagnostics and semantic tokens are revision-paired, with semantic colors overriding only covered parser spans and severity underlines layered over both. The editor-services exhibit uses explicit caller fixtures for ready, loading, refusal and hover.

AccessibleTextCache::publish_document accepts persistent snapshots and resegments changed LF-delimited paragraphs, preserving unchanged offscreen TextRun ids and payloads across byte/line shifts. It verifies unchanged row mappings and falls back to a full segmentation when direction or wrapping outside the edit changes. Native position lookup indexes the run first and uses at most one run's selectable units instead of recounting the document prefix. Old published snapshots still refuse a different current revision. TextArea::accessibility_work exposes the last publication's segmented bytes, compared bytes, published run/value bytes and retained run count. These are not whole-frame allocation counters: complete source compatibility strings, run metadata, parent child-id lists and native parent values remain linear. The parent value is deliberately preserved: upstream AccessKit 0.24.1 omits Windows Value-pattern support and macOS AXValue when a multiline input omits its own value, even when all TextRun descendants remain available. Linux platform-independent tests cover incremental native trees and Unicode equivalence; macOS/Windows execution remains the separate platform lane.

TextArea keeps current logical text children connected on the first edit relayout frame. Stale layout withholds painted geometry, not document content; soft wrapping temporarily publishes complete hard rows until its new measured rows are available. The mounted first-draw regression checks native value and all 1,003 text runs before any settling frame, plus the combined former/current viewport publication budget. This continuity is required for retained native ids to remain reusable across real edits.

Source folding preserves document coordinates

EditableLineProjection stores visible line spans rather than one entry per source line. EditableTextLayout::unwrapped_projected shares the projection across paint, clipping geometry, hit testing, selection and vertical navigation. AccessibleTextCache::publish_document_regions keeps disjoint painted ranges separate while retaining complete logical text and native Value/AXValue. This does not make complete metadata or native parent values sublinear.

Editor::set_folds accepts revision-tagged, caller-identified hard-line ranges. The header remains visible. Nested ranges are accepted, crossing ranges refused. Gutter controls and Ctrl-Alt-F toggle transient state; a source edit invalidates the ranges, and navigation into hidden text expands its ancestors. Callers publish new ranges after parsing the edited revision. Disabled controls have no toggle handler; read-only controls still allow browsing. The additive EditorEvent::FoldChanged variant requires exhaustive consumers to add a case. Line geometry reports original source line numbers, not projected row numbers. The editor-folding exhibit reviews nested collapsed and expanded headers. Linux framework/input checks cover projection and retained Unicode text; macOS/Windows rendering and native adapter checks remain their dispatch lanes.

Retained editor options preserve the editing session

TextArea, Editor and RichTextEditor expose mutable option setters; hosts do not need to replace an entity when layout or service policy changes. The editor-options exhibit applies these options after construction. Text, selection, IME composition and history remain attached to the original session. Wrapping/size changes invalidate measured geometry without resetting text. Disabling keeps the existing refusal/cancellation semantics; re-enabling does not steal keyboard focus.

TextArea::set_max_length(None) removes the future-input byte limit. Lowering the limit never truncates existing text or history. Optional row caps on both text editors accept None to keep fixed minimum-row height, including after later minimum-row changes; TextArea's optional autosize pair can also be removed. Editor owns its retained rows/read-only/disabled state and updates its child immediately, so rendering does not overwrite host transitions. Optional indentation and syntax providers accept None; disabling language services removes outstanding popups and releases claimed completion/navigation keys. Native full-document values remain complete; these setters make no additional large-document performance claim.

Explicit touch sizing is not mobile platform certification

ControlSize::Touch selects the new required control.touch token step. Custom theme JSON must add that step; exhaustive Rust matches on ControlSize must handle the new variant. Bundled themes use a 48 logical-pixel target height, 16px text and 20px icons. Compact density leaves touch metrics unchanged, while explicit Theme::scaled scales them like other subtree geometry.

Desktop size defaults are unchanged. Components opting into Touch must retain usable nested actions and allocate actual target width, hit bounds and accessible bounds consistently. The token does not expand an arbitrary element's hit area or establish mobile keyboard, screen-reader or device support. Native platform and mobile component validation remains separately required by the delivery ledger in tasks/mobile-platform-delivery.md.

BoundsTree balance preserves primitive ordering

The framework-private bounds index uses equal-depth leaves and propagated overflow splits. Its generic unit bounds and public scene/renderer contracts are unchanged. Each insertion still returns one plus the maximum assigned order among prior bounds intersecting under Bounds::intersects, including strict edge comparisons and the existing zero-size behavior. A global-max representative miss does not rule out a tied maximum elsewhere in the tree.

Insertion depth is logarithmic; arbitrary overlapping-subtree search remains linear in the worst case. CPU-only workload evidence and reproduction commands live in bounds-tree-performance.md. These checks do not establish FPS, GPU performance or native presentation. Linux headless catalog and full gate checks are integration requirements; macOS Metal and Windows WARP remain their separately executed platform lanes. No baseline, shader, renderer, package authority or frozen historical receipt is changed.

Measured descriptive leaves are not interactive controls

gpui_kit_semantics::MeasuredLeafBatch publishes many caller-measured Image or Text leaves through one layout element and a real native Group. It does not accept general NodeSpec, focus, actions, ranges or cross-node relationships. Diagnostic parentage is explicit and does not change native ancestry. Native leaf ids derive from the mounted batch identity and stable caller business ids, not list order. Label/description/value redaction and diagnostic selection are preserved; Image/Text native selection remains unset, as for ordinary semantics.

The current-prepaint callback supplies untransformed logical window bounds and is skipped when both outputs are inactive. Diagnostics retain the existing transformed-logical, unclipped convention. Native publication uses the existing physical-pixel transform and conservative ancestor clips, including zero-area fully clipped leaves while the owner is published. The caller owns actual shape visibility, holes and viewport intersection. No per-leaf layout snapping is introduced; fractional caller bounds can differ from old Div/Taffy rounding. No hitboxes or input handlers are installed by the batch.

Window::debug_a11y_tree_json additionally exposes committed physical bounds as {x0,y0,x1,y1} when present. This is additive inspection data, not a native behavior change. See measured-semantic-leaves.md for usage, mounted tests and CPU evidence. Linux TestPlatform checks are not macOS/Windows screen-reader, device-touch or native GPU certification.

Virtualized row layout motion uses framework placement

Window::with_placed_element_offset declares the actual placement of a root-laid-out subtree separately from its scroll offset. ambient_element_offset excludes that layout contribution. UniformList supplies its own measured slot; FLIP no longer mistakes virtual-row reorder for ambient scrolling. Existing offset APIs and paint, clip, hit and native bounds remain unchanged. Ordinary nonvirtual FLIP coordinates are unchanged outside declared placement scopes.

TraceView and SpanTimeline animate surviving mounted hierarchy rows by default. animate_layout(false) settles them; layout_animation changes their timing independently of time-viewport motion. Caller collapse/selection remains authoritative; removed rows immediately lose live authority. Newly revealed rows wait for survivors to settle before mounting in place, so final-slot content cannot overlap moving rows. Waiting rows have no handlers or semantic targets. Caller selection changes, scrolling, disabled motion and reduced motion settle immediately. Initial mounting and ordinary scrolling do not delay publication. There is no recorded Trace row exit fade. Variable-height List and other custom root-placement adapters do not yet declare content-space placement; virtual reflow support for those adapters is not claimed. Linux mounted tests do not replace macOS/Windows native acceptance.