diff --git a/crates/gpui_windows/src/display.rs b/crates/gpui_windows/src/display.rs index bb75bf7dd5..ee02309d8c 100644 --- a/crates/gpui_windows/src/display.rs +++ b/crates/gpui_windows/src/display.rs @@ -92,6 +92,12 @@ impl WindowsDisplay { WindowsDisplay::new(Self::display_id_for_monitor(monitor)) } + /// The DPI scale factor of this monitor, independent of whatever monitor + /// a not-yet-positioned window currently happens to be on. + pub(crate) fn scale_factor(&self) -> f32 { + self.scale_factor + } + /// Check if the center point of given bounds is inside this monitor pub fn check_given_bounds(&self, bounds: Bounds) -> bool { let center = bounds.center(); diff --git a/crates/gpui_windows/src/window.rs b/crates/gpui_windows/src/window.rs index d81efacc8c..37e9d9a176 100644 --- a/crates/gpui_windows/src/window.rs +++ b/crates/gpui_windows/src/window.rs @@ -552,13 +552,8 @@ impl WindowsWindow { set_non_rude_hwnd(hwnd, true); configure_dwm_dark_mode(hwnd, appearance); this.state.border_offset.update(hwnd)?; - let placement = retrieve_window_placement( - hwnd, - display, - params.bounds, - this.state.scale_factor.get(), - &this.state.border_offset, - )?; + let placement = + retrieve_window_placement(hwnd, display, params.bounds, &this.state.border_offset)?; if params.show { let mut placement = placement; if !params.focus { @@ -1528,7 +1523,6 @@ fn retrieve_window_placement( hwnd: HWND, display: WindowsDisplay, initial_bounds: Bounds, - scale_factor: f32, border_offset: &WindowBorderOffset, ) -> Result { let mut placement = WINDOWPLACEMENT { @@ -1542,7 +1536,14 @@ fn retrieve_window_placement( } else { display.default_bounds() }; - let bounds = bounds.to_device_pixels(scale_factor); + // `bounds` is expressed in logical pixels for `display`, so it must be converted + // to device pixels using that display's own scale factor. The window's current + // scale factor can't be used here: `CreateWindowExW` was called with + // `CW_USEDEFAULT`, so at this point the window may still be sitting on whichever + // monitor Windows picked by default, which can have a different DPI than `display` + // and would otherwise throw off the physical position (e.g. leaving the window + // partially off-screen when moved to a monitor with a different scale factor). + let bounds = bounds.to_device_pixels(display.scale_factor()); placement.rcNormalPosition = calculate_window_rect(bounds, border_offset); Ok(placement) }