JDK-8322748 : Caret blinking in JavaFX should only stop when caret moves
  • Type: Enhancement
  • Component: javafx
  • Sub-Component: controls
  • Affected Version: jfx17,jfx21
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2023-12-27
  • Updated: 2024-11-05
  • Resolved: 2024-02-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
jfx23 b06Fixed
Related Reports
Relates :  
Relates :  
Description
The Behavior in JavaFX is currently responsible for signaling (to the Skin) when to stop animating the caret. It does this by wrapping every possible key press and key typed in a start/stop animating callback.

However, not only does this catch too many cases (cases where key presses don't lead to cursor position changes), it also fails to catch all caret position changes (key pad navigation for example does not stop the animation).

Furthermore, this is not a behavioral concern, which is clearly demonstrated by the fact that this is forwarded to the skin -- replacing the behavior should not break caret animation.

The rule for caret animation is pretty simple. The user needs to be able to see the caret immediately if it changes position, which means animation is temporarily reset to keep the caret visible while it moves (ie. when typing, or when navigating). This rule has been confirmed by looking at similar controls (Windows, Chrome). If the cursor doesn't move (like when using DELETE or navigation has reached the start/end position) then the blinking ALSO doesn't stop, which makes sense as the cursor position didn't change and so there is no need to "highlight" it for the user to see.

JavaFX's implementation breaks down in many of these cases due to its complicated handling of caret animation (basing it on keys pressed and typed, instead of cursor movement).

Solution:

Move caret animation handling to the Skin, by registering a listener on the caretPosition property. The animation should be restarted each time the caretPosition changes.

Clean-up all caret animation handling from the current internal behaviors.
Comments
Changeset: 9a06bf9c Author: Andy Goryachev <angorya@openjdk.org> Date: 2024-02-21 22:07:55 +0000 URL: https://git.openjdk.org/jfx/commit/9a06bf9c5bce40cf842ddf25fe3360c366c3156c
21-02-2024

I think it is worth looking a bit deeper, as removing it completely from the behavior removes some of the entanglement. Partially removing it is of much lower value. The caret animation change on mouse clicks is there because the mouse may change the position of the caret, but we already catch that by listening to the caret position property. As for focus, the Skin can register a listener to stop animation when focus is lost. There is also a special case to not animate the caret when there is a selection, I suspect this either will work out of the box correctly, and otherwise may need a further tweak in the skin.
15-02-2024

A pull request was submitted for review. URL: https://git.openjdk.org/jfx/pull/1368 Date: 2024-02-14 22:44:07 +0000
14-02-2024

Toggling the caret animation cannot be completely removed from the behavior, as it is also being controlled by the mouse and focus event handlers. However, removing it from the key event handler has merit, as it simplifies the behavior in regards of the possible InputMap RFE https://bugs.openjdk.org/browse/JDK-8314968
14-02-2024

Good idea, though this looks like an enhancement rather than a bug.
02-01-2024