Skip to main content

Module focus

Module focus 

Source
Expand description

Keyboard focus traversal — tab and shift-tab between controls.

gpui has all the machinery and none of it is on by default: a focus handle carries a tab_index and a tab_stop flag, .track_focus registers the handle for the frame, and Window::focus_next walks the order — but tab_stop starts false and gpui binds no keys. This module turns it on.

§Order is paint order

gpui sorts tab stops by their tab_index path and then by insertion, so leaving every index at 0 yields the order the controls are painted in. Nothing has to be numbered by hand, and inserting a control in the middle of a form does not renumber the rest — which is the failure mode that makes HTML tabindex a liability.

§Where the handle lives

Most of this crate is fn(&Theme, ..) -> Div: stateless, with the app owning whether a checkbox is checked. Focus is more of that state, so the app owns the handle too and focusable wires it up. Giving every widget a handle of its own would mean giving every widget an identity and a lifetime, which is the entity machinery crate::input::TextField needs and a checkbox does not.

ui::focus::init(cx);                    // once, at startup

// ..and on the root view, so `tab` works wherever focus currently is:
focus::traversal(div().track_focus(&self.focus_handle))
    .child(focus::focusable(&theme, &self.ok_focus, popover::button(&theme, "OK", "ok")))

Structs§

Activate
Decrement
FocusNext
FocusPrev
Increment

Constants§

CLAIMS_TAB
Added to a surface’s key context when tab is its own key — a document nests a list with it. traversal stands down while that surface holds focus.
CONTROL_KEY_CONTEXT
Claimed by every focusable control, so enter and space mean “press this” only where something is actually focused.

Functions§

bindings
Traversal’s keymap, as data, so an app can have it without having to take it — see crate::keys for layering over it or taking a chord away.
focusable
Put a stateless control into the tab order, show when it holds focus, and let enter/space press it.
init
Install the bindings — bindings, bound. Call once at startup.
pressable
One activation path for pointer and keyboard, with a shared enabled gate. The caller still owns the value changed by the callback.
traversal
Attach the traversal handlers, normally to the app’s root element.