Summary
Add the javafx.scene.Node.focusVisible
and javafx.scene.Node.focusWithin
properties, as well as the corresponding focus-visible
and focus-within
CSS pseudo-classes.
Problem
The W3C CSS Selectors Level 4 specification defines three focus-related pseudo-classes:
focus
, which applies to a node that currently accepts keyboard or mouse input;
focus-visible
, which applies to a focused node that visibly indicates focus, and
focus-within
, which applies to a focused node and any of its parents.
JavaFX currently implements the focused
property only, which corresponds to the focus
CSS pseudoclass.
However, many contemporary UI designs do not always indicate focus in the same way that the built-in JavaFX themes do. For example, the Windows 10 theme or modern "Fluent" design implementations generally only indicate the focused element as a consequence of keyboard input. There are also "Material" design implementations with the same behavior.
Solution
Add the javafx.scene.Node.focusVisible
and javafx.scene.Node.focusWithin
properties, as well as the corresponding focus-visible
and focus-within
CSS pseudo-classes. The focus traversal engine will be modified to differentiate between mouse/programmatic and keyboard-initiated focus traversal, and will set the new properties accordingly.
Specification
Add the focusVisible
property to javafx.scene.Node
:
/**
* Indicates whether this {@code Node} should visibly indicate focus.
* This flag is set when the node acquires input focus via keyboard navigation,
* and it is cleared when the node loses focus or when {@link #requestFocus()}
* is called.
*
* @defaultValue false
* @since 19
*/
private final ReadOnlyBooleanProperty focusVisible;
public final boolean isFocusVisible() {
return focusVisible.get();
}
public final ReadOnlyBooleanProperty focusVisibleProperty() {
return focusVisible;
}
Add the focusWithin
property to javafx.scene.Node
:
/**
* Indicates whether this {@code Node} or any of its descendants currently
* has the input focus.
*
* @defaultValue false
* @since 19
*/
private final ReadOnlyBooleanProperty focusWithin;
public final boolean isFocusWithin() {
return focusWithin.get();
}
public final ReadOnlyBooleanProperty focusWithinProperty() {
return focusWithin;
}
Change the documentation of javafx.scene.Node.requestFocus
:
/**
* Requests that this {@code Node} get the input focus, and that this
* {@code Node}'s top-level ancestor become the focused window. To be
* eligible to receive the focus, the node must be part of a scene, it and
* all of its ancestors must be visible, and it must not be disabled.
* If this node is eligible, this function will cause it to become this
* {@code Scene}'s "focus owner". Each scene has at most one focus owner
* node. The focus owner will not actually have the input focus, however,
* unless the scene belongs to a {@code Stage} that is both visible
* and active.
+ * <p>This method will clear the {@link #focusVisible} flag.
*/
public void requestFocus()
Add the following documentation to "cssref.html":
1780 + <tr>
1781 + <th class="propertyname" scope="row">focus-visible</th>
1782 + <td>applies when the <strong>focusVisible</strong> variable is true</td>
1783 + </tr>
1784 + <tr>
1785 + <th class="propertyname" scope="row">focus-within</th>
1786 + <td>applies when the <strong>focusWithin</strong> variable is true</td>
1787 + </tr>
- csr of
-
JDK-8268225 Support :focus-visible and :focus-within CSS pseudoclasses
-
- Resolved
-