Skip to content

Commit cddeee6

Browse files
committed
fix(tauri): correct screenshot rect on Windows under DPI scaling
GDI APIs (GetClientRect, PrintWindow, GetDIBits) operate in physical pixels for DPI-aware processes, but the JS caller sends the capture rect in CSS pixels (scaled only by the webview zoom factor, not the OS DPI). At Windows display scaling >100%, this produced screenshots that were both shifted and undersized. Multiply the incoming rect by window.scale_factor() (the OS DPI scale, e.g. 1.25 at 125% scaling) before clamping to the physical client area. macOS is unaffected because WKSnapshotConfiguration.setRect takes view points, which map 1:1 to CSS pixels. Electron (Linux) is unaffected because capturePage already accepts CSS-pixel rects.
1 parent 97f68e7 commit cddeee6

1 file changed

Lines changed: 11 additions & 5 deletions

File tree

src-tauri/src/main.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,11 @@ fn capture_page_windows(window: tauri::Window, rect: Option<CaptureRect>) -> Res
538538
};
539539
use winapi::shared::windef::{RECT, HGDIOBJ};
540540

541+
// GDI works in physical pixels, but the JS caller sends the rect in CSS pixels
542+
// (scaled only by the webview zoom factor, not by the OS DPI). Convert by
543+
// multiplying with the window's OS scale factor (1.25 at Windows 125% scaling).
544+
let dpi_scale = window.scale_factor().unwrap_or(1.0);
545+
541546
unsafe {
542547
let hwnd = window.hwnd().map_err(|e| e.to_string())?;
543548
let hwnd = hwnd.0 as winapi::shared::windef::HWND;
@@ -584,12 +589,13 @@ fn capture_page_windows(window: tauri::Window, rect: Option<CaptureRect>) -> Res
584589
chunk.swap(0, 2);
585590
}
586591

587-
// Extract the requested region (or full image)
592+
// Extract the requested region (or full image). Convert the incoming
593+
// CSS-pixel rect into physical pixels using the OS DPI scale factor.
588594
let (cap_x, cap_y, cap_w, cap_h) = if let Some(r) = &rect {
589-
let x = (r.x as i32).max(0).min(full_width);
590-
let y = (r.y as i32).max(0).min(full_height);
591-
let w = (r.width as i32).min(full_width - x).max(0);
592-
let h = (r.height as i32).min(full_height - y).max(0);
595+
let x = ((r.x * dpi_scale).round() as i32).max(0).min(full_width);
596+
let y = ((r.y * dpi_scale).round() as i32).max(0).min(full_height);
597+
let w = ((r.width * dpi_scale).round() as i32).min(full_width - x).max(0);
598+
let h = ((r.height * dpi_scale).round() as i32).min(full_height - y).max(0);
593599
(x, y, w, h)
594600
} else {
595601
(0, 0, full_width, full_height)

0 commit comments

Comments
 (0)