On Tue, 3 Sep 2024 19:09:15 GMT, Andy Goryachev <ango...@openjdk.org> wrote:

> Public APIs for focus traversal and the focus traversal policy:
> 
> https://github.com/andy-goryachev-oracle/Test/blob/main/doc/FocusTraversal/FocusTraversal.md
> 
> This work is loosely based on the patch
> https://cr.openjdk.org/~jgiles/8061673/

By its own admission, this proposal basically promotes an internal 
implementation to public API (albeit with some refactoring). This may or may 
not be a good idea, so I'd like to take a step back and look at the problem 
we're trying to solve.

Looking at several of the linked JBS issues, a missing feature of JavaFX is the 
ability to customize the focus traversal logic of a custom control (or a 
container of nodes in the widest sense of the word). Any proposed solution 
should support complex scenarios like toolbars with overflow, or [radio 
groups](https://www.w3.org/TR/2009/WD-wai-aria-practices-20090224/#radiobutton).

I think there are two distinct modes of focus traversal: logical ("tabbing") 
and directional (arrow keys). Both modes are independent axes of the problem at 
hand, and should be customizable independently from each other.

The current implementation provides a single `Algorithm` (or `TraversalPolicy` 
after the refactoring) for both traversal modes. I've played around with the 
code for a while, and while in theory I can provide my own `TraversalPolicy`, 
it can be quite a lot of code and it's not as easy as it could be. 
Additionally, it is hard to customize the traversal policies of the 
substructure of skinnable controls.

I question whether we need custom traversal policies at all, as the ways in 
which focus can move from one node to the next are quite limited:
1. **Permeable edges**: The next node in a container is selected until an edge 
is reached, then the input focus leaves the container.
2. **Confined to container**: The next node in a container is selected until 
the end of the container is reached; then the input focus doesn't move on.
3. **Cyclic in container**: Like confined, but at the end of the container, the 
input focus wraps around to the first element.
4. **Single focused node in container**: When the input focus enters a 
container, it moves to the node that was most recently selected (or to the 
first node in the container if none of the nodes was selected before); after 
that the input focus leaves the container.

Having two traversal toggles (logical and directional), each with four possible 
modes, already solves most of the problem. The advantage of this over a custom 
policy implementation is that these properties can be modelled with an 
enumeration and easily be set by control and application developers, and they 
can also be set via CSS. This allows developers to customize the focus 
traversal behavior of existing skinnable controls, as the substructure of a 
skin is accessible via CSS.

The "single focused node in container" mode is required for scenarios like 
radio groups, when the developers wants to return to the point of previous 
focus when tabbing into the group a second time. This requires another API that 
allows a focus container to indicate its entry point, which is the initial 
element that is selected when the input focus moves into the container.

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

PR Comment: https://git.openjdk.org/jfx/pull/1555#issuecomment-2342418714

Reply via email to