Skip to content

wgc-capture.exe is DPI-unaware, and its monitor lookup silently depends on it #346

Description

@EtienneLescot

5efe5e62 opted cursor-sampler.exe into per-monitor-v2 DPI awareness. wgc-capture.exe — the recorder itself — never got the same treatment, and its monitor lookup quietly depends on staying unaware.

Where

findMonitorForCapture (electron/native/wgc-capture/src/monitor_utils.cpp) picks the capture target by matching the bounds it was handed against the rects from EnumDisplayMonitors:

if (rectMatchesBounds(candidate.rect, *bounds)) { return candidate.monitor; }

Those bounds come from sourceDisplay?.bounds and are serialized as displayX/Y/W/H (electron/ipc/handlers.ts:2335). Electron's Display.bounds is in DIPs. The enumerated rects, in a DPI-unaware process, are virtualized — divided by the primary display's scale factor, whatever monitor they actually describe.

Why it works today, and where it stops

Single monitor at any scale: virtualized == DIP, so the two sides agree by accident and the exact match hits.

Mixed-DPI multi-monitor: Electron's DIP rect for each display uses that display's scale, while virtualization uses the primary's for all of them. The two spaces diverge on any non-primary display whose scale differs, rectMatchesBounds misses, and the lookup falls through to the overlap heuristic — which can land on the wrong monitor, or on the primary via MONITOR_DEFAULTTOPRIMARY.

Why it's a paired change, not a one-liner

Adding SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) to main.cpp on its own flips the enumerated rects to physical while displayX/Y/W/H stay DIPs — that breaks the single-monitor scaled case that currently works. The awareness call has to land together with screen.dipToScreenRect on the TS side (the same conversion windowsNativeRecordingSession.ts:240 already does for the cursor payload), so both sides of the match move to physical at once.

#110 proposed the awareness half (a shared dpi_awareness.h plus the call in main.cpp). That PR is closed as superseded, but this piece of it was never re-landed — hence this issue.

Repro

Needs a mixed-DPI multi-monitor Windows box; not reproducible on a single 100%-scale display, which is what the dev machine is. Same hardware gap as #252.

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: fixed in mainWork is merged into main but may not be in a downloadable release yet.status: pending releaseMerged change is waiting for a packaged desktop release.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions