On Mon, 14 Jul 2025 18:59:49 GMT, John Hendrikx <jhendr...@openjdk.org> wrote:

>> Yeah, I'm sure traversal is solvable, I just wanted to spend some cycles 
>> figuring it out. For example, would you set focusTraversable on the 
>> date/time control AND it's delegates? My guess is just the delegates but 
>> this is the sort of thing one would want to prototype.
>> 
>> To be clear I'm not trying to solve traversal in this round. I just want to 
>> make sure we have mapped out the path forward so the API will accommodate 
>> traversal eventually.
>
> When I have a few moments, I'll see if I can create the date entry control, 
> and see how it works with this solution.  I can then override Scene code to 
> see if navigation is a quick fix or a huge issue.

> Currently we turn on input method processing at the platform level if and 
> only if there's any control in the focus chain that is set up to receive 
> input method events and respond to input method requests. That could be any 
> focusOwner in any focused Scene or any one of the focusOwners' delegates. So 
> I need to see the entire delegate chain.
> 
> If we don't expect the focus delegate to change while a focus scope node has 
> focus then all I need is getFocusDelegate with no parameters. If we expect 
> the focus delegate to change dynamically it should become a property.

The focus delegate can change while a focus scope has focus, but only due to a 
focus request (i.e. navigation or calling `Node.requestFocus()`). I'm 
reasonably certain that we don't need or want the delegate to be a property. As 
of now, the delegate chain is simply re-evaluated in response to a focus 
request.

However, there's currently no easy way for `Scene` to know when the delegate 
chain has changed.

> The existing traversal machinery is designed to update a Scene's focusOwner 
> not which delegate is active within the current focusOwner.

Focus traversal is not aware of what a delegate is, nor should it be. This 
means that focus traversal _will_ update the delegate chain if you traverse 
into a node that hoists focus.

I think it's important to point out that the primary use case of focus 
delegation is the creation of black-box controls, but focus delegation is not 
the same level of abstraction as black-box controls. It's better to think of 
focus delegation as a basic building block, and black-box controls as a 
higher-level abstraction.

At the `Node` level (where controls are not a thing yet), it is more approriate 
to picture focus delegation as a kind of openly visible multi-level focus. In 
this model, focus traversal doesn't differentiate between nodes based on how 
they came into being (e.g. as part of a skin), it simply applies the traversal 
algorithm on the scene graph as it is, being completely unaware of the logical 
grouping that is established by controls.

> In the Date/Time control you give as an example how would the user move focus 
> between the various delegates? What would be the most intuitive model for the 
> user? Personally I prefer the one used in macOS Calendar where Tab is used to 
> move between the month, day, and year (or hour and minute). But that creates 
> a conflict with using Tab to move focus into and out of the Date/Time control 
> as a whole.

I don't know what it would mean to move focus into and out of a control as a 
whole. You can only meaningfully move focus into a composite control if it has 
at least one sub-node that can be focused. If there is no such node, then you 
trivially can't use focus delegation. If, on the other hand, you have a 
focusable sub-node, then "moving into" the composite control just means 
focusing the sub-node. And "moving out" of the composite control means focusing 
the next logically focusable node in the scene graph. I don't see any conflict 
here.

> In any case the question is whether a monolithic control with multiple 
> delegates is expected to roll its own internal traversal mechanism or if we 
> need to extend the existing mechanism to include delegates. Having each 
> control roll its own internal traversal would hide it from the accessibility 
> frameworks. And if we expect the existing traversal keys (like Tab) to work 
> internally we should extend the existing traversal machinery to work with 
> delegates.

I haven't extensively tested this yet with custom composite controls, but I 
think the existing traversal logic will just work as it is.

-------------

PR Review Comment: https://git.openjdk.org/jfx/pull/1632#discussion_r2212343939

Reply via email to