JDK-8342906 : Public focus traversal API for use in custom controls
  • Type: CSR
  • Component: javafx
  • Sub-Component: controls
  • Priority: P4
  • Status: Provisional
  • Resolution: Unresolved
  • Fix Versions: jfx24
  • Submitted: 2024-10-23
  • Updated: 2024-11-08
Related Reports
CSR :  
Description
Summary
-------

Establishes a public API for focus traversal within a JavaFX application.

Problem
-------

While focus traversal is currently implemented in JavaFX, there is no public API to access it.
The lack of public API makes it impossible for a custom skin or custom control to support focus traversal
in the specific direction.

Solution
--------

The focus traversal is provided adding a single method to the **Node** class:

```
public final boolean requestFocusTraversal(TraversalDirection direction)
```

where **TraversalDirection** enumerates the search direction relative to the current node [1].

Typically, controls do not need to handle focus traversal keys explicitly, relying instead on the built-in
traversal logic, unless:

- the traversal is conditional upon the state of the control
- the key used to traverse is used in a non-traversal capacity (one example is the **tab** key in the context of a text editor)

The following example illustrates the use of new API in the context of a text editor conditionally handling
of the **tab** key:

```
    Node from = ...
    KeyEvent ev = ...
    if (!ev.isAltDown() && !ev.isControlDown() && !ev.isMetaDown() && !ev.isShiftDown() && !ev.isShortcutDown()) {
        switch (ev.getCode()) {
        case TAB:
            if (isEditable()) {
                insertTab();
            } else {
                from.requestFocusTraversal(TraversalDirection.NEXT);
            }
            ev.consume();
            break;
	    }
	}
```

Specification
-------------

**modules/javafx.graphics/src/main/java/javafx/scene/Node.java**:

```
+    /**
+     * Requests to move the focus from this {@code Node} in the specified direction.
+     * The {@code Node} serves as a reference point and does not have to be focused or focusable.
+     * A successful traversal results in a new {@code Node} being focused.
+     * <p>
+     * This method is expected to be called in response to a {@code KeyEvent}; therefore the {@code Node}
+     * receiving focus will have the {@link #focusVisibleProperty() focusVisible} property set.
+     *
+     * @param direction the direction of focus traversal, non-null
+     * @return {@code true} if traversal was successful
+     * @since 24
+     */
+    public final boolean requestFocusTraversal(TraversalDirection direction)
```

**modules/javafx.graphics/src/main/java/javafx/scene/TraversalDirection.java**:

```
+/**
+ * Specifies the direction of focus traversal.
+ *
+ * @since 24
+ * @see Node#requestFocusTraversal(TraversalDirection)
+ */
+public enum TraversalDirection {
+    /** Indicates a focus change to the node below the currently focused node. */
+    DOWN,
+    /** Indicates a focus change to the node to the left of the currently focused node. */
+    LEFT,
+    /** Indicates a focus change to the next focusable node. */
+    NEXT,
+    /** Indicates a focus change to the previous focusable node. */
+    PREVIOUS,
+    /** Indicates a focus change to the node to the right of the currently focused node. */
+    RIGHT,
+    /** Indicates a focus change to the node above the currently focused node. */
+    UP;
+}
```


**REFERENCES**

JavaFX JEP: https://github.com/andy-goryachev-oracle/Test/blob/main/doc/FocusTraversal/FocusTraversal-v3.md

Comments
Reviewed. It should be all read to Finalize.
08-11-2024

updated.
08-11-2024

[~angorya] This looks good. Can you update the specification to match the latest wording changes in the docs? Then I'll formally Review it.
08-11-2024

Moving to Provisional.
25-10-2024