Skip to content

Add FocusGained and FocusLost entity events#23723

Open
alice-i-cecile wants to merge 5 commits intobevyengine:mainfrom
alice-i-cecile:focus-events
Open

Add FocusGained and FocusLost entity events#23723
alice-i-cecile wants to merge 5 commits intobevyengine:mainfrom
alice-i-cecile:focus-events

Conversation

@alice-i-cecile
Copy link
Copy Markdown
Member

Objective

When working with more complex widgets, users have repeatedly asked for a way to reliably detect when an entity gains or loses focus. They have not, however, filed an issue about this 🎟️

These are called focus / focusin + blur / focusout on the web. The former element in these pairs does not bubble, while the latter does.

Because Bevy's observer infrastructure allows you to get the original target of a bubbled event, we can create only bubbling variations.

@viridia has suggested that #23707 would benefit from a form of this feature.

Rejected designs

The simplest approach would be to simply add a previously_focused field on InputFocus, and then emit events based on the difference using an ordinary system. Unfortunately, this has a serious flaw: events are lost if this changes state multiple times in the same frame.

We can resolve this problem by completely locking down access, and requiring commands or events to be used to change the input focus. This ensures no changes are lost and sends them off semi-immediately, but is a major breaking change to this API and prevents immediate-mode checks of "what is the current input focus".

Solution

We can do better. If we sacrifice "FocusGained and Lost must be emitted immediately", we can track changes inside of InputFocus, before sending them off in an ordinary system.

This is minimally breaking (you have to use the getters/setters now), and ensures no gained/lost events are ever missed. Users who completely overwrite InputFocus (e.g. by using from_entity) will miss changes, but frankly, you deserve it if you ignore the nice setters and clear warnings in the docs.

  • Define FocusGained and FocusLost events. Split to their own file for cleanliness.
  • Lock down access to InputFocus, forcing users to always go through the existing getters and setters.
  • Modify InputFocus to track changes as they have been made.
  • Add a system to drain these once-per-frame in PostUpdate, converting them into FocusGained and FocusLost.
    • This timing helps ensure that any user / library code that changes the focus has time to run, but rendering code that relies on accurate focus information to display widgets has the information available.
    • I could not find existing systems in PostUpdate that this needed a relative ordering for.
  • Create an InputFocusPlugin to store this new system, stealing some of the setup that was previously in InputDispatchPlugin. Somewhat incidentally, this fixes Dependency coupling between widgets and input focus #19057, by selecting option 1.

Testing

I was not very confident that my implementation of this logic was correct, so I wrote a rather aggressive set of mid-level tests, using App.

They pass, so apparently my first implementation was actually good enough.

@alice-i-cecile alice-i-cecile added C-Feature A new feature, making something new possible A-UI Graphical user interfaces, styles, layouts, and widgets M-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide X-Contentious There are nontrivial implications that should be thought through D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes labels Apr 8, 2026
@alice-i-cecile alice-i-cecile added the S-Needs-Review Needs reviewer attention (from anyone!) to move forward label Apr 8, 2026
@github-project-automation github-project-automation bot moved this to Needs SME Triage in UI Apr 8, 2026
@alice-i-cecile alice-i-cecile added this to the 0.19 milestone Apr 8, 2026
@alice-i-cecile
Copy link
Copy Markdown
Member Author

I'm adding this to the 0.19 milestone as I think it will be extremely useful for building UI widgets in earnest, but we can cut it if needed.

Copy link
Copy Markdown
Contributor

@viridia viridia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect.

Copy link
Copy Markdown
Contributor

@Zeophlite Zeophlite left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very cool

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-UI Graphical user interfaces, styles, layouts, and widgets C-Feature A new feature, making something new possible D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes M-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Contentious There are nontrivial implications that should be thought through

Projects

Status: Needs SME Triage

Development

Successfully merging this pull request may close these issues.

Dependency coupling between widgets and input focus

3 participants