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

Commit c1f1d85f authored by Prabir Pradhan's avatar Prabir Pradhan Committed by Cherrypicker Worker
Browse files

Support key gesture detection for stylus tail button in SysUI

Here, we add gesture detection logic for the stylus tail button in
SysUI.

The notes task will only be shown immediately on the UP event of the
first key press of a key gesture. A long press will not do anything for
now. If there is a multi-press (e.g. double-press, triple-press), only
the first press will react to the event.

Bug: 298056902
Test: manual with stylus
Test: atest NoteTaskInitializerTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:515a1625d4948f2fdb1ef6e966fe4469b0ed4d9f)
Merged-In: I90391f411d84ec5c749bb4d8cdefd7e610539e6e
Change-Id: I90391f411d84ec5c749bb4d8cdefd7e610539e6e
parent e0f1e64f
Loading
Loading
Loading
Loading
+35 −10
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.os.UserHandle
import android.view.KeyEvent
import android.view.KeyEvent.KEYCODE_N
import android.view.KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL
import android.view.ViewConfiguration
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.dagger.qualifiers.Background
@@ -128,15 +129,39 @@ constructor(
                controller.updateNoteTaskForCurrentUserAndManagedProfiles()
            }
        }
}

    /**
 * Maps a [KeyEvent] to a [NoteTaskEntryPoint]. If the [KeyEvent] does not represent a
 * [NoteTaskEntryPoint], returns null.
     * Tracks a [KeyEvent], and determines if it should trigger an action to show the note task.
     * Returns a [NoteTaskEntryPoint] if an action should be taken, and null otherwise.
     */
    private fun KeyEvent.toNoteTaskEntryPointOrNull(): NoteTaskEntryPoint? =
        when {
        keyCode == KEYCODE_STYLUS_BUTTON_TAIL && action == KeyEvent.ACTION_UP -> TAIL_BUTTON
            keyCode == KEYCODE_STYLUS_BUTTON_TAIL && isTailButtonNotesGesture() -> TAIL_BUTTON
            keyCode == KEYCODE_N && isMetaPressed && isCtrlPressed -> KEYBOARD_SHORTCUT
            else -> null
        }

    private var lastStylusButtonTailUpEventTime: Long = -MULTI_PRESS_TIMEOUT

    /**
     * Perform gesture detection for the stylus tail button to make sure we only show the note task
     * when there is a single press. Long presses and multi-presses are ignored for now.
     */
    private fun KeyEvent.isTailButtonNotesGesture(): Boolean {
        if (keyCode != KEYCODE_STYLUS_BUTTON_TAIL || action != KeyEvent.ACTION_UP) {
            return false
        }

        val isMultiPress = (downTime - lastStylusButtonTailUpEventTime) < MULTI_PRESS_TIMEOUT
        val isLongPress = (eventTime - downTime) >= LONG_PRESS_TIMEOUT
        lastStylusButtonTailUpEventTime = eventTime
        // For now, trigger action immediately on UP of a single press, without waiting for
        // the multi-press timeout to expire.
        return !isMultiPress && !isLongPress
    }

    companion object {
        val MULTI_PRESS_TIMEOUT = ViewConfiguration.getMultiPressTimeout().toLong()
        val LONG_PRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout().toLong()
    }
}
+38 −0
Original line number Diff line number Diff line
@@ -235,4 +235,42 @@ internal class NoteTaskInitializerTest : SysuiTestCase() {

        verify(controller).showNoteTask(any())
    }

    @Test
    fun tailButtonGestureDetection_doublePress_shouldNotShowNoteTaskTwice() {
        val underTest = createUnderTest(isEnabled = true, bubbles = bubbles)
        underTest.initialize()
        val callback = withArgCaptor { verify(commandQueue).addCallback(capture()) }

        callback.handleSystemKey(
            createKeyEvent(ACTION_DOWN, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 0, eventTime = 0)
        )
        callback.handleSystemKey(
            createKeyEvent(ACTION_UP, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 0, eventTime = 50)
        )
        callback.handleSystemKey(
            createKeyEvent(ACTION_DOWN, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 99, eventTime = 99)
        )
        callback.handleSystemKey(
            createKeyEvent(ACTION_UP, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 99, eventTime = 150)
        )

        verify(controller, times(1)).showNoteTask(any())
    }

    @Test
    fun tailButtonGestureDetection_longPress_shouldNotShowNoteTask() {
        val underTest = createUnderTest(isEnabled = true, bubbles = bubbles)
        underTest.initialize()
        val callback = withArgCaptor { verify(commandQueue).addCallback(capture()) }

        callback.handleSystemKey(
            createKeyEvent(ACTION_DOWN, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 0, eventTime = 0)
        )
        callback.handleSystemKey(
            createKeyEvent(ACTION_UP, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 0, eventTime = 1000)
        )

        verify(controller, never()).showNoteTask(any())
    }
}