Hi Sergey,
The fix looks good to me.
The trick with WM_WINDOWPOSCHANGING should work to avoid covering the
Taskbar on the secondary monitor too.
Regards,
Alexey
On 26/01/2020 22:43, Sergey Bylokhov wrote:
Hello.
Please review the fix for JDK 15.
Bugs: 8231564: setMaximizedBounds is broken with large display scale
and multiple monitors
https://bugs.openjdk.java.net/browse/JDK-8231564
8176359: Frame#setMaximizedbounds not working properly in multi
screen environments
https://bugs.openjdk.java.net/browse/JDK-8176359
Fix: http://cr.openjdk.java.net/~serb/8176359/webrev.01
Short description:
=================
The fix changes the way on how we limit the size and position of the
maximized window.
Long description:
=================
On Windows supports of maximized is done by the WM_GETMINMAXINFO[1]
message. This
message provides MINMAXINFO[2] which has two related fields: ptMaxSize
and ptMaxPosition.
ptMaxPosition: The position of the left side of the maximized window
(x member) and
the position of the top of the maximized window (y
member). For top-level
windows, this value is based on the position of the
primary monitor.
ptMaxSize: The maximized width (x member) and the maximized height
(y member) of the
window. For top-level windows, this value is based on the
width of the primary
monitor.
"For systems with multiple monitors, the ptMaxSize and ptMaxPosition
members describe the
maximized size and position of the window on the primary monitor, even
if the window
ultimately maximizes onto a secondary monitor. In that case, the
window manager adjusts
these values to compensate for differences between the primary monitor
and the monitor that
displays the window. Thus, if the user leaves ptMaxSize untouched, a
window on a monitor
larger than the primary monitor maximizes to the size of the larger
monitor."
My observation:
=================
1. Description of "ptMaxPosition" in the documentation is wrong,
this value is based on the
actual window's monitor not a primary monitor. I have read about
it here[3] and confirmed
by the tests using three monitors setup.
2. ptMaxSize will be used as-is if the size is smaller than the
!!main!! monitor. If the size
is larger than the main monitor then the window manager adjusts
the size, like this:
// result = requested.w + (current.w - main.w); =>> This results
in the correct size if we
want to fully maximize the window on the current monitor, but if
we want to set a smaller
size then we will get the wrong result.
We can try to compensate for this adjustment like this:
// requested = requested.w - (current.w - main.w);
but this can result to the size smaller than the main screen, so
no adjustment will be
done by the window manager =>> wrong size again.
Note that the result does not depend on the monitor on which we
maximize the window.
3. For example for the three monitors setup: W1=600, W2=1600,
W3=1080. It is not possible
to maximize the window on W3 if the current window is on W2
monitor, because if we
request size=1080 which is bigger than 600 and it will be
adjusted by the window
manager: resulted size = 1080+(1600-600) = 2080. If we will try
to compensate this value:
size = 1080 - (1600-600) = 80, which is smaller than main monitor
and will be used as-is.
Fix description:
1. To fix JDK-8231564 we should convert all coordinates from the
user's virtual space to
the device space.
2. To fix JDK-8176359 we need to translate the bounds.x/y from the
global virtual coordinate
system related to the main monitor to the coordinate system of
the window's actual monitor.
3. The current code already tried to compensate adjustment, but it
missed the fact that the
width and height should be adjusted separately, but even if that
be fixed, in some situations
this logic will be broken(see observation point 3). So instead of
fixing that I have passed
these values to the native as-is, and cut the adjustment in the
WM_WINDOWPOSCHANGING event,
just before the window is resized.
Known issue:
- The current approach, as well as most of the API which uses user's
space coordinates, does
not work well if different scales are used for each screen and the
coordinates "overlaps".
- It looks like the user in the JDK-8231564 tried to avoid covers the
taskbar by the maximized
undecorated window, this is a know issue JDK-8022302.
[1]
https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-getminmaxinfo
[2]
https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-minmaxinfo?redirectedfrom=MSDN
[3] https://devblogs.microsoft.com/oldnewthing/20150501-00/?p=44964