Repository navigation
NSWindow: skip the screen-parameters remap when the frame already fits the new screen - #1008
Conversation
applicationDidChangeScreenParameters: remaps the frame by the old->new screen delta, but the window's cached _screen can already reflect the new screen when the handler reads it (the screen list is rebuilt during the notification dispatch, and -screen recomputes against it), so the delta collapses to zero exactly when a remap is needed and the previous-screen frame is re-applied against the new screen. If the frame already fits the new screen it has been realigned already (or sits on an unaffected screen): skip both the remap and the re-apply in that case. Details and analysis: gnustep#1006.
|
If I understad the general idea, isn't NSContainsRect() the wrong test? |
|
|
Yes, NSContainsRect() is the wrong test — a frame can fit the new
The unambiguous signal seems to be "this frame was already realigned", I could rework the PR in that direction — or whichever you prefer. |
| [self _applyFrame: newFrame]; | ||
| /* Skip the remap when the frame already fits the new screen: | ||
| it has already been realigned against it. */ | ||
| if (NSContainsRect(newScreenFrame, newFrame) == NO) |
There was a problem hiding this comment.
I think, it would be clearer to have newFrame only inside the if and use _frame here.
fredkiefer
left a comment
There was a problem hiding this comment.
Just move the variable, the rest is fine.
Per review: clearer to have newFrame only inside the if.
|
Done — |
fredkiefer
left a comment
There was a problem hiding this comment.
In some cases we now will do to little and in others to much. But as you pointed out the screen the window holds may already be updated. So there is no way to clearly tell, how much the frame should be changed.
Richard's idea to see, whether the frame of the old and the new screen differ at all, will also not work.
Implements the fix proposed in #1006.
applicationDidChangeScreenParameters:remaps the window frame by the old→new screen delta, readingoldScreenFramefrom the window's cached_screen. As analyzed in #1006, that cached screen can already reflect the new state when the handler reads it: the screen list is rebuilt during the notification dispatch, and-screen's recompute — reachable e.g. via[NSScreen mainScreen]→[keyWindow screen]— refreshes later observers'_screento the new frame before their own handlers run. The delta then collapses to zero exactly when a remap was needed, and the previous-screen frame is re-applied against the new screen height — the window moves by exactly the height difference.This adds the minimal guard from #1006: if the frame already fits the new screen, skip both the remap and the re-apply — the window has already been realigned against it (or sits on an unaffected screen). The delta path is unchanged for frames that do not fit.
Validation (Xvfb + RANDR, WM-less, paired with the backend-side realignment from gnustep/libs-back#251): a window's title bar across a 1280×800 → 1024×768 → 1280×800 cycle moves 271 → 270 → 270 px (a 1 px rounding difference), stable across repeated runs and multi-cycle sequences; without the guard the window jumps ±32 px on every cycle.