rust-windowing / rust-windowing/winit
Windows 11 24H2 mixed-DPI drag still grows windows in 0.30.13
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 6.2k
- Forks
- 1.3k
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 9
Description
Description
This is a follow-up to the closed issue #4041. The same Windows mixed-DPI drag/resize feedback loop is still reproducible with winit 0.30.13 on Windows 11 24H2.
When a maximized window is dragged from a 125% scaled primary monitor to a 100% scaled monitor, the restored window can grow to an extremely large size and remain attached to the original monitor instead of landing on the target monitor. This also reproduces through eframe 0.29.1, because it uses winit underneath.
Monitor layout used for reproduction
DISPLAY5: 1920x1080, 100% scale, positioned left of primary:(-1920,0)-(0,1080)DISPLAY1: 1920x1080, 125% scale, primary:(0,0)-(1920,1080)DISPLAY6: 1920x1200, 125% scale, positioned right:(1920,-65)-(3456,895)
Minimal repro
Two minimal binaries were tested:
- Raw
winit 0.30.13:
use winit::{
application::ApplicationHandler,
dpi::LogicalSize,
event::WindowEvent,
event_loop::{ActiveEventLoop, EventLoop},
window::{Window, WindowAttributes, WindowId},
};
#[derive(Default)]
struct App { window: Option<Window> }
impl ApplicationHandler for App {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
if self.window.is_none() {
let attrs = WindowAttributes::default()
.with_title("repro_winit")
.with_inner_size(LogicalSize::new(1000.0, 650.0))
.with_maximized(true);
self.window = Some(event_loop.create_window(attrs).expect("create window"));
}
}
fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
if matches!(event, WindowEvent::CloseRequested) {
event_loop.exit();
}
}
}
fn main() {
let event_loop = EventLoop::new().expect("event loop");
let mut app = App::default();
event_loop.run_app(&mut app).expect("run app");
}
eframe 0.29.1withViewportBuilder::with_maximized(true)also reproduces the same behavior.
Both binaries used a PerMonitorV2 manifest.
Observed measurement without patch
Raw winit 0.30.13, after dragging from DISPLAY1 to the left monitor:
Before:
ShowCmd: 3
Rect: (-9,-9)-(1929,1029)
Normal: (32,32)-(1300,892)
Monitor: \\.\DISPLAY1
DPI: 120
After drag:
ShowCmd: 1
Rect: (-1329,75)-(2545,2701)
Size: 3874x2626
Monitor: \\.\DISPLAY1
DPI: 120
eframe 0.29.1 showed the same class of failure:
After drag:
Rect: (-1164,75)-(1935,2176)
Size: 3099x2101
Monitor: \\.\DISPLAY1
DPI: 120
Local patch tested
The issue disappears when WM_DPICHANGED while WindowFlags::MARKER_IN_SIZE_MOVE uses the Windows-provided suggested_rect directly instead of applying the current conservative rect / monitor nudge logic.
Patch tested locally against winit 0.30.13:
let new_outer_rect: RECT;
if dragging_window {
new_outer_rect = suggested_rect;
} else {
// existing conservative_rect + monitor nudge logic
}
Observed measurement with local patch
Raw winit 0.30.13 patched:
Before:
ShowCmd: 3
Rect: (-9,-9)-(1929,1029)
Normal: (160,160)-(1428,1020)
Monitor: \\.\DISPLAY1
DPI: 120
After drag:
ShowCmd: 1
Rect: (-1417,79)-(-403,767)
Size: 1014x688
Monitor: \\.\DISPLAY5
DPI: 96
eframe 0.29.1 using the patched winit also behaves correctly:
After drag:
Rect: (-1404,79)-(-390,767)
Size: 1014x688
Monitor: \\.\DISPLAY5
DPI: 96
Notes
This matches the analysis already posted in #4041: during WM_DPICHANGED, the current monitor check / nudge logic can keep the window on the old monitor, trigger another DPI change, and repeatedly enlarge the window. Microsoft's WM_DPICHANGED guidance recommends applying the suggested rectangle from lParam with SetWindowPos.
Reference: https://learn.microsoft.com/en-us/windows/win32/hidpi/wm-dpichanged
Platform
- Windows 11 24H2
winit 0.30.13- Reproduces with raw
winitand througheframe 0.29.1 - Process DPI awareness: Per Monitor Aware (
GetProcessDpiAwareness == 2)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating the Windows WM_DPICHANGED handling for WindowFlags::MARKER_IN_SIZE_MOVE, then run the minimal winit binary on the documented mixed-DPI monitor layout. Compare the drag path with the existing conservative-rect and monitor-nudge logic; done means the restored window lands on the target monitor without growing excessively, while preserving the non-drag behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- desktop, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100