MouseInjectionScope


The receiver scope of the mouse input injection lambda from performMouseInput.

The functions in MouseInjectionScope can roughly be divided into two groups: full gestures and individual mouse events. The individual mouse events are: press, moveTo and friends, release, cancel, scroll and advanceEventTime. Full gestures are all the other functions, like MouseInjectionScope.click, MouseInjectionScope.doubleClick, MouseInjectionScope.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 mouse move event can be sent with moveTo and moveBy. The mouse 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 mouse events consistent with actual mouse input, such as a hover exit event. A cancel event can be sent at any time when at least one button is pressed. Use scroll to send a mouse scroll event.

The entire event injection state is shared between all perform.*Input methods, meaning you can continue an unfinished mouse gesture in a subsequent invocation of performMouseInput or performMultiModalInput. Note however that while the mouse'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 performMouseInput 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 performMouseInput has executed its code block.

Example of performing a mouse click:

import androidx.compose.ui.test.click
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performMouseInput

composeTestRule.onNodeWithTag("myComponent").performMouseInput {
    // Click in the middle of the node
    click(center)
}

Example of scrolling the mouse wheel while the mouse button is pressed:

import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performMouseInput

composeTestRule
    .onNodeWithTag("verticalScrollable")
    // Scroll downwards while keeping a button pressed:
    .performMouseInput {
        // Presses the primary mouse button
        press()
        // Scroll the scroll wheel by 6 units
        repeat(6) {
            advanceEventTime()
            scroll(1f)
        }
        // And release the mouse button
        advanceEventTime()
        release()
    }
See also
InjectionScope

Summary

Public functions

Unit
cancel(delayMillis: Long)

Sends a cancel event delayMillis after the last sent event to cancel a stream of mouse events with pressed mouse buttons.

Cmn
Unit
enter(position: Offset, delayMillis: Long)

Sends a hover enter event at the given position, delayMillis after the last sent event, without sending a hover move event.

Cmn
Unit
exit(position: Offset, delayMillis: Long)

Sends a hover exit event at the given position, delayMillis after the last sent event, without sending a hover move event.

Cmn
open Unit
moveBy(delta: Offset, delayMillis: Long)

Sends a move event delayMillis after the last sent event on the associated node, with the position of the mouse moved by the given delta.

Cmn
Unit
moveTo(position: Offset, delayMillis: Long)

Sends a move event delayMillis after the last sent event on the associated node, with the position of the mouse updated to position.

Cmn
Unit
press(button: MouseButton)

Sends a down and button pressed event for the given button on the associated node.

Cmn
Unit

Sends a button released and up event for the given button on the associated node.

Cmn
Unit
scroll(delta: Float, scrollWheel: ScrollWheel)

Sends a scroll event with the given delta on the given scrollWheel.

Cmn
open Unit

Updates the position of the mouse by the given delta, but does not send a move or hover event.

Cmn
Unit

Updates the position of the mouse to the given position, but does not send a move or hover event.

Cmn

Public properties

Offset

Returns the current position of the mouse.

Cmn

Extension functions

Unit
MouseInjectionScope.animateMoveAlong(
    curve: (timeMillis: Long) -> Offset,
    durationMillis: Long
)

Move the mouse along the given curve, sending a stream of move events to get an animated path of durationMillis milliseconds.

Cmn
Unit
MouseInjectionScope.animateMoveBy(delta: Offset, durationMillis: Long)

Move the mouse from the current position by the given delta, sending a stream of move events to get an animated path of durationMillis milliseconds.

Cmn
Unit
MouseInjectionScope.animateMoveTo(
    position: Offset,
    durationMillis: Long
)

Move the mouse from the current position to the given position, sending a stream of move events to get an animated path of durationMillis milliseconds.

Cmn
Unit

Use button to click on position, or on the current mouse position if position is unspecified.

Cmn
Unit

Use button to double-click on position, or on the current mouse position if position is unspecified.

Cmn
Unit
MouseInjectionScope.dragAndDrop(
    start: Offset,
    end: Offset,
    button: MouseButton,
    durationMillis: Long
)

Use button to drag and drop something from start to end in durationMillis milliseconds.

Cmn
Unit

Use button to long-click on position, or on the current mouse position if position is unspecified.

Cmn
Unit

Secondary-click on position, or on the current mouse position if position is unspecified.

Cmn
Unit
MouseInjectionScope.smoothScroll(
    scrollAmount: Float,
    durationMillis: Long,
    scrollWheel: ScrollWheel
)

Rotate the mouse's scrollWheel by the given scrollAmount.

Cmn
Unit

Use button to triple-click on position, or on the current mouse position if position is unspecified.

Cmn

Inherited functions

From androidx.compose.ui.unit.Density
open Int

Convert Dp to Int by rounding

Cmn
open Int

Convert Sp to Int by rounding

Cmn
open Dp

Convert an Int pixel value to Dp.

Cmn
open Dp

Convert a Float pixel value to a Dp

Cmn
open DpSize

Convert a Size to a DpSize.

Cmn
open Float

Convert Dp to pixels.

Cmn
open Float

Convert Sp to pixels.

Cmn
open Rect

Convert a DpRect to a Rect.

Cmn
open Size

Convert a DpSize to a Size.

Cmn
open TextUnit

Convert an Int pixel value to Sp.

Cmn
open TextUnit

Convert a Float pixel value to a Sp

Cmn
From androidx.compose.ui.unit.FontScaling
open Dp

Convert Sp to Dp.

Cmn
open TextUnit

Convert Dp to Sp.

Cmn
From androidx.compose.ui.test.InjectionScope
Unit
advanceEventTime(durationMillis: Long)

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

Cmn
open Offset

Creates an Offset relative to the size of the node we're interacting with.

Cmn

Inherited properties

From androidx.compose.ui.unit.Density
Float

The logical density of the display.

Cmn
From androidx.compose.ui.unit.FontScaling
Float

Current user preference for the scaling factor for fonts.

Cmn
From androidx.compose.ui.test.InjectionScope
open Float

The y-coordinate for the bottom of the node we're interacting with in px, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Offset

The center of the bottom edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Offset

The bottom left corner of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Offset

The bottom right corner of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Offset

The center of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Offset

The center of the left edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Offset

The center of the right edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Float

The x-coordinate for the center of the node we're interacting with in px, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Float

The y-coordinate for the center of the node we're interacting with in px, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Long

The default time between two successive events.

Cmn
open Int

The height of the node in px.

Cmn
open Float

The x-coordinate for the left edge of the node we're interacting with in px, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Float

The x-coordinate for the right edge of the node we're interacting with in px, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Float

The y-coordinate for the bottom of the node we're interacting with in px, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Offset

The center of the top edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Offset

The top left corner of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
open Offset

The top right corner of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Cmn
ViewConfiguration

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

Cmn
IntSize

The size of the visible part of the node we're interacting with in px, i.e. its clipped bounds.

Cmn
open Int

The width of the node in px.

Cmn

Public functions

cancel

fun cancel(delayMillis: Long = eventPeriodMillis): Unit

Sends a cancel event delayMillis after the last sent event to cancel a stream of mouse events with pressed mouse buttons. All buttons will be released as a result. A mouse cancel event can only be sent when mouse buttons are pressed.

Parameters
delayMillis: Long = eventPeriodMillis

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

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.

An IllegalStateException will be thrown when mouse buttons are down, or if the mouse is already hovering.

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 mouse 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 mouse, in the node's local coordinate system. currentPosition by default.

delayMillis: Long = eventPeriodMillis

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

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.

An IllegalStateException will be thrown if the mouse was not hovering.

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 mouse 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 mouse, in the node's local coordinate system currentPosition by default.

delayMillis: Long = eventPeriodMillis

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

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 mouse moved by the given delta.

If no mouse buttons are pressed, a hover event will be sent instead of a move event. If the mouse 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 mouse. For example, `delta = Offset(10.px, -10.px) will add 10.px to the mouse's x-position, and subtract 10.px from the mouse's y-position.

delayMillis: Long = eventPeriodMillis

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

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 mouse 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 mouse buttons are pressed, a hover event will be sent instead of a move event. If the mouse wasn't hovering yet, a hover enter event is sent as well.

Parameters
position: Offset

The new position of the mouse, in the node's local coordinate system

delayMillis: Long = eventPeriodMillis

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

press

fun press(button: MouseButton = MouseButton.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.

Throws an IllegalStateException if the button is already pressed.

Parameters
button: MouseButton = MouseButton.Primary

The mouse button that is pressed. By default the primary mouse button.

release

fun release(button: MouseButton = MouseButton.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 mouse will enter hovering mode and send an accompanying mouse move event after the button has been released. All events will be sent at the current event time.

Throws an IllegalStateException if the button is not pressed.

Parameters
button: MouseButton = MouseButton.Primary

The mouse button that is released. By default the primary mouse button.

scroll

fun scroll(delta: Float, scrollWheel: ScrollWheel = ScrollWheel.Vertical): Unit

Sends a scroll event with the given delta on the given scrollWheel. The event will be sent at the current event time.

Positive delta values correspond to scrolling forward (new content appears at the bottom of a column, or at the end of a row), negative values correspond to scrolling backward (new content appears at the top of a column, or at the start of a row).

Note that the correlation between scroll delta and pixels scrolled is platform specific. For example, on Android a scroll delta of 1f corresponds to a scroll of 64.dp. However, on any platform, this conversion factor could change in the future to improve the mouse scroll experience.

Example of how scroll could be used:

import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performMouseInput

composeTestRule
    .onNodeWithTag("verticalScrollable")
    // Scroll downwards while keeping a button pressed:
    .performMouseInput {
        // Presses the primary mouse button
        press()
        // Scroll the scroll wheel by 6 units
        repeat(6) {
            advanceEventTime()
            scroll(1f)
        }
        // And release the mouse button
        advanceEventTime()
        release()
    }
Parameters
delta: Float

The amount of scroll

scrollWheel: ScrollWheel = ScrollWheel.Vertical

Which scroll wheel to rotate. Can be either ScrollWheel.Vertical (the default) or ScrollWheel.Horizontal.

updatePointerBy

open fun updatePointerBy(delta: Offset): Unit

Updates the position of the mouse by the given delta, but does not send a move or hover event. This can be useful to adjust the mouse position before sending for example a press event.

Parameters
delta: Offset

The position for this move event, relative to the current position of the mouse. For example, `delta = Offset(10.px, -10.px) will add 10.px to the mouse's x-position, and subtract 10.px from the mouse's y-position.

updatePointerTo

fun updatePointerTo(position: Offset): Unit

Updates the position of the mouse to the given position, but does not send a move or hover event. This can be useful to adjust the mouse 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 mouse, in the node's local coordinate system

Public properties

currentPosition

val currentPositionOffset

Returns the current position of the mouse. 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 mouse'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

animateMoveAlong

fun MouseInjectionScope.animateMoveAlong(
    curve: (timeMillis: Long) -> Offset,
    durationMillis: Long = DefaultMouseGestureDurationMillis
): Unit

Move the mouse along the given curve, sending a stream of move events to get an animated path of durationMillis milliseconds. The mouse 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 mouse 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.performMouseInput

composeTestRule.onNodeWithTag("myComponent").performMouseInput {
    // 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 mouse 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 mouse at that point in time

durationMillis: Long = DefaultMouseGestureDurationMillis

The duration of the gesture. By default 300 milliseconds.

animateMoveBy

fun MouseInjectionScope.animateMoveBy(
    delta: Offset,
    durationMillis: Long = DefaultMouseGestureDurationMillis
): Unit

Move the mouse 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 mouse to, relative to the current position of the mouse. For example, `delta = Offset(100.px, -100.px) will move the mouse 100 pixels to the right and 100 pixels upwards.

durationMillis: Long = DefaultMouseGestureDurationMillis

The duration of the gesture. By default 300 milliseconds.

animateMoveTo

fun MouseInjectionScope.animateMoveTo(
    position: Offset,
    durationMillis: Long = DefaultMouseGestureDurationMillis
): Unit

Move the mouse from the current position to the given position, sending a stream of move events to get an animated path of durationMillis milliseconds. Move the mouse 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 mouse along a line:

import androidx.compose.ui.test.animateMoveTo
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performMouseInput

composeTestRule.onNodeWithTag("myComponent").performMouseInput {
    // 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
    moveTo(topRight)
    animateMoveTo(bottomLeft)
}
Parameters
position: Offset

The position where to move the mouse to, in the node's local coordinate system

durationMillis: Long = DefaultMouseGestureDurationMillis

The duration of the gesture. By default 300 milliseconds.

fun MouseInjectionScope.click(
    position: Offset = center,
    button: MouseButton = MouseButton.Primary
): Unit

Use button to click on position, or on the current mouse 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. There is a small 60ms delay between the press and release events to have a realistic simulation.

Parameters
position: Offset = center

The position where to click, in the node's local coordinate system. If omitted, the center of the node will be used. If unspecified, clicks on the current mouse position.

button: MouseButton = MouseButton.Primary

The button to click with. Uses the primary by default.

doubleClick

fun MouseInjectionScope.doubleClick(
    position: Offset = center,
    button: MouseButton = MouseButton.Primary
): Unit

Use button to double-click on position, or on the current mouse 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 center of the node will be used. If unspecified, clicks on the current mouse position.

button: MouseButton = MouseButton.Primary

The button to click with. Uses the primary by default.

dragAndDrop

fun MouseInjectionScope.dragAndDrop(
    start: Offset,
    end: Offset,
    button: MouseButton = MouseButton.Primary,
    durationMillis: Long = DefaultMouseGestureDurationMillis
): Unit

Use button to drag and drop something from start to end in durationMillis milliseconds. The mouse 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 mouse button and initiate the drag, in the node's local coordinate system.

end: Offset

The position where to release the primary mouse button and end the drag, in the node's local coordinate system.

button: MouseButton = MouseButton.Primary

The button to drag with. Uses the primary by default.

durationMillis: Long = DefaultMouseGestureDurationMillis

The duration of the gesture. By default 300 milliseconds.

longClick

fun MouseInjectionScope.longClick(
    position: Offset = center,
    button: MouseButton = MouseButton.Primary
): Unit

Use button to long-click on position, or on the current mouse 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 center of the node will be used. If unspecified, clicks on the current mouse position.

button: MouseButton = MouseButton.Primary

The button to click with. Uses the primary by default.

rightClick

fun MouseInjectionScope.rightClick(position: Offset = center): Unit

Secondary-click on position, or on the current mouse position if position is unspecified. While the secondary mouse button is not necessarily the right mouse button (e.g. on left-handed mice), 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 center of the node will be used. If unspecified, clicks on the current mouse position.

smoothScroll

fun MouseInjectionScope.smoothScroll(
    scrollAmount: Float,
    durationMillis: Long = DefaultMouseGestureDurationMillis,
    scrollWheel: ScrollWheel = ScrollWheel.Vertical
): Unit

Rotate the mouse's scrollWheel by the given scrollAmount. The total scroll delta is linearly smoothed out over a stream of scroll events between each scroll event.

Positive scrollAmount values correspond to scrolling forward (new content appears at the bottom of a column, or at the end of a row), negative values correspond to scrolling backward (new content appears at the top of a column, or at the start of a row).

Example of a horizontal smooth scroll:

import androidx.compose.ui.test.ScrollWheel
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performMouseInput
import androidx.compose.ui.test.smoothScroll

composeTestRule.onNodeWithTag("horizontalScrollable").performMouseInput {
    // Scroll forwards horizontally, which is rightwards
    // unless scroll direction is reversed
    smoothScroll(100f, durationMillis = 500L, ScrollWheel.Horizontal)
    // The 100f scroll delta is equally divided into smaller scrolls,
    // such that the time in between two scroll events is more or less
    // equal to the default time between events, 16ms.
}
Parameters
scrollAmount: Float

The total delta to scroll the scrollWheel by

durationMillis: Long = DefaultMouseGestureDurationMillis

The duration of the gesture. By default 300 milliseconds.

scrollWheel: ScrollWheel = ScrollWheel.Vertical

Which scroll wheel will be rotated. By default ScrollWheel.Vertical.

See also
scroll

tripleClick

fun MouseInjectionScope.tripleClick(
    position: Offset = center,
    button: MouseButton = MouseButton.Primary
): Unit

Use button to triple-click on position, or on the current mouse 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 center of the node will be used. If unspecified, clicks on the current mouse position.

button: MouseButton = MouseButton.Primary

The button to click with. Uses the primary by default.