TrackpadInjectionScope
-
Cmn
interface TrackpadInjectionScope : InjectionScope
The receiver scope of the trackpad input injection lambda from performTrackpadInput.
The functions in TrackpadInjectionScope can roughly be divided into two groups: full gestures and individual trackpad events. The individual trackpad events are: press, moveTo and friends, release, cancel, pan and advanceEventTime. Full gestures are all the other functions, like TrackpadInjectionScope.click, TrackpadInjectionScope.doubleClick, TrackpadInjectionScope.animateMoveTo, etc. These are built on top of the individual events and serve as a good example on how you can build your own full gesture functions.
A trackpad move event can be sent with moveTo and moveBy. The trackpad position can be updated with updatePointerTo and updatePointerBy, which will not send an event and only update the position internally. This can be useful if you want to send an event that is not a move event with a location other then the current location, but without sending a preceding move event. Use press and release to send button pressed and button released events. This will also send all other necessary events that keep the stream of trackpad events consistent with actual trackpad input, such as a hover exit event. A cancel event can be sent at any time when at least one button is pressed. Use pan to send a trackpad pan event.
The entire event injection state is shared between all perform.*Input methods, meaning you can continue an unfinished trackpad gesture in a subsequent invocation of performTrackpadInput or performMultiModalInput. Note however that while the trackpad's position is retained across invocation of perform.*Input methods, it is always manipulated in the current node's local coordinate system. That means that two subsequent invocations of performTrackpadInput on different nodes will report a different currentPosition, even though it is actually the same position on the screen.
All events sent by these methods are batched together and sent as a whole after performTrackpadInput has executed its code block.
Example of performing a trackpad click:
import androidx.compose.ui.test.click import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performTrackpadInput composeTestRule.onNodeWithTag("myComponent").performTrackpadInput { // Click in the middle of the node click(center) }
| See also | |
|---|---|
InjectionScope |
Summary
Public functions |
||
|---|---|---|
Unit |
Sends a cancel event |
Cmn
|
Unit |
Sends a hover enter event at the given |
Cmn
|
Unit |
Sends a hover exit event at the given |
Cmn
|
open Unit |
Sends a move event |
Cmn
|
Unit |
Sends a move event |
Cmn
|
Unit |
Ends a pan gesture. |
Cmn
|
Unit |
Updates the ongoing pan gesture, by applying the given |
Cmn
|
Unit |
panStart()Starts a pan gesture. |
Cmn
|
Unit |
press(button: TrackpadButton)Sends a down and button pressed event for the given |
Cmn
|
Unit |
release(button: TrackpadButton)Sends a button released and up event for the given |
Cmn
|
Unit |
scaleChangeBy(Updates the ongoing scale gesture, by applying the given multiplicative |
Cmn
|
Unit |
Ends a scale gesture. |
Cmn
|
Unit |
Starts a scale gesture. |
Cmn
|
open Unit |
updatePointerBy(delta: Offset)Updates the position of the trackpad by the given |
Cmn
|
Unit |
updatePointerTo(position: Offset)Updates the position of the trackpad to the given |
Cmn
|
Public properties |
||
|---|---|---|
Offset |
Returns the current position of the cursor. |
Cmn
|
Extension functions |
||
|---|---|---|
Unit |
TrackpadInjectionScope.animateMoveAlong(Move the trackpad along the given |
Cmn
|
Unit |
TrackpadInjectionScope.animateMoveBy(Move the trackpad from the |
Cmn
|
Unit |
TrackpadInjectionScope.animateMoveTo(Move the trackpad from the |
Cmn
|
Unit |
TrackpadInjectionScope.click(position: Offset, button: TrackpadButton)Use |
Cmn
|
Unit |
TrackpadInjectionScope.doubleClick(Use |
Cmn
|
Unit |
TrackpadInjectionScope.dragAndDrop(Use |
Cmn
|
Unit |
TrackpadInjectionScope.longClick(Use |
Cmn
|
Unit |
TrackpadInjectionScope.pan(offset: Offset)Sends a pan gesture with the given total |
Cmn
|
Unit |
TrackpadInjectionScope.pan(Sends a pan gesture with the offsets in the panning coordinate space following the given |
Cmn
|
Unit |
TrackpadInjectionScope.panWithVelocity(Performs a pan gesture on the associated node such that it ends with the given |
Cmn
|
Unit |
TrackpadInjectionScope.rightClick(position: Offset)Secondary-click on |
Cmn
|
Unit |
TrackpadInjectionScope.scale(Sends a scale event with the given |
Cmn
|
Unit |
TrackpadInjectionScope.tripleClick(Use |
Cmn
|
Inherited functions |
|||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|||||||||||||||||||||||||||||||||
|
Inherited properties |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Public functions
cancel
fun cancel(delayMillis: Long = eventPeriodMillis): Unit
Sends a cancel event delayMillis after the last sent event to cancel a stream of trackpad events with pressed buttons. All buttons will be released as a result. A trackpad cancel event can only be sent when buttons are pressed.
| Parameters | |
|---|---|
delayMillis: Long = eventPeriodMillis |
The time between the last sent event and this event. |
enter
fun enter(
position: Offset = currentPosition,
delayMillis: Long = eventPeriodMillis
): Unit
Sends a hover enter event at the given position, delayMillis after the last sent event, without sending a hover move event.
The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.
Note: enter and exit events are already sent as a side effect of movement when necessary. Whether or not this is part of the contract of trackpad events is platform dependent, so it is highly discouraged to manually send enter or exit events. Only use this method for tests that need to make assertions about a component's state in between the enter/exit and move event.
| Parameters | |
|---|---|
position: Offset = currentPosition |
The new position of the trackpad, in the node's local coordinate system. |
delayMillis: Long = eventPeriodMillis |
The time between the last sent event and this event. |
| Throws | |
|---|---|
IllegalStateException |
if buttons are down, or if the trackpad is already hovering. |
exit
fun exit(position: Offset = currentPosition, delayMillis: Long = eventPeriodMillis): Unit
Sends a hover exit event at the given position, delayMillis after the last sent event, without sending a hover move event.
The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.
Note: enter and exit events are already sent as a side effect of movement when necessary. Whether or not this is part of the contract of trackpad events is platform dependent, so it is highly discouraged to manually send enter or exit events. Only use this method for tests that need to make assertions about a component's state in between the enter/exit and move event.
| Parameters | |
|---|---|
position: Offset = currentPosition |
The new position of the trackpad, in the node's local coordinate system |
delayMillis: Long = eventPeriodMillis |
The time between the last sent event and this event. |
| Throws | |
|---|---|
IllegalStateException |
if the trackpad was not hovering. |
moveBy
open fun moveBy(delta: Offset, delayMillis: Long = eventPeriodMillis): Unit
Sends a move event delayMillis after the last sent event on the associated node, with the position of the trackpad moved by the given delta.
If no buttons are pressed, a hover event will be sent instead of a move event. If the trackpad wasn't hovering yet, a hover enter event is sent as well.
| Parameters | |
|---|---|
delta: Offset |
The position for this move event, relative to the current position of the trackpad. For example, `delta = Offset(10.px, -10.px) will add 10.px to the trackpad's x-position, and subtract 10.px from the trackpad's y-position. |
delayMillis: Long = eventPeriodMillis |
The time between the last sent event and this event. |
moveTo
fun moveTo(position: Offset, delayMillis: Long = eventPeriodMillis): Unit
Sends a move event delayMillis after the last sent event on the associated node, with the position of the trackpad updated to position. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.
If no buttons are pressed, a hover event will be sent instead of a move event. If the trackpad wasn't hovering yet, a hover enter event is sent as well.
| Parameters | |
|---|---|
position: Offset |
The new position of the trackpad, in the node's local coordinate system |
delayMillis: Long = eventPeriodMillis |
The time between the last sent event and this event. |
panEnd
fun panEnd(delayMillis: Long = eventPeriodMillis): Unit
Ends a pan gesture. The androidx.compose.ui.input.pointer.PointerEventType.PanEnd will be sent at the current event time.
The helper function pan allows combining these calls into a single call, to pan by a given offset sending the appropriate event in sequence.
| Parameters | |
|---|---|
delayMillis: Long = eventPeriodMillis |
The time between the last sent event and this event. |
| Throws | |
|---|---|
IllegalStateException |
if the trackpad is not in a pan gesture started by |
panMoveBy
fun panMoveBy(delta: Offset, delayMillis: Long = eventPeriodMillis): Unit
Updates the ongoing pan gesture, by applying the given delta as part of the pan. The androidx.compose.ui.input.pointer.PointerEventType.PanMove will be sent at the current event time.
The helper function pan allows combining these calls into a single call, to pan by a given offset sending the appropriate event in sequence.
| Parameters | |
|---|---|
delta: Offset |
the incremental change in the pan offset. |
delayMillis: Long = eventPeriodMillis |
The time between the last sent event and this event. |
| Throws | |
|---|---|
IllegalStateException |
if the trackpad is not in a pan gesture started by |
panStart
fun panStart(): Unit
Starts a pan gesture. The androidx.compose.ui.input.pointer.PointerEventType.PanStart will be sent at the current event time. This should be followed by any number of calls to panMoveBy, followed by panEnd.
The helper function pan allows combining these calls into a single call, to pan by a given offset sending the appropriate event in sequence.
| Throws | |
|---|---|
IllegalStateException |
if the trackpad was already sending a pan gesture. |
press
fun press(button: TrackpadButton = TrackpadButton.Primary): Unit
Sends a down and button pressed event for the given button on the associated node. When no buttons were down yet, this will exit hovering mode before the button is pressed. All events will be sent at the current event time. Trackpads behave similarly to mice, with platform interpreted gestures that send button events.
| Parameters | |
|---|---|
button: TrackpadButton = TrackpadButton.Primary |
The button that is pressed. By default the primary button. |
| Throws | |
|---|---|
IllegalStateException |
if the |
release
fun release(button: TrackpadButton = TrackpadButton.Primary): Unit
Sends a button released and up event for the given button on the associated node. If this was the last button to be released, the trackpad will enter hovering mode and send an accompanying trackpad move event after the button has been released. All events will be sent at the current event time. Trackpads behave similarly to mice, with platform interpreted gestures that send button events.
| Parameters | |
|---|---|
button: TrackpadButton = TrackpadButton.Primary |
The button that is released. By default the primary button. |
| Throws | |
|---|---|
IllegalStateException |
if the |
scaleChangeBy
fun scaleChangeBy(
scaleFactor: @FloatRange(from = 0.0, fromInclusive = false) Float,
delayMillis: Long = eventPeriodMillis
): Unit
Updates the ongoing scale gesture, by applying the given multiplicative scaleFactor as part of the gesture. The androidx.compose.ui.input.pointer.PointerEventType.ScaleChange will be sent at the current event time.
The helper function scale allows combining these calls into a single call, to scale by a given factor sending the appropriate events in sequence.
| Parameters | |
|---|---|
scaleFactor: @FloatRange(from = 0.0, fromInclusive = false) Float |
the incremental multiplicative change in the scale factor. |
delayMillis: Long = eventPeriodMillis |
The time between the last sent event and this event. |
| Throws | |
|---|---|
IllegalStateException |
if the trackpad is not in a scale gesture started by |
scaleEnd
fun scaleEnd(delayMillis: Long = eventPeriodMillis): Unit
Ends a scale gesture. The androidx.compose.ui.input.pointer.PointerEventType.ScaleEnd will be sent at the current event time.
The helper function scale allows combining these calls into a single call, to scale by a given factor sending the appropriate events in sequence.
| Parameters | |
|---|---|
delayMillis: Long = eventPeriodMillis |
The time between the last sent event and this event. |
| Throws | |
|---|---|
IllegalStateException |
if the trackpad is not in a scale gesture started by |
scaleStart
fun scaleStart(): Unit
Starts a scale gesture. The androidx.compose.ui.input.pointer.PointerEventType.ScaleStart will be sent at the current event time. This should be followed by any number of calls to scaleChangeBy, followed by scaleEnd.
The helper function scale allows combining these calls into a single call, to scale by a given factor sending the appropriate events in sequence.
| Throws | |
|---|---|
IllegalStateException |
if the trackpad was already sending a scale gesture. |
updatePointerBy
open fun updatePointerBy(delta: Offset): Unit
Updates the position of the trackpad by the given delta, but does not send a move or hover event. This can be useful to adjust the trackpad position before sending for example a press event.
| Parameters | |
|---|---|
delta: Offset |
The position for this move event, relative to the current position of the trackpad. For example, `delta = Offset(10.px, -10.px) will add 10.px to the trackpad's x-position, and subtract 10.px from the trackpad's y-position. |
updatePointerTo
fun updatePointerTo(position: Offset): Unit
Updates the position of the trackpad to the given position, but does not send a move or hover event. This can be useful to adjust the trackpad position before sending for example a press event. The position is in the node's local coordinate system, where (0.px, 0.px) is the top left corner of the node.
| Parameters | |
|---|---|
position: Offset |
The new position of the trackpad, in the node's local coordinate system |
Public properties
currentPosition
val currentPosition: Offset
Returns the current position of the cursor. The position is returned in the local coordinate system of the node with which we're interacting. (0, 0) is the top left corner of the node. If none of the move or updatePointer methods have been used yet, the trackpad's position will be (0, 0) in the Compose host's coordinate system, which will be -[topLeft] in the node's local coordinate system.
Extension functions
TrackpadInjectionScope.animateMoveAlong
fun TrackpadInjectionScope.animateMoveAlong(
curve: (timeMillis: Long) -> Offset,
durationMillis: Long = DefaultTrackpadGestureDurationMillis
): Unit
Move the trackpad along the given curve, sending a stream of move events to get an animated path of durationMillis milliseconds. The trackpad will initially be moved to the start of the path, curve(0), if it is not already there. The positions defined by the curve are in the node's local coordinate system, where (0, 0) is the top left corner of the node.
Example of moving the trackpad along a curve:
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.test.animateMoveAlong import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performTrackpadInput composeTestRule.onNodeWithTag("myComponent").performTrackpadInput { // Hover over the node, making a full circle with a radius of 100px val r = 100f animateMoveAlong( curve = { val angle = 2 * PI * it / 1000 center + Offset(r * cos(angle).toFloat(), r * sin(angle).toFloat()) }, durationMillis = 1000L, ) }
| Parameters | |
|---|---|
curve: (timeMillis: Long) -> Offset |
The function that defines the position of the trackpad over time for this gesture, in the node's local coordinate system. The argument passed to the function is the time in milliseconds since the start of the animated move, and the return value is the location of the trackpad at that point in time |
durationMillis: Long = DefaultTrackpadGestureDurationMillis |
The duration of the gesture. By default 300 milliseconds. |
TrackpadInjectionScope.animateMoveBy
fun TrackpadInjectionScope.animateMoveBy(
delta: Offset,
durationMillis: Long = DefaultTrackpadGestureDurationMillis
): Unit
Move the trackpad from the current position by the given delta, sending a stream of move events to get an animated path of durationMillis milliseconds.
| Parameters | |
|---|---|
delta: Offset |
The position where to move the trackpad to, relative to the current position of the trackpad. For example, `delta = Offset(100.px, -100.px) will move the trackpad 100 pixels to the right and 100 pixels upwards. |
durationMillis: Long = DefaultTrackpadGestureDurationMillis |
The duration of the gesture. By default 300 milliseconds. |
TrackpadInjectionScope.animateMoveTo
fun TrackpadInjectionScope.animateMoveTo(
position: Offset,
durationMillis: Long = DefaultTrackpadGestureDurationMillis
): Unit
Move the trackpad from the current position to the given position, sending a stream of move events to get an animated path of durationMillis milliseconds. Move the trackpad to the desired start position if you want to start from a different position. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.
Example of moving the trackpad along a line:
import androidx.compose.ui.test.animateMoveTo import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performTrackpadInput composeTestRule.onNodeWithTag("myComponent").performTrackpadInput { // Hover over the node, making an X shape moveTo(topLeft) animateMoveTo(bottomRight) // Note that an actual user wouldn't be able to instantly // move from the bottom right to the top right advanceEventTime() moveTo(topRight) animateMoveTo(bottomLeft) }
TrackpadInjectionScope.click
fun TrackpadInjectionScope.click(
position: Offset = center,
button: TrackpadButton = TrackpadButton.Primary
): Unit
Use button to click on position, or on the current cursor position if position is unspecified. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default button is the primary button.
| Parameters | |
|---|---|
position: Offset = center |
The position where to click, in the node's local coordinate system. If omitted, the |
button: TrackpadButton = TrackpadButton.Primary |
The button to click with. Uses the |
TrackpadInjectionScope.doubleClick
fun TrackpadInjectionScope.doubleClick(
position: Offset = center,
button: TrackpadButton = TrackpadButton.Primary
): Unit
Use button to double-click on position, or on the current trackpad position if position is unspecified. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default button is the primary button.
| Parameters | |
|---|---|
position: Offset = center |
The position where to click, in the node's local coordinate system. If omitted, the |
button: TrackpadButton = TrackpadButton.Primary |
The button to click with. Uses the |
TrackpadInjectionScope.dragAndDrop
fun TrackpadInjectionScope.dragAndDrop(
start: Offset,
end: Offset,
button: TrackpadButton = TrackpadButton.Primary,
durationMillis: Long = DefaultTrackpadGestureDurationMillis
): Unit
Use button to drag and drop something from start to end in durationMillis milliseconds. The trackpad position is updated to the start position before starting the gesture. The positions defined by the start and end are in the node's local coordinate system, where (0, 0) is the top left corner of the node.
| Parameters | |
|---|---|
start: Offset |
The position where to press the primary button and initiate the drag, in the node's local coordinate system. |
end: Offset |
The position where to release the primary button and end the drag, in the node's local coordinate system. |
button: TrackpadButton = TrackpadButton.Primary |
The button to drag with. Uses the |
durationMillis: Long = DefaultTrackpadGestureDurationMillis |
The duration of the gesture. By default 300 milliseconds. |
TrackpadInjectionScope.longClick
fun TrackpadInjectionScope.longClick(
position: Offset = center,
button: TrackpadButton = TrackpadButton.Primary
): Unit
Use button to long-click on position, or on the current trackpad position if position is unspecified. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default button is the primary button.
| Parameters | |
|---|---|
position: Offset = center |
The position where to click, in the node's local coordinate system. If omitted, the |
button: TrackpadButton = TrackpadButton.Primary |
The button to click with. Uses the |
TrackpadInjectionScope.pan
fun TrackpadInjectionScope.pan(offset: Offset): Unit
Sends a pan gesture with the given total offset. The event will be sent starting at the current event time.
To send a pan gesture with a curve, use pan(curve, durationMillis, keyTimes).
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.pan import androidx.compose.ui.test.performTrackpadInput composeTestRule.onNodeWithTag("verticalScrollable").performTrackpadInput { pan(Offset(0f, 100f)) }
| Parameters | |
|---|---|
offset: Offset |
The amount of pan |
TrackpadInjectionScope.pan
fun TrackpadInjectionScope.pan(
curve: (timeMillis: Long) -> Offset,
durationMillis: Long = 200,
keyTimes: List<Long> = emptyList()
): Unit
Sends a pan gesture with the offsets in the panning coordinate space following the given curve. It is expected that the curve starts at Offset.Zero, as a pan gesture starts with no delta, and then move outward from the origin.
To send a pan with just a single amount, use pan(offset).
| Parameters | |
|---|---|
curve: (timeMillis: Long) -> Offset |
The function that describes the gesture. The argument passed to the function is the time in milliseconds since the start of the swipe, and the return value is the location of the pan from the origin at that point in time. |
durationMillis: Long = 200 |
The duration of the gesture |
keyTimes: List<Long> = emptyList() |
An optional list of timestamps in milliseconds at which a pan move event must be sampled |
TrackpadInjectionScope.panWithVelocity
fun TrackpadInjectionScope.panWithVelocity(
offset: Offset,
endVelocity: @FloatRange(from = 0.0) Float,
durationMillis: Long = VelocityPathFinder.calculateDefaultDuration(Offset.Zero, offset, endVelocity)
): Unit
Performs a pan gesture on the associated node such that it ends with the given endVelocity.
The pan will go from Offset.Zero at t=0 to offset at t=durationMillis. In between, the pan will go monotonically from Offset.Zero and offset, but not strictly. Due to imprecision, no guarantees can be made for the actual velocity at the end of the gesture, but generally it is within 0.1 of the desired velocity.
When a pan cannot be created that results in the desired velocity (because the input is too restrictive), an exception will be thrown with suggestions to fix the input.
The coordinates are in the pan coordinate system, which has the same scale as the display in pixel coordinates, where Offset.Zero indicates no panning.
Use pan(curve, duration, durationMillis) to directly control the curve of the pan.
| Parameters | |
|---|---|
offset: Offset |
The end position of the pan |
endVelocity: @FloatRange(from = 0.0) Float |
The velocity of the gesture at the moment it ends in px/second. Must be positive. |
durationMillis: Long = VelocityPathFinder.calculateDefaultDuration(Offset.Zero, offset, endVelocity) |
The duration of the gesture in milliseconds. Must be long enough that at least 3 input events are generated, which happens with a duration of 40ms or more. If omitted, a duration is calculated such that a valid pan with velocity can be created. |
| Throws | |
|---|---|
IllegalArgumentException |
When no pan can be generated that will result in the desired velocity. The error message will suggest changes to the input parameters such that a pan will become feasible. |
TrackpadInjectionScope.rightClick
fun TrackpadInjectionScope.rightClick(position: Offset = center): Unit
Secondary-click on position, or on the current cursor position if position is unspecified. While the secondary button is not necessarily a physical right button (e.g. a multi-finger tap), this method is still called rightClick for it's widespread use. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.
| Parameters | |
|---|---|
position: Offset = center |
The position where to click, in the node's local coordinate system. If omitted, the |
TrackpadInjectionScope.scale
fun TrackpadInjectionScope.scale(
scaleFactor: @FloatRange(from = 0.0, fromInclusive = false) Float
): Unit
Sends a scale event with the given scaleFactor. The event will be sent starting at the current event time.
The scaleFactor is a multiplicative zoom factor. A scaleFactor of 1 represents no change. A scaleFactor less than 1 represents a "zoom out" gesture, while a factor of more than one represents a "zoom in" gesture.
import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performTrackpadInput import androidx.compose.ui.test.scale composeTestRule.onNodeWithTag("transformable").performTrackpadInput { // Performs a scale with a factor of 0.9f, which corresponds to a "zoom out" gesture. scale(0.9f) }
| Parameters | |
|---|---|
scaleFactor: @FloatRange(from = 0.0, fromInclusive = false) Float |
The amount to scale. |
TrackpadInjectionScope.tripleClick
fun TrackpadInjectionScope.tripleClick(
position: Offset = center,
button: TrackpadButton = TrackpadButton.Primary
): Unit
Use button to triple-click on position, or on the current trackpad position if position is unspecified. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default button is the primary button.
| Parameters | |
|---|---|
position: Offset = center |
The position where to click, in the node's local coordinate system. If omitted, the |
button: TrackpadButton = TrackpadButton.Primary |
The button to click with. Uses the |