Skip to content

Add native visionOS client with independent spatial windows - #158

Open
GeezusChrotch wants to merge 27 commits into
Saffsanity:mainfrom
GeezusChrotch:visionos-client
Open

GeezusChrotch wants to merge 27 commits into
Saffsanity:mainfrom
GeezusChrotch:visionos-client

Conversation

@GeezusChrotch

@GeezusChrotch GeezusChrotch commented Oct 18, 2026 •

Copy link
Copy Markdown

Native Vision Pro client

Related to #119. This adds a native visionOS 2+ client built around Sill’s shared iPad interface and streaming stack. The current review candidate is 0.39.0 (39) with Mac host 0.5.1 (807). Both are installed on the development hardware. Following iterative headset testing, the contributor considers this version ready to share for maintainer review; this is not a distribution-ready or exhaustively device-qualified release.

User experience

  • Toolbar controls use white icons on individual black circles; both bar containers are transparent. Window thumbnails have individual rounded black backings. Active controls retain a white outline and accessible selected state. The native Mac menu trigger uses an explicit circular highlight to match the toolbar controls.

  • Window previews and Desktop sit above the picture; Apps, Mac menus, text size, Touch/Mouse, Keyboard, Settings and Lock sit to its left. Borderless black glance pills at50% opacity and sized to one-third of the window width or height reveal both bars in Auto mode; the build34 gaze presentation remains after build35 caused rapid flicker and unclickable controls. Build37 keeps one group identity on visionOS26+, resets its phase through one override owner, and separates native control highlights from coordinated fades. The bars cover the pills without changing stream layout. Full-size hidden hover geometry remains unresolved; compact-only interaction is not claimed. Lock keeps them open. Revealing both bars requires a0.65-second gaze dwell, including with Reduce Motion.

  • Hold a preview for half a second to close, minimize, enter full screen, or Open as own window. Each additional spatial scene has its own app/Desktop selection, controls and stream.

  • Scenes fit the selected window’s aspect ratio. A transparent edge buffer separates remote controls from native resize corners. The picture and input surface share the inset viewport; a proportional margin preserves the aspect during native resizing (about8pt on the shorter opening edge, capped at1.67% per side). Outer scene size/restoration and toolbar anchors remain unchanged. Desktop uses source-acknowledged HEVC dimensions. Geometry changes release the old ratio, observe the actual resized bounds, then confirm the new uniform lock. Opening sizes remain unchanged; native resizing permits a source-fitted3840×2880-point envelope (3840×2160 for16:9 Desktop), subject to system constraints.

  • Touch supports direct targeting and scrolling; Mouse supports precise relative pointer movement. A physical mouse/trackpad owns the native pointer while over the surface, suppressing the duplicate app sprite through typing and scrolling; host movement and hand input reclaim sprite ownership. Physical hover filtering remains a headset qualification gate. Keyboard tap enables typing until that Sill scene loses focus; repeated taps keep it enabled, and a half-second hold opens keyboard/paste tools. Mac window/Desktop switches preserve capture. Local controls suspend the responder while preserving the enabled session; a deliberate stream tap or Keyboard resumes. Capture requires deliberate local intent: only the Keyboard action may make the window key; a recent single-use click plus matching host confirmation may acquire in an already-key scene. Passive restoration and gate reopening cannot reacquire; resignation invalidates pending intent. The contributor reports build26 focus stealing appears fixed; build27 session persistence and cross-app headset behavior still need confirmation.

  • Running-app inventory includes minimized apps. Launch-only sill://open and sill:// links preserve session state; pairing links retain confirmation. Settings opens on the left beside its toolbar button on visionOS; iPad placement remains unchanged. Touch/Mouse instructions and cursor recovery live in a Settings disclosure; no pointer-help panel covers the Mac picture.

  • Workspace restoration saves each scene’s paired Mac, selected window/Desktop, native size, Touch/Mouse mode, text scale and toolbar Auto/Lock preference. Window identities reconcile against the host catalog rather than trusting recycled numeric IDs. Missing or ambiguous windows fall back to Desktop after a bounded catalog grace; source restoration requires host acknowledgement. No apps are launched to recreate missing windows. Keyboard starts off. Disconnect/Forget clear saved intent; a bounded journal now recovers missing scenes after whole-app exit using stable scene identities. Native session bindings and bounded replay prevent duplicates. Restore membership is separate from fallback descriptors; legacy entries enroll only when their scenes are observed active. All-background followed by actual activation reopens hidden scenes even when the process survives. Individual disconnect/discard retirement is settled briefly to distinguish whole-workspace closure; explicit Disconnect/Forget clears saved intent. Single-window background alone is ambiguous with out-of-view backgrounding and does not retire membership. Settings → Sill windows provides persistent restore exclusions, Restore only this window, and explicit Close this Sill window; exclusion is saved before native dismissal so late saves cannot re-enroll it. Exact placement remains system-controlled.

Host changes and review boundaries

The host supports up to four opt-in independent sessions. Capture, encoder, viewport, menu state, pointer geometry and stream replies are scoped per connection; TLS identity, admission, revocation and listeners remain shared. Legacy clients retain their shared pipeline. Additional scenes require an independent-capable host, receive an explicit refusal otherwise, and restore only through existing trusted pairings. The primary scene can still use an older host.

The Mac still has one physical keyboard/mouse and key window. Foreground ownership, held-key release and stale queued work are fenced. Multiple viewers can share a Mac window; the first owns fitting and original placement is restored after the last leaves. Independent sessions can use separate Virtual Displays with distinct display identities, per-stage restoration and child teardown. A window staged by one session cannot be selected by another until released; already-shared real windows stay in regular capture. Desktop excludes Sill virtual displays. Session settings are local; reconnect inherits the Mac default. A generation barrier prevents retired encoders from emitting stale format/video after source changes. See docs/independent-sessions.md for the detailed boundaries.

Optional host capabilities add running-app inventory, eligible offscreen/cross-Space discovery, minimized-window restoration and editable-focus confirmation. The kind-33 protocol allocation and shared-host changes need maintainer review, including compatibility with other ongoing protocol work. This contribution can be split if preferred.

Validation and remaining qualification

  • Build30 addresses a second owner-reported two-window restoration failure. Device inspection confirmed build29 survived close/reopen in the same process and its capped journal held four secondary descriptors with no primary. The new journal separates observed membership from fallbacks, admits visible scenes over stale descriptors, and rearms bounded recovery after all scenes background and Sill becomes active again. Legacy desired windows must be opened once under build30 to enroll. Numeric-only bounded diagnostics distinguish presentation requests from subsequent native activation. The scene-set policies passed2,557 checks covering this lifecycle; the simulator Home overlay did not background the scenes, so a same-process native UI success is not claimed. The owner subsequently confirmed the whole-app two-window recovery worked on build30. Broader individual-close and lifecycle qualification remains pending.

  • Build28 added32 workspace restoration checks covering descriptor privacy/bounds, partial catalogs, identity ambiguity, acknowledgement/timeouts, stale callbacks and size recording. Native simulator restoration preserved2400×1350 through disconnected/no-source/pending-dimensions states and confirmed the final uniform lock and saved size. This synthetic diagnostic does not establish force-quit/relaunch or multi-scene restoration on a headset.

  • Build35 was rejected on the headset: native hover-presented bars flickered and their controls/window previews were unclickable. Build36 restores the exact build34 toolbar code and preserves build35 pointer ownership, explicit restoration controls and removal of nine unused prototype files. Canonical visionOS Simulator Debug and signed Release builds, strict signature verification and controls1,015 checks passed. Build36 is installed, inventoried and remotely launched. Headset retest is pending. The original full-size hidden hover geometry remains unresolved. Build35 pointer/scene/keyboard checks remain valid for unchanged code, but did not establish toolbar usability.

  • Current client: canonical visionOS Simulator Debug and signed device Release builds passed. Build30 workspace32, scene-opening18, controls1,015, size-policy and spatial input138 checks passed. Earlier hardware-keyboard59 plus20,000 randomized sessions (690353 events), editable-focus policy/wire and key-stroke347 plus randomized coverage also passed.

  • Host changes passed focused checks and synthetic loopback tests for independent routing, legacy coexistence, clipboard, teardown, capacity/refusal and slot reclamation. Mac app/CLI Release builds passed.

  • iPad flat-reference builds passed on Xcode 27.0; normal Duo-enabled Xcode 27.1 validation remains required. Current shared changes also passed the iPad flat-reference build.

  • Native simulator aspect transitions and toolbar layouts were inspected. A native resize reached2400×1350 with uniform restriction. The real UIKit responder diagnostic confirmed explicit acquisition, rejection of passive/canceled/blocked restoration, repeated-button/source-switch persistence, local UITextField suspension, deliberate resume, and an observed same-scene key-window handoff clearing the session without automatic return; it does not simulate cross-process headset keyboard routing. Numeric headset diagnostics confirmed initial Desktop geometry. Public contribution files match the validated canonical source; changed upload bytes and commit ranges passed secret scans. No GitHub checks are currently reported for this branch.

Headset iteration has established practical usability, but targeted cross-app keyboard ownership, gaze/hidden hit behavior, simultaneous-scene focus/restoration, IME/dictation, Bluetooth input, clipboard consent, reconnect/remote pairing, old-host fallback, sustained performance and shared-host iPhone/iPad regression still need broader qualification. Launch-link end-to-end confirmation also remains outstanding.

Apache-2.0 is retained. The visionOS project includes no development team or provisioning profile; contributors select their own signing identity and bundle ID. Official signing, release versioning, TestFlight/App Store distribution and final platform support remain maintainer decisions. Developed with AI coding assistance and human headset testing.

Build37 follow-up: owner reports zones appear after actions and identifies top-right/bottom-left corners. Source confirms unbounded prior hover-group identity changes and inherited native highlight coupling; it does not establish that either caused every phantom.25 policy checks cover10,000 admitted input events plus structural single-owner/local-highlight invariants. Canonical visionOS Debug/signed Release/iPad flat-reference builds and strict signature pass. Settings-left visually checked in simulator. Installed/inventoried37; remote launch timed out, manual launch required. The owner tentatively reports that build37 helped the phantom zones; broader interaction qualification remains pending. No manual-pill redesign integrated.

Host807 follow-up: explicit off-Space picks activate the running app and fetch a fresh ScreenCaptureKit handle for the exact selected window before capture. Conservative catalog eligibility remains unchanged. Packaged Release and strict signature pass; installed/launch verified with unchanged designated requirement. Focused source lifecycle8, app-selection32/client14, catalog17 plus bounded worker tests pass; independent synthetic routing/teardown/capacity harness and window-restore41,506 checks pass. Actual full-screen Space selection, simultaneous virtual displays and display-loss recovery still require hardware acceptance. Client37 is unchanged.

Build38: canonical visionOS Simulator Debug/signed Release/iPad flat-reference builds and strict signature pass. Geometry, actual production input-transform extraction and hover25/structural checks pass; workspace32, controls1,015, spatial138 and scene-opening18 checks pass. Blue-sample simulator layout inspected. Installed/inventoried/launched0.38.0(38); physical corner targeting with gaze/trackpad remains pending. Host807 unchanged.

Build39 reduces the complete build38 buffer to one third, including cap/fallback, and makes it transparent. Canonical visionOS Debug/signed Release/signature and geometry/input/hover checks pass; simulator appearance inspected. Installed/inventoried39; physical edge-targeting qualification remains pending. iPad and host paths unchanged.

@GeezusChrotch GeezusChrotch mentioned this pull request Oct 18, 2026
@GeezusChrotch GeezusChrotch changed the title Add native visionOS client with shared iPad UI and spatial input Add native visionOS client with independent spatial windows Oct 18, 2026
@GeezusChrotch
GeezusChrotch marked this pull request as ready for review October 18, 2026 23:44
@Saffsanity

Copy link
Copy Markdown
Owner

From a pass over all the open pull requests (nothing is decided yet): kind 33, which this PR takes for editableFocus, is case audio = 33 in #66 (and #72 and #73, built on it), and #94 puts audio on kind 43 with checks that assert 33 unknown; since kind numbers are never reused, one of them has to move before either merges. #66's side streams and this PR's independent sessions are two multi-window host designs in the same StreamCoordinator, StreamServer and WindowCatalog, and #124 reworks StreamServer for QUIC, so the second to land fits into the other's (#156's per-coordinator desktop is only a latent clash: only visionOS hellos ask for independent sessions). The visionOS target would also compile other PRs' iOS-only code from iOSClient (window?.screen.scale in #96 and #107, #94's audio files, #147's text input and #161's Immersive in InputOverlay.swift and StreamScreen.swift, #156's device desktop, #128's macOS branches, #155's iOS 16 shims), and the rest (#99, #100, #111, #142, #150, #152, #159) are textual overlaps where both sides stay.

@GeezusChrotch

Copy link
Copy Markdown
Author

Thanks for mapping out the overlaps. Happy to adapt this contribution to the direction you choose rather than introduce competing host designs.

Do you have a preferred protocol allocation for editableFocus, and a preferred integration order/design for #66’s side streams, this PR’s independent sessions, and #124’s transport changes? We’ll hold off on renumbering or restructuring until that direction is clearer. We can also split the visionOS client and host changes if that makes review easier.

The audio work is exciting too—especially #94’s shared device playback path. We’d love to bring that to Vision Pro and help test it on the headset once the shared approach is settled. We haven’t validated visionOS audio compatibility yet; multi-scene playback and avoiding duplicate audio from the same Mac app will need attention.

The current headset build is working well in hands-on testing, and Virtual Display behavior has now been confirmed. We’ll keep that working baseline stable while coordinating the integration and checking shared iOS code for visionOS compatibility.

Saffsanity added a commit that referenced this pull request Oct 19, 2026
The plan gains the section on #66 (DisplayInfo's shape, its kind 40),
#156 and #161 (the device desktop as main) and #158 (a coordinator per
session); CLAUDE.md's Current step gains this change's entry, its results
to follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants