<div dir="ltr">Hi,<div><br></div><div>I feel shy to add any thoughts on this. So don't mind if I don't make sense of it:</div><div><br></div><div>I don't think all key bindings qualify as "navigation", but pressing ESCAPE on a text input control will eat the key even if there's no edit to cancel.</div><div><br></div><div>So if you bind ESCAPE on the Scene as a shortcut (for closing the window for example) and you are on a text input control with no edit to cancel, it will eat the event.</div><div><br></div><div>I think this logic should be applied:</div><div><br></div><div>If the key event applies any change to the control, it should be consumed. If it does not change any control state, it should propagate.</div><div><br></div><div>So on a ScrollPane, if the user presses UP to the top and there's nothing more to scroll, it should not consume the key event.</div><div>Same for text input. If the user presses ESCAPE, and there's nothing to edit (no control state change), let it propagate.</div><div><br></div><div>I hope it makes sense :)</div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Em qui., 19 de set. de 2024 às 12:38, John Hendrikx <<a href="mailto:john.hendrikx@gmail.com">john.hendrikx@gmail.com</a>> escreveu:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I've been looking into how exactly navigation keys are being used in FX, <br>
and who is responsible for handling them:<br>
<br>
- Controls can choose to install navigational keys directly in their <br>
input map (using FocusTraversalInputMap::getFocusTraversalMappings)<br>
- Controls can choose to do nothing and leave navigation keys to bubble <br>
up to Scene, at which point Scene will act on any unconsumed navigation <br>
keys (in the same was as the traversal mappings would)<br>
<br>
Scene basically is capable of almost all navigation you could possibly <br>
want out of the box. Any control that does not install navigation keys, <br>
and leaves said keys to bubble up gets navigation for **free**. This is <br>
almost all controls in JavaFX, and it makes sense as Controls should not <br>
care about navigation, they should only care about key presses that <br>
affect them directly. Navigation should be a concern somewhere higher <br>
up in the hierarchy.<br>
<br>
So why do some controls install their own navigation keys?<br>
<br>
There are two answers:<br>
<br>
1. For some controls, navigation is conditional. A Spinner only allows <br>
directional navigation for the left/right keys, or up/down keys <br>
depending on its orientation.<br>
2. There is an unfortunate choice in ScrollPane that consumes <br>
directional keys for scrolling purposes, and so if such keys were left <br>
to bubble up, they would not end up at Scene. Any control supporting <br>
directional navigation therefore must **specifically** install these <br>
bindings directly, even though navigation is not their concern (a Button <br>
cares about being pressed, not about activating unrelated controls nearby).<br>
<br>
The ScrollPane eating directional keys is an odd choice. In order for it <br>
to do so one of the following must be true:<br>
<br>
- A control inside it has focus that should act on directional <br>
navigation, but forgot to install navigation bindings (a custom <br>
control). Such a control would work perfectly when not part of a <br>
ScrollPane (as Scene would then handle directional navigation), but <br>
break when placed inside it. Note that all JavaFX controls do this <br>
"properly". I couldn't find any controls that would leave directional <br>
keys to bubble up for a ScrollPane to consume.<br>
<br>
- The ScrollPane itself has focus; this can only happen when directly <br>
selected with the mouse (or focus traversable is set to true) and no <br>
specific control inside the pane was selected. The ScrollPane receives <br>
the ":focused" style, clearly indicating that it is the target for <br>
keyboard events to the user.<br>
<br>
In short, ScrollPane is making navigation a lot more complex within FX <br>
than it needs to be. Especially custom controls that do not have access <br>
(currently) to install navigational bindings will suffer from this, and <br>
will have to resort to their own navigation implementation for <br>
directional keys when placed inside a ScrollPane.<br>
<br>
# Proposal<br>
<br>
I think ScrollPane violates what I think should be a fundamental rule. <br>
Keys should only be consumed by what the user perceives as the focused <br>
control (ie. the one outlined with a highlighted border), with the only <br>
exceptions being short cuts (from a menu) or mnemonics. Containers such <br>
controls happen to be placed in should NOT consume key events -- the <br>
container is not the control with the focus, and so would confuse the <br>
user. Only ScrollPane is violating this currently. Note that if the <br>
ScrollPane has focus itself (and it has the :focused highlight) then it <br>
is perfectly fine and expected for it to consume keys as much as it wants.<br>
<br>
This is why I think we should modify ScrollPane to not consume the <br>
directional keys, unless it specifically has the focus. All other <br>
controls can then remove their navigational bindings and leave them to <br>
bubble up to Scene, cleaning up their behaviors so they can focus on <br>
other concerns. Custom controls would no longer need to install <br>
navigational bindings either, and would not need to worry about being <br>
placed inside a ScrollPane and having their directional navigation broken.<br>
<br>
Optional, but recommended, controls like Spinner should only act on the <br>
directional keys intended for them, and leave the ones they can't use to <br>
bubble up. So a vertical spinner would consume up/down for changing the <br>
spinner value, but would leave left/right untouched for Scene to <br>
handle. Controls that install a full set of navigational keys (like <br>
Button, ListView and TitledPane) don't need to do so anymore.<br>
<br>
I think I will file a ticket for this soon, but I'm curious what others <br>
think of this analysis.<br>
<br>
Note that by solving this problem, the need to make navigation <br>
functionality available to custom controls severely diminishes as one <br>
can simple leave the KeyEvents responsible for standard navigation to <br>
bubble up (recommended as this may be different for each platform).<br>
<br>
--John<br>
<br>
</blockquote></div>