-
-
Notifications
You must be signed in to change notification settings - Fork 194
Fix landscape screenshot orientation #186
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix landscape screenshot orientation #186
Conversation
The simctl screenshot command captures the raw framebuffer in portrait orientation regardless of the device's actual rotation. When the simulator is in landscape mode, this results in a rotated image. This fix: - Detects simulator window orientation using CoreGraphics via Swift - Applies +90° rotation using sips when landscape mode is detected - Handles edge cases gracefully (detection failure, rotation failure) The orientation detection works by querying the Simulator window dimensions via CGWindowListCopyWindowInfo and comparing width vs height. Tested with both Landscape Left and Landscape Right orientations. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
WalkthroughThis change introduces landscape orientation detection and automatic image correction to the screenshot tool. Two new functions are added to detect landscape mode via window dimensions and rotate images using the sips command. The screenshot capture flow is enhanced to check orientation before optimisation; if landscape is detected, a +90° rotation is applied to the captured image. Test cases are updated to reflect the new three-step process: screenshot capture, orientation detection, then image optimisation. A changelog entry documents this landscape handling behaviour. 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@CHANGELOG.md`:
- Line 24: Update the CHANGELOG entry for "Fix screenshot tool capturing rotated
images when simulator is in landscape orientation..." to include the external
contributor attribution and PR link per project changelog format: append " (PR
#<number>, @<github-username>)" or the project's required attribution template
to that line so it reads with the PR number and author; ensure the text still
mentions detection via window dimensions and +90° rotation and matches the
repository's changelog style.
In `@src/mcp/tools/ui-automation/screenshot.ts`:
- Around line 32-46: The window-detection Swift snippet
(WINDOW_DETECTION_SWIFT_CODE) currently picks the first "Simulator" window and
can pick the wrong device; update the Swift logic to also match the requested
simulatorId (or device name) against the window title (kCGWindowName) so it only
selects the window whose title contains the simulatorId/device identifier, and
apply the same change to the related detection code used in the other block
(lines ~52-75) so both detection paths filter by simulatorId/device name before
extracting Width/Height; reference the kCGWindowName/kCGWindowOwnerName keys and
the WINDOW_DETECTION_SWIFT_CODE constant when making this change.
- Add PR link and author attribution to CHANGELOG.md - Fix multi-simulator detection by filtering window lookup by device name: - Add getDeviceNameForSimulatorId() to resolve simulator UUID to device name - Update getWindowDetectionSwiftCode() to filter by device name - Update detectLandscapeMode() to accept optional device name parameter - Add TypeScript interfaces for simctl device list JSON response - Update tests to account for new device name lookup command sequence Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Addressed CodeRabbit Review Comments1. CHANGELOG Attribution ✅Added PR link and author attribution as suggested: - Fixed screenshot tool capturing rotated images when simulator is in landscape orientation by detecting window dimensions and applying +90° rotation to correct the framebuffer capture. ([`#186`](https://github.com/cameroncooke/XcodeBuildMCP/pull/186) by [`@VincentStark`](https://github.com/VincentStark))2. Multi-Simulator Window Detection ✅Fixed the issue where the Swift window detection could pick up the wrong simulator when multiple are open. The implementation now:
All tests have been updated to account for the new device name lookup command in the sequence. |
Bug 1: Fix fallback logic that hardcoded 'iPhone' for iPad simulators - When device name lookup fails, skip orientation detection entirely - This is safer than guessing, as we don't know if it's iPhone or iPad Bug 2: Fix substring matching that could select wrong simulator - Changed from n.contains(deviceName) to hasPrefix + boundary check - Prevents "iPhone 15" from incorrectly matching "iPhone 15 Pro" window - Window title format is "Device Name – iOS version" so check for space separator Updated tests: - Added device name parameter to all detectLandscapeMode tests - Added test for "no device name provided" scenario - Updated simulator tests to return valid device list JSON in mocks Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
@VincentStark Thanks for the contribution! Will merge once checks have passed. |
|
@VincentStark can you fix the typechecke errors: |
Add missing 'process' property to mock executor return values. The CommandResponse type requires a process property, which was missing from the custom mock executors introduced in the previous commit. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
@cameroncooke no problem! Pushed the fix, should be fine now. |
|
@VincentStark formatter checks are failing too, can you run |
|
@cameroncooke sorry about that! Ran everything from CONTRIBUTING pre-commit checklist now, it passes, so should be good. |
Summary
simctl screenshotcommand captures raw framebuffer in portrait regardless of device rotationProblem
When taking screenshots with the simulator in landscape mode, the resulting images were incorrectly oriented - the content appeared rotated 90° within a portrait-shaped frame. This made the screenshots unusable for visual verification workflows.
Root cause:
xcrun simctl io screenshotcaptures the raw framebuffer which is always in portrait orientation, regardless of the simulated device's actual rotation.Solution
Orientation Detection: After capturing the screenshot, detect the simulator window dimensions using CoreGraphics via Swift:
If window width > height, the simulator is in landscape mode.
Rotation Correction: When landscape is detected, rotate the image +90° using
sips --rotate 90to correct the orientation.Graceful Degradation: If orientation detection or rotation fails, the tool continues and returns the original (unrotated) image rather than failing completely.
Testing
detectLandscapeMode()functionrotateImage()functionTest Plan
npm run lint- passesnpm run format:check- passesnpm test- all 1143 tests pass🤖 Generated with Claude Code