diff options
| author | 2025-01-08 07:07:30 -0800 | |
|---|---|---|
| committer | 2025-01-08 07:07:30 -0800 | |
| commit | bbb858a19d3382cb6efcd255269ff0e28cf4d2eb (patch) | |
| tree | 403f97358168e9b508627013fabf391f1e47c0aa | |
| parent | af24557c37410983e1cef138ca359e9f25541d78 (diff) | |
| parent | 352d50b320a66385938188c98bc6682851d381d4 (diff) | |
Merge "Ignore nested scrolls from mouse wheel" into main
| -rw-r--r-- | packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt | 34 | ||||
| -rw-r--r-- | packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt | 30 |
2 files changed, 61 insertions, 3 deletions
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt b/packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt index 5f1f588bb2b5..c7d6e8aed3b4 100644 --- a/packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt +++ b/packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt @@ -34,6 +34,7 @@ import androidx.compose.ui.input.nestedscroll.nestedScrollModifierNode import androidx.compose.ui.input.pointer.AwaitPointerEventScope import androidx.compose.ui.input.pointer.PointerEvent import androidx.compose.ui.input.pointer.PointerEventPass +import androidx.compose.ui.input.pointer.PointerEventType import androidx.compose.ui.input.pointer.PointerId import androidx.compose.ui.input.pointer.PointerInputChange import androidx.compose.ui.input.pointer.PointerInputScope @@ -168,6 +169,12 @@ private class NestedDraggableNode( CompositionLocalConsumerModifierNode, OrientationAware { private val nestedScrollDispatcher = NestedScrollDispatcher() + private var trackWheelScroll: SuspendingPointerInputModifierNode? = null + set(value) { + field?.let { undelegate(it) } + field = value?.also { delegate(it) } + } + private var trackDownPositionDelegate: SuspendingPointerInputModifierNode? = null set(value) { field?.let { undelegate(it) } @@ -189,6 +196,7 @@ private class NestedDraggableNode( * This is use to track the started position of a drag started on a nested scrollable. */ private var lastFirstDown: Offset? = null + private var lastEventWasScrollWheel: Boolean = false /** The pointers currently down, in order of which they were done and mapping to their type. */ private val pointersDown = linkedMapOf<PointerId, PointerType>() @@ -218,8 +226,11 @@ private class NestedDraggableNode( nestedScrollController?.ensureOnDragStoppedIsCalled() nestedScrollController = null - if (!enabled && trackDownPositionDelegate != null) { + if (!enabled && trackWheelScroll != null) { + check(trackDownPositionDelegate != null) check(detectDragsDelegate != null) + + trackWheelScroll = null trackDownPositionDelegate = null detectDragsDelegate = null } @@ -232,17 +243,22 @@ private class NestedDraggableNode( ) { if (!enabled) return - if (trackDownPositionDelegate == null) { + if (trackWheelScroll == null) { + check(trackDownPositionDelegate == null) check(detectDragsDelegate == null) + + trackWheelScroll = SuspendingPointerInputModifierNode { trackWheelScroll() } trackDownPositionDelegate = SuspendingPointerInputModifierNode { trackDownPosition() } detectDragsDelegate = SuspendingPointerInputModifierNode { detectDrags() } } + checkNotNull(trackWheelScroll).onPointerEvent(pointerEvent, pass, bounds) checkNotNull(trackDownPositionDelegate).onPointerEvent(pointerEvent, pass, bounds) checkNotNull(detectDragsDelegate).onPointerEvent(pointerEvent, pass, bounds) } override fun onCancelPointerInput() { + trackWheelScroll?.onCancelPointerInput() trackDownPositionDelegate?.onCancelPointerInput() detectDragsDelegate?.onCancelPointerInput() } @@ -457,6 +473,13 @@ private class NestedDraggableNode( * =============================== */ + private suspend fun PointerInputScope.trackWheelScroll() { + awaitEachGesture { + val event = awaitPointerEvent(pass = PointerEventPass.Initial) + lastEventWasScrollWheel = event.type == PointerEventType.Scroll + } + } + private suspend fun PointerInputScope.trackDownPosition() { awaitEachGesture { try { @@ -501,7 +524,12 @@ private class NestedDraggableNode( } val sign = offset.sign - if (nestedScrollController == null && draggable.shouldConsumeNestedScroll(sign)) { + if ( + nestedScrollController == null && + // TODO(b/388231324): Remove this. + !lastEventWasScrollWheel && + draggable.shouldConsumeNestedScroll(sign) + ) { val startedPosition = checkNotNull(lastFirstDown) { "lastFirstDown is not set" } // TODO(b/382665591): Ensure that there is at least one pointer down. diff --git a/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt b/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt index 7f70e97411f4..f9cf495d9d9f 100644 --- a/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt +++ b/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt @@ -18,6 +18,8 @@ package com.android.compose.gesture import androidx.compose.foundation.ScrollState import androidx.compose.foundation.gestures.Orientation +import androidx.compose.foundation.gestures.rememberScrollableState +import androidx.compose.foundation.gestures.scrollable import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize @@ -35,6 +37,7 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.pointer.PointerInputChange import androidx.compose.ui.input.pointer.PointerType import androidx.compose.ui.platform.LocalViewConfiguration +import androidx.compose.ui.test.ScrollWheel import androidx.compose.ui.test.junit4.ComposeContentTestRule import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onRoot @@ -710,6 +713,33 @@ class NestedDraggableTest(override val orientation: Orientation) : OrientationAw rule.onRoot().performTouchInput { down(center) } } + @Test + // TODO(b/388231324): Remove this. + fun nestedScrollWithMouseWheelIsIgnored() { + val draggable = TestDraggable() + val touchSlop = + rule.setContentWithTouchSlop { + Box( + Modifier.fillMaxSize() + .nestedDraggable(draggable, orientation) + .scrollable(rememberScrollableState { 0f }, orientation) + ) + } + + rule.onRoot().performMouseInput { + enter(center) + scroll( + touchSlop + 1f, + when (orientation) { + Orientation.Horizontal -> ScrollWheel.Horizontal + Orientation.Vertical -> ScrollWheel.Vertical + }, + ) + } + + assertThat(draggable.onDragStartedCalled).isFalse() + } + private fun ComposeContentTestRule.setContentWithTouchSlop( content: @Composable () -> Unit ): Float { |