The focus system in UI Toolkit manages which element currently receives keyboard or navigation input. It controls how focus moves between elements, and raises focus events when elements gain or lose focus.
The focus system consists of several key components:
focusable
: Can this element receive focus?canGrabFocus
: Is this element currently able to be focused (visible, enabled, etc.)?tabIndex
: Order in which elements are focused when navigating.delegatesFocus
: If true, passes focus to a suitable child element.Focus()
: Method to request focus on an element.Blur()
: Method to remove focus from an element.FocusController
: Manages focus state and navigation for a panel.IFocusRing
: Interface for focus navigation logic.FocusChangeDirection
: Describes navigation direction, such as Next, Previous, Up, and Down.The focus system operates as follows:
EventDispatcher
processes input and, when appropriate, asks the FocusController
to change focus.FocusController
consults the IFocusRing
to determine the next focusable element.FocusController
generates focus change events (such as FocusEvent
and BlurEvent
) and adds them to the EventDispatcher
’s event queue. The EventDispatcher
dispatches these events after it finishes processing the current user input.EventDispatcher
dispatches the focus events, the newly focused element receives focus. Each element along the event propagation path can handle these events using event callbacks in code.delegatesFocus = true
, focus is automatically given to a child element that can be focused.The following diagram illustrates the focus system components and their interactions:
Each panel has a focus ring that defines the focus order of elements. By default, a depth-first search (DFS) on the visual treeAn object graph, made of lightweight nodes, that holds all the elements in a window or panel. It defines every UI you build with the UI Toolkit.
See in Glossary defines the focus order of elements. For example, the focus order for the tree depicted in the following image is F, B, A, D, C, E, G, I, H.
Some events use the focus order to define which element holds the focus. For example, the target for a keyboard event is the element in focus.
You can use the tabIndex
property to customize the focus order as follows:
tabIndex
is zero, the element keeps its default tab order, as determined by the focus ring algorithm.tabIndex
is positive, the element is placed in front of other elements that either have a zero tabIndex
(tabIndex = 0
) or a tabIndex
value smaller than its own.tabIndex
is negative, the element is removed from the tab navigation.
Focus events occur when an element gains or loses focus. You can use the element.Focus()
method to change focus. This method sends a FocusEvent
that is processed in the event queue. The actual focus change takes effect after the current event callback has finished executing.
The following example sets focus on a button and tracks focus events:
using UnityEngine;
using UnityEngine.UIElements;
[RequireComponent(typeof(UIDocument))]
public class FocusExample : MonoBehaviour
{
void OnEnable()
{
var startGameButton = GetComponent<UIDocument>().rootVisualElement.Q<Button>("StartGame");
startGameButton.RegisterCallback<FocusInEvent>(ev =>
{
Debug.Log("FocusInEvent: button is focused and can be activated with keyboard or gamepad input.");
});
Debug.Log("Calling startGameButton.Focus().");
startGameButton.Focus();
var isFocused = startGameButton.focusController.focusedElement == startGameButton;
Debug.Log("Immediately after startGameButton.Focus(): isFocused=" + isFocused);
// Expected output:
// > Calling startGameButton.Focus().
// > FocusInEvent: button is focused and can be activated with keyboard or gamepad input.
// > Immediately after startGameButton.Focus(): isFocused=true
}
}