Description
In Wails v2.12.0 on macOS, window.devicePixelRatio returns 1 inside the WKWebView on Retina displays, where it should return 2. This causes all canvas-based rendering (, xterm.js WebGL/Canvas, chart libraries) to render at half resolution — macOS upscales the 1x content to 2x, producing visibly blurry output.
The root cause is that WKWebView does not automatically propagate the display's backing scale factor to JavaScript's devicePixelRatio when content is loaded via a custom URL scheme (wails://). This affects both wails dev and wails build.
This results in visibly blurry text and graphics in any app that uses <canvas> — terminal emulators (xterm.js), chart libraries, drawing tools, games, and code editors all render at half the expected resolution. Text on canvas is particularly affected, appearing soft and hard to read compared to native DOM text.
window.matchMedia('(-webkit-min-device-pixel-ratio: 2)') also returns false.
To Reproduce
- Create a new Wails project on a Mac with a Retina display:
wails init -n dpr-test -t vanilla
cd dpr-test
- Edit frontend/index.html — add this inline script before the module script:
<div id="dpr-info" style="position:fixed;top:10px;left:10px;background:#000;color:#0f0;padding:10px;font-family:mono
space;font-size:16px;z-index:9999;border-radius:4px;"></div>
<script>
var info = 'devicePixelRatio: ' + window.devicePixelRatio + '\n'
+ 'matchMedia 2x: ' + window.matchMedia('(-webkit-min-device-pixel-ratio: 2)').matches + '\n'
+ 'screen: ' + screen.width + 'x' + screen.height;
document.getElementById('dpr-info').innerText = info;
</script>
- Build and open:
wails build
open build/bin/dpr-test.app
- The overlay shows devicePixelRatio: 1 (also reproducible with wails dev)
Expected behaviour
window.devicePixelRatio should return 2 on Retina displays (matching NSScreen.mainScreen.backingScaleFactor).
Canvas-based content should render at native resolution.
Screenshots
Before Fix bug:
After fix:
Another example with blur:
Without blur after fix:
Attempted Fixes
NSHighResolutionCapable in Info.plist: Already set to true — does not affect WKWebView's DPR reporting.
- JavaScript
Object.defineProperty override of devicePixelRatio: Forces canvas to render at 2x, but the WKWebView compositor still operates at 1x internally. Creates glyph rendering artifacts at small font sizes due to sub-pixel alignment mismatch.
wantsLayer = YES + layer.contentsScale = backingScaleFactor on the WKWebView: Does not affect window.devicePixelRatio — contentsScale controls the CALayer rendering, not WebKit's internal device scale factor.
_setOverrideDeviceScaleFactor: SPI on WKWebView (working fix): Sets WebPageProxy::customDeviceScaleFactor, which is the authoritative source for window.devicePixelRatio in JavaScript. This SPI is stable since macOS 10.11 and used by Electron, Playwright, and WebKit's own test infrastructure. I have a working patch and can submit a PR.
System Details
Wails Doctor
# Wails
Version | v2.11.0
# System
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
| OS | MacOS |
| Version | 15.7.4 |
| ID | 24G517 |
| Branding | |
| Go Version | go1.25.6 |
| Platform | darwin |
| Architecture | arm64 |
| CPU 1 | Apple M3 |
| CPU 2 | Apple M3 |
| GPU | Chipset Model: Apple M3 Type: GPU Bus: Built-In Total Number of Cores: 10 Vendor: Apple (0x106b) Metal Support: Metal 3 |
| Memory | 24GB |
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
# Dependencies
┌────────────────────────────────────────────────────────────────┐
| Dependency | Package Name | Status | Version |
| Xcode command line tools | N/A | Installed | 2410 |
| Nodejs | N/A | Installed | 22.18.0 |
| npm | N/A | Installed | 10.9.3 |
| *Xcode | N/A | Available | |
| *upx | N/A | Available | |
| *nsis | N/A | Available | |
| |
└─────────────────── * - Optional Dependency ────────────────────┘
# Diagnosis
Optional package(s) installation details:
- Xcode: Available at https://apps.apple.com/us/app/xcode/id497799835
- upx : Available at https://upx.github.io/
- nsis : More info at https://wails.io/docs/guides/windows-installer/
Additional context
Affects any Wails v2 app using <canvas> on macOS Retina: terminals (xterm.js), charts, games, editors, drawing apps.
- The issue is specific to the custom
wails:// URL scheme. WKWebView correctly reports DPR when loading content via http:// or https://.
- The fix is in
v2/internal/frontend/desktop/darwin/WailsContext.m, after the WKWebView is created.
Description
In Wails v2.12.0 on macOS, window.devicePixelRatio returns 1 inside the WKWebView on Retina displays, where it should return 2. This causes all canvas-based rendering (, xterm.js WebGL/Canvas, chart libraries) to render at half resolution — macOS upscales the 1x content to 2x, producing visibly blurry output.
The root cause is that WKWebView does not automatically propagate the display's backing scale factor to JavaScript's devicePixelRatio when content is loaded via a custom URL scheme (wails://). This affects both wails dev and wails build.
This results in visibly blurry text and graphics in any app that uses
<canvas>— terminal emulators (xterm.js), chart libraries, drawing tools, games, and code editors all render at half the expected resolution. Text on canvas is particularly affected, appearing soft and hard to read compared to native DOM text.window.matchMedia('(-webkit-min-device-pixel-ratio: 2)')also returns false.To Reproduce
Expected behaviour
window.devicePixelRatioshould return 2 on Retina displays (matching NSScreen.mainScreen.backingScaleFactor).Canvas-based content should render at native resolution.
Screenshots
Before Fix bug:
After fix:
Another example with blur:
Without blur after fix:
Attempted Fixes
NSHighResolutionCapablein Info.plist: Already set totrue— does not affect WKWebView's DPR reporting.Object.definePropertyoverride ofdevicePixelRatio: Forces canvas to render at 2x, but the WKWebView compositor still operates at 1x internally. Creates glyph rendering artifacts at small font sizes due to sub-pixel alignment mismatch.wantsLayer = YES+layer.contentsScale = backingScaleFactoron the WKWebView: Does not affectwindow.devicePixelRatio—contentsScalecontrols the CALayer rendering, not WebKit's internal device scale factor._setOverrideDeviceScaleFactor:SPI on WKWebView (working fix): SetsWebPageProxy::customDeviceScaleFactor, which is the authoritative source forwindow.devicePixelRatioin JavaScript. This SPI is stable since macOS 10.11 and used by Electron, Playwright, and WebKit's own test infrastructure. I have a working patch and can submit a PR.System Details
Wails Doctor # Wails Version | v2.11.0 # System ┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ | OS | MacOS | | Version | 15.7.4 | | ID | 24G517 | | Branding | | | Go Version | go1.25.6 | | Platform | darwin | | Architecture | arm64 | | CPU 1 | Apple M3 | | CPU 2 | Apple M3 | | GPU | Chipset Model: Apple M3 Type: GPU Bus: Built-In Total Number of Cores: 10 Vendor: Apple (0x106b) Metal Support: Metal 3 | | Memory | 24GB | └────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ # Dependencies ┌────────────────────────────────────────────────────────────────┐ | Dependency | Package Name | Status | Version | | Xcode command line tools | N/A | Installed | 2410 | | Nodejs | N/A | Installed | 22.18.0 | | npm | N/A | Installed | 10.9.3 | | *Xcode | N/A | Available | | | *upx | N/A | Available | | | *nsis | N/A | Available | | | | └─────────────────── * - Optional Dependency ────────────────────┘ # Diagnosis Optional package(s) installation details: - Xcode: Available at https://apps.apple.com/us/app/xcode/id497799835 - upx : Available at https://upx.github.io/ - nsis : More info at https://wails.io/docs/guides/windows-installer/Additional context
Affects any Wails v2 app using
<canvas>on macOS Retina: terminals (xterm.js), charts, games, editors, drawing apps.wails://URL scheme. WKWebView correctly reports DPR when loading content viahttp://orhttps://.v2/internal/frontend/desktop/darwin/WailsContext.m, after the WKWebView is created.