Skip to content

feat(screenshot): add --with-frame for full macOS window capture#15

Closed
Shadow-Azure wants to merge 9 commits into
mainfrom
feature/screenshot-with-frame
Closed

feat(screenshot): add --with-frame for full macOS window capture#15
Shadow-Azure wants to merge 9 commits into
mainfrom
feature/screenshot-with-frame

Conversation

@Shadow-Azure

@Shadow-Azure Shadow-Azure commented Jun 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add --with-frame flag to sandbox screenshot command for capturing the full macOS window (titlebar, traffic lights, tab bar, status bar)
  • Default mode captures terminal-only content via Renderer WebSocket → xterm.js captureToPng()
  • --with-frame mode captures full Electron window via ScreenCaptureKit
  • Two capture paths: renderer-based (terminal only) vs ScreenCaptureKit (full window)

Architecture

CLI screenshot --id <id>
  → daemon HTTP GET /sandbox/{id}/screenshot?with_frame=true
  → if with_frame: request_renderer_screenshot_with_frame() → switch tab → ScreenCaptureKit → switch back
  → if default: request_renderer_screenshot() → renderer WebSocket → xterm.js captureToPng()
  → fallback: ScreenCaptureKit if renderer unavailable

Bug Fixes

1. Default screenshots showed window frame instead of terminal-only

Problem: After adding --with-frame, the default screenshot mode also showed the full macOS window frame.

Root cause: request_renderer_screenshot() function was removed during --with-frame implementation, causing all screenshots to fall back to ScreenCaptureKit which captures the entire window.

Fix: Restored request_renderer_screenshot() function and added capture_request handler to renderer.

2. White border at bottom of --with-frame screenshots

Problem: --with-frame screenshots had a white border/shadow at the bottom of the window.

Root cause: ScreenCaptureKit captures window shadows by default.

Fix: Added .with_ignores_shadows_single_window(true) to SCStreamConfiguration in capture_window().

Test Results

Mode Content Size
Default Pure terminal content (zn-ice@MacBook-Neo ~ %) 18,895 B
--with-frame Full macOS window with titlebar, traffic lights, tab bar, status bar 36,144 B

Test plan

  • cargo check --all-targets passes
  • Default mode captures terminal-only content
  • --with-frame mode captures full macOS window
  • No white border in --with-frame screenshots
  • Per-tab screenshots for different sandboxes (requires renderer WebSocket connection)

🤖 Generated with Claude Code

ZN-Ice and others added 2 commits June 1, 2026 13:32
@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown

🔒 门禁检查结果

检查项 状态
Rust 格式化 ✅ success
Rust Clippy ✅ success
Rust 测试 & 覆盖率 ✅ success
前端测试 & 覆盖率 ✅ success
安全检查 ✅ success

Rust 测试覆盖率

指标 覆盖率
行覆盖率 69.1%
分支覆盖率 0.0%
模块 行覆盖率
crates.sandbox-core.src.daemon ██████████░░░░░░░░░░ 51.6%
crates.sandbox-core.src.instance ███████████████████░ 99.1%
crates.sandbox-core.src.process █████████████░░░░░░░ 65.7%
crates.sandbox-core.src.capture ████████████████████ 100.0%
crates.sandbox-core.src.sandbox ███████████████████░ 98.8%
crates.sandbox-core.src.server █████████████████░░░ 87.5%
crates.sandbox-core.src ███████████░░░░░░░░░ 55.3%
crates.sandbox-core.src.automation ███████████░░░░░░░░░ 58.8%

详细报告见 Rust 覆盖率 artifact

前端测试覆盖率

指标 覆盖率
行覆盖率 ██░░░░░░░░░░░░░░░░░░ 11.4%
分支覆盖率 0.0%
函数覆盖率 17.6%
语句覆盖率 9.1%
文件 行覆盖率
src/renderer/api.ts ██░░░░░░░░░░░░░░░░░░ 11.4%

详细报告见前端覆盖率 artifact

✅ 所有检查通过,可以合入

点击 Squash and merge 合并此PR

ZN-Ice and others added 7 commits June 1, 2026 13:38
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…frame

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
When a CLI sandbox's window_id is None (e.g., Electron window not yet
registered at creation time), fall back to discovering the window by
title "System Test Sandbox" using ScreenCaptureKit. Cache the result
so subsequent screenshots don't need to search again.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The --with-frame feature removed the renderer-based capture path for
default screenshots, causing all screenshots to fall back to
ScreenCaptureKit (full window with frame). This restores the
request_renderer_screenshot function that captures the xterm.js
canvas directly, giving terminal-only screenshots without the
macOS window chrome.

Also adds capture_request handler in the renderer WebSocket to
respond to per-tab screenshot requests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Use with_ignores_shadows_single_window(true) to prevent the macOS
window shadow from appearing as a white border at the bottom of
--with-frame screenshots.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Update release build timestamp to 2026-06-01
- Add test point 6 for comparing default vs --with-frame screenshots

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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