Skip to content

[patch] Add native macOS DPI detection path#263

Merged
matt-edmondson merged 3 commits into
mainfrom
fix/macos-dpi-detection
Jul 24, 2026
Merged

[patch] Add native macOS DPI detection path#263
matt-edmondson merged 3 commits into
mainfrom
fix/macos-dpi-detection

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Problem

On modern macOS there is no X11 (XQuartz is not present by default). But ForceDpiAware.GetActualScaleFactor() only special-cased Windows, then read XDG_SESSION_TYPE and fell into the X11 branch whenever it was null — which it always is on macOS — via the null or "x11" match. That P/Invoked libX11.so.6, a Linux-only library absent on macOS, throwing DllNotFoundException and taking the app down on startup DPI detection.

Fix

Add a native macOS branch before the X11/Wayland fork. GetMacOSDpiScale() reads the main display's current mode via CoreGraphics and takes the pixel-width to point-width ratio as the backing scale factor:

  • CGDisplayModeGetPixelWidth / CGDisplayModeGetWidth1.0 on a standard display, 2.0 on Retina.
  • Returns scale * StandardDpiScale (96).
  • Releases the mode in a finally (Core Foundation "Copy" ownership rule).
  • Degrades to StandardDpiScale on a null mode, zero width, or a missing library/entry point (for example, a headless host), rather than crashing.

The CoreGraphics P/Invokes load by full framework path since macOS frameworks are not on the default dylib search path, and they omit DefaultDllImportSearchPaths (that attribute controls the Windows loader only). OperatingSystem.IsMacOS() is a recognized platform guard, so the native calls stay analyzer-clean, and ForceDpiAware.cs is already <Compile Remove>d on net10.0-ios, so there is no Mac Catalyst / iOS overlap.

Verification

  • dotnet build clean, zero warnings (warnings-as-errors is on).
  • ForceDpiAware tests: 7/7 pass on Windows, confirming the existing Windows path is unchanged.

Not runtime-verified on macOS. The new branch only executes on a Mac and could not be exercised from the Windows dev environment. Manual check on a Mac: dotnet run --project examples/ImGuiAppDemo should launch (previously crashed) and scale correctly on a Retina display.

🤖 Generated with Claude Code

Modern macOS has no X11, but GetActualScaleFactor routed macOS into the
X11 branch because XDG_SESSION_TYPE is null and matched `null or "x11"`.
That P/Invoked libX11.so.6, which does not exist on macOS, throwing
DllNotFoundException.

Add a macOS branch that reads the main display backing scale via
CoreGraphics (CGDisplayModeGetPixelWidth / CGDisplayModeGetWidth), giving
1.0 on standard displays and 2.0 on Retina. Falls back to the standard
DPI scale when the display mode is unavailable or CoreGraphics cannot be
loaded (for example, a headless host).
The macOS DPI branch was all native CoreGraphics interop that only runs
on a Mac with a display, so it registered 0% new-code coverage on the
Windows coverage runner and tripped the SonarCloud coverage gate.

Extract the pure pixel-to-point scale arithmetic into an internal
MacOSBackingScaleToDpi helper and unit-test it (standard, Retina,
fractional, zero-width fallback). Mark the thin native wrapper
GetMacOSDpiScale with [ExcludeFromCodeCoverage] and a justification,
matching the repo's treatment of other C ABI boundary code. Microsoft
Code Coverage honors the attribute, removing the unreachable lines from
the denominator.
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@matt-edmondson
matt-edmondson merged commit 966da26 into main Jul 24, 2026
6 of 7 checks passed
@matt-edmondson
matt-edmondson deleted the fix/macos-dpi-detection branch July 24, 2026 05:39
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