Skip to content

On Windows, read the new scale factor's monitor from the suggested rect - #4704

Closed
bigtree108-dmytro wants to merge 1 commit into
rust-windowing:masterfrom
bigtree108-dmytro:windows-dpi-monitor-from-suggested-rect
Closed

bigtree108-dmytro wants to merge 1 commit into
rust-windowing:masterfrom
bigtree108-dmytro:windows-dpi-monitor-from-suggested-rect

Conversation

@bigtree108-dmytro

Copy link
Copy Markdown

On Windows, a window grows by the ratio between two monitors' scale factors every time it is dragged across the boundary between them, until it is larger than the desktop.

WM_DPICHANGED is about the monitor the window is moving onto, and the suggested rect the message carries is on that monitor. apply_win10_dpi_adjustment asks MonitorFromWindow instead, which answers with the monitor the window is still mostly on. While a drag is in progress those are different monitors, so the conservative rect is judged to be on the wrong one and the window is nudged back onto the monitor it is leaving. That move produces another WM_DPICHANGED, which scales the size by the ratio again, and the two feed each other for as long as the drag lasts.

Reading the monitor from the suggested rect is what the rest of the file already does for this question: the WM_NCCALCSIZE/WM_WINDOWPOSCHANGING path a thousand lines above carries the comment "Use MonitorFromRect instead of MonitorFromWindow to select the target monitor" for the same reason.

Measured on Windows 11 26200, two monitors side by side at 100 % and 125 %, primary on the right at 125 %, with a Slint application on the software renderer. Dragging the window from the left monitor onto the right one and back, its physical size before:

2145x1364 dpi 120
2683x1706 dpi 120
3354x2133 dpi 120
2685x1708 dpi 96

and after, over a minute of dragging back and forth across the boundary:

882x561  dpi 96
1101x700 dpi 120
882x561  dpi 96
1101x700 dpi 120

which is one logical size, kept.

Reported downstream as slint-ui/slint#11073, and this is the line named in #3040.

The import of MonitorFromWindow goes with it: nothing else in the file uses it now.

Comment thread winit-win32/src/event_loop.rs Outdated
WM_DPICHANGED is about the monitor the window is moving onto, and the suggested rect is on it. MonitorFromWindow answers with the monitor the window is still mostly on, so while a window is dragged across a boundary between two monitors of different scale factors it is nudged back onto the one it is leaving, the next WM_DPICHANGED scales the size by the ratio again, and a few crossings leave the window larger than the desktop.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@bigtree108-dmytro
bigtree108-dmytro force-pushed the windows-dpi-monitor-from-suggested-rect branch from 155fdef to d8d1590 Compare September 22, 2026 12:34
@bigtree108-dmytro

Copy link
Copy Markdown
Author

All feedback applied 😊

@bigtree108-dmytro

Copy link
Copy Markdown
Author

I owe you a correction on this one, @ogoffart. While reading #4600 and #4694 I found that #4341 already changed this on master last year: on Windows 11 the WM_DPICHANGED handler now applies the suggested rect as it is and never calls apply_win10_dpi_adjustment. The measurements in the description were taken with 0.30.13, which is what Slint uses, and there the same adjustment still runs on every Windows version. On master this change only reaches Windows 10 (builds before 22000), and I haven't tested it there, so I'm closing it rather than ask you to review it.

For 0.30 the open issue is #4600, and the fix master already has is #4341. I'll test a backport of #4341 on two screens with different scale factors, including the maximized drag from #4600, and post the results there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants