Loading packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt +5 −4 Original line number Diff line number Diff line Loading @@ -70,11 +70,11 @@ import com.airbnb.lottie.compose.rememberLottieDynamicProperties import com.airbnb.lottie.compose.rememberLottieDynamicProperty import com.android.compose.theme.LocalAndroidColorScheme import com.android.systemui.res.R import com.android.systemui.touchpad.tutorial.ui.gesture.BackGestureMonitor import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRESS import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGesture.BACK import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler data class TutorialScreenColors( Loading @@ -99,9 +99,10 @@ fun BackGestureTutorialScreen( val gestureHandler = remember(swipeDistanceThresholdPx) { TouchpadGestureHandler( BACK, BackGestureMonitor( swipeDistanceThresholdPx, onGestureStateChanged = { gestureState = it } gestureStateChangedCallback = { gestureState = it } ), ) } TouchpadGesturesHandlingBox(gestureHandler, gestureState) { Loading packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitor.kt +0 −17 Original line number Diff line number Diff line Loading @@ -22,18 +22,6 @@ import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRES import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED import kotlin.math.abs /** * Monitor for touchpad gestures that calls [gestureStateChangedCallback] when [GestureState] * changes. All tracked motion events should be passed to [processTouchpadEvent] */ interface TouchpadGestureMonitor { val gestureDistanceThresholdPx: Int val gestureStateChangedCallback: (GestureState) -> Unit fun processTouchpadEvent(event: MotionEvent) } class BackGestureMonitor( override val gestureDistanceThresholdPx: Int, override val gestureStateChangedCallback: (GestureState) -> Unit Loading Loading @@ -62,9 +50,4 @@ class BackGestureMonitor( } } } private fun isThreeFingerTouchpadSwipe(event: MotionEvent): Boolean { return event.classification == MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE && event.getAxisValue(MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT) == 3f } } packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandler.kt +2 −7 Original line number Diff line number Diff line Loading @@ -24,14 +24,9 @@ import android.view.MotionEvent * motion events passed to [onMotionEvent] and will filter touchpad events accordingly */ class TouchpadGestureHandler( touchpadGesture: TouchpadGesture, swipeDistanceThresholdPx: Int, onGestureStateChanged: (GestureState) -> Unit private val gestureMonitor: TouchpadGestureMonitor, ) { private val gestureRecognition = touchpadGesture.toMonitor(swipeDistanceThresholdPx, onStateChanged = onGestureStateChanged) fun onMotionEvent(event: MotionEvent): Boolean { // events from touchpad have SOURCE_MOUSE and not SOURCE_TOUCHPAD because of legacy reasons val isFromTouchpad = Loading @@ -41,7 +36,7 @@ class TouchpadGestureHandler( event.actionMasked == MotionEvent.ACTION_DOWN && event.isButtonPressed(MotionEvent.BUTTON_PRIMARY) return if (isFromTouchpad && !buttonClick) { gestureRecognition.processTouchpadEvent(event) gestureMonitor.processTouchpadEvent(event) true } else { false Loading packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGesture.kt→packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureMonitor.kt +40 −0 Original line number Diff line number Diff line Loading @@ -16,17 +16,25 @@ package com.android.systemui.touchpad.tutorial.ui.gesture enum class TouchpadGesture { BACK, HOME; fun toMonitor( swipeDistanceThresholdPx: Int, onStateChanged: (GestureState) -> Unit ): TouchpadGestureMonitor { return when (this) { BACK -> BackGestureMonitor(swipeDistanceThresholdPx, onStateChanged) else -> throw IllegalArgumentException("Not implemented yet") } import android.view.MotionEvent /** * Monitor for touchpad gestures that calls [gestureStateChangedCallback] when [GestureState] * changes. All tracked motion events should be passed to [processTouchpadEvent] */ interface TouchpadGestureMonitor { val gestureDistanceThresholdPx: Int val gestureStateChangedCallback: (GestureState) -> Unit fun processTouchpadEvent(event: MotionEvent) } fun isThreeFingerTouchpadSwipe(event: MotionEvent) = isNFingerTouchpadSwipe(event, fingerCount = 3) fun isFourFingerTouchpadSwipe(event: MotionEvent) = isNFingerTouchpadSwipe(event, fingerCount = 4) private fun isNFingerTouchpadSwipe(event: MotionEvent, fingerCount: Int): Boolean { return event.classification == MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE && event.getAxisValue(MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT) == fingerCount.toFloat() } packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt +20 −112 Original line number Diff line number Diff line Loading @@ -17,20 +17,13 @@ package com.android.systemui.touchpad.tutorial.ui.gesture import android.view.MotionEvent import android.view.MotionEvent.ACTION_DOWN import android.view.MotionEvent.ACTION_MOVE import android.view.MotionEvent.ACTION_POINTER_DOWN import android.view.MotionEvent.ACTION_POINTER_UP import android.view.MotionEvent.ACTION_UP import android.view.MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT import android.view.MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE import android.view.MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRESS import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.runner.RunWith Loading @@ -46,135 +39,50 @@ class BackGestureMonitorTest : SysuiTestCase() { gestureStateChangedCallback = { gestureState = it } ) companion object { const val SWIPE_DISTANCE = 100f } @Test fun triggersGestureFinishedForThreeFingerGestureRight() { val events = listOf( threeFingerEvent(ACTION_DOWN, x = 0f, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), threeFingerEvent(ACTION_MOVE, x = SWIPE_DISTANCE / 2, y = 0f), threeFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_UP, x = SWIPE_DISTANCE, y = 0f), ) events.forEach { gestureMonitor.processTouchpadEvent(it) } assertThat(gestureState).isEqualTo(FINISHED) assertStateAfterEvents(events = ThreeFingerGesture.swipeRight(), expectedState = FINISHED) } @Test fun triggersGestureFinishedForThreeFingerGestureLeft() { val events = listOf( threeFingerEvent(ACTION_DOWN, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_MOVE, x = SWIPE_DISTANCE / 2, y = 0f), threeFingerEvent(ACTION_POINTER_UP, x = 0f, y = 0f), threeFingerEvent(ACTION_POINTER_UP, x = 0f, y = 0f), threeFingerEvent(ACTION_UP, x = 0f, y = 0f), ) events.forEach { gestureMonitor.processTouchpadEvent(it) } assertThat(gestureState).isEqualTo(FINISHED) assertStateAfterEvents(events = ThreeFingerGesture.swipeLeft(), expectedState = FINISHED) } @Test fun triggersGestureProgressForThreeFingerGestureStarted() { val events = listOf( threeFingerEvent(ACTION_DOWN, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f), assertStateAfterEvents( events = ThreeFingerGesture.startEvents(x = 0f, y = 0f), expectedState = IN_PROGRESS ) events.forEach { gestureMonitor.processTouchpadEvent(it) } assertThat(gestureState).isEqualTo(IN_PROGRESS) } private fun threeFingerEvent(action: Int, x: Float, y: Float): MotionEvent { return motionEvent( action = action, x = x, y = y, classification = CLASSIFICATION_MULTI_FINGER_SWIPE, axisValues = mapOf(AXIS_GESTURE_SWIPE_FINGER_COUNT to 3f) @Test fun doesntTriggerGestureFinished_onGestureDistanceTooShort() { assertStateAfterEvents( events = ThreeFingerGesture.swipeLeft(distancePx = SWIPE_DISTANCE / 2), expectedState = NOT_STARTED ) } @Test fun doesntTriggerGestureFinished_onThreeFingersSwipeUp() { val events = listOf( threeFingerEvent(ACTION_DOWN, x = 0f, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), threeFingerEvent(ACTION_MOVE, x = 0f, y = SWIPE_DISTANCE / 2), threeFingerEvent(ACTION_POINTER_UP, x = 0f, y = SWIPE_DISTANCE), threeFingerEvent(ACTION_POINTER_UP, x = 0f, y = SWIPE_DISTANCE), threeFingerEvent(ACTION_UP, x = 0f, y = SWIPE_DISTANCE), ) events.forEach { gestureMonitor.processTouchpadEvent(it) } assertThat(gestureState).isEqualTo(NOT_STARTED) fun doesntTriggerGestureFinished_onThreeFingersSwipeInOtherDirections() { assertStateAfterEvents(events = ThreeFingerGesture.swipeUp(), expectedState = NOT_STARTED) assertStateAfterEvents(events = ThreeFingerGesture.swipeDown(), expectedState = NOT_STARTED) } @Test fun doesntTriggerGestureFinished_onTwoFingersSwipe() { fun twoFingerEvent(action: Int, x: Float, y: Float) = motionEvent( action = action, x = x, y = y, classification = CLASSIFICATION_TWO_FINGER_SWIPE, axisValues = mapOf(AXIS_GESTURE_SWIPE_FINGER_COUNT to 2f) ) val events = listOf( twoFingerEvent(ACTION_DOWN, x = 0f, y = 0f), twoFingerEvent(ACTION_MOVE, x = SWIPE_DISTANCE / 2, y = 0f), twoFingerEvent(ACTION_UP, x = SWIPE_DISTANCE, y = 0f), ) events.forEach { gestureMonitor.processTouchpadEvent(it) } assertThat(gestureState).isEqualTo(NOT_STARTED) assertStateAfterEvents(events = TwoFingerGesture.swipeRight(), expectedState = NOT_STARTED) } @Test fun doesntTriggerGestureFinished_onFourFingersSwipe() { fun fourFingerEvent(action: Int, x: Float, y: Float) = motionEvent( action = action, x = x, y = y, classification = CLASSIFICATION_MULTI_FINGER_SWIPE, axisValues = mapOf(AXIS_GESTURE_SWIPE_FINGER_COUNT to 4f) ) val events = listOf( fourFingerEvent(ACTION_DOWN, x = 0f, y = 0f), fourFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), fourFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), fourFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), fourFingerEvent(ACTION_MOVE, x = SWIPE_DISTANCE / 2, y = 0f), fourFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f), fourFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f), fourFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f), fourFingerEvent(ACTION_UP, x = SWIPE_DISTANCE, y = 0f), ) assertStateAfterEvents(events = FourFingerGesture.swipeRight(), expectedState = NOT_STARTED) } private fun assertStateAfterEvents(events: List<MotionEvent>, expectedState: GestureState) { events.forEach { gestureMonitor.processTouchpadEvent(it) } assertThat(gestureState).isEqualTo(NOT_STARTED) assertThat(gestureState).isEqualTo(expectedState) } } Loading
packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt +5 −4 Original line number Diff line number Diff line Loading @@ -70,11 +70,11 @@ import com.airbnb.lottie.compose.rememberLottieDynamicProperties import com.airbnb.lottie.compose.rememberLottieDynamicProperty import com.android.compose.theme.LocalAndroidColorScheme import com.android.systemui.res.R import com.android.systemui.touchpad.tutorial.ui.gesture.BackGestureMonitor import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRESS import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGesture.BACK import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler data class TutorialScreenColors( Loading @@ -99,9 +99,10 @@ fun BackGestureTutorialScreen( val gestureHandler = remember(swipeDistanceThresholdPx) { TouchpadGestureHandler( BACK, BackGestureMonitor( swipeDistanceThresholdPx, onGestureStateChanged = { gestureState = it } gestureStateChangedCallback = { gestureState = it } ), ) } TouchpadGesturesHandlingBox(gestureHandler, gestureState) { Loading
packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitor.kt +0 −17 Original line number Diff line number Diff line Loading @@ -22,18 +22,6 @@ import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRES import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED import kotlin.math.abs /** * Monitor for touchpad gestures that calls [gestureStateChangedCallback] when [GestureState] * changes. All tracked motion events should be passed to [processTouchpadEvent] */ interface TouchpadGestureMonitor { val gestureDistanceThresholdPx: Int val gestureStateChangedCallback: (GestureState) -> Unit fun processTouchpadEvent(event: MotionEvent) } class BackGestureMonitor( override val gestureDistanceThresholdPx: Int, override val gestureStateChangedCallback: (GestureState) -> Unit Loading Loading @@ -62,9 +50,4 @@ class BackGestureMonitor( } } } private fun isThreeFingerTouchpadSwipe(event: MotionEvent): Boolean { return event.classification == MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE && event.getAxisValue(MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT) == 3f } }
packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureHandler.kt +2 −7 Original line number Diff line number Diff line Loading @@ -24,14 +24,9 @@ import android.view.MotionEvent * motion events passed to [onMotionEvent] and will filter touchpad events accordingly */ class TouchpadGestureHandler( touchpadGesture: TouchpadGesture, swipeDistanceThresholdPx: Int, onGestureStateChanged: (GestureState) -> Unit private val gestureMonitor: TouchpadGestureMonitor, ) { private val gestureRecognition = touchpadGesture.toMonitor(swipeDistanceThresholdPx, onStateChanged = onGestureStateChanged) fun onMotionEvent(event: MotionEvent): Boolean { // events from touchpad have SOURCE_MOUSE and not SOURCE_TOUCHPAD because of legacy reasons val isFromTouchpad = Loading @@ -41,7 +36,7 @@ class TouchpadGestureHandler( event.actionMasked == MotionEvent.ACTION_DOWN && event.isButtonPressed(MotionEvent.BUTTON_PRIMARY) return if (isFromTouchpad && !buttonClick) { gestureRecognition.processTouchpadEvent(event) gestureMonitor.processTouchpadEvent(event) true } else { false Loading
packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGesture.kt→packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/TouchpadGestureMonitor.kt +40 −0 Original line number Diff line number Diff line Loading @@ -16,17 +16,25 @@ package com.android.systemui.touchpad.tutorial.ui.gesture enum class TouchpadGesture { BACK, HOME; fun toMonitor( swipeDistanceThresholdPx: Int, onStateChanged: (GestureState) -> Unit ): TouchpadGestureMonitor { return when (this) { BACK -> BackGestureMonitor(swipeDistanceThresholdPx, onStateChanged) else -> throw IllegalArgumentException("Not implemented yet") } import android.view.MotionEvent /** * Monitor for touchpad gestures that calls [gestureStateChangedCallback] when [GestureState] * changes. All tracked motion events should be passed to [processTouchpadEvent] */ interface TouchpadGestureMonitor { val gestureDistanceThresholdPx: Int val gestureStateChangedCallback: (GestureState) -> Unit fun processTouchpadEvent(event: MotionEvent) } fun isThreeFingerTouchpadSwipe(event: MotionEvent) = isNFingerTouchpadSwipe(event, fingerCount = 3) fun isFourFingerTouchpadSwipe(event: MotionEvent) = isNFingerTouchpadSwipe(event, fingerCount = 4) private fun isNFingerTouchpadSwipe(event: MotionEvent, fingerCount: Int): Boolean { return event.classification == MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE && event.getAxisValue(MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT) == fingerCount.toFloat() }
packages/SystemUI/tests/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureMonitorTest.kt +20 −112 Original line number Diff line number Diff line Loading @@ -17,20 +17,13 @@ package com.android.systemui.touchpad.tutorial.ui.gesture import android.view.MotionEvent import android.view.MotionEvent.ACTION_DOWN import android.view.MotionEvent.ACTION_MOVE import android.view.MotionEvent.ACTION_POINTER_DOWN import android.view.MotionEvent.ACTION_POINTER_UP import android.view.MotionEvent.ACTION_UP import android.view.MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT import android.view.MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE import android.view.MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.FINISHED import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.IN_PROGRESS import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NOT_STARTED import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.runner.RunWith Loading @@ -46,135 +39,50 @@ class BackGestureMonitorTest : SysuiTestCase() { gestureStateChangedCallback = { gestureState = it } ) companion object { const val SWIPE_DISTANCE = 100f } @Test fun triggersGestureFinishedForThreeFingerGestureRight() { val events = listOf( threeFingerEvent(ACTION_DOWN, x = 0f, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), threeFingerEvent(ACTION_MOVE, x = SWIPE_DISTANCE / 2, y = 0f), threeFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_UP, x = SWIPE_DISTANCE, y = 0f), ) events.forEach { gestureMonitor.processTouchpadEvent(it) } assertThat(gestureState).isEqualTo(FINISHED) assertStateAfterEvents(events = ThreeFingerGesture.swipeRight(), expectedState = FINISHED) } @Test fun triggersGestureFinishedForThreeFingerGestureLeft() { val events = listOf( threeFingerEvent(ACTION_DOWN, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_MOVE, x = SWIPE_DISTANCE / 2, y = 0f), threeFingerEvent(ACTION_POINTER_UP, x = 0f, y = 0f), threeFingerEvent(ACTION_POINTER_UP, x = 0f, y = 0f), threeFingerEvent(ACTION_UP, x = 0f, y = 0f), ) events.forEach { gestureMonitor.processTouchpadEvent(it) } assertThat(gestureState).isEqualTo(FINISHED) assertStateAfterEvents(events = ThreeFingerGesture.swipeLeft(), expectedState = FINISHED) } @Test fun triggersGestureProgressForThreeFingerGestureStarted() { val events = listOf( threeFingerEvent(ACTION_DOWN, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = SWIPE_DISTANCE, y = 0f), assertStateAfterEvents( events = ThreeFingerGesture.startEvents(x = 0f, y = 0f), expectedState = IN_PROGRESS ) events.forEach { gestureMonitor.processTouchpadEvent(it) } assertThat(gestureState).isEqualTo(IN_PROGRESS) } private fun threeFingerEvent(action: Int, x: Float, y: Float): MotionEvent { return motionEvent( action = action, x = x, y = y, classification = CLASSIFICATION_MULTI_FINGER_SWIPE, axisValues = mapOf(AXIS_GESTURE_SWIPE_FINGER_COUNT to 3f) @Test fun doesntTriggerGestureFinished_onGestureDistanceTooShort() { assertStateAfterEvents( events = ThreeFingerGesture.swipeLeft(distancePx = SWIPE_DISTANCE / 2), expectedState = NOT_STARTED ) } @Test fun doesntTriggerGestureFinished_onThreeFingersSwipeUp() { val events = listOf( threeFingerEvent(ACTION_DOWN, x = 0f, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), threeFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), threeFingerEvent(ACTION_MOVE, x = 0f, y = SWIPE_DISTANCE / 2), threeFingerEvent(ACTION_POINTER_UP, x = 0f, y = SWIPE_DISTANCE), threeFingerEvent(ACTION_POINTER_UP, x = 0f, y = SWIPE_DISTANCE), threeFingerEvent(ACTION_UP, x = 0f, y = SWIPE_DISTANCE), ) events.forEach { gestureMonitor.processTouchpadEvent(it) } assertThat(gestureState).isEqualTo(NOT_STARTED) fun doesntTriggerGestureFinished_onThreeFingersSwipeInOtherDirections() { assertStateAfterEvents(events = ThreeFingerGesture.swipeUp(), expectedState = NOT_STARTED) assertStateAfterEvents(events = ThreeFingerGesture.swipeDown(), expectedState = NOT_STARTED) } @Test fun doesntTriggerGestureFinished_onTwoFingersSwipe() { fun twoFingerEvent(action: Int, x: Float, y: Float) = motionEvent( action = action, x = x, y = y, classification = CLASSIFICATION_TWO_FINGER_SWIPE, axisValues = mapOf(AXIS_GESTURE_SWIPE_FINGER_COUNT to 2f) ) val events = listOf( twoFingerEvent(ACTION_DOWN, x = 0f, y = 0f), twoFingerEvent(ACTION_MOVE, x = SWIPE_DISTANCE / 2, y = 0f), twoFingerEvent(ACTION_UP, x = SWIPE_DISTANCE, y = 0f), ) events.forEach { gestureMonitor.processTouchpadEvent(it) } assertThat(gestureState).isEqualTo(NOT_STARTED) assertStateAfterEvents(events = TwoFingerGesture.swipeRight(), expectedState = NOT_STARTED) } @Test fun doesntTriggerGestureFinished_onFourFingersSwipe() { fun fourFingerEvent(action: Int, x: Float, y: Float) = motionEvent( action = action, x = x, y = y, classification = CLASSIFICATION_MULTI_FINGER_SWIPE, axisValues = mapOf(AXIS_GESTURE_SWIPE_FINGER_COUNT to 4f) ) val events = listOf( fourFingerEvent(ACTION_DOWN, x = 0f, y = 0f), fourFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), fourFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), fourFingerEvent(ACTION_POINTER_DOWN, x = 0f, y = 0f), fourFingerEvent(ACTION_MOVE, x = SWIPE_DISTANCE / 2, y = 0f), fourFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f), fourFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f), fourFingerEvent(ACTION_POINTER_UP, x = SWIPE_DISTANCE, y = 0f), fourFingerEvent(ACTION_UP, x = SWIPE_DISTANCE, y = 0f), ) assertStateAfterEvents(events = FourFingerGesture.swipeRight(), expectedState = NOT_STARTED) } private fun assertStateAfterEvents(events: List<MotionEvent>, expectedState: GestureState) { events.forEach { gestureMonitor.processTouchpadEvent(it) } assertThat(gestureState).isEqualTo(NOT_STARTED) assertThat(gestureState).isEqualTo(expectedState) } }