Skip to content

Commit b41eb3c

Browse files
authored
windows: Fix maximized window size when DPI scale changes (zed-industries#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>
1 parent 6899448 commit b41eb3c

File tree

1 file changed

+51
-24
lines changed

1 file changed

+51
-24
lines changed

crates/gpui/src/platform/windows/events.rs

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -740,31 +740,58 @@ impl WindowsWindowInner {
740740
lock.border_offset.update(handle).log_err();
741741
drop(lock);
742742

743-
let rect = unsafe { &*(lparam.0 as *const RECT) };
744-
let width = rect.right - rect.left;
745-
let height = rect.bottom - rect.top;
746-
// this will emit `WM_SIZE` and `WM_MOVE` right here
747-
// even before this function returns
748-
// the new size is handled in `WM_SIZE`
749-
unsafe {
750-
SetWindowPos(
751-
handle,
752-
None,
753-
rect.left,
754-
rect.top,
755-
width,
756-
height,
757-
SWP_NOZORDER | SWP_NOACTIVATE,
758-
)
759-
.context("unable to set window position after dpi has changed")
760-
.log_err();
761-
}
762-
763-
// When maximized, SetWindowPos doesn't send WM_SIZE, so we need to manually
764-
// update the size and call the resize callback
765743
if is_maximized {
766-
let device_size = size(DevicePixels(width), DevicePixels(height));
767-
self.handle_size_change(device_size, new_scale_factor, true);
744+
// Get the monitor and its work area at the new DPI
745+
let monitor = unsafe { MonitorFromWindow(handle, MONITOR_DEFAULTTONEAREST) };
746+
let mut monitor_info: MONITORINFO = unsafe { std::mem::zeroed() };
747+
monitor_info.cbSize = std::mem::size_of::<MONITORINFO>() as u32;
748+
if unsafe { GetMonitorInfoW(monitor, &mut monitor_info) }.as_bool() {
749+
let work_area = monitor_info.rcWork;
750+
let width = work_area.right - work_area.left;
751+
let height = work_area.bottom - work_area.top;
752+
753+
// Update the window size to match the new monitor work area
754+
// This will trigger WM_SIZE which will handle the size change
755+
unsafe {
756+
SetWindowPos(
757+
handle,
758+
None,
759+
work_area.left,
760+
work_area.top,
761+
width,
762+
height,
763+
SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED,
764+
)
765+
.context("unable to set maximized window position after dpi has changed")
766+
.log_err();
767+
}
768+
769+
// SetWindowPos may not send WM_SIZE for maximized windows in some cases,
770+
// so we manually update the size to ensure proper rendering
771+
let device_size = size(DevicePixels(width), DevicePixels(height));
772+
self.handle_size_change(device_size, new_scale_factor, true);
773+
}
774+
} else {
775+
// For non-maximized windows, use the suggested RECT from the system
776+
let rect = unsafe { &*(lparam.0 as *const RECT) };
777+
let width = rect.right - rect.left;
778+
let height = rect.bottom - rect.top;
779+
// this will emit `WM_SIZE` and `WM_MOVE` right here
780+
// even before this function returns
781+
// the new size is handled in `WM_SIZE`
782+
unsafe {
783+
SetWindowPos(
784+
handle,
785+
None,
786+
rect.left,
787+
rect.top,
788+
width,
789+
height,
790+
SWP_NOZORDER | SWP_NOACTIVATE,
791+
)
792+
.context("unable to set window position after dpi has changed")
793+
.log_err();
794+
}
768795
}
769796

770797
Some(0)

0 commit comments

Comments
 (0)