Page MenuHome

Fix T88384: Improved W32 Clamping of Window Size and Position
ClosedPublic

Authored by Harley Acheson (harley) on May 19 2021, 7:42 PM.

Details

Summary

This bug was reported both in T88384 and T86804.

Our placement and sizing of windows can be off by a small number of pixels because Windows 10 includes a thin invisible border (typically 7 pixels at left, right, bottom, but not at top) which we don't take into account.

Weirdest example is in trying to make a window at exactly a monitor's left edge. Passing 0 as "left" to CreateWindowExW() will create a window that is 7 pixels from the edge instead. AdjustWindowRectEx() does properly adjust for this and gives us the proper value to use, which is -7. But we clamp that to values within the monitor bounds.

This patch fixes this issue properly by first clamping our requested values to the monitor, then passing those values AdjustWindowRectEx() and then using those values for CreateWindowExW()

Following is a capture of me trying to place a window within a pixel or two of each edge:

But it ends up like this instead with all four edges incorrect.

After this patch is applied all the edges are perfect.

For testing, this bug report has good instructions: place a window in any specific size and location near edges, "Save Startup File", then close and relaunch.

Diff Detail

Repository
rB Blender

Event Timeline

Harley Acheson (harley) requested review of this revision.May 19 2021, 7:42 PM
Harley Acheson (harley) created this revision.
Harley Acheson (harley) edited the summary of this revision. (Show Details)May 19 2021, 7:51 PM

Simplified by using IntersectRect()

intern/ghost/intern/GHOST_WindowWin32.cpp
126–129

Did you rule out monitor.rcWork being the issue here? I haven't dived into it but the symptoms are in line with what would happen if monitor.rcMonitor was the intended clip space.

@Nicholas Rishel (nicholas_rishel) - Did you rule out monitor.rcWork being the issue here? I haven't dived into it but the symptoms are in line with what would happen if monitor.rcMonitor was the intended clip space.

Yes, I can start with an intention to create at window at 0,0. That Monitor.rcMonitor will contain the actual extend of my monitor (0,0,1920,1080), but Monitor.rcWork is better to use because it does not contain the taskbar area, so 0,0,1920,1040.

The problem really is that from Windows 10 there is an invisible border of 7 pixels all around, except for top. Passing my intended Window rect to AdjustWindowRectEx() returns what seems odd:-7, 0 but passing that to CreateWindowExW makes the window appear at left edge.

Here is a StackOverflow on the same issue: https://stackoverflow.com/questions/60700133/windows-desktop-coordinate-system-is-off-for-certain-windows/60703194#60703194

See comment change in clamp behavior, otherwise lgtm.

intern/ghost/intern/GHOST_WindowWin32.cpp
125

Intersecting with the monitor rect will be subtly different from clamping the origin and width/height; a change in origin now changes the clipped width/height. I'm not sure which behavior is preferable but I'd call this change in behavior out in the commit message if kept.

This revision is now accepted and ready to land.May 20 2021, 5:46 AM

@Nicholas Rishel (nicholas_rishel) - Intersecting with the monitor rect will be subtly different...

Yes, thanks for noticing this mistake. Using IntersectRect() would truncate windows at the monitor edge. This version puts back in the code that clamps the window size then repositions rather than truncating.

LGTM, good job noticing the subtle change in behavior there @Nicholas Rishel (nicholas_rishel), i kinda feel bad for suggesting it to harley now :)