Repository navigation
Conversation
|
Thanks for this. Your host side (DeviceDesktop, the StreamCoordinator and WindowCatalog changes, and |
The viewport carries a new optional Viewport.deviceDesktop. With it, the host makes a virtual display at the device's size (divided by Aa's scale, 2x HiDPI, at least 320x240 pt) and makes it the main display while the Desktop streams, so the device shows a whole Mac desktop edge to edge with no black bars. Another source, the last device leaving, or Quit gives the main role back and removes the virtual display. WindowCatalog never takes one of Sill's virtual displays for the real screen. Split from the single commit of Saffsanity#156 so the host side can be carried separately. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Thanks for the heads-up, and for carrying the host side unchanged. That works for me. I've split my commit into a host-side one and a device-side one (the second-tap full screen), so the device side rebases cleanly onto #161 once it lands. I'll keep #156 open until then and, if #161 goes in first, rebase it down to just the device-side commit. |
|
From a pass over all the open pull requests (nothing is decided yet): #161 carries this PR's host half unchanged and replaces the second tap on Desktop with its Immersive mode, conflicting in |
While the Desktop streams, a second tap on Desktop shows it full screen: the bars, thumbnails, key row and trackpad go, and two small buttons on the trailing edge bring up the keyboard or leave full screen. iPadOS's status bar is hidden and its edge gestures are deferred so a touch at the top reaches the Mac's menu bar. The viewport asks for Viewport.deviceDesktop while full screen is shown. Depends on the host side (Viewport.deviceDesktop). Split from the single commit of Saffsanity#156. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
490d97a to
8a759d1
Compare
|
Thanks for going through all of them. Agreed on landing the device desktop once: #156 is now split into two commits, the host side (same as in #161) and the device side (second tap), so whichever goes first, I'll rebase this PR down to the device commit. On #155: the new For #66, #72, #73, #158 and #150, I'll reconcile with whichever lands first rather than guess now. Happy to adjust the Sill-display filter or the full-screen pane if you tell me which direction you prefer. |
|
Update on the build: I have now built it. Debug and Release for the iOS Simulator and Debug for a device (unsigned, Xcode 27.1) all succeed, with only the known |
|
The decision on hiding the bar is on #92: a toggle in Settings on the device, with a shake of the device bringing the bar back. A second tap on Desktop does not fit that shape, so the device half here would change to it, or stay out. |
|
A heads-up, since you were holding #156 for #161: I've closed #161 in favour of #197 for hiding the bar, per Noah's decision on #92. Your host commit is now carried unchanged, under your name, in #312, which sits on top of #197. The one conflict with main is in |
Conflicts: - StreamCoordinator: the Desktop's capture moved into desktopCapture(). It takes the device's own display (on:), as Saffsanity#312 resolves it, and the one more try after a failed start passes it too while it lives, so capture and input stay on one display. - StreamScreen, PortraitStreamScreen: both sides kept (the caret note and the pinch zoom beside the full-screen mode). The full-screen picture follows the layouts' since main: ZoomedStreamView and the zoom, the Mac's key repeat for a hardware keyboard, the locked Mac's cover. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, I checked #312. DeviceDesktop, WindowCatalog and Viewport match my commit line for line, and passing the device display through One thing in the retry: guard !shuttingDown, let next = await desktopCapture(on: deviceDesktop.isLive ? deviceDesktop.scDisplay : nil) else {(or release it before the retry, if you'd rather fall back to the real screen). I've merged main into #156 (43f38f6) with the same resolution as yours plus that line, so whichever lands first carries it. The merge also brings the full-screen picture in line with main's ( |
…Desktop's display While a device plays the Mac's sound, the Mac's own output is muted (MacOutputMute), as High Performance screen sharing does, and unmuted when no device plays it, when Sill quits, or at the next start after a crash. Only a device Sill muted itself is unmuted, and only while it is still muted. ScreenCaptureKit takes each app's sound before the output device: a probe on this Mac caught the same peak (0.0547) with the output muted and not. The Desktop's sound is captured on its display: the device's own while it lives. A capture made on the other ended when the display changed (SCStreamErrorDomain -3815), and the pipeline tried again only at its next request, 10 s at the soonest. AudioPipeline.renew starts the same source again when the Desktop's display changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ives The Mac's own displays get a black window of Sill's at the shielding level, and the windows on them are moved onto the device's display (WindowSizer, each back to where it was on release), as Screen Sharing's High Performance mode leaves the host. Mirroring the Mac's screens onto it, tried first, cost the stream its rate (a 2560x1440 HiDPI screen among them: 0.7 Mbps carried, frame age 3 to 5 s) and ignored its gamma, so it is gone. Not working yet: at the device desktop's start AppKit listed one screen of three and the window list still had the old frames, so nothing was covered or moved (the new log lines say so). The rest of the feature is unaffected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the sound Out of full screen every frame shows as it decodes, as before. In full screen each frame shows at its stamp plus the offset at which the Mac's sound of the same stamp is heard (AudioPlayout.pictureOffset, published by AudioOutput), on a host-clock timebase on the display layer (PictureClock); with no sound, at its stamp plus the link's floor and jitter cover of the last 10 s (20 to 150 ms). On Wi-Fi a 25 fps video showed 21 to 23 frames a second and the sound trailed the picture by about 165 ms; now its frames keep their cadence and the picture and the sound go together, for 100 to 170 ms more latency in full screen alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The windows are read (frames and their Accessibility elements) before the device's display becomes main, while the window list still has their frames; read after it, every window looked as though it already was on the device's display or matched no Accessibility window (5 of 5 left). They move once AppKit has caught up (at most 3 s), and go back after the main role has, in the arrangement their frames were read in. The curtains are placed by CoreGraphics' bounds in AppKit's coordinates: AppKit had listed one screen of three there. On this Mac (a 2560x1440 screen and the MacBook's): 2 windows moved onto the device's display, both screens dark with "This Mac is in use on a device." Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A suggestion: the Desktop in full screen, with the Mac giving it a display of the device's own size, as Screen Sharing's High Performance mode does: the Mac's own screens dark, its sound heard on the device alone, and the picture in step with it.
What it does
On the device
defersSystemGestures(on: .all)), so a touch at the top reaches the Mac's menu bar. Anything else streaming ends full screen. The full-screen picture is the layouts' (ZoomedStreamViewand the pinch zoom, the Mac's key repeat, the locked Mac's cover).PictureClockin HEVCDisplayView.swift, a host-clock timebase on the display layer): its stamp plus the offset at which the Mac's sound of the same stamp is heard (AudioPlayout.pictureOffset, published byAudioOutput); with no sound, its stamp plus the link's floor and jitter cover of the last 10 s (20 to 150 ms). On Wi-Fi a 25 fps video showed 21 to 23 frames a second with the sound about 165 ms behind; now the frames keep their cadence and picture and sound go together, for 100 to 170 ms more latency in full screen alone. Out of full screen every frame shows as it decodes, as before.On the Mac
Viewport.deviceDesktop. With it, the host makes a virtual display at the device's size (÷ Aa's scale, 2x HiDPI, at least 320×240 pt) and makes it the main display while the Desktop streams: menu bar and Dock move there. A rotation or an Aa step makes it again at the new size. Another source, leaving full screen, the last device leaving, or Quit gives the main role back and removes it (DeviceDesktop.swift, the same private API and vendor ID asVirtualStage, its own product ID).WindowCatalognever takes one of Sill's virtual displays for the real screen.WindowSizer, read before the arrangement changes, each back to its frame afterwards), and each of the Mac's own screens gets a black window of Sill's at the shielding level, "This Mac is in use on a device.". No mirroring: mirroring the Mac's screens onto the virtual one, tried first, cost the stream its rate (0.7 Mbps carried with a 2560×1440 HiDPI screen among them) and ignored its gamma.MacOutputMute), and unmuted when none does, at Quit, or at the next start after a crash; only a mute Sill set is undone. ScreenCaptureKit takes each app's sound before the output device: a probe here caught the same peak with the output muted and not. The Desktop's sound is captured on the device's display while it lives, andAudioPipeline.renewstarts it again when the Desktop's display changes (a capture on the other one ended with SCStreamErrorDomain -3815).Compatibility
Additive only:
deviceDesktopis optional. An older host ignores it and the device shows the Mac's real screen full screen (fitted); an older device never sends it. The device desktop needs the AppKit loop (Sill.app, or the CLI with--virtual-display) and is never made on a synthetic host, which also never mutes the Mac. On the hiding-the-bar decision in #92 (a Settings toggle with a shake back): the device half here is a second tap; it can move to that shape, or stay out and leave the host half to #312.Tested
swift build -c release, Sill.app viamake-app.sh, the iOS app Debug and Release for the simulator and Debug for a device (Xcode 27.1), only the known warnings;Tests/checks/run-all.sh, all passingsillclient.py, as before; the harness on an iPad simulator, in and out of full screenKnown, not done
DeviceDesktoporPictureClock; no docs or plan file; nothing on an iPhone or with two devices at once.Happy to adjust anything.
🤖 Generated with Claude Code