Skip to content

Events and Input

ssbaxys edited this page Oct 26, 2026 · 1 revision

Mouse, keyboard, focus and gamepad.

Events are typed and go through two phases: capture (root to target) and bubble (target to root).

panel.on(PointerEvent.CLICK, e -> select(e.localX(), e.localY()));
panel.on(ScrollEvent.SCROLL, e -> zoom(e));
field.on(KeyEvent.PRESS, e -> { if (e.key() == Keys.ENTER) { submit(); e.consume(); } });
root.content().onCapture(KeyEvent.PRESS, e -> {});   // intercept before children

Types: PointerEvent (PRESS, RELEASE, MOVE, DRAG, CLICK, ENTER, LEAVE), ScrollEvent.SCROLL, KeyEvent (PRESS, RELEASE), CharEvent.TYPED, FocusEvent (GAINED, LOST). e.stopPropagation() stops bubbling, e.consume() marks the event as handled. Custom events: EventType.create("my-event", true) and root.dispatch(target, event).

Focus: setFocusable(true), root.setFocus(el); Tab and Shift+Tab move focus; arrow keys and gamepad go through root.gamepad() and UiRoot.focusDirection(...).

Gamepad (root.gamepad(), UiRoot.focusDirection)

The root polls Platform.pollGamepad() every frame (in game, the first GLFW gamepad):

Button Action
D-pad, left stick move focus in a direction (focusDirection), with auto-repeat while held
A press: Enter to the focused element, and if it doesn't take it, a click at its center
B Escape (closes a popup), otherwise onBack: the loader screen closes
LB / RB neighboring tab of the nearest Tabs / SideNav (TabSwitchable)

focusDirection(NavDirection) works without a gamepad too: it picks the nearest focusable element in that direction (distance along the direction plus a penalty for sideways offset), or the top-left one without focus. Focus that came from the keyboard or gamepad scrolls a ScrollPanel to the element (UiElement.revealChild). Settings: enabled, deadzone, repeat(delay, rate), onBack(...).


← Data and Signals · English home · Widget Catalog →

Clone this wiki locally