rust-windowing / rust-windowing/winit
set_outer_position and request_inner_size use current monitor's scale factor instead of target monitor's on macOS
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 6.2k
- Forks
- 1.3k
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 9
Description
Description
Description
When calling set_outer_position() or request_inner_size() to move/resize a window to a position on a different monitor with a different scale factor, winit converts the coordinates using the current window's monitor scale factor instead of the target monitor's scale factor.
This is the write-side counterpart to #2645, which documents the same fundamental issue for read operations (outer_position(), MonitorHandle::position()).
Environment
- macOS (tested on Tahoe 26.1)
- Multi-monitor setup with different scale factors (e.g., Retina 2.0x + external 1.0x)
Reproduction
- Connect a Retina display (scale factor 2.0) and an external display (scale factor 1.0)
- Launch application on the 1.0x monitor
- Save a window position from the 2.0x monitor (e.g., physical position (1728, 68))
- Call set_outer_position(PhysicalPosition::new(1728, 68)) to restore
Expected: Window appears at physical position (1728, 68) on the 2.0x monitor
Actual: Window appears at physical position (3456, 136) — coordinates are doubled
Root Cause
In the macOS backend, set_outer_position converts PhysicalPosition to the internal coordinate system using backingScaleFactor() from the window's current monitor. When the target position is on a different monitor, this conversion is incorrect.
Similarly, request_inner_size uses the current monitor's scale factor when converting physical size to logical size for setContentSize:.
Impact
Applications that save/restore window position across sessions cannot correctly restore windows to monitors with different scale factors than the launch monitor. The position/size error is proportional to the scale factor ratio between monitors.
Workaround
We currently compensate by pre-multiplying coordinates by (current_scale / target_scale) before calling these methods, but this requires:
- Knowing which monitor the window will land on
- Different strategies for high→low vs low→high DPI transitions
- A two-phase approach for high→low transitions due to size clamping
Related Issues
- #2645 — Same root cause, but for read operations (outer_position(), MonitorHandle::position())
- #837 — HiDPI scaling architecture discussion
macOS version
ProductName: macOS
ProductVersion: 26.1
BuildVersion: 25B78
Winit version
0.30
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 tracing the macOS backend entry points for set_outer_position and request_inner_size, focusing on how backingScaleFactor() is selected during conversion. Compare the write-side behavior with related issue #2645 and the reported reproduction. Done means positions and sizes use the target monitor's scale factor across mixed-DPI monitors without the workaround.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, rust
- Domain
- desktop, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100