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

Commit d00d46e2 authored by Michal Brzezinski's avatar Michal Brzezinski
Browse files

1/n refactoring TouchpadGestureHandler

TouchpadGestureHandler is now simlpified to TouchpadEventsFilter and it's easier to use, without a need to create wrapper object which needs to be recreated for every change in recognizer

Bug: 384509663
Test: TouchpadEventsFilterTest
Flag: com.android.systemui.shared.new_touchpad_gestures_tutorial
Change-Id: Iacf6797caa4613f960c4bd1c5d39201bb03c50fe
parent 5e1de3e7
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ class EasterEggGestureRecognizerTest : SysuiTestCase() {

    private var triggered = false
    private val gestureRecognizer = EasterEggGestureRecognizer()
    private val handler = TouchpadGestureHandler(gestureRecognizer)

    @Before
    fun setup() {
@@ -99,7 +98,7 @@ class EasterEggGestureRecognizerTest : SysuiTestCase() {
    }

    private fun assertStateAfterEvents(events: List<MotionEvent>, wasTriggered: Boolean) {
        events.forEach { handler.onMotionEvent(it) }
        events.forEach { gestureRecognizer.accept(it) }
        assertThat(triggered).isEqualTo(wasTriggered)
    }

+5 −21
Original line number Diff line number Diff line
@@ -33,12 +33,11 @@ import org.junit.runner.RunWith

@SmallTest
@RunWith(AndroidJUnit4::class)
class TouchpadGestureHandlerTest : SysuiTestCase() {
class TouchpadEventsFilterTest : SysuiTestCase() {

    private var gestureState: GestureState = GestureState.NotStarted
    private val gestureRecognizer =
        BackGestureRecognizer(gestureDistanceThresholdPx = SWIPE_DISTANCE.toInt())
    private val handler = TouchpadGestureHandler(gestureRecognizer)

    @Before
    fun before() {
@@ -48,21 +47,21 @@ class TouchpadGestureHandlerTest : SysuiTestCase() {
    @Test
    fun handlesEventsFromTouchpad() {
        val event = downEvent(source = SOURCE_MOUSE, toolType = TOOL_TYPE_FINGER)
        val eventHandled = handler.onMotionEvent(event)
        val eventHandled = gestureRecognizer.handleTouchpadMotionEvent(event)
        assertThat(eventHandled).isTrue()
    }

    @Test
    fun ignoresEventsFromMouse() {
        val event = downEvent(source = SOURCE_MOUSE, toolType = TOOL_TYPE_MOUSE)
        val eventHandled = handler.onMotionEvent(event)
        val eventHandled = gestureRecognizer.handleTouchpadMotionEvent(event)
        assertThat(eventHandled).isFalse()
    }

    @Test
    fun ignoresEventsFromTouch() {
        val event = downEvent(source = SOURCE_TOUCHSCREEN, toolType = TOOL_TYPE_FINGER)
        val eventHandled = handler.onMotionEvent(event)
        val eventHandled = gestureRecognizer.handleTouchpadMotionEvent(event)
        assertThat(eventHandled).isFalse()
    }

@@ -70,25 +69,10 @@ class TouchpadGestureHandlerTest : SysuiTestCase() {
    fun ignoresButtonClicksFromTouchpad() {
        val event = downEvent(source = SOURCE_MOUSE, toolType = TOOL_TYPE_FINGER)
        event.buttonState = MotionEvent.BUTTON_PRIMARY
        val eventHandled = handler.onMotionEvent(event)
        val eventHandled = gestureRecognizer.handleTouchpadMotionEvent(event)
        assertThat(eventHandled).isFalse()
    }

    private fun downEvent(source: Int, toolType: Int) =
        motionEvent(action = ACTION_DOWN, x = 0f, y = 0f, source = source, toolType = toolType)

    @Test
    fun triggersGestureDoneForThreeFingerGesture() {
        backGestureEvents().forEach { handler.onMotionEvent(it) }

        assertThat(gestureState).isEqualTo(GestureState.Finished)
    }

    private fun backGestureEvents(): List<MotionEvent> {
        return ThreeFingerGesture.eventsForFullGesture {
            move(deltaX = SWIPE_DISTANCE / 4)
            move(deltaX = SWIPE_DISTANCE / 2)
            move(deltaX = SWIPE_DISTANCE)
        }
    }
}
+16 −16
Original line number Diff line number Diff line
@@ -18,27 +18,27 @@ package com.android.systemui.touchpad.tutorial.ui.gesture

import android.view.InputDevice
import android.view.MotionEvent
import java.util.function.Consumer
import android.view.MotionEvent.ACTION_DOWN
import android.view.MotionEvent.BUTTON_PRIMARY

/**
 * Allows listening to touchpadGesture and calling onDone when gesture was triggered. Can have all
 * motion events passed to [onMotionEvent] and will filter touchpad events accordingly
 */
class TouchpadGestureHandler(private vararg val eventConsumers: Consumer<MotionEvent>) {
object TouchpadEventsFilter {

    fun onMotionEvent(event: MotionEvent): Boolean {
    fun isTouchpadAndNonClickEvent(event: MotionEvent): Boolean {
        // events from touchpad have SOURCE_MOUSE and not SOURCE_TOUCHPAD because of legacy reasons
        val isFromTouchpad =
            event.isFromSource(InputDevice.SOURCE_MOUSE) &&
                event.getToolType(0) == MotionEvent.TOOL_TYPE_FINGER
        val buttonClick =
            event.actionMasked == MotionEvent.ACTION_DOWN &&
                event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)
        return if (isFromTouchpad && !buttonClick) {
            eventConsumers.forEach { it.accept(event) }
        val isButtonClicked =
            event.actionMasked == ACTION_DOWN && event.isButtonPressed(BUTTON_PRIMARY)
        return isFromTouchpad && !isButtonClicked
    }
}

fun GestureRecognizer.handleTouchpadMotionEvent(event: MotionEvent): Boolean {
    return if (TouchpadEventsFilter.isTouchpadAndNonClickEvent(event)) {
        this.accept(event)
        true
    } else {
        false
    }
}
}
+5 −6
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ import com.android.systemui.touchpad.tutorial.ui.gesture.GestureDirection
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.InProgress
import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler
import com.android.systemui.touchpad.tutorial.ui.gesture.handleTouchpadMotionEvent
import com.android.systemui.util.kotlin.pairwiseBy
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -38,7 +38,7 @@ class BackGestureScreenViewModel
@Inject
constructor(configurationInteractor: ConfigurationInteractor) : TouchpadTutorialScreenViewModel {

    private var handler: TouchpadGestureHandler? = null
    private var recognizer: BackGestureRecognizer? = null

    private val distanceThreshold: Flow<Int> =
        configurationInteractor
@@ -49,16 +49,15 @@ constructor(configurationInteractor: ConfigurationInteractor) : TouchpadTutorial
    override val gestureUiState: Flow<GestureUiState> =
        distanceThreshold
            .flatMapLatest {
                val recognizer = BackGestureRecognizer(gestureDistanceThresholdPx = it)
                handler = TouchpadGestureHandler(recognizer)
                GestureFlowAdapter(recognizer).gestureStateAsFlow
                recognizer = BackGestureRecognizer(gestureDistanceThresholdPx = it)
                GestureFlowAdapter(recognizer!!).gestureStateAsFlow
            }
            .pairwiseBy(GestureState.NotStarted) { previous, current ->
                toGestureUiState(current, previous)
            }

    override fun handleEvent(event: MotionEvent): Boolean {
        return handler?.onMotionEvent(event) ?: false
        return recognizer?.handleTouchpadMotionEvent(event) ?: false
    }

    private fun toGestureUiState(current: GestureState, previous: GestureState): GestureUiState {
+3 −5
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ import android.view.MotionEvent
import com.android.systemui.touchpad.tutorial.ui.gesture.EasterEggGestureRecognizer
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler
import com.android.systemui.touchpad.tutorial.ui.gesture.handleTouchpadMotionEvent
import java.util.function.Consumer
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.filter
@@ -30,11 +30,9 @@ import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.receiveAsFlow

class EasterEggGestureViewModel(
    gestureRecognizer: EasterEggGestureRecognizer = EasterEggGestureRecognizer()
    private val gestureRecognizer: EasterEggGestureRecognizer = EasterEggGestureRecognizer()
) : Consumer<MotionEvent> {

    private val handler = TouchpadGestureHandler(gestureRecognizer)

    private val gestureDone =
        GestureFlowAdapter(gestureRecognizer).gestureStateAsFlow.filter {
            it == GestureState.Finished
@@ -56,7 +54,7 @@ class EasterEggGestureViewModel(
            .onStart { emit(false) }

    override fun accept(event: MotionEvent) {
        handler.onMotionEvent(event)
        gestureRecognizer.handleTouchpadMotionEvent(event)
    }

    fun onEasterEggFinished() {
Loading