RFR: 8291087: Wrong position of focus of screen reader on Windows with screen scale > 1
Kevin Rushforth
kcr at openjdk.org
Fri Aug 5 18:42:34 UTC 2022
On Thu, 28 Jul 2022 15:01:34 GMT, Kevin Rushforth <kcr at openjdk.org> wrote:
> When using the Windows Narrator screen reader on a Hi-DPI screen, the visible focus is drawn in the wrong location and with the wrong size. This happens because the the JavaFX Windows accessibility code that returns the screen bounds of the requested UI element does not take the screen scale into account.
>
> The fix is to adjust the bounds by the screen scale before returning it.
>
> You can test it on a Windows machine with scaling set to >= 125% as follows:
> 1. Turn on Windows Narrator
> 2. Run any JavaFX program with at least UI controls, for example, `hello.HelloTextField` in `apps/toys/Hello`
> 3. TAB between the controls
>
> Without the fix, Narrator shows the focus indicator in the wrong position and is too small. With the fix, it is correct. While testing this, I discovered an unrelated (and preexisting) bug where the focus indicator for a TextField or TextArea whose content is larger that the control (and is displayed with scroll bars) is not clipped to the visible area. This happens regardless of screen scale. I will file a follow-up bug for this.
>
> Note that this bug is specific to Windows. It does not occur on macOS, which works correctly on a retina or non-retina display.
Getting back to this, I discovered what the problem was with some multi-screens layouts when two screens have a different scale. Computing the platform x and y by simply multiplying by the scale is not right, and only work for a screen that touches the origin of the virtual screen space (in both X and Y). When the secondary screen is to the left or above the primary screen, the simple (but incorrect) calculation gives the same result as the correct calculation. For a secondary screen below or to the right of the primary screen, it doesn't. Simply scaling the coordinate about the origin produces a value that is either too small or too large when the two screens have a different scale.
The right fix is to use the `Screen.toPlatformX` and `Screen.toPlatformY` methods, which take this into account, and translates the coordinate to the right origin, scales it, and then translates it back. In order to do that, I needed to get the `Window` from which I could get the `Screen`, which required making the quantum `WindowStage` class public along with its `getWindow` method. This is an internal implementation class, so is not a concern.
I've tested this updated version in various combinations of layout and screen scales, and everything now works as expected.
-------------
PR: https://git.openjdk.org/jfx/pull/853
More information about the openjfx-dev
mailing list