Skip to content

macOS: Window size resets to default when dragging between monitors with different scale factors after programmatic resize #4441

@natepiano

Description

@natepiano

Description

summary

When a window is created on a high-DPI monitor (scale 2.0), programmatically moved to a low-DPI monitor (scale 1.0) and resized, then manually dragged back to the original monitor, the window size incorrectly resets to the original default size instead of maintaining the programmatically set size.

repro

hardware

  • macOS with dual monitor setup
  • Monitor 0: High-DPI (Retina, scale factor 2.0)
  • Monitor 1: Low-DPI (external, scale factor 1.0)

clone from my example based on a branch of v0.30.12

Minimal reproduction example and debug logging available at:
https://github.com/natepiano/winit/tree/macos-scale-restore-bug

git clone https://github.com/natepiano/winit.git
cd winit
cargo run --example macos_scale_restore_bug

repro steps

  1. Launch example on Monitor 0 (Retina) - window appears at 800x600 logical
  2. Press 'R' to programmatically move to Monitor 1 and resize to 600x400
  3. Drag window back to Monitor 0
  4. BUG: Window resets to 800x600 instead of staying at 600x400

workaround

If you manually resize the window (even slightly) on Monitor 1 before dragging back, the bug does not occur. Try it yourself to see the difference.

hypothetical root cause

AppKit internally tracks "user intended size" per scale factor. When a window is created at size X on scale=2, AppKit remembers X as the intended size for scale=2.

  • Programmatic resize via setContentSize does NOT update this internal tracking

  • Manual resize via windowDidEndLiveResize DOES update the tracking

    When the window returns to scale=2, AppKit "helpfully" restores the original size it has cached for that scale factor.

Debug logging in the example shows:

[DEFERRED RESIZE] Now applying 600x400 physical at scale=1 ✓ Correct
[RESIZE] 1200x800 physical (600x400 logical at scale 2) ✓ Initially correct when dragged back
[winit macOS] windowWillStartLiveResize
[winit macOS] frameDidChange: logical 800x600 ✗ BUG: Reset to default

caveat

This is just a hypothesis - i don't for sure know what's happening but i do know that for now in my code on my system i need to provide a workaround for this situation.

Possible Fix

Winit may need to work around this AppKit behavior by either:

  1. Re-applying the desired size after detecting an unwanted reset during frameDidChange
  2. Triggering whatever internal state update windowDidEndLiveResize performs after programmatic resizes

macOS version

ProductName:		macOS
ProductVersion:		26.1
BuildVersion:		25B78

Winit version

0.30.12

Metadata

Metadata

Assignees

No one assigned

    Labels

    B - bugDang, that shouldn't have happenedDS - appkitAffects the AppKit/macOS backend

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions