https://kotlinlang.org logo
Title
c

Casey Brooks

01/14/2021, 5:02 PM
Is it possible to detect simple mouse up/down events? I’m wanting to implement a kind of arbitrary drag-and-drop across a window. Items are being positioned globally within a
Box
using
pointerMoveFilter
, but I need to detect down events to focus a single item, and up to drop. However, it seems like using
Modifier.pointerInput { handlePointerInput { ... } }
can detect up/down events, but move events are handled by the child relative to the child, and the parent
Box
never receives those move events until I drop the child
For more context: this video uses a simple
Modifier.clickable { }
to “pick up” and “drop” a piece, which then tracks with the window mouse position properly
This clip shows trying to set the piece’s offset using the coordinates from the child’s
handlePointerInput
, which might work if I could figure out how to calculate its new absolute position. But also notice how the global offset stops updating when I have the child picked up and dragging
i

Igor Demin

01/14/2021, 8:07 PM
parent 
Box
 never receives those move events until I drop the child
When we click on some component it becomes a target of all mouse events including events outside the component (until we release the button). You need to apply the modifier directly to the child, not the parent box. There is also already a suitable modifier for dragging (rawDragGestureFilter):
import androidx.compose.desktop.Window
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.gesture.DragObserver
import androidx.compose.ui.gesture.rawDragGestureFilter
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round

fun main() = Window {
    var offset by remember { mutableStateOf(Offset.Zero) }

    val dragObserver = object : DragObserver {
        override fun onDrag(dragDistance: Offset): Offset {
            offset += dragDistance
            return dragDistance
        }
    }

    Box(Modifier.fillMaxSize()) {
        Box(
            Modifier.offset { offset.round() }
                .size(100.dp)
                .background(Color.Red)
                .rawDragGestureFilter(dragObserver)
        )
    }
}
c

Casey Brooks

01/14/2021, 10:02 PM
That totally makes sense that only the focused node receives events. And your snippet is working perfectly, thank you so much!