> 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 src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java Comments clean-up Co-authored-by: Alexey Ivanov <70774172+aivanov-...@users.noreply.github.com> ------------- Changes: - all: https://git.openjdk.java.net/jdk/pull/7835/files - new: https://git.openjdk.java.net/jdk/pull/7835/files/008e9c19..a5d4a68f Webrevs: - full: https://webrevs.openjdk.java.net/?repo=jdk&pr=7835&range=03 - incr: https://webrevs.openjdk.java.net/?repo=jdk&pr=7835&range=02-03 Stats: 2 lines in 1 file changed: 0 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