On Wed, 4 May 2022 07:48:17 GMT, Dmitry Kulikov <[email protected]> wrote:
>> 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
Marked as reviewed by aivanov (Reviewer).
src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java line 485:
> 483: // Note: window will get resized to actual full-screen
> dimensions
> 484: // in the upcoming display change event, when the DPI scales
> 485: // would already be correctly set etc.
Suggestion:
// Note: the window will get resized to the actual full-screen
dimensions
// in the upcoming display change event, when the DPI scales
// would already be correctly set etc.
Or to re-use the original comment:
Suggestion:
// Note: the full-screen window will get resized to the dimensions
of the new
// display mode in the upcoming display change event, when the DPI
scales
// would already be correctly set etc.
-------------
PR: https://git.openjdk.java.net/jdk/pull/7835