summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2025-01-08 07:07:30 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-01-08 07:07:30 -0800
commitbbb858a19d3382cb6efcd255269ff0e28cf4d2eb (patch)
tree403f97358168e9b508627013fabf391f1e47c0aa
parentaf24557c37410983e1cef138ca359e9f25541d78 (diff)
parent352d50b320a66385938188c98bc6682851d381d4 (diff)
Merge "Ignore nested scrolls from mouse wheel" into main
-rw-r--r--packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt34
-rw-r--r--packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt30
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 {