Hello,
Please review this fix for JDK-8282863.

The failing 
`java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java` test 
basically checks that full-screen window remains full-screen when a display 
mode change occurs. It has been introduced in JDK-8211999, which also contains 
numerous fixes for HiDPI displays. In particular, JDK-8211999 changed the code 
of `Win32GraphicsDevice.setDisplayMode()` so that it uses screen dimensions in 
user space instead of device space, which is correct. However, if the display 
mode change incurs display scaling change, as it has been observed on Windows 
10 laptop with HiDPI screen, the method used for obtaining screen bounds in 
user space returns incorrect values under certain conditions.

The issue is reproducible on Windows 10, when resolution of the primary screen 
is higher than 1024x768 with scaling greater than 100%. Resolution and scaling 
of secondary screen(s) is irrelevant. I used a laptop with 2160x1350 display 
resolution and scaling set to 150%. When the 
`java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java` test is 
run with these initial conditions, roughly the following happens:

1. `java.awt.Frame` is created and set as full-screen.
2. `Win32GraphicsDevice.setDisplayMode()` is called to change screen resolution 
from 2160x1350 to 1024x768.
3. `Win32GraphicsDevice.configDisplayMode()` call immediately changes the 
display resolution to 1024x768, which also incurs the immediate display scaling 
change from 150% to 100%.
4. Inside the `Win32GraphicsDevice.setDisplayMode()` screen bounds in user 
space are obtained via `Win32GraphicsConfig.getBounds()`:
5. In the native code of `Win32GraphicsConfig.getBounds()` new screen bounds in 
device space (1024x768) are correctly obtained via `MonitorBounds()`.
6. Then screen bounds are converted to user space by applying **scaling 
factors, which are not yet updated and correspond to previous display mode**. 
In our case, 1024x768 is scaled down by 150% and becomes 683x512.
7. Back in `Win32GraphicsDevice.setDisplayMode()` full-screen window bounds are 
set to incorrectly scaled 683x512 instead of 1024x768.
8. After returning from `Win32GraphicsDevice.setDisplayMode()` the test waits 4 
seconds.
9. `WM_DISPLAYCHANGE` message is received and processed, followed by 
`WM_DPICHANGED`, which updates the scaling factors used by 
`Win32GraphicsConfig.getBounds()` to the correct value of 100%.
10. After 4 seconds test wakes up and obtains screen bounds in user space by 
calling `Win32GraphicsConfig.getBounds()`, which now correctly returns 1024x768.
11. Test compares full-screen window bounds with screen bounds, and fails with 
`java.lang.RuntimeException: width is wrong` as 683 is not equal to 1024 ± 30 
pixels.

Proposed fix adds a `Win32GraphicsDevice.initScaleFactors()` call to 
`Win32GraphicsDevice.setDisplayMode()` code, between calling 
`Win32GraphicsDevice.configDisplayMode()` and 
`Win32GraphicsConfig.getBounds()`. This updates the scaling factors without 
waiting for `WM_DISPLAYCHANGE` or `WM_DPICHANGED`, 
`Win32GraphicsConfig.getBounds()` returns correctly scaled screen bounds in 
user space, and full-screen window remains correctly sized after display mode 
change.

I've run tests from `jdk_awt` group, and applying the fix did not introduce any 
new test failures.

-------------

Commit messages:
 - 8282863: 
java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java fails on 
Windows 10 with HiDPI screen

Changes: https://git.openjdk.java.net/jdk/pull/7835/files
 Webrev: https://webrevs.openjdk.java.net/?repo=jdk&pr=7835&range=00
  Issue: https://bugs.openjdk.java.net/browse/JDK-8282863
  Stats: 5 lines in 1 file changed: 5 ins; 0 del; 0 mod
  Patch: https://git.openjdk.java.net/jdk/pull/7835.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/7835/head:pull/7835

PR: https://git.openjdk.java.net/jdk/pull/7835

Reply via email to