PressInteraction.Cancel is sent on mouse press and drag outside surface
I'm using a MutableInteractionSource.interactions for a Button control, to know when it's focused/pressed/hovered.
I noticed that, when I press the button, a PressInteraction.Press is sent (as you would expect), but then if I drag outside of the button while keeping pressed, PressInteraction.Cancel is sent, and mouse press isn't being tracked further (no PressInteraction.Release is sent when releasing the mouse button).
Is it on purpose?
On Mac at least, it looks like the usual behavior (system apps) is that if you press a button, and then move wherever, as long as you come back inside the button bounds when you release the mouse, it will be counted as a press.
The way InteractionSource works right now though, it's not possible to have the desktop press behavior. It works however if I use .onPointerEvent(PointerEventType.Press) and .onPointerEvent(PointerEventType.Release).
I'm wondering if, InteractionSource and onPointerEvent are supposed to have the same behaviors?
Affected platforms
- Mac
Versions
- Compose jvm 1.6.2
- Kotlin version: 1.9.23
- OS version(s) (required for Desktop and iOS issues): Mac OS 14.4.1
- OS architecture (x86 or arm64): arm
- Device (model or simulator for iOS issues): mac book pro
- JDK (for desktop issues): JBR 17.0.10 or coretto 18, both exhibit this issue
To Reproduce You can use this snippet on desktop
The observed behaviour is the same on Android, so it's inherited from Jetpack Compose.
From InteractionSource docs:
A common use case is androidx.compose.foundation.indication, where androidx.compose.foundation.Indication implementations can subscribe to an InteractionSource to draw indication for different Interactions, such as a ripple effect for PressInteraction.Press and a state overlay for DragInteraction.Start.
So using InteractionSource is not the best way to derive the actions on buttons (clicked, double-clicked, etc). Listening to Pointer Events is a better choice for this.
JFYI: When dragging after PointerEventType.Press there is also PointerEventType.Exit event before PointerEventType.Release.
Considering the visual effects manifested by a Button when I interact with it, I assume the behaviour of InteractionSource is correct. If your use case requires not visual effects, but some other logic probably PointerEvents is better option.
Could you please share more details about your use case?
Could you please share more details about your use case?
The use case is to match native desktop apps behavior, when you press drag outside of a tappable control with a ripple and come back to it. Today, if you press and drag outisde of a button you get a PressInteraction.Release even though the mouse isn't released. But to match desktop behavior - at least on mac os, when you re-enter the button it should go back to pressed state, and when releasing over the button should send release event. I thought, PressInteraction is supposed to provide all events of the underlying platform, but right now it doesn't do that on desktop I would say. Like if you want to make a multiplatform Compose controls library, right now you would need some platform specific modifier and using onPointerEvent on desktop it seems.
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.