From b41eb3cdaf492f990834a7ca78b5195eb169f68e Mon Sep 17 00:00:00 2001 From: Xiaobo Liu Date: Fri, 21 Nov 2025 04:34:17 +0800 Subject: [PATCH] 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 --- crates/gpui/src/platform/windows/events.rs | 75 +++++++++++++++------- 1 file changed, 51 insertions(+), 24 deletions(-) diff --git a/crates/gpui/src/platform/windows/events.rs b/crates/gpui/src/platform/windows/events.rs index cc39d3bcedd370fb4dc2fdb4c1d8304ad6b99b79..7b1d0efd1821c0651cc2f092f51041c0de84cc14 100644 --- a/crates/gpui/src/platform/windows/events.rs +++ b/crates/gpui/src/platform/windows/events.rs @@ -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::() 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)