Interface

IndirectPointerInjectionScope

The receiver scope of the indirect pointer input injection lambda from performIndirectPointerInput.

Source set: Common
@JvmDefaultWithCompatibility
interface IndirectPointerInjectionScope : Density

The receiver scope of the indirect pointer input injection lambda from performIndirectPointerInput.

Indirect pointer input events are dispatched through the focused tree, and components will only receive these events if they are focused, or an ancestor of a focused item. Therefore, this API requires an active focus state.

An indirect pointer gesture (just like a regular touch gesture) starts with a down event, followed by a sequence of move events and finally an up event, optionally combined with more sets of down and up events for multitouch gestures.

Most methods accept a pointerId to specify which pointer (finger) the event applies to. Movement can be expressed absolutely with moveTo and updatePointerTo, or relative to the current pointer position with moveBy and updatePointerBy. The moveTo/By methods enqueue an event immediately, while the updatePointerTo/By methods don't. This allows you to update the position of multiple pointers in a single move event for multitouch gestures. Indirect pointer input gestures can be canceled with cancel. All events, regardless the method used, will always contain the current position of all pointers.

The entire event injection state is shared between all perform.*Input methods, meaning you can continue an unfinished Indirect pointer input gesture in a subsequent invocation of performIndirectPointerInput or performMultiModalInput.

All events sent by these methods are batched together and sent as a whole after performIndirectPointerInput has executed its code block. Because gestures don't have to be defined all in the same performIndirectPointerInput block, keep in mind that while the gesture is not complete, all code you execute in between these blocks will be executed while imaginary fingers are actively touching the indirect pointer input device. Remember, indirect pointer events do NOT correlate to the screen, so those finger locations won't map to a screen x and y. The x and y coordinates are instead mapped to the specific input device being used during the interaction.

The events sent as part of the same batch will not be interrupted by recomposition. However, if a gesture spans multiple performIndirectPointerInput blocks it is important to remember that recomposition, layout and drawing could take place during the gesture, which may lead to events being injected into a moving target.

This scope also provides general capabilities such as advancing event time and accessing the system ViewConfiguration. It also implements Density to facilitate conversion between pixels and density-independent pixels.

For injection methods that require specific node information (e.g., performTouchInput, performMouseInput), use InjectionScope.

Example of performing an indirect pointer click:

Example of performing an indirect pointer swipe:

Properties

eventPeriodMillis

Source set: Common
val eventPeriodMillis

The default time between two successive events.

inputDeviceSize

Source set: Common
val inputDeviceSize: IntSize

The dimensions of the external indirect pointer input device that provide the boundaries for indirect input. If you go outside these dimensions, the tests will throw an exception. Note: This is not related to the screen coordinates.

indirectPointerEventPrimaryDirectionalMotionAxis

Source set: Common
val indirectPointerEventPrimaryDirectionalMotionAxis:
    IndirectPointerEventPrimaryDirectionalMotionAxis

The primary axis for motion from an IndirectPointerEvent. Indirect input devices (such as touchpads) that do not move a cursor on screen may define a primary axis for motion (such as scrolling). This facilitates the translation of a 2D input gesture into a 1D scroll on the screen. For example, an input device might be wide horizontally but narrow vertically. In such a case, it would designate X as its primary axis of motion. This means horizontal scrolling on the input device would cause a horizontal list to scroll horizontally, and a vertical list to scroll vertically - even though the direction of motion on the input device is horizontal in both cases.

viewConfiguration

Source set: Common
val viewConfiguration: ViewConfiguration

The ViewConfiguration in use by the SemanticsNode from the SemanticsNodeInteraction on which the input injection method is called.

Functions

advanceEventTime

fun advanceEventTime(durationMillis: Long = eventPeriodMillis)

Adds the given durationMillis to the current event time, delaying the next event by that time.

currentPosition

fun currentPosition(pointerId: Int = 0): Offset?

Returns the current position of the given pointerId. The default pointerId is 0. The position is returned in the coordinate system of the device sending the input (see inputDeviceSize). It is NOT related to the screen location.

down

fun down(pointerId: Int, position: Offset)

Sends a down event for the pointer with the given pointerId at position on the external indirect pointer input device. The position is NOT in the node's local coordinate system (see inputDeviceSize).

If no pointers are down yet, this will start a new Indirect pointer input gesture. If a gesture is already in progress (that is, there are other pointer ids that are down), this event is sent at the same timestamp as the last event. You cannot call down with a pointer id that is already down.

Parameters

pointerId The id of the pointer, can be any number not yet in use by another pointer
position The position of the down event, in the input device's coordinate system.

down

fun down(position: Offset)

Sends a down event for the default pointer at position on the indirect pointer input device sending the input. The position is NOT in the node's local coordinate system (see inputDeviceSize).

If no pointers are down yet, this will start a new Indirect pointer input gesture. If a gesture is already in progress, this event is sent at the same timestamp as the last event. If the given pointer is already down, @throws IllegalArgumentException.

Parameters

position The position of the down event, in the input device's coordinate system.

moveTo

fun moveTo(pointerId: Int, position: Offset, delayMillis: Long = eventPeriodMillis)

Sends a move event delayMillis after the last sent event on nodes in the focus path, with the position of the pointer with the given pointerId updated to position. The position is NOT in the node's local coordinate system (see inputDeviceSize).

If the pointer is not yet down, @throws IllegalArgumentException.

Parameters

pointerId The id of the pointer to move, as supplied in down
position The new position of the pointer, in the indirect pointer input device's coordinate system
delayMillis The time between the last sent event and this event. eventPeriodMillis by default.

moveTo

fun moveTo(position: Offset, delayMillis: Long = eventPeriodMillis)

Sends a move event delayMillis after the last sent event on nodes in the focus path, with the position of the default pointer updated to position. The position is NOT in the node's local coordinate system (see inputDeviceSize).

If the default pointer is not yet down, @throws IllegalArgumentException.

Parameters

position The new position of the pointer, in the indirect pointer input device's coordinate system
delayMillis The time between the last sent event and this event. eventPeriodMillis by default.

updatePointerTo

fun updatePointerTo(pointerId: Int, position: Offset)

Updates the position of the pointer with the given pointerId to the given position within the indirect pointer input device's bounds, but does not send a move event. The move event can be sent with move. The position is NOT in the node's local coordinate system (see inputDeviceSize).

If the pointer is not yet down, @throws IllegalArgumentException.

Parameters

pointerId The id of the pointer to move, as supplied in down
position The new position of the pointer, in the indirect pointer input device's coordinate system

updatePointerTo

fun updatePointerTo(position: Offset)

Updates the position of the default pointer (pointerId = 0) to the given position within the indirect pointer input device's bounds, but does not send a move event. The move event can be sent with move. The position is NOT in the node's local coordinate system (see inputDeviceSize).

If the pointer is not yet down, @throws IllegalArgumentException.

Parameters

position The new position of the pointer, in the indirect pointer input device's coordinate system

moveBy

fun moveBy(pointerId: Int, delta: Offset, delayMillis: Long = eventPeriodMillis)

Sends a move event delayMillis after the last sent event on nodes in the focus path, with the position of the pointer with the given pointerId moved by the given delta.

If the pointer is not yet down, @throws IllegalArgumentException.

Parameters

pointerId The id of the pointer to move, as supplied in down
delta The position for this move event, relative to the current position of the pointer. For example, `delta = Offset(10.px, -10.px) will add 10.px to the pointer's x-position, and subtract 10.px from the pointer's y-position.
delayMillis The time between the last sent event and this event. eventPeriodMillis by default.

moveBy

fun moveBy(delta: Offset, delayMillis: Long = eventPeriodMillis)

Sends a move event delayMillis after the last sent event on nodes in the focus path, with the position of the default pointer moved by the given delta. The default pointer has pointerId = 0.

If the pointer is not yet down, @throws IllegalArgumentException.

Parameters

delta The position for this move event, relative to the current position of the pointer. For example, `delta = Offset(10.px, -10.px) will add 10.px to the pointer's x-position, and subtract 10.px from the pointer's y-position.
delayMillis The time between the last sent event and this event. eventPeriodMillis by default.

updatePointerBy

fun updatePointerBy(pointerId: Int, delta: Offset)

Updates the position of the pointer with the given pointerId by the given delta, but does not send a move event. The move event can be sent with move.

If the pointer is not yet down, @throws IllegalArgumentException.

Parameters

pointerId The id of the pointer to move, as supplied in down
delta The position for this move event, relative to the last sent position of the pointer. For example, `delta = Offset(10.px, -10.px) will add 10.px to the pointer's x-position, and subtract 10.px from the pointer's y-position.

move

fun move(delayMillis: Long = eventPeriodMillis)

Sends a move event delayMillis after the last sent event without updating any of the pointer positions. This can be useful when batching movement of multiple pointers together, which can be done with updatePointerTo and updatePointerBy.

Parameters

delayMillis The time between the last sent event and this event. eventPeriodMillis by default.

moveWithHistoryMultiPointer

fun moveWithHistoryMultiPointer(
        relativeHistoricalTimes: List<Long>,
        historicalCoordinates: List<List<Offset>>,
        delayMillis: Long = eventPeriodMillis,
    )

Sends a move event delayMillis after the last sent event without updating any of the pointer positions, while adding the historicalCoordinates at the relativeHistoricalTimes to the move event. This corresponds to the scenario where an external touchpad generates Indirect pointer input events quicker than can be dispatched and batches them together.

Parameters

relativeHistoricalTimes Time of each historical event, as a millisecond relative to the time the actual event is sent. For example, -10L means 10ms earlier.
historicalCoordinates Coordinates of each historical event, in the same coordinate space as moveTo. The outer list must have the same size as the number of pointers in the event, and each inner list must have the same size as relativeHistoricalTimes. The ith pointer is assigned the ith history, with the pointers sorted on ascending pointerId.
delayMillis The time between the last sent event and this event. eventPeriodMillis by default.

moveWithHistory

fun moveWithHistory(
        relativeHistoricalTimes: List<Long>,
        historicalCoordinates: List<Offset>,
        delayMillis: Long = eventPeriodMillis,
    ) =
        moveWithHistoryMultiPointer(
            relativeHistoricalTimes,
            listOf(historicalCoordinates),
            delayMillis,
        )

Sends a move event delayMillis after the last sent event without updating any of the pointer positions, while adding the historicalCoordinates at the relativeHistoricalTimes to the move event. This corresponds to the scenario where the external device generates Indirect pointer input events quicker than can be dispatched and batches them together.

This overload is a convenience method for the common case where the gesture only has one pointer.

Parameters

relativeHistoricalTimes Time of each historical event, as a millisecond relative to the time the actual event is sent. For example, -10L means 10ms earlier.
historicalCoordinates Coordinates of each historical event, in the same coordinate space as moveTo. The list must have the same size as relativeHistoricalTimes.
delayMillis The time between the last sent event and this event. eventPeriodMillis by default.

up

fun up(pointerId: Int = 0)

Sends an up event for the pointer with the given pointerId, or the default pointer if pointerId is omitted, on nodes in the focus path.

Parameters

pointerId The id of the pointer to liftup, as supplied in down

cancel

fun cancel(delayMillis: Long = eventPeriodMillis)

Sends a cancel event delayMillis after the last sent event to cancel the current gesture. The cancel event contains the current position of all active pointers.

Parameters

delayMillis The time between the last sent event and this event. eventPeriodMillis by default.

Last updated: