Fix: set device does not apply deviceScaleFactor - HiDPI screenshots not possible (#270)

Fixes #255
This commit is contained in:
Chris Tate
2026-01-25 15:27:03 -06:00
committed by GitHub
parent a22af0e675
commit 45506fbff0
2 changed files with 53 additions and 0 deletions
+19
View File
@@ -1147,10 +1147,29 @@ async function handleDevice(command: DeviceCommand, browser: BrowserManager): Pr
// Apply device viewport
await browser.setViewport(device.viewport.width, device.viewport.height);
// Apply or clear device scale factor
if (device.deviceScaleFactor && device.deviceScaleFactor !== 1) {
// Apply device scale factor for HiDPI/retina displays
await browser.setDeviceScaleFactor(
device.deviceScaleFactor,
device.viewport.width,
device.viewport.height,
device.isMobile ?? false
);
} else {
// Clear device scale factor override to restore default (1x)
try {
await browser.clearDeviceMetricsOverride();
} catch {
// Ignore error if override was never set
}
}
return successResponse(command.id, {
device: command.device,
viewport: device.viewport,
userAgent: device.userAgent,
deviceScaleFactor: device.deviceScaleFactor,
});
}
+34
View File
@@ -393,6 +393,40 @@ export class BrowserManager {
await page.setViewportSize({ width, height });
}
/**
* Set device scale factor (devicePixelRatio) via CDP
* This sets window.devicePixelRatio which affects how the page renders and responds to media queries
*
* Note: When using CDP to set deviceScaleFactor, screenshots will be at logical pixel dimensions
* (viewport size), not physical pixel dimensions (viewport × scale). This is a Playwright limitation
* when using CDP emulation on existing contexts. For true HiDPI screenshots with physical pixels,
* deviceScaleFactor must be set at context creation time.
*
* Must be called after setViewport to work correctly
*/
async setDeviceScaleFactor(
deviceScaleFactor: number,
width: number,
height: number,
mobile: boolean = false
): Promise<void> {
const cdp = await this.getCDPSession();
await cdp.send('Emulation.setDeviceMetricsOverride', {
width,
height,
deviceScaleFactor,
mobile,
});
}
/**
* Clear device metrics override to restore default devicePixelRatio
*/
async clearDeviceMetricsOverride(): Promise<void> {
const cdp = await this.getCDPSession();
await cdp.send('Emulation.clearDeviceMetricsOverride');
}
/**
* Get device descriptor
*/