RFR: 8343956: Focus delegation API

John Hendrikx jhendrikx at openjdk.org
Mon Jul 7 04:55:23 UTC 2025


On Sun, 9 Feb 2025 11:31:09 GMT, John Hendrikx <jhendrikx at openjdk.org> wrote:

>>> @hjohn Could you provide an outline of the algorithm that a control would use to automatically determine the focus delegate? I really can't envision what that would look like. For that matter I'm not sure why we would rely on an algorithm when in the few existing cases where focus delegation is needed the control knows exactly which node to delegate to.
>> 
>> Well, `Scene` determines the initial focus node by doing a depth first search on its children and focusing the first child that is focus traversable and enabled.  I don't see why this wouldn't work for controls exactly the same way.  It's almost always the correct default, and in cases when it isn't, it could still be overridden manually.  Take a ComboBox for example.  It consists of a field and a button (or vice versa if you have a different skin).  In either case however it would focus the field as the button in the combo is not focus traversable.
>> 
>> Skins therefore can control the focus delegate by making appropriate use of focus traversable and enabled, just like you can control what Scene would pick for its initial focus.
>
>> @hjohn I think what's missing in your model is the option to have an independently focusable node inside of a control. For example, think of a Button placed within a Button (via its `graphic` property). Clicking the nested button should not transfer the focus to its parent button. Whether a focus request should be hoisted is a choice that depends on the specifics of the control, and we probably need an API for that.
> 
> Okay, agreed, so it would be good to have Nodes control whether or not the focus traverses up.  
> 
> I could imagine the flag could also in the future perhaps allow the Root Node or Scene to determine whether the Window should receive focus (perhaps special cases like popups or transparent overlays would allow interaction without hoisting focus to the Window?)
> 
> Then what about the focus delegate?  This is not a full FX property in this API, but seems very similar to `focusOwner` in Scene, in that it determines to which `Node` (keyboard) events are directed.  One could say that, since Window/Scene are also focusable, Scene is **delegating** events/focus to a node.  Would it be reasonable to have `focusDelegate` be a read-only property like in `Scene`, and perhaps rename it to focus owner (or if that's too drastic, ensure that `Scene` at some later stage --might-- implement the same interface and then duplicating its focus owner property as focus delegate)?
> 
> This can be achieved later, just interested in hearing your thoughts:
> - A getter can later become a property
> - A getter can later become part of an interface
> - Scene can later implement an interface, even if it means duplicating the functionality of a property (if not named the same already)
> 
> I see some overlap, and having Nodes/Scene/Window implement a common interface (like `EventTarget`) is not unheard of.
> 
> Again, I love this proposal, and would like to move it forward.

> > > @hjohn I think what's missing in your model is the option to have an independently focusable node inside of a control. For example, think of a Button placed within a Button (via its `graphic` property). Clicking the nested button should not transfer the focus to its parent button. Whether a focus request should be hoisted is a choice that depends on the specifics of the control, and we probably need an API for that.
> > 
> > 
> > Okay, agreed, so it would be good to have Nodes control whether or not the focus traverses up.
> > I could imagine the flag could also in the future perhaps allow the Root Node or Scene to determine whether the Window should receive focus (perhaps special cases like popups or transparent overlays would allow interaction without hoisting focus to the Window?)
> 
> Do you mean window focus in a JavaFX sense, or in a window manager sense? For example, in Windows you can make a window non-activatable, which means it won't steal the focus from other windows when interacted with (for example, an on-screen keyboard window).

Perhaps the analogy does break down here.  I was thinking, if you could interact with a control on an inactive window, the control could decide if interacting with it should focus the window or not with the hoist focus flag.  However, that would presumably also means the Scene's focus owner shouldn't be changed (or be `null`).

> > Then what about the focus delegate? This is not a full FX property in this API, but seems very similar to `focusOwner` in Scene, in that it determines to which `Node` (keyboard) events are directed. One could say that, since Window/Scene are also focusable, Scene is **delegating** events/focus to a node. Would it be reasonable to have `focusDelegate` be a read-only property like in `Scene`, and perhaps rename it to focus owner (or if that's too drastic, ensure that `Scene` at some later stage --might-- implement the same interface and then duplicating its focus owner property as focus delegate)?
> 
> It works quite well to say that a `Scene` delegates focus to a `Node`. It doesn't seem to work quite as well (linguistically) to say that a `TextField` is the focus owner of a `ComboBox` (the `ComboBox` is also focused, why would the `TextField` be its focus owner?). But linguistics aside, the question is whether `focusOwner`/`focusDelegate` should be a read-only property.

I agree that focusOwner probably only works for well for Scene, although it could have been named focusDelegate and work quite well if there had been sufficient foresight :)

> That's a very good question. It would allow observers to know when the focus delegate changes. But can the focus delegate change? It can probably go from non-null to null, and vice versa. Let's consider a hypothetical control that is like a combo box, but it contains two separate text fields. It seems reasonable that the focus delegate can probably change between the two text fields.
> 
> But the proposed API doesn't seem to easily support this scenario. When I click on the second text field, it hoists the focus request up to the combo box, which in turn delegates its focus to... the first or the second text field? How would it choose? Is this a scenario that we need to solve?

Why doesn't it just set the delegate to whatever hoisted focus in the first place?  A not entirely hypothetical `DateEntryControl` with 3 separate fields internally (with borders stripped) could have a day-month-year area (such controls were quite common before fancy date pickers).  Each of the subfields could set hoist focus.  Clicking on a specific subfield would put the cursor there, but focus the `DateEntryControl` as a whole.

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

PR Comment: https://git.openjdk.org/jfx/pull/1632#issuecomment-2646634700


More information about the openjfx-dev mailing list