diff --git a/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt b/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt index bc42fa7e4..5d8ad8e39 100644 --- a/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt +++ b/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt @@ -2394,6 +2394,7 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback { gestureConfig = com.droiddeck.launcher.input.GesturePrefs.read(this, gestureGame) gestureTouchStreamGate.reset() if (::touchscreenGestures.isInitialized) touchscreenGestures.configure(gestureConfig) + if (::directTouchHold.isInitialized) directTouchHold.configure(gestureConfig) gesturePointerReady = false recognizedGesture = null } diff --git a/app/src/main/java/com/droiddeck/launcher/input/DirectTouchHold.kt b/app/src/main/java/com/droiddeck/launcher/input/DirectTouchHold.kt index 318941c71..8bf852fdb 100644 --- a/app/src/main/java/com/droiddeck/launcher/input/DirectTouchHold.kt +++ b/app/src/main/java/com/droiddeck/launcher/input/DirectTouchHold.kt @@ -15,6 +15,7 @@ class DirectTouchHold( private var y = 0f private var consumed = false private var pressed = false + private var delayMs = 0L private val release = Runnable { if (pressed) listener.onButton(PointerGestures.BTN_RIGHT, false, x, y) pressed = false @@ -28,6 +29,11 @@ class DirectTouchHold( handler.postDelayed(release, 50L) } + fun configure(config: TouchGestureConfig) { + cancel() + delayMs = if (config.longPressEnabled) config.longPressDelay.toLong().coerceAtLeast(1L) else 0L + } + fun cancel() { handler.removeCallbacks(hold) handler.removeCallbacks(release) @@ -40,7 +46,7 @@ class DirectTouchHold( MotionEvent.ACTION_DOWN -> { cancel() x = event.x; y = event.y - handler.postDelayed(hold, 500L) + if (delayMs > 0L) handler.postDelayed(hold, delayMs) } MotionEvent.ACTION_MOVE -> if (event.pointerCount > 1 || abs(event.x - x) > slopPx || abs(event.y - y) > slopPx) handler.removeCallbacks(hold) diff --git a/app/src/test/java/com/droiddeck/launcher/input/DirectTouchHoldTest.kt b/app/src/test/java/com/droiddeck/launcher/input/DirectTouchHoldTest.kt index d7dd5307a..513ee330f 100644 --- a/app/src/test/java/com/droiddeck/launcher/input/DirectTouchHoldTest.kt +++ b/app/src/test/java/com/droiddeck/launcher/input/DirectTouchHoldTest.kt @@ -22,7 +22,7 @@ class DirectTouchHoldTest { } override fun onWheel(steps: Int) {} override fun onLongPress() {} - }) { events += "cancel touch" } + }) { events += "cancel touch" }.also { it.configure(TouchGestureConfig(longPressEnabled = true, longPressDelay = 500)) } @Test fun holdReleasesRawTouchBeforeClickAndConsumesTheLift() { assertFalse(touch(MotionEvent.ACTION_DOWN)) @@ -35,6 +35,25 @@ class DirectTouchHoldTest { hold.cancel() } + @Test fun stillHoldKeepsTheTouchWhenLongPressIsOff() { + hold.configure(TouchGestureConfig()) + assertFalse(touch(MotionEvent.ACTION_DOWN)) + advance(2000) + assertFalse(touch(MotionEvent.ACTION_MOVE)) + assertFalse(touch(MotionEvent.ACTION_UP)) + assertTrue(events.isEmpty()) + } + + @Test fun longPressFollowsTheConfiguredDelay() { + hold.configure(TouchGestureConfig(longPressEnabled = true, longPressDelay = 800)) + touch(MotionEvent.ACTION_DOWN) + advance(700) + assertTrue(events.isEmpty()) + advance(100) + assertEquals(listOf("cancel touch", "true at 40.0,30.0"), events) + hold.cancel() + } + @Test fun tapDragSecondFingerAndCancellationDoNotRightClick() { for (action in listOf(MotionEvent.ACTION_UP, MotionEvent.ACTION_MOVE, MotionEvent.ACTION_POINTER_DOWN, MotionEvent.ACTION_CANCEL)) { diff --git a/app/src/test/java/com/droiddeck/launcher/input/SessionGestureRoutingTest.kt b/app/src/test/java/com/droiddeck/launcher/input/SessionGestureRoutingTest.kt index 7b2a55e2e..7b33c7170 100644 --- a/app/src/test/java/com/droiddeck/launcher/input/SessionGestureRoutingTest.kt +++ b/app/src/test/java/com/droiddeck/launcher/input/SessionGestureRoutingTest.kt @@ -172,7 +172,7 @@ class SessionGestureRoutingTest { val event = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 400f, 300f, 0) try { assertTrue(activity.onTouchEvent(event)) } finally { event.recycle() } val gestureMode = mode == SessionPrefs.TOUCH_GESTURES - shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(if (gestureMode) 350 else 500)) + shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(if (gestureMode) 350 else 320)) assertEquals(if (gestureMode) listOf(18 to true) else emptyList(), keys) assertEquals(if (gestureMode) emptyList() else listOf(PointerGestures.BTN_RIGHT to true), directButtons) ReflectionHelpers.callInstanceMethod(activity, "onPause") @@ -220,7 +220,7 @@ class SessionGestureRoutingTest { override fun onButton(button: Int, pressed: Boolean, x: Float, y: Float) { directButtons += button to pressed } override fun onWheel(steps: Int) {} override fun onLongPress() {} - }) {} + }) {}.also { it.configure(config) } setField("directTouchHold", directHold) launcherScroll = ScrollTouchGestures(8f, 50f, object : ScrollTouchGestures.Listener { override fun onMove(x: Float, y: Float) { scrollPositions += x to y }