Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Unexpected resize when move window to secondary monitor if dpi diff in Windows 11 24H2 #4041

Open
Kr328 opened this issue Dec 14, 2024 · 1 comment
Labels
B - bug Dang, that shouldn't have happened DS - windows

Comments

@Kr328
Copy link

Kr328 commented Dec 14, 2024

Description

When I move the window from monitor 1 (1440p, 150% scale) to monitor 2 (1080p, 125% scale), the window size keeps getting bigger.

Notes

  1. Appears only in Windows 11 24H2
  2. Appears only dragging the left side of the window's title bar.

Reproduce Screen Record

reproduce.mp4

Reproduce Project

reproduce.zip
Just copy from example :)

Windows version

Microsoft Windows [Version 10.0.26100.2605]

Winit version

0.30.5

@Kr328 Kr328 added B - bug Dang, that shouldn't have happened DS - windows labels Dec 14, 2024
@DorianRudolph
Copy link

DorianRudolph commented Jan 1, 2025

I also noticed this. The issue disappears if you remove

let new_physical_surface_size = *new_surface_size.lock().unwrap();
drop(new_surface_size);
let dragging_window: bool;
{
let window_state = userdata.window_state_lock();
dragging_window =
window_state.window_flags().contains(WindowFlags::MARKER_IN_SIZE_MOVE);
// Unset maximized if we're changing the window's size.
if new_physical_surface_size != old_physical_surface_size {
WindowState::set_window_flags(window_state, window, |f| {
f.set(WindowFlags::MAXIMIZED, false)
});
}
}
let new_outer_rect: RECT;
{
let suggested_ul =
(suggested_rect.left + margin_left, suggested_rect.top + margin_top);
let mut conservative_rect = RECT {
left: suggested_ul.0,
top: suggested_ul.1,
right: suggested_ul.0 + new_physical_surface_size.width as i32,
bottom: suggested_ul.1 + new_physical_surface_size.height as i32,
};
conservative_rect = window_flags
.adjust_rect(window, conservative_rect)
.unwrap_or(conservative_rect);
// If we're dragging the window, offset the window so that the cursor's
// relative horizontal position in the title bar is preserved.
if dragging_window {
let bias = {
let cursor_pos = {
let mut pos = unsafe { mem::zeroed() };
unsafe { GetCursorPos(&mut pos) };
pos
};
let suggested_cursor_horizontal_ratio = (cursor_pos.x - suggested_rect.left)
as f64
/ (suggested_rect.right - suggested_rect.left) as f64;
(cursor_pos.x
- (suggested_cursor_horizontal_ratio
* (conservative_rect.right - conservative_rect.left) as f64)
as i32)
- conservative_rect.left
};
conservative_rect.left += bias;
conservative_rect.right += bias;
}
// Check to see if the new window rect is on the monitor with the new DPI factor.
// If it isn't, offset the window so that it is.
let new_dpi_monitor = unsafe { MonitorFromWindow(window, MONITOR_DEFAULTTONULL) };
let conservative_rect_monitor =
unsafe { MonitorFromRect(&conservative_rect, MONITOR_DEFAULTTONULL) };
new_outer_rect = if conservative_rect_monitor == new_dpi_monitor {
conservative_rect
} else {
let get_monitor_rect = |monitor| {
let mut monitor_info = MONITORINFO {
cbSize: mem::size_of::<MONITORINFO>() as _,
..unsafe { mem::zeroed() }
};
unsafe { GetMonitorInfoW(monitor, &mut monitor_info) };
monitor_info.rcMonitor
};
let wrong_monitor = conservative_rect_monitor;
let wrong_monitor_rect = get_monitor_rect(wrong_monitor);
let new_monitor_rect = get_monitor_rect(new_dpi_monitor);
// The direction to nudge the window in to get the window onto the monitor with
// the new DPI factor. We calculate this by seeing which monitor edges are
// shared and nudging away from the wrong monitor based on those.
#[allow(clippy::bool_to_int_with_if)]
let delta_nudge_to_dpi_monitor = (
if wrong_monitor_rect.left == new_monitor_rect.right {
-1
} else if wrong_monitor_rect.right == new_monitor_rect.left {
1
} else {
0
},
if wrong_monitor_rect.bottom == new_monitor_rect.top {
1
} else if wrong_monitor_rect.top == new_monitor_rect.bottom {
-1
} else {
0
},
);
let abort_after_iterations = new_monitor_rect.right - new_monitor_rect.left
+ new_monitor_rect.bottom
- new_monitor_rect.top;
for _ in 0..abort_after_iterations {
conservative_rect.left += delta_nudge_to_dpi_monitor.0;
conservative_rect.right += delta_nudge_to_dpi_monitor.0;
conservative_rect.top += delta_nudge_to_dpi_monitor.1;
conservative_rect.bottom += delta_nudge_to_dpi_monitor.1;
if unsafe { MonitorFromRect(&conservative_rect, MONITOR_DEFAULTTONULL) }
== new_dpi_monitor
{
break;
}
}
conservative_rect
};
}
unsafe {
SetWindowPos(
window,
0,
new_outer_rect.left,
new_outer_rect.top,
new_outer_rect.right - new_outer_rect.left,
new_outer_rect.bottom - new_outer_rect.top,
SWP_NOZORDER | SWP_NOACTIVATE,
)
};

Cursory testing did not reveal any adverse effects from removing that snippet.

Edit: If the monitors are stacked vertically, it is practically impossible to drag the window between them, regardless of where you grab it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B - bug Dang, that shouldn't have happened DS - windows
Development

No branches or pull requests

2 participants