simvx.core.ui.focus¶
The focus model: one authority for who can hold focus and who is in the tab order.
focus_mode is that authority, on two independent axes:
Can it hold focus?
focus_mode != FocusMode.NONE– :func:is_focusable.Is it in the tab order?
focus_mode == FocusMode.ALL– :func:is_tab_stop.
Both axes additionally require the control to be enabled and effectively visible (tested through
the whole ancestor chain via Node._visible_in_hierarchy, not just the control’s own flag): a
control the player cannot see or use is not one the keyboard can reach. A CLICK control can
therefore hold focus without ever being a Tab destination, which is the web platform’s
tabindex="-1".
- func:
next_focusis the single traversal routine. Everything that moves focus by keyboard goes through it: the UI router’s Tab handling,Control.focus_next_controland its reverse. It walks the scope in pre-order and resolves the successor from the focus owner’s POSITION in that walk, so an owner that is not itself a tab stop (a clickedButton) still hands over to its neighbour rather than restarting at the first control.
Module Contents¶
Functions¶
True when |
|
True when |
|
The Tab order inside |
|
First tab stop inside |
|
The control Tab (or Shift+Tab, with |
|
The traversal scope for |
Data¶
API¶
- simvx.core.ui.focus.__all__¶
[‘first_tab_stop’, ‘is_focusable’, ‘is_tab_stop’, ‘next_focus’, ‘tab_stops’]
- simvx.core.ui.focus.is_focusable(control: simvx.core.ui.core.Control) bool[source]¶
True when
controlmay hold keyboard focus (visible, enabled,focus_mode != NONE).
- simvx.core.ui.focus.is_tab_stop(control: simvx.core.ui.core.Control) bool[source]¶
True when
controlis a Tab destination (visible, enabled,focus_mode == ALL).
- simvx.core.ui.focus.tab_stops(scope_root: simvx.core.node.Node) list[simvx.core.ui.core.Control][source]¶
The Tab order inside
scope_root: its tab stops in pre-order.
- simvx.core.ui.focus.first_tab_stop(scope_root: simvx.core.node.Node, *, skip: Any = None) simvx.core.ui.core.Control | None[source]¶
First tab stop inside
scope_rootin pre-order, ignoringskip.
- simvx.core.ui.focus.next_focus(scope_root: simvx.core.node.Node, current: simvx.core.ui.core.Control | None, *, reverse: bool = False) simvx.core.ui.core.Control | None[source]¶
The control Tab (or Shift+Tab, with
reverse) should focus next insidescope_root.currentis the focus owner, orNone. An explicitfocus_next/focus_previouslink on the owner wins when it points at a focusable control inside the scope; a link to a hidden, disabled orNONE-mode control falls through to the walk rather than focusing something unreachable.Otherwise the scope is walked in pre-order and the search starts from the owner’s position in that walk, wrapping at the ends. An owner absent from the walk (a different scope, or
None) starts at the first tab stop, or the last one underreverse. ReturnsNonewhen the scope holds no tab stop at all.
- simvx.core.ui.focus.scope_root_for(control: simvx.core.ui.core.Control) simvx.core.node.Node[source]¶
The traversal scope for
control: the capturing overlay chain it sits in, else the root.Keyboard traversal never leaves an open capturing overlay, so a dialog’s Tab order is the dialog. Outside one (or for a control beneath one), the scope is the whole tree.