diff --git a/src/platform/win/drop_target.rs b/src/platform/win/drop_target.rs index 5a84fe68..b2c7c56c 100644 --- a/src/platform/win/drop_target.rs +++ b/src/platform/win/drop_target.rs @@ -66,7 +66,14 @@ impl DropTarget { } fn parse_coordinates(&self, pt: POINTL) { - let Ok(phy_point) = self.hwnd.screen_to_client(PhysicalPosition::new(pt.x, pt.y)) else { + let Some(window_state) = self.window_state.upgrade() else { + return; + }; + + let dpi_aware = !window_state.shared.dpi_scaling_strategy.get().assume_96_dpi; + let Ok(phy_point) = + self.hwnd.screen_to_client(PhysicalPosition::new(pt.x, pt.y), dpi_aware) + else { return; }; diff --git a/src/wrappers/win32/window/handle.rs b/src/wrappers/win32/window/handle.rs index 72d855b7..8b4e718e 100644 --- a/src/wrappers/win32/window/handle.rs +++ b/src/wrappers/win32/window/handle.rs @@ -15,7 +15,10 @@ use windows_sys::Win32::Graphics::Gdi::{ MONITOR_DEFAULTTOPRIMARY, }; use windows_sys::Win32::System::Ole::{RegisterDragDrop, RevokeDragDrop}; -use windows_sys::Win32::UI::HiDpi::{DPI_HOSTING_BEHAVIOR_MIXED, MDT_DEFAULT}; +use windows_sys::Win32::UI::HiDpi::{ + LogicalToPhysicalPointForPerMonitorDPI, PhysicalToLogicalPointForPerMonitorDPI, + DPI_HOSTING_BEHAVIOR_MIXED, MDT_DEFAULT, +}; use windows_sys::Win32::UI::Input::KeyboardAndMouse::{ GetFocus, ReleaseCapture, SetCapture, SetFocus, TrackMouseEvent, TME_LEAVE, TRACKMOUSEEVENT, }; @@ -298,11 +301,26 @@ impl HWnd { } } - pub fn screen_to_client(&self, pt: PhysicalPosition) -> Result> { + /// Converts screen coordinates to client coordinates. + /// + /// For DPI-aware windows, OLE screen points can disagree with what + /// [`ScreenToClient`] expects, so we convert to logical space first and then back to physical. + pub fn screen_to_client( + &self, pt: PhysicalPosition, dpi_aware: bool, + ) -> Result> { let mut pt = POINT { x: pt.x, y: pt.y }; - let result = unsafe { ScreenToClient(self.as_raw(), &mut pt as *mut POINT) }; - if result == 0 { + if dpi_aware && unsafe { PhysicalToLogicalPointForPerMonitorDPI(null_mut(), &mut pt) } == 0 + { + return Err(Error::from_thread()); + } + + if unsafe { ScreenToClient(self.as_raw(), &mut pt) } == 0 { + return Err(Error::from_thread()); + } + + if dpi_aware && unsafe { LogicalToPhysicalPointForPerMonitorDPI(null_mut(), &mut pt) } == 0 + { return Err(Error::from_thread()); }