> The TextField of a ComboBox or Spinner is not just an artifact of its skin. > They are both explicitly composite controls that contains a TextField inside. > It’s part of the API. And if you were to install some filters on the Scene to > track Key and InputMethod events you could easily conclude that that > TextField is the focus owner (it walks like the focus owner, it quacks like > the focus owner). > > I believe the implementation of Spinner predates focusWithin and > focusVisible. I think the natural way to drive the focus indicators these > days would be to use focused for the TextEdit and focus-within for the > Spinner. In any case I think it’s a good idea to somehow separate these out > and not force all of these flags to be set in unison across the entire > delegate chain. > > If we were to make the Spinner’s TextEdit the focus owner input methods would > work, the focused and focus-within pseudo-classes would sort themselves out > in a natural way, and the double firing of KeyEvents would go away. The > downside is that you would create an information deficit during event > processing; the event target would be the TextEdit and not the logical > control. But that’s an existing problem that also affects mouse click events. > Perhaps we should focus on closing that information gap instead.
I think you might be onto something here: Let's close down the "Node.setFocused" loophole, no more tampering with the focused flag. This entails fixing TableView and other controls that misuse this flag. With this improvement, there's only ever going to be a single focused node in the scene graph, and "focused == input focus" is always true. Then we would need to redefine "Node.requestFocus()" to allow a control to delegate the focus request to one of its descendants instead. This means: 1. If a control accepts requestFocus(), the focusWithin flag will _always_ be set on the control. 2. It _might_ also have the focused flag, but this is implementation-specific and should not be relied upon. 3. Scene.focusOwner might not point to the control, but to one of its descendants. As a consequence, controls that now use the focused style class to adjust their appearance (with a focus ring) should use focusWithin instead. The same is true for user code: you should always use focusWithin on controls, and only use focused if you're sure that you are interested in the actual input focus owner. Additionally, there should be an additional Event.originalTarget property. This property will always correspond to the node that fired the event, in the case of Spinner this would be the TextField. The Event.target property, on the other hand, would correspond to the logical target that an observer would expect, in our example the Spinner. I think this approach would still allow us to clean up the skin implementations, remove the duplicate events, and have logically consistent events.