-
Notifications
You must be signed in to change notification settings - Fork 182
Use DwmGetWindowAttribute for Shell#getLocation to avoid shadow margins #2426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
9395761
to
8a135d1
Compare
Test Results 111 files - 7 111 suites - 7 11m 42s ⏱️ + 1m 39s For more details on these failures, see this check. Results for commit 3811c13. ± Comparison against base commit 75c97fd. This pull request removes 56 tests.
♻️ This comment has been updated with latest results. |
bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Shell.java
Outdated
Show resolved
Hide resolved
bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java
Outdated
Show resolved
Hide resolved
a4ebaa5
to
49cfcde
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change looks good when using monitor-specific UI scaling and significantly improves UX in that case: shells properly open on the correct monitor and not on the monitor to the left if the parent is maximized. The given reproducer is a good way to test it.
For testing I have added some logging of the new and old values to compare where one can see that the x values are off by some pixels:
However, the change is incompatible with monitor-specific scaling being disabled. In that case, the offset between the two values is incorporated when reopening a shell, leading it to slightly move to the right on every reopen. See this capture:
Some interesting information on the issue in general can also be found here: https://stackoverflow.com/questions/34139450/getwindowrect-returns-a-size-including-invisible-borders
bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Shell.java
Outdated
Show resolved
Hide resolved
I tested this and figured out it happens even with monitor-specific scaling enabled. The stored coordinates when windows is closed and when it's open are identical. However the move event is occurred after opening the shell and when the getLocation is called again and from OS DwmGetWindowAttribute location is requested for the handle, it returns the +7px which I don't understand why since the position hasn't changed. I am unable to figure out this issue and currently I don't have any solution to prevent this right shifting of the shell when it's reopened. @HeikoKlare |
GetWindowRect includes invisible shadow borders on Windows 10/11, causing Shell#getLocation to return coordinates offset by ~9px from the visible frame. Replaced with DwmGetWindowAttribute(DWMWA_EXTENDED_FRAME_BOUNDS) to report the true window bounds in screen space, with GetWindowRect as a fallback if DWM is unavailable.
49cfcde
to
3811c13
Compare
That's interesting. I thought I have tested it and found that to work properly (as the windows use a different logical positioning when running in different DPI awareness), but maybe I did not analyze properly. What about looking for solutions others may have already found the problem? This seems to be a general "issue" with Win32 API, so many consumers will have already run into the problem (like in the linked Stack Overflow post), so there is a chance to find something in the web (either with or without AI assistance ;-) ). |
GetWindowRect
returns the bounding rectangle of the entire window including invisible shadows and glass margins. This leads toShell#getLocation
reporting coordinates that do not match the actual visible frame location. For example, when positioning a dialog close to the left edge of a monitor, the reported X coordinate can be shifted by ~9 pixels compared to the visible window frame. The same discrepancy appears when opening dialogs under a maximized parent shell.This patch changes
Shell#getLocation
to use:This API returns the extended frame bounds rectangle in screen space, which corresponds to the true visible window frame and excludes the transparent shadow margins. This produces values that align with what the user sees on screen and avoids subtle layout issues in multi-monitor or mixed-DPI setups.
If DWM is not available (e.g., on older Windows versions or when composition is disabled), the implementation falls back to
GetWindowRect
, preserving backward compatibility.Benefits:
Steps to Reproduce
Ctrl + Shift + T
Expected result
The sub-shell or dialog should open where it was last closed. There should be no shadow margins that leads to change of coordinates and resulting in window opening in the other monitor.