On 06/08/2025 20:38, Michael Strauß wrote: >> 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. I think that for purposes of focus, the Control should still be regarded as a leaf node. Letting focusOwner point to a descendant is just adding more leaks to the Control black box. The fact that Nodes happen to be Parents for rendering purposes that can have children added by Skins was just a convenient way to apply styling and do further rendering. For the user world, Controls should be black boxes that preferably even hide the fact they have any children at all. This is already the case at construction time, as the children are only added after the Skin is applied. For rendering, children was just a convenient place to add more nodes, but it should have been kept separate, also because the user can't really manipulate the control's children without interfering with what Skins are doing (it's basically undefined -- perhaps Control should not have been based on Region, but on Parent, or some intermediate class that still kept `getChildren` read-only...)
--John