Skip to main content

Events

APIs for pointer interactions and listener-trigger payloads.

Runtime baseline

This page reflects released Web 2.42.0 -> C++ runtime-v0.1.344, with source pins tracked in Runtime Compatibility Baseline.

August 14 Editor reference validation

The names and signatures below were revalidated through the Rive MCP against the built-in rive/artboards and rive/interfaces references in Rive Beta 0.8.5390 build 5377. A temporary Tests script covering the complete surface recompiled with diagnostics []; the original three runtime cases still passed after the probe was removed. This proves Editor analyzer acceptance, not hardware gamepad dispatch or the released Web runtime path. Those evidence tiers remain separate in the compatibility page.


PointerEvent

Pointer interaction event data.

PointerType

The current Editor reference types PointerEvent.type with this string union:

export type PointerType =
"pointerEnter"
| "pointerExit"
| "pointerDown"
| "pointerUp"
| "pointerMove"
| "click"
| "pointerDrag"
| "unknown"

The upstream reference still labels the standalone alias "Coming soon," even though the current Editor reference exposes it and uses it for PointerEvent.type. It is a type alias, not a runtime enum table.

Constructor

PointerEvent.new(id, position)

Creates a new PointerEvent. Used for forwarding events to nested artboards.

PointerEvent.new(id: number, position: Vector): PointerEvent

Example:

-- Forward event to nested artboard
local childPos = transformToChildSpace(event.position)
local childEvent = PointerEvent.new(event.id, childPos)

Attributes

AttributeTypeDescription
positionVectorLocal coordinates
idnumberPointer ID (for multitouch)
typePointerTypeCurrent event-kind string

Methods

event:hit(isTranslucent?)

Marks the event as handled. If isTranslucent is true, the event may continue to propagate through translucent hit targets.

event:hit() -- Standard: stops propagation
event:hit(true) -- Translucent: may continue through

Example:

function pointerDown(self, event: PointerEvent)
if isInBounds(event.position) then
self.pressed = true
event:hit()
end
end

ListenerContext

ListenerAction scripts receive listenerContext via:

function performAction(self: MyAction, listenerContext: ListenerContext)
-- inspect event kind with is... methods
end

Type Guards

  • listenerContext:isPointerEvent()
  • listenerContext:isKeyboardEvent()
  • listenerContext:isTextInput()
  • listenerContext:isFocus()
  • listenerContext:isReportedEvent()
  • listenerContext:isViewModelChange()
  • listenerContext:isGamepadConnected()
  • listenerContext:isGamepadEvent()
  • listenerContext:isGamepadDisconnected()
  • listenerContext:isNone()

Typed Accessors

  • listenerContext:asPointerEvent(): PointerEvent?
  • listenerContext:asKeyboardEvent(): KeyboardEvent?
  • listenerContext:asTextInput(): TextInput?
  • listenerContext:asFocus(): FocusEvent?
  • listenerContext:asReportedEvent(): ReportedEvent?
  • listenerContext:asViewModelChange(): ViewModelChange?
  • listenerContext:asGamepadConnected(): GamepadConnected?
  • listenerContext:asGamepadEvent(): GamepadEvent?
  • listenerContext:asGamepadDisconnected(): GamepadDisconnected?
  • listenerContext:asNone(): NoneEvent?

Safe Branching Example

function performAction(self: MyAction, listenerContext: ListenerContext)
if listenerContext:isPointerEvent() then
local evt = listenerContext:asPointerEvent()
if evt then
print("pointer:", evt.type, evt.position.x, evt.position.y)
end
elseif listenerContext:isKeyboardEvent() then
local evt = listenerContext:asKeyboardEvent()
if evt then
print("keyboard:", evt.key, evt.phase)
end
elseif listenerContext:isTextInput() then
local evt = listenerContext:asTextInput()
if evt then
print("text:", evt.text)
end
elseif listenerContext:isGamepadEvent() then
local evt = listenerContext:asGamepadEvent()
if evt then
print("gamepad change:", evt.changeKind, evt.changeIndex, evt.changeValue)
end
end
end

KeyboardEvent

Keyboard payload exposed via listenerContext:asKeyboardEvent().

export type KeyPhase = "down" | "repeat" | "up"
FieldTypeDescription
keynumberKey code
shiftbooleanShift modifier active
controlbooleanControl modifier active
altbooleanAlt modifier active
metabooleanMeta/Command modifier active
phaseKeyPhase"down", "repeat", or "up"

TextInput

Text input payload exposed via listenerContext:asTextInput().

FieldTypeDescription
textstringCommitted text input

alignValue (serialized key 222) and verticalAlignValue (key 1094) are TextInput component metadata parsed from .riv files; they are not fields on this Luau event payload. The accepted runtime also retains serialized obscured key 1095; it is likewise not a Luau event field.


FocusEvent

Focus payload exposed via listenerContext:asFocus().

FieldTypeDescription
isFocusbooleantrue when focus gained, false when focus lost

The accepted target includes fixes for gamepad device indexing, root-artboard FocusManager ownership, re-homing focus for nested instances, visibility transitions, and destroyed focus-tree state. Those are runtime behavior fixes; they do not add fields to FocusEvent or change callback signatures.


ReportedEvent

listenerContext:asReportedEvent() returns ReportedEvent?. The current Editor reference declares no public fields on this type, so current-facing examples must treat it as a presence/kind signal only.


ViewModelChange

listenerContext:asViewModelChange() returns ViewModelChange?. The current Editor reference declares no public fields on this type.


Gamepad Events

Gamepad listener payloads are three distinct types. Do not collapse them into a generic GamepadInvocation.

export type GamepadMappingKind = "standard" | "unknown"

GamepadConnected

Access with isGamepadConnected() and asGamepadConnected().

FieldTypeDescription
deviceIdnumberStable device ID for the logical gamepad session
buttonMasknumberPressed-button bitmask
buttons{ number }1-based analog button values
axes{ number }1-based analog axes
isStandardMappingbooleanWhether the embedder normalized the standard layout
mappingGamepadMappingKind"standard" or "unknown"
gamepadMappingnumberRaw mapping enum value (0 standard, 1 unknown)
west, south, north, eastbooleanStandard face-button state
leftShoulder, rightShoulderbooleanShoulder-button state
back, forward, startbooleanStandard navigation/start-button state
leftStickButton, rightStickButtonbooleanStick-click state
dpadUp, dpadDown, dpadLeft, dpadRightbooleanDirection-pad state
leftStick, rightStickVectorAnalog stick vectors
leftTrigger, rightTriggernumberAnalog trigger values
leftTriggerPressed, rightTriggerPressedbooleanDigital trigger-button state

Methods:

  • event:buttonPressed(index: number): boolean
  • event:buttonValue(index: number): number
  • event:axis(index: number): number

The current reference documents these indices as 1-based.

GamepadEvent

Access with isGamepadEvent() and asGamepadEvent(). It contains the same full device-state fields and query methods as GamepadConnected, plus:

FieldTypeDescription
changeKindstring"button" or "axis"
changeIndexnumber1-based button or axis index
changeValuenumberNew analog value
hasStandardButtonIntentbooleanWhether a standard button intent exists
hasStandardAxisIntentbooleanWhether a standard axis intent exists
intentButtonstring?Optional semantic button intent
intentAxisstring?Optional semantic axis intent

GamepadDisconnected

Access with isGamepadDisconnected() and asGamepadDisconnected(). It exposes only deviceId: number.

Node Gamepad Callbacks

The current Editor Node<T> reference exposes these optional callbacks:

function gamepadConnected(self: MyNode, event: GamepadConnected)
print("connected", event.deviceId, event.mapping)
end

function gamepadEvent(self: MyNode, event: GamepadEvent)
print(event.changeKind, event.changeIndex, event.changeValue)
end

function gamepadDisconnected(self: MyNode, event: GamepadDisconnected)
print("disconnected", event.deviceId)
end

runtime-v0.1.344 also corrects gamepad focus-device selection. Re-test real controller navigation and focus destruction/restoration in the selected runtime because analyzer acceptance alone does not execute those paths.


NoneEvent

Fallback event shape for unknown or unsupported listener event kinds. The current Editor reference declares no public fields.

  • Check with listenerContext:isNone()
  • Access with listenerContext:asNone()

Historical Runtime Wrapper Names

The pinned runtime-v0.1.262 source snapshot still uses Lua userdata wrapper names such as KeyboardInvocation, TextInputInvocation, FocusInvocation, ReportedEventInvocation, ViewModelChangeInvocation, and NoneInvocation. It also exposes delaySeconds on that historical reported-event wrapper. These names explain older source and LERP material; they are not the type names in the current Editor reference and should not be used for new Editor-authored code.

The generic GamepadInvocation / isGamepad() / asGamepad() shape previously shown by LERP is not the current reference contract. Current gamepad code must use the connected/event/disconnected triad above.


Trigger

See Data & Input: Trigger for the Trigger type reference, and Trigger Inputs for the full usage guide.

Knowledge Check

Q:What is the safest pattern for accessing listener event payloads?
Q:Which guard reads a changed gamepad button or axis payload?

Next Steps