Skip to content

Conversation

@HexyWitch
Copy link
Contributor

@HexyWitch HexyWitch commented Dec 22, 2025

Part of this is discussed in #145 but here is my motivation for the changes:

  1. The Dom doesn't need to be involved in requesting focus. The only utility it provided here was to be globally available. Selection happens on input, and affects only other input, so we treat it as input.

  2. Having the current selection available in InputState lets us more consistently clear selection on mouse clicks. Clear selection on mousedown, then let widgets capturing the mousedown set selected again. This removes a FIXME in the code and makes it so e.g. textboxes get blurred when you click a button.

  3. To not regress in features, add a new API through Yakui to request focus. This is done through a new Event, matching the model of how changes are passed from application state to input state.

  4. Autofocus was using a special WidgetResponse API (plus pending_request_focus in Dom) to request focus on a widget ID. This doesn't need to be a first class feature. The model for passing widget results back as input for the next frame in yakui is to track the state externally and pass it in next frame. Yakui wasn't providing any utility here that you can't implement as a user, and it was coming at the cost of added complexity to some clean APIs (Dom and Response).

In the case of the autofocus example I implemented it as a basic callback list in ExampleState, for general utility. But in user code this could be a thread local, a Option<WidgetId>, or whatever.

There's no need to go all the way through Dom
This looks worse than the previous API, but this matches the model of how we pass state and events into yakui
@HexyWitch HexyWitch requested a review from LPGhatguy as a code owner December 22, 2025 23:12
@HexyWitch
Copy link
Contributor Author

This is a breaking change:

There is no way to prevent a mousedown event from blurring the current focus. You can re-focus on the next frame, but the widget will receive two FocusChanged events. In the case of the TextBox this also means setting lost_focus.

This is an issue if you want something like a panel that closes when a textbox is blurred, and you want to keep the textbox widget focused even if you click within the panel. Behavior for this type of panel seems to vary:

image Google search results: Clicking within the panel blurs the textbox on mousedown but keeps the panel open. image Linear context panel: Clicking within the panel keeps the focus on the textbox. But the textbox gets a 'blur' event and 'focus' event each time you click outside.
Element lost focus
Element gained focus
Element lost focus
Element gained focus
Element lost focus
Element gained focus
Element lost focus
Element gained focus

I think this points toward web handling this like I have in this PR. Mousedown anywhere not inside the textbox clears focus, and then user code can manually set the focus again.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant