Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f7b4a5b8 authored by omarmt's avatar omarmt
Browse files

multiPointerDraggable shouldn't start drag gesture with consumed events

ag/28051296 calculates startedPosition when at least one pointer is
present on the screen.
Previously, we used awaitConsumableEvent to determine the starting
position.

The drag gesture might begin with start followed by an immediate
cancellation if the initial position turns out to be a consumed event.

This behavior is now fixed with this CL, as onDragStart requires that
the event is consumable.

Test: atest MultiPointerDraggableTest
Bug: 330200163
Flag: com.android.systemui.scene_container
Change-Id: If9f58c3774bdc26c0dae104a87d26b0541b4e4a0
parent 8f453fe0
Loading
Loading
Loading
Loading
+4 −6
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ import androidx.compose.ui.input.pointer.PointerId
import androidx.compose.ui.input.pointer.PointerInputChange
import androidx.compose.ui.input.pointer.PointerInputScope
import androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode
import androidx.compose.ui.input.pointer.changedToDownIgnoreConsumed
import androidx.compose.ui.input.pointer.changedToDown
import androidx.compose.ui.input.pointer.changedToUpIgnoreConsumed
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.input.pointer.positionChangeIgnoreConsumed
@@ -415,12 +415,10 @@ internal class MultiPointerDraggableNode(
        fun canBeConsumed(changes: List<PointerInputChange>): Boolean {
            // At least one pointer down AND
            return changes.fastAny { it.pressed } &&
                // All pointers must be:
                // All pointers must be either:
                changes.fastAll {
                    // A) recently pressed: even if the event has already been consumed, we can
                    // still use the recently added finger event to determine whether to initiate
                    // dragging the scene.
                    it.changedToDownIgnoreConsumed() ||
                    // A) unconsumed AND recently pressed
                    it.changedToDown() ||
                        // B) unconsumed AND in a new position (on the current axis)
                        it.positionChange().toFloat() != 0f
                }
+10 −8
Original line number Diff line number Diff line
@@ -128,7 +128,7 @@ class MultiPointerDraggableTest {
        var started = false
        var dragged = false
        var stopped = false
        var consumeBeforeMultiPointerDraggable = false
        var consumedByDescendant = false

        var touchSlop = 0f
        rule.setContent {
@@ -138,6 +138,7 @@ class MultiPointerDraggableTest {
                    .multiPointerDraggable(
                        orientation = Orientation.Vertical,
                        enabled = { true },
                        // We want to start a drag gesture immediately
                        startDragImmediately = { true },
                        onDragStarted = { _, _, _ ->
                            started = true
@@ -157,7 +158,7 @@ class MultiPointerDraggableTest {
                            awaitPointerEventScope {
                                while (isActive) {
                                    val change = awaitPointerEvent().changes.first()
                                    if (consumeBeforeMultiPointerDraggable) {
                                    if (consumedByDescendant) {
                                        change.consume()
                                    }
                                }
@@ -168,18 +169,19 @@ class MultiPointerDraggableTest {
        }

        // The first part of the gesture is consumed by our descendant
        consumeBeforeMultiPointerDraggable = true
        consumedByDescendant = true
        rule.onRoot().performTouchInput {
            down(middle)
            moveBy(Offset(0f, touchSlop))
        }

        started = false
        dragged = false
        stopped = false
        // The events were consumed by our descendant, we should not start a drag gesture.
        assertThat(started).isFalse()
        assertThat(dragged).isFalse()
        assertThat(stopped).isFalse()

        // The next events could be consumed by us
        consumeBeforeMultiPointerDraggable = false
        consumedByDescendant = false
        rule.onRoot().performTouchInput {
            // The pointer is moved to a new position without reporting it
            updatePointerBy(0, Offset(0f, touchSlop))
@@ -188,7 +190,7 @@ class MultiPointerDraggableTest {
            up()
        }

        // This event should not be used to start a drag gesture
        // The "up" event should not be used to start a drag gesture
        assertThat(started).isFalse()
        assertThat(dragged).isFalse()
        assertThat(stopped).isFalse()