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

Open
#4,440 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

B - bug DS - appkit
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

  1. Connect a Retina display (scale factor 2.0) and an external display (scale factor 1.0)
  2. Launch application on the 1.0x monitor
  3. Save a window position from the 2.0x monitor (e.g., physical position (1728, 68))
  4. 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:

  1. Knowing which monitor the window will land on
  2. Different strategies for high→low vs low→high DPI transitions
  3. 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.