Skip to content

Commit 0fc773f

Browse files
committed
windows: Fix maximized window size when DPI scale changes
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. Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
1 parent c6373cc commit 0fc773f

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
@@ -775,31 +775,58 @@ impl WindowsWindowInner {
775775
lock.border_offset.update(handle).log_err();
776776
drop(lock);
777777

778-
let rect = unsafe { &*(lparam.0 as *const RECT) };
779-
let width = rect.right - rect.left;
780-
let height = rect.bottom - rect.top;
781-
// this will emit `WM_SIZE` and `WM_MOVE` right here
782-
// even before this function returns
783-
// the new size is handled in `WM_SIZE`
784-
unsafe {
785-
SetWindowPos(
786-
handle,
787-
None,
788-
rect.left,
789-
rect.top,
790-
width,
791-
height,
792-
SWP_NOZORDER | SWP_NOACTIVATE,
793-
)
794-
.context("unable to set window position after dpi has changed")
795-
.log_err();
796-
}
797-
798-
// When maximized, SetWindowPos doesn't send WM_SIZE, so we need to manually
799-
// update the size and call the resize callback
800778
if is_maximized {
801-
let device_size = size(DevicePixels(width), DevicePixels(height));
802-
self.handle_size_change(device_size, new_scale_factor, true);
779+
// Get the monitor and its work area at the new DPI
780+
let monitor = unsafe { MonitorFromWindow(handle, MONITOR_DEFAULTTONEAREST) };
781+
let mut monitor_info: MONITORINFO = unsafe { std::mem::zeroed() };
782+
monitor_info.cbSize = std::mem::size_of::<MONITORINFO>() as u32;
783+
if unsafe { GetMonitorInfoW(monitor, &mut monitor_info) }.as_bool() {
784+
let work_area = monitor_info.rcWork;
785+
let width = work_area.right - work_area.left;
786+
let height = work_area.bottom - work_area.top;
787+
788+
// Update the window size to match the new monitor work area
789+
// This will trigger WM_SIZE which will handle the size change
790+
unsafe {
791+
SetWindowPos(
792+
handle,
793+
None,
794+
work_area.left,
795+
work_area.top,
796+
width,
797+
height,
798+
SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED,
799+
)
800+
.context("unable to set maximized window position after dpi has changed")
801+
.log_err();
802+
}
803+
804+
// SetWindowPos may not send WM_SIZE for maximized windows in some cases,
805+
// so we manually update the size to ensure proper rendering
806+
let device_size = size(DevicePixels(width), DevicePixels(height));
807+
self.handle_size_change(device_size, new_scale_factor, true);
808+
}
809+
} else {
810+
// For non-maximized windows, use the suggested RECT from the system
811+
let rect = unsafe { &*(lparam.0 as *const RECT) };
812+
let width = rect.right - rect.left;
813+
let height = rect.bottom - rect.top;
814+
// this will emit `WM_SIZE` and `WM_MOVE` right here
815+
// even before this function returns
816+
// the new size is handled in `WM_SIZE`
817+
unsafe {
818+
SetWindowPos(
819+
handle,
820+
None,
821+
rect.left,
822+
rect.top,
823+
width,
824+
height,
825+
SWP_NOZORDER | SWP_NOACTIVATE,
826+
)
827+
.context("unable to set window position after dpi has changed")
828+
.log_err();
829+
}
803830
}
804831

805832
Some(0)

0 commit comments

Comments
 (0)