RFR: 8282863: java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java fails on Windows 10 with HiDPI screen [v3]
Dmitry Kulikov
duke at openjdk.java.net
Wed May 4 07:48:17 UTC 2022
> 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 on Windows 10 using a laptop with the same settings that caused the issue (primary screen with 2160x1350 resolution and 150% scaling), and applying the fix did not introduce any new test failures.
Dmitry Kulikov has updated the pull request incrementally with one additional commit since the last revision:
Update the JavaDoc for added method
-------------
Changes:
- all: https://git.openjdk.java.net/jdk/pull/7835/files
- new: https://git.openjdk.java.net/jdk/pull/7835/files/cab8c316..008e9c19
Webrevs:
- full: https://webrevs.openjdk.java.net/?repo=jdk&pr=7835&range=02
- incr: https://webrevs.openjdk.java.net/?repo=jdk&pr=7835&range=01-02
Stats: 5 lines in 1 file changed: 3 ins; 0 del; 2 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
More information about the client-libs-dev
mailing list