windows: Fix maximized window size when DPI scale changes (#40053)

The WM_DPICHANGED suggested RECT is calculated for non-maximized
windows. When a maximized window's DPI changes, we now query the
monitor's work area directly to ensure the window correctly fills the
entire screen.

For non-maximized windows, the original behavior using the
system-suggested RECT is preserved.

Release Notes:

- windows: Fixed maximized window size when DPI scale changes

Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
This commit is contained in:
Xiaobo Liu
2025-11-20 20:34:17 +00:00
committed by GitHub
parent 6899448812
commit b41eb3cdaf
+51 -24
View File
@@ -740,31 +740,58 @@ impl WindowsWindowInner {
lock.border_offset.update(handle).log_err();
drop(lock);
let rect = unsafe { &*(lparam.0 as *const RECT) };
let width = rect.right - rect.left;
let height = rect.bottom - rect.top;
// this will emit `WM_SIZE` and `WM_MOVE` right here
// even before this function returns
// the new size is handled in `WM_SIZE`
unsafe {
SetWindowPos(
handle,
None,
rect.left,
rect.top,
width,
height,
SWP_NOZORDER | SWP_NOACTIVATE,
)
.context("unable to set window position after dpi has changed")
.log_err();
}
// When maximized, SetWindowPos doesn't send WM_SIZE, so we need to manually
// update the size and call the resize callback
if is_maximized {
let device_size = size(DevicePixels(width), DevicePixels(height));
self.handle_size_change(device_size, new_scale_factor, true);
// Get the monitor and its work area at the new DPI
let monitor = unsafe { MonitorFromWindow(handle, MONITOR_DEFAULTTONEAREST) };
let mut monitor_info: MONITORINFO = unsafe { std::mem::zeroed() };
monitor_info.cbSize = std::mem::size_of::<MONITORINFO>() as u32;
if unsafe { GetMonitorInfoW(monitor, &mut monitor_info) }.as_bool() {
let work_area = monitor_info.rcWork;
let width = work_area.right - work_area.left;
let height = work_area.bottom - work_area.top;
// Update the window size to match the new monitor work area
// This will trigger WM_SIZE which will handle the size change
unsafe {
SetWindowPos(
handle,
None,
work_area.left,
work_area.top,
width,
height,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED,
)
.context("unable to set maximized window position after dpi has changed")
.log_err();
}
// SetWindowPos may not send WM_SIZE for maximized windows in some cases,
// so we manually update the size to ensure proper rendering
let device_size = size(DevicePixels(width), DevicePixels(height));
self.handle_size_change(device_size, new_scale_factor, true);
}
} else {
// For non-maximized windows, use the suggested RECT from the system
let rect = unsafe { &*(lparam.0 as *const RECT) };
let width = rect.right - rect.left;
let height = rect.bottom - rect.top;
// this will emit `WM_SIZE` and `WM_MOVE` right here
// even before this function returns
// the new size is handled in `WM_SIZE`
unsafe {
SetWindowPos(
handle,
None,
rect.left,
rect.top,
width,
height,
SWP_NOZORDER | SWP_NOACTIVATE,
)
.context("unable to set window position after dpi has changed")
.log_err();
}
}
Some(0)