fix: process window position before size in changed_windows#23248
fix: process window position before size in changed_windows#23248mockersf merged 1 commit intobevyengine:mainfrom
Conversation
Move the position block above the resolution block so the window is on the correct monitor (and scale_factor() returns the target monitor's value) before request_inner_size runs. This is a prerequisite for the winit fix to set_outer_position's scale factor resolution (rust-windowing/winit#4440).
note from my PR to winit:I did not apply this fix to the X11 backend. X11 typically reports the same scale factor for all monitors (via the global Xft.dpi setting), so the bug does not manifest in practice. note i didn't provide to winitWayland doesn't matter - can't set position on Wayland |
Isn't this solved by the recently merged xx-zones PR: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/264? |
|
well well - i had no idea - i wonder when that will make its way into the distribution i test with (asahi running on a partition on my m2 mac). I would definitely love to be able to relax / remove special casing for wayland in my code. As i'm parsing your link - it seems that this is an experimental feature you have to enable. I'm a linux beginner so don't know how to get this to work or test for its existence. Any pointers? Regardless - even though i didn't test this on Wayland, it should still be a no-op for wayland right now just as it is for everything else I tested - and it's only a net positive for wayland as well after winit merges (rust-windowing/winit#4505) for anyone that has the experimental wayland positioning turned on. Thanks for the link. |
|
I'm not that well versed with Wayland tbh, thought I would just highlight it. You can see which compositors support it here though: https://wayland.app/protocols/xx-zones-v1#compositor-support, which is none right now. |
Summary
When a bevy app starts, winit creates the window on a default monitor. If the app then sets the window's position to a location on a different monitor with a different scale factor, both position and size may be applied in the same pass through
changed_windows().Currently, size is processed first (via
request_inner_size), then position (viaset_outer_position). Since the window hasn't moved yet whenrequest_inner_sizeruns, it uses the default monitor's scale factor for the size calculation — not the scale factor of the monitor the window is about to move to. This produces the wrong size when the two monitors have different scale factors.This PR moves the position block above the size block so the window is on the target monitor before
request_inner_sizeruns.Context
This change is a no-op with current released versions of winit. Today, winit's
set_outer_positionhas a bug where it uses the window's current monitor's scale factor instead of the target monitor's (rust-windowing/winit#4505), so the window doesn't reliably land at the correct position regardless of ordering.Once winit merges that fix and bevy takes a dependency on a version that includes it, the ordering will matter:
set_outer_positionwill correctly move the window to the target monitor, andrequest_inner_sizeneeds to run after that move so it sees the correctscale_factor().The change is safe and backwards-compatible — it just reorders two independent blocks within the same function.
Testing
Tested on macOS (1x + 2x) and Windows (1x + 1.5x) with the patched winit. Window appears at the correct position and size on the target monitor.