There is also the focus traversable flag that interacts with this, but perhaps there is a bug. When a button has focusTraversable set to false, clicking it will not give it focus. One may say that a property named "focus traversable" would only affect focus *traversal* with the keyboard (as I'd hardly call clicking with the mouse "traversal").
That still leaves mnemonic short-cuts and default actions for buttons though. Pretty sure those also don't focus the button and aren't intended to, yet do execute the action. --John On 15/10/2025 17:20, Andy Goryachev wrote: > > * > Buttons are one of those (either with mouse press or keyboard > short cut) > > > This looks like a bug to me, really. What is the main purpose of the > focus subsystem? > I know we like to reinvent the wheel, but focus in Swing works as > expected, and one does get focus lost event on mouse press, and the > target button gets the focus. Why should FX be different? > > -andy > > > *From: *John Hendrikx <[email protected]> > *Date: *Wednesday, October 15, 2025 at 08:05 > *To: *Marius Hanl <[email protected]>, Andy Goryachev > <[email protected]>, [email protected] > <[email protected]> > *Subject: *[External] : Re: Allowing a cell to commit the value on > focus loss > > Hi Marius, > > Focus lost is currently sort of a proxy of starting an interaction > with a new control, but not all controls gain focus when interacted > with. Buttons are one of those (either with mouse press or keyboard > short cut), but there is I think also the scroll wheel that can > interact with a control without focusing it (and perhaps even popup > menu's). > > I can only think of one half-baked solution to this: > > - Have a new Event type that is always targetted at the current focus > owner ("InterestLostEvent" ? :)) > - This event is automatically fired by Scene just before an event is > fired that is not targetted at the current focus owner, AND the last > event fired did have the focus owner as target > > What would happen in practice then would be something like: > > - User edits field, keypress events go to current focus owner > - User does something else (moves mouse, scrolls, presses a hotkey, or > presses a button): > - An InterestLostEvent is fired at the current focus owner BEFORE > the new event is fired > - The delayed new event is now fired > - No further InterestLostEvents are fired until the focus owner > has received a normal event again > - User goes back to editing after playing with the mouse; events > targetted at the focus owner renew the interest in that control, and > so next time an InterestLostEvent is fired again when needed > > It feels a bit awkward, especially because simple things like mouse > moves may trigger it already (but a mouse move may trigger something > that requires the model to be up to date...); perhaps it would need to > be selective in some way so one can choose to only be interested in > the InterestLostEvent on focus loss and mouse clicks. > > I can immediately see some problems as well. Some controls I think > allow editing without focus gain/loss at all (I think some controls > can be edited by just scrolling the mouse wheel over them). When > should those controls "commit" their values...? > > --John > > > On 15/10/2025 16:39, Marius Hanl wrote: > > Hi John, > > you are right that there might be corner cases. I hope that > we could, what Andy suggests, find all cases and have a deeper > look at them. > We can also check whether the focus delegation API from Michael is > something that could help us here (but might be completely unrelated). > > The other options as you also mentioned, also have their problems. > Even debouncing a commit on every keystroke can be unreliable if > the user is too fast. > I really hope we can make the focus loss reliable, as we then do > not need much of an API changes inside the Cell Framework. > > -- Marius > *Gesendet: *Montag, 13. Oktober 2025 um 19:32 > *Von: *"Andy Goryachev" <[email protected]> > *An: *"John Hendrikx" <[email protected]>, > "[email protected]" <[email protected]> > *Betreff: *Re: Allowing a cell to commit the value on focus loss > I wonder if we should find out exactly why onFocusLost does not > work in these cases, as expected. Then, if I understand the > proposal correctly, we won't need any API changes. > > -andy > > > > *From: *openjfx-dev <[email protected]> on behalf of > John Hendrikx <[email protected]> > *Date: *Monday, October 13, 2025 at 07:17 > *To: *[email protected] <[email protected]> > *Subject: *Re: Allowing a cell to commit the value on focus loss > > Hi Marius, > > This may be unrelated, but it may be problematic to rely on > committing values using focus lost: > > I've built a lot of code that relies on focus lost to "commit" > values to some underlying model. However, I noticed that a focus > lost handler for committing values is insufficient when an action > is triggered that doesn't trigger a loss of focus. For example, > if I have a field "email address" and a Button "Send Email", and I > have a focus lost handler to commit the email address textfield to > an underlying model, then pressing the Button will not trigger > that handler and the underlying model may not have been updated > with the latest edits. > > Solutions to trigger the correct action are all a bit tricky or > annoying: > > - Query all fields for their current contents as focus lost is not > entirely reliable for this purpose > - Have fields update models immediately (which would be on every > key press...) -- this is not very efficient, and can get in the > way of validation / model restrictions > - Have controls listen to a "COMMIT" event (this is fired at the > current focus owner by the Button). This event may be veto'd if > committing the value resulted in a validation error, in which case > the button press is cancelled > > I don't like any of these, but using the last option at the moment > because I like constant updates and having to requery UI > components even less... > > --John > > > I noticed however that if you edit some field (it doesn't have to > be in a table view, just a regular field), and have a focus lost > handler that commits the value, that this focus lost handler is > insufficient... > > On 13/10/2025 14:53, [email protected] wrote: > > All, > > I created an initial poc 1* to support developers to commit > the cell value when the focus is lost 2* (including 3*). > More specifically, this gives the maximum flexibility to > choose what should happen when the focus is lost or the > editing index changed (which may happen when clicking into > another cell while editing). > All information mentioned here are also in the description of > the PR. > > *API* > * * > - Instead of calling `/cancelEdit/`, every cell now calls > `/stopEdit/` when the focus is lost or the editing index > changed. The default behavior is cancelling the edit, but > developers can now override the behavior and allow a > `/commitEdit/` instead > - There are multiple 'events' that can lead to a editing > change. Every change will now call `/stopEdit/`. > It is therefore the responsibility of the developer to decide, > when it makes sense to actually commit the value instead of > cancelling it. This decision was made as the behavior is > manipulating the editing index, but you as a developer can as > well. We do not really know what intention led to e.g. a > change of the editing index. > - Every `/MOUSE_PRESSED/` shifts the focus to the cell > container, which is undesired in case of editing the cell. So > this event is now consumed. > - All `/TextField/` cells now commit their value (instead of > cancel) on focus loss > - `/TextField/` Escape handling was badly implemented (it was > never really called, as the cell container handled Escape before) > > *Considerations* > > - I tried to make the API minimal, and without breaking > changes (other than the `/TextField/` cells committing their > values, but we may split this up) > - The Cell Container focus behavior is, well, weird right now. > That is why consuming the event is needed to better support > this PR. One thing we may can consider is using the > `/focusWithin/` property instead for all 4 Cell Containers and > not calling `/requestFocus/` for nearly every > `/MOUSE_PRESSED/` event. If we decide so, this is needs to be > done before merging this PR. > - Clicking the `/ScrollBar/` now commits/cancels the edit. I > checked other applications and this is very common. But > something I need to note here. This probably can be fixed in > the same way mentioned above (`/focusWithin/`) > - It might be hard for a developer to exactly know the cause > why `/stopEdit/` is called. This does not seem like a problem, > as e.g. for a `/TextField/`, you normally register listeners > for e.g. pressing the Escape key on it, so you keep full control. > > *Another Approach* > > - Another Approach I tested could be to request the focus to a > cell when clicked/edited, to ensure that the focus listener is > ALWAYS called before another cell will reach the editing > state. Again, we probably need to change the focus handling to > e.g. use the `/focusWithin/` property. With this approach, we > can only call `/stopEdit` /when the focus changed (since it is > now called always), but not when the editing index changed. > > 1* - https://github.com/openjdk/jfx/pull/1935 > 2* - https://bugs.openjdk.org/browse/JDK-8089514 > 3* - https://bugs.openjdk.org/browse/JDK-8089311 > > -- Marius >
