@@ -18,8 +18,8 @@ use crate::utils::Lazy;
1818use windows_sys:: Win32 :: Devices :: HumanInterfaceDevice :: MOUSE_MOVE_RELATIVE ;
1919use windows_sys:: Win32 :: Foundation :: { HWND , LPARAM , LRESULT , POINT , RECT , WPARAM } ;
2020use windows_sys:: Win32 :: Graphics :: Gdi :: {
21- MonitorFromRect , RedrawWindow , ScreenToClient , ValidateRect , MONITOR_DEFAULTTONULL ,
22- RDW_INTERNALPAINT , SC_SCREENSAVE ,
21+ GetMonitorInfoW , MonitorFromRect , MonitorFromWindow , RedrawWindow , ScreenToClient ,
22+ ValidateRect , MONITORINFO , MONITOR_DEFAULTTONULL , RDW_INTERNALPAINT , SC_SCREENSAVE ,
2323} ;
2424use windows_sys:: Win32 :: System :: Ole :: RevokeDragDrop ;
2525use windows_sys:: Win32 :: System :: Threading :: { GetCurrentThreadId , INFINITE } ;
@@ -2196,45 +2196,110 @@ unsafe fn public_window_callback_inner(
21962196 }
21972197
21982198 let new_outer_rect: RECT ;
2199- {
2200- let suggested_ul =
2201- ( suggested_rect. left + margin_left, suggested_rect. top + margin_top) ;
2202-
2203- let mut conservative_rect = RECT {
2204- left : suggested_ul. 0 ,
2205- top : suggested_ul. 1 ,
2206- right : suggested_ul. 0 + new_physical_inner_size. width as i32 ,
2207- bottom : suggested_ul. 1 + new_physical_inner_size. height as i32 ,
2208- } ;
2199+ if util:: WIN_VERSION . build < 22000 {
2200+ // The window position needs adjustment on Windows 10.
2201+ {
2202+ let suggested_ul =
2203+ ( suggested_rect. left + margin_left, suggested_rect. top + margin_top) ;
2204+
2205+ let mut conservative_rect = RECT {
2206+ left : suggested_ul. 0 ,
2207+ top : suggested_ul. 1 ,
2208+ right : suggested_ul. 0 + new_physical_inner_size. width as i32 ,
2209+ bottom : suggested_ul. 1 + new_physical_inner_size. height as i32 ,
2210+ } ;
22092211
2210- conservative_rect = window_flags
2211- . adjust_rect ( window, conservative_rect)
2212- . unwrap_or ( conservative_rect) ;
2213-
2214- // If we're dragging the window, offset the window so that the cursor's
2215- // relative horizontal position in the title bar is preserved.
2216- if dragging_window {
2217- let bias = {
2218- let cursor_pos = {
2219- let mut pos = unsafe { mem:: zeroed ( ) } ;
2220- unsafe { GetCursorPos ( & mut pos) } ;
2221- pos
2212+ conservative_rect = window_flags
2213+ . adjust_rect ( window, conservative_rect)
2214+ . unwrap_or ( conservative_rect) ;
2215+
2216+ // If we're dragging the window, offset the window so that the cursor's
2217+ // relative horizontal position in the title bar is preserved.
2218+ if dragging_window {
2219+ let bias = {
2220+ let cursor_pos = {
2221+ let mut pos = unsafe { mem:: zeroed ( ) } ;
2222+ unsafe { GetCursorPos ( & mut pos) } ;
2223+ pos
2224+ } ;
2225+ let suggested_cursor_horizontal_ratio =
2226+ ( cursor_pos. x - suggested_rect. left ) as f64
2227+ / ( suggested_rect. right - suggested_rect. left ) as f64 ;
2228+
2229+ ( cursor_pos. x
2230+ - ( suggested_cursor_horizontal_ratio
2231+ * ( conservative_rect. right - conservative_rect. left ) as f64 )
2232+ as i32 )
2233+ - conservative_rect. left
22222234 } ;
2223- let suggested_cursor_horizontal_ratio = ( cursor_pos. x - suggested_rect. left )
2224- as f64
2225- / ( suggested_rect. right - suggested_rect. left ) as f64 ;
2226-
2227- ( cursor_pos. x
2228- - ( suggested_cursor_horizontal_ratio
2229- * ( conservative_rect. right - conservative_rect. left ) as f64 )
2230- as i32 )
2231- - conservative_rect. left
2235+ conservative_rect. left += bias;
2236+ conservative_rect. right += bias;
2237+ }
2238+
2239+ // Check to see if the new window rect is on the monitor with the new DPI factor.
2240+ // If it isn't, offset the window so that it is.
2241+ let new_dpi_monitor =
2242+ unsafe { MonitorFromWindow ( window, MONITOR_DEFAULTTONULL ) } ;
2243+ let conservative_rect_monitor =
2244+ unsafe { MonitorFromRect ( & conservative_rect, MONITOR_DEFAULTTONULL ) } ;
2245+ new_outer_rect = if conservative_rect_monitor == new_dpi_monitor {
2246+ conservative_rect
2247+ } else {
2248+ let get_monitor_rect = |monitor| {
2249+ let mut monitor_info = MONITORINFO {
2250+ cbSize : mem:: size_of :: < MONITORINFO > ( ) as _ ,
2251+ ..unsafe { mem:: zeroed ( ) }
2252+ } ;
2253+ unsafe { GetMonitorInfoW ( monitor, & mut monitor_info) } ;
2254+ monitor_info. rcMonitor
2255+ } ;
2256+ let wrong_monitor = conservative_rect_monitor;
2257+ let wrong_monitor_rect = get_monitor_rect ( wrong_monitor) ;
2258+ let new_monitor_rect = get_monitor_rect ( new_dpi_monitor) ;
2259+
2260+ // The direction to nudge the window in to get the window onto the monitor with
2261+ // the new DPI factor. We calculate this by seeing which monitor edges are
2262+ // shared and nudging away from the wrong monitor based on those.
2263+ #[ allow( clippy:: bool_to_int_with_if) ]
2264+ let delta_nudge_to_dpi_monitor = (
2265+ if wrong_monitor_rect. left == new_monitor_rect. right {
2266+ -1
2267+ } else if wrong_monitor_rect. right == new_monitor_rect. left {
2268+ 1
2269+ } else {
2270+ 0
2271+ } ,
2272+ if wrong_monitor_rect. bottom == new_monitor_rect. top {
2273+ 1
2274+ } else if wrong_monitor_rect. top == new_monitor_rect. bottom {
2275+ -1
2276+ } else {
2277+ 0
2278+ } ,
2279+ ) ;
2280+
2281+ let abort_after_iterations = new_monitor_rect. right - new_monitor_rect. left
2282+ + new_monitor_rect. bottom
2283+ - new_monitor_rect. top ;
2284+ for _ in 0 ..abort_after_iterations {
2285+ conservative_rect. left += delta_nudge_to_dpi_monitor. 0 ;
2286+ conservative_rect. right += delta_nudge_to_dpi_monitor. 0 ;
2287+ conservative_rect. top += delta_nudge_to_dpi_monitor. 1 ;
2288+ conservative_rect. bottom += delta_nudge_to_dpi_monitor. 1 ;
2289+
2290+ if unsafe { MonitorFromRect ( & conservative_rect, MONITOR_DEFAULTTONULL ) }
2291+ == new_dpi_monitor
2292+ {
2293+ break ;
2294+ }
2295+ }
2296+
2297+ conservative_rect
22322298 } ;
2233- conservative_rect. left += bias;
2234- conservative_rect. right += bias;
22352299 }
2236-
2237- new_outer_rect = conservative_rect;
2300+ } else {
2301+ // The suggested position is fine w/o adjustment on Windows 11.
2302+ new_outer_rect = suggested_rect
22382303 }
22392304
22402305 unsafe {
0 commit comments