Skip to content

Direct IOSurface screenshots and JPEG encoding#33

Merged
obj-p merged 4 commits intomainfrom
screenshots
Mar 21, 2026
Merged

Direct IOSurface screenshots and JPEG encoding#33
obj-p merged 4 commits intomainfrom
screenshots

Conversation

@obj-p
Copy link
Owner

@obj-p obj-p commented Mar 21, 2026

Summary

  • iOS simulator screenshots: Replace xcrun simctl io screenshot subprocess (~200-500ms) with direct IOSurface framebuffer capture via CoreSimulator's SimDeviceIOClient (~5-10ms). Falls back to simctl if IOSurface access fails.
  • JPEG encoding: Switch both macOS and iOS paths from PNG to JPEG (default quality 0.85) for ~10-50x smaller payloads. Add quality parameter to preview_snapshot MCP tool.
  • macOS snapshots: Replace deprecated CGWindowListCreateImage with NSView.cacheDisplay(in:to:) — captures content view directly, no Screen Recording TCC permission needed.

Addresses #11, #26, and partially #19.

Changes

  • SimulatorBridge.h/m — New SBCaptureFramebuffer() accessing SimDevice.io → IO ports → SimDisplayIOSurfaceRenderable → IOSurface → CIImage → JPEG/PNG
  • SimulatorManager.swift — Tries direct capture first, falls back to simctl subprocess
  • Snapshot.swiftNSView.cacheDisplay with JPEG/PNG format support
  • MCPServer.swiftpreview_snapshot accepts optional quality param (0.0–1.0 = JPEG, ≥1.0 = PNG)
  • Package.swift — Link IOSurface, CoreImage, CoreGraphics, ImageIO, UniformTypeIdentifiers on SimulatorBridge

Test plan

  • swift build — clean build, zero warnings
  • swift test --filter "PreviewParser|IOSHostBuilder|ThunkGenerator|LiteralDiffer|Compiler|BuildSystem" — all 29 fast tests pass
  • Integration tests (SPM example) — macOS rendering, iOS interaction, hot reload all pass
  • swift test --filter "bootAndShutdown" — validates IOSurface capture on real booted simulator

🤖 Generated with Claude Code

obj-p and others added 4 commits March 20, 2026 23:35
Replace simctl subprocess with direct framebuffer capture via
CoreSimulator's SimDeviceIOClient for iOS simulator screenshots.
Falls back to simctl if IOSurface access fails. Switch both macOS
and iOS paths from PNG to JPEG (default quality 0.85) for ~10-50x
smaller payloads. Migrate macOS snapshots from deprecated
CGWindowListCreateImage to ScreenCaptureKit's SCScreenshotManager.

Addresses #11, #26, and partially #19.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ScreenCaptureKit requires Screen Recording TCC permission, which
fails for a headless MCP server. Use NSView.cacheDisplay(in:to:)
instead — captures the content view directly from the layer tree
with no permissions needed. Also reverts callers to synchronous
since cacheDisplay is not async.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix simctl fallback passing --type=jpeg when JPEG was requested,
  preventing MIME type mismatch (PNG data labeled as JPEG)
- Cache CIContext as static singleton instead of recreating per capture
- Wrap ioPortDescriptor call in @try/@catch for private API resilience
- Inline screenshotViaSimctl into screenshotDataViaSimctl
- Clamp quality parameter to 0.0-1.0 (not 1.5)
- Update SnapshotCommand to default to .jpg and respect file extension
- Remove unnecessary CoreGraphics linked framework
- Add PNG output test case (jpegQuality: 1.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@obj-p obj-p enabled auto-merge (squash) March 21, 2026 03:38
@obj-p obj-p merged commit 853831b into main Mar 21, 2026
2 checks passed
@obj-p obj-p deleted the screenshots branch March 21, 2026 03:40
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.

1 participant