Skip to content

Improve Windows screenshot behavior for multi-monitor setups#281

Open
AstroAir wants to merge 2 commits intoopenai:mainfrom
AstroAir:main
Open

Improve Windows screenshot behavior for multi-monitor setups#281
AstroAir wants to merge 2 commits intoopenai:mainfrom
AstroAir:main

Conversation

@AstroAir
Copy link

Summary

  • default Windows full-screen captures to one file per display on multi-monitor setups, and add -VirtualDesktop to opt into a single stitched image when needed
  • preserve the exact user-provided -Path for the first display while writing additional displays as suffixed sibling files such as -d2
  • harden the PowerShell helper with nullable window handles, DPI-awareness setup, and clearer validation/error handling for invalid bounds and minimized windows
  • update the screenshot skill docs to reflect the Windows-specific multi-display behavior, -VirtualDesktop usage, and troubleshooting guidance

Test Plan

  • ran a Windows smoke check in helper test mode with:
    • CODEX_SCREENSHOT_TEST_MODE=1
    • CODEX_SCREENSHOT_TEST_DISPLAYS=1,2
    • powershell.exe -NoProfile -ExecutionPolicy Bypass -File skills/.curated/screenshot/scripts/take_screenshot.ps1 -Path "$env:TEMP\\codex-pr-smoke.png"
  • verified the helper emitted two output paths and preserved the explicit first path:
    • C:\Users\qwdma\AppData\Local\Temp\codex-pr-smoke.png
    • C:\Users\qwdma\AppData\Local\Temp\codex-pr-smoke-d2.png
  • attempted to run python skills/.system/skill-creator/scripts/quick_validate.py skills/.curated/screenshot, but python is not installed on this machine, so that validation could not be completed here

…and Linux; add VirtualDesktop option and improve error handling
@AstroAir AstroAir requested review from a team and Copilot March 19, 2026 05:38
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Windows PowerShell screenshot helper to behave better on multi-monitor setups by defaulting full-screen capture to one image per display (with an opt-in -VirtualDesktop stitched capture), and aligns the skill documentation with the new Windows behavior and troubleshooting guidance.

Changes:

  • Windows PowerShell helper: multi-monitor full-screen now outputs one file per display by default; adds -VirtualDesktop to force a stitched virtual-desktop capture.
  • Windows PowerShell helper: improves robustness around nullable window handles, DPI-awareness setup, and clearer validation/errors for invalid/minimized bounds.
  • Skill docs: document Windows multi-display output behavior, -VirtualDesktop usage, and troubleshooting tips.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
skills/.curated/screenshot/scripts/take_screenshot.ps1 Implements per-display full-screen capture on Windows (default), -VirtualDesktop override, test-mode behavior, and capture hardening.
skills/.curated/screenshot/SKILL.md Documents Windows multi-monitor behavior, -VirtualDesktop, output naming, and troubleshooting guidance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

}

$hasWindowHandle = $PSBoundParameters.ContainsKey("WindowHandle")
$hasExplicitPath = $PSBoundParameters.ContainsKey("Path")
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 067ffc8.

I aligned the “explicit path” check with Resolve-OutputPath so only non-empty, non-whitespace -Path values are
treated as explicit. That means -Path "" now follows the implicit-path flow and produces suffixed multi-display outputs
(-d1, -d2, etc.) instead of preserving the unsuffixed first path.

I did not broaden this to silently rewrite whitespace-only paths into defaults; those still fail as invalid input rather
than changing a malformed user-provided path behind the caller’s back. I also added a regression check for the empty-
string case.

Comment on lines +267 to +272
[NativeMethods]::SetProcessDpiAwarenessContext([IntPtr]::new(-4)) | Out-Null
} catch {
try {
[NativeMethods]::SetProcessDPIAware() | Out-Null
} catch {
# Best effort only; continue when APIs are unavailable.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 067ffc8.

The DPI initialization now falls back to SetProcessDPIAware() whenever SetProcessDpiAwarenessContext(...) either
throws or returns false, so the legacy path still runs on hosts where PMv2 is unsupported but the API exists.

I added regression coverage for the false return path to make sure we keep the fallback behavior.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 003a53b7bc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +267 to +270
[NativeMethods]::SetProcessDpiAwarenessContext([IntPtr]::new(-4)) | Out-Null
} catch {
try {
[NativeMethods]::SetProcessDPIAware() | Out-Null

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fall back when SetProcessDpiAwarenessContext returns false

On Windows 10 1607 / Server 2016, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (-4) is not supported even though SetProcessDpiAwarenessContext exists, so this call fails by returning false rather than throwing. Because the code only enters the fallback path on exceptions, those hosts stay DPI-unaware and the new per-display capture can still read virtualized bounds, leaving mixed-DPI screenshots offset instead of applying the older SetProcessDPIAware() fallback.

Useful? React with 👍 / 👎.

- treat empty or whitespace -Path values as implicit output paths for multi-display suffixing

- fall back to SetProcessDPIAware when per-monitor v2 DPI setup returns false

- add PowerShell regression coverage for explicit path preservation and DPI fallback
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