Mouse event listeners
Edit pageLast modified: 01 October 2024In your desktop project, you can listen to various mouse events, like clicking, moving, scrolling, or entering and exiting the input region.
Click listeners
Click listeners are available in both Compose Multiplatform for Android and Compose Multiplatform for desktop, so your code will work on both platforms. For example, here is how to set up simple click listeners with the onClick
, onDoubleClick
, and onLongClick
modifiers:
Box(modifier = Modifier.combinedClickable(onClick = { text =
{...}

The combinedClickable
modifier supports only the primary button (left mouse button) and touch events. If you need to handle buttons differently, see the Modifier.onClick
section.
Move listeners
warning
The
onPointerEvent
modifier is Experimental. Opt-in is required (see details below), and you should use it only for evaluation purposes. For a Stable API, seeModifier.pointerInput
.
To create a pointer move listener that changes the background color of the window according to the mouse pointer position, add the following code:
Box(modifier = Modifier.onPointerEvent(PointerEventType.Move) { color =
{...}

Enter listeners
warning
The
onPointerEvent
modifier is Experimental. Opt-in is required (see details below), and you should use it only for evaluation purposes. For a Stable API, seeModifier.pointerInput
.
Compose Multiplatform for desktop supports handlers of the pointer entering and exiting the input region. For example, the following code will change the font style of a line on hover:
Text(modifier = Modifier.onPointerEvent(PointerEventType.Enter) { active =
{...}

Scroll listeners
warning
The
onPointerEvent
modifier is Experimental. Opt-in is required (see details below), and you should use it only for evaluation purposes. For a Stable API, seeModifier.pointerInput
.
The following code sample demonstrates how you can increase or decrease the displayed number depending on the mouse scroll direction:
Box(Modifier.onPointerEvent(PointerEventType.Scroll) { number +=
{...}

Experimental onClick handlers
warning
The
onClick
modifier is Experimental and supported in desktop projects only. Opt-in is required (see details below), and you should use it only for evaluation purposes.
Modifier.onClick
provides independent callbacks for clicks, double clicks, and long clicks. It handles clicks originating from pointer events only and doesn't handle accessibility click
events out of the box.
You can configure each onClick
to target specific pointer events using matcher: PointerMatcher
and keyboardModifiers: PointerKeyboardModifiers.() -> Boolean
:
matcher
allows you to choose which mouse button should trigger a click event.keyboardModifiers
allows you to filter pointer events that have specified key pressed.
You can also create a chain of multiple onClick
modifiers to handle different clicks with different conditions of the matcher and keyboard modifiers. Unlike clickable
, onClick
doesn't have default Modifier.indication
and Modifier.semantics
, and it doesn't trigger a click event when you press Enter
. If necessary, add these modifiers separately. You should declare the most generic (with the least number of conditions) onClick
handlers before others to ensure correct propagation of events.
Box(modifier = Modifier.onClick {
{...}

Experimental onDrag modifier
warning
The
onDrag
modifier is Experimental and supported in desktop projects only. Opt-in is required (see details below), and you should use it only for evaluation purposes.
With Modifier.onDrag
, you can specify the pointer that should trigger the drag via matcher: PointerMatcher
. Similar to onClick
, you can chain together many onDrag
modifiers.
You can also check the state of keyboard modifiers via LocalWindowInfo.current.keyboardModifier
for cases when keys can alter the behavior of the drag. For example, when you move an item with a simple drag, and copy/paste an item with a drag and Ctrl
pressed.
The following code sample demonstrates how to handle drag events triggered by left and right mouse buttons, and with the keyboard involved:
Box(modifier = Modifier.onDrag {
{...}

There is also a non-modifier way to handle drags using suspend fun PointerInputScope.detectDragGestures
:
Modifier.pointerInput(Unit) { detectDragGestures(matcher = PointerMatcher.Primary)
{...}
Accessing raw AWT events with Swing interoperability
warning
The
onPointerEvent
modifier is Experimental. Opt-in is required (see details below), and you should use it only for evaluation purposes. For a Stable API, seeModifier.pointerInput
.
Compose Multiplatform for desktop uses Swing under the hood and allows to access raw AWT events:
Box(Modifier.onPointerEvent(PointerEventType.Press) { text =
{...}

Listening for raw events in common code via pointerInput
In the snippets above we use the Modifier.onPointerEvent
function, which is a helper function that subscribes to a type of pointer events. It is a new and short variant of the Modifier.pointerInput
function. It is currently experimental and desktop-only, so you can't use it in common code.
If you need to subscribe to events in common code, or if you need a stable API, you can use the Modifier.pointerInput
function:
Column(Modifier.pointerInput(Unit) { awaitPointerEventScope {
{...}

What's next
Explore the tutorials about other desktop components.
Thanks for your feedback!