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

Commit 9c60e917 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

Add NestedDraggable.shouldStartDrag()

This CL adds an additional callback to NestedDraggable
shouldStartDrag(), which is necessary to be feature complete with
MultiPointerDraggable and that will be used by Communal to make sure
that STL does not consume vertical drags.

Bug: 378470603
Test: atest NestedDraggableTest
Flag: EXEMPT new API not used anywhere yet
Change-Id: Id950af783e7984841bab4f081a97943f4848b79c
parent 2bc40f19
Loading
Loading
Loading
Loading
+30 −3
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode
import androidx.compose.ui.input.pointer.changedToDownIgnoreConsumed
import androidx.compose.ui.input.pointer.changedToUpIgnoreConsumed
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.input.pointer.positionChangeIgnoreConsumed
import androidx.compose.ui.input.pointer.util.VelocityTracker
import androidx.compose.ui.input.pointer.util.addPointerInputChange
import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
@@ -66,6 +67,16 @@ import kotlinx.coroutines.launch
 * scrollable.
 */
interface NestedDraggable {
    /**
     * Return whether we should start a drag given the pointer [change].
     *
     * This is called when the touch slop is reached. If this returns `true`, then the [change] will
     * be consumed and [onDragStarted] will be called. If this returns `false`, then the current
     * touch slop detection will be reset and restarted at the current
     * [change position][PointerInputChange.position].
     */
    fun shouldStartDrag(change: PointerInputChange): Boolean = true

    /**
     * Called when a drag is started in the given [position] (*before* dragging the touch slop) and
     * in the direction given by [sign], with the given number of [pointersDown] when the touch slop
@@ -248,10 +259,16 @@ private class NestedDraggableNode(

            var overSlop = 0f
            val onTouchSlopReached = { change: PointerInputChange, over: Float ->
                if (draggable.shouldStartDrag(change)) {
                    change.consume()
                    overSlop = over
                }

                // If shouldStartDrag() returned false, then we didn't consume the event and
                // awaitTouchSlopOrCancellation() will reset the touch slop detector so that the
                // user has to drag by at least the touch slop again.
            }

            suspend fun AwaitPointerEventScope.awaitTouchSlopOrCancellation(
                pointerId: PointerId
            ): PointerInputChange? {
@@ -288,7 +305,17 @@ private class NestedDraggableNode(

            if (drag != null) {
                velocityTracker.resetTracking()
                val sign = (drag.position - down.position).toFloat().sign
                val sign = drag.positionChangeIgnoreConsumed().toFloat().sign
                check(sign != 0f) {
                    buildString {
                        append("sign is equal to 0 ")
                        append("touchSlop ${currentValueOf(LocalViewConfiguration).touchSlop} ")
                        append("down.position ${down.position} ")
                        append("drag.position ${drag.position} ")
                        append("drag.previousPosition ${drag.previousPosition}")
                    }
                }

                check(pointersDownCount > 0) { "pointersDownCount is equal to $pointersDownCount" }
                val wrappedController =
                    WrappedController(
+28 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.input.pointer.PointerInputChange
import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.junit4.createComposeRule
@@ -457,6 +458,30 @@ class NestedDraggableTest(override val orientation: Orientation) : OrientationAw
        assertThat(draggable.onDragStartedPointersDown).isEqualTo(6)
    }

    @Test
    fun shouldStartDrag() {
        val draggable = TestDraggable()
        val touchSlop =
            rule.setContentWithTouchSlop {
                Box(Modifier.fillMaxSize().nestedDraggable(draggable, orientation))
            }

        // Drag in one direction.
        draggable.shouldStartDrag = false
        rule.onRoot().performTouchInput {
            down(center)
            moveBy(touchSlop.toOffset())
        }
        assertThat(draggable.onDragStartedCalled).isFalse()

        // Drag in the other direction.
        draggable.shouldStartDrag = true
        rule.onRoot().performTouchInput { moveBy(-touchSlop.toOffset()) }
        assertThat(draggable.onDragStartedCalled).isTrue()
        assertThat(draggable.onDragStartedSign).isEqualTo(-1f)
        assertThat(draggable.onDragDelta).isEqualTo(0f)
    }

    private fun ComposeContentTestRule.setContentWithTouchSlop(
        content: @Composable () -> Unit
    ): Float {
@@ -481,6 +506,7 @@ class NestedDraggableTest(override val orientation: Orientation) : OrientationAw
        private val onDragStopped: suspend (Float) -> Float = { it },
        private val shouldConsumeNestedScroll: (Float) -> Boolean = { true },
    ) : NestedDraggable {
        var shouldStartDrag = true
        var onDragStartedCalled = false
        var onDragCalled = false
        var onDragStoppedCalled = false
@@ -490,6 +516,8 @@ class NestedDraggableTest(override val orientation: Orientation) : OrientationAw
        var onDragStartedPointersDown = 0
        var onDragDelta = 0f

        override fun shouldStartDrag(change: PointerInputChange): Boolean = shouldStartDrag

        override fun onDragStarted(
            position: Offset,
            sign: Float,