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

Commit c323e4fd authored by Ale Nijamkin's avatar Ale Nijamkin Committed by Automerger Merge Worker
Browse files

Merge "Long-press not required for mouse or stylus." into tm-qpr-dev am: 7ae05438

parents 6a088277 7ae05438
Loading
Loading
Loading
Loading
+122 −61
Original line number Original line Diff line number Diff line
@@ -381,6 +381,13 @@ object KeyguardBottomAreaViewBinder {
            return when (event?.actionMasked) {
            return when (event?.actionMasked) {
                MotionEvent.ACTION_DOWN ->
                MotionEvent.ACTION_DOWN ->
                    if (viewModel.configKey != null) {
                    if (viewModel.configKey != null) {
                        if (isUsingAccurateTool(event)) {
                            // For accurate tool types (stylus, mouse, etc.), we don't require a
                            // long-press.
                        } else {
                            // When not using a stylus, we require a long-press to activate the
                            // quick affordance, mostly to do "falsing" (e.g. protect from false
                            // clicks in the pocket/bag).
                            longPressAnimator =
                            longPressAnimator =
                                view
                                view
                                    .animate()
                                    .animate()
@@ -388,43 +395,40 @@ object KeyguardBottomAreaViewBinder {
                                    .scaleY(PRESSED_SCALE)
                                    .scaleY(PRESSED_SCALE)
                                    .setDuration(longPressDurationMs)
                                    .setDuration(longPressDurationMs)
                                    .withEndAction {
                                    .withEndAction {
                                    view.setOnClickListener {
                                        dispatchClick(viewModel.configKey)
                                        vibratorHelper?.vibrate(
                                            if (viewModel.isActivated) {
                                                Vibrations.Activated
                                            } else {
                                                Vibrations.Deactivated
                                            }
                                        )
                                        viewModel.onClicked(
                                            KeyguardQuickAffordanceViewModel.OnClickedParameters(
                                                configKey = viewModel.configKey,
                                                expandable = Expandable.fromView(view),
                                            )
                                        )
                                    }
                                    view.performClick()
                                    view.setOnClickListener(null)
                                        cancel()
                                        cancel()
                                    }
                                    }
                        }
                        true
                        true
                    } else {
                    } else {
                        false
                        false
                    }
                    }
                MotionEvent.ACTION_MOVE -> {
                MotionEvent.ACTION_MOVE -> {
                    if (event.historySize > 0) {
                    if (!isUsingAccurateTool(event)) {
                        val distance =
                        // Moving too far while performing a long-press gesture cancels that
                            sqrt(
                        // gesture.
                                (event.y - event.getHistoricalY(0)).pow(2) +
                        val distanceMoved = distanceMoved(event)
                                    (event.x - event.getHistoricalX(0)).pow(2)
                        if (distanceMoved > ViewConfiguration.getTouchSlop()) {
                            )
                        if (distance > ViewConfiguration.getTouchSlop()) {
                            cancel()
                            cancel()
                        }
                        }
                    }
                    }
                    true
                    true
                }
                }
                MotionEvent.ACTION_UP -> {
                MotionEvent.ACTION_UP -> {
                    if (isUsingAccurateTool(event)) {
                        // When using an accurate tool type (stylus, mouse, etc.), we don't require
                        // a long-press gesture to activate the quick affordance. Therefore, lifting
                        // the pointer performs a click.
                        if (
                            viewModel.configKey != null &&
                                distanceMoved(event) <= ViewConfiguration.getTouchSlop()
                        ) {
                            dispatchClick(viewModel.configKey)
                        }
                    } else {
                        // When not using a stylus, lifting the finger/pointer will actually cancel
                        // the long-press gesture. Calling cancel after the quick affordance was
                        // already long-press activated is a no-op, so it's safe to call from here.
                        cancel(
                        cancel(
                            onAnimationEnd =
                            onAnimationEnd =
                                if (event.eventTime - event.downTime < longPressDurationMs) {
                                if (event.eventTime - event.downTime < longPressDurationMs) {
@@ -457,6 +461,7 @@ object KeyguardBottomAreaViewBinder {
                                    null
                                    null
                                }
                                }
                        )
                        )
                    }
                    true
                    true
                }
                }
                MotionEvent.ACTION_CANCEL -> {
                MotionEvent.ACTION_CANCEL -> {
@@ -467,6 +472,28 @@ object KeyguardBottomAreaViewBinder {
            }
            }
        }
        }


        private fun dispatchClick(
            configKey: String,
        ) {
            view.setOnClickListener {
                vibratorHelper?.vibrate(
                    if (viewModel.isActivated) {
                        Vibrations.Activated
                    } else {
                        Vibrations.Deactivated
                    }
                )
                viewModel.onClicked(
                    KeyguardQuickAffordanceViewModel.OnClickedParameters(
                        configKey = configKey,
                        expandable = Expandable.fromView(view),
                    )
                )
            }
            view.performClick()
            view.setOnClickListener(null)
        }

        private fun cancel(onAnimationEnd: Runnable? = null) {
        private fun cancel(onAnimationEnd: Runnable? = null) {
            longPressAnimator?.cancel()
            longPressAnimator?.cancel()
            longPressAnimator = null
            longPressAnimator = null
@@ -475,6 +502,40 @@ object KeyguardBottomAreaViewBinder {


        companion object {
        companion object {
            private const val PRESSED_SCALE = 1.5f
            private const val PRESSED_SCALE = 1.5f

            /**
             * Returns `true` if the tool type at the given pointer index is an accurate tool (like
             * stylus or mouse), which means we can trust it to not be a false click; `false`
             * otherwise.
             */
            private fun isUsingAccurateTool(
                event: MotionEvent,
                pointerIndex: Int = 0,
            ): Boolean {
                return when (event.getToolType(pointerIndex)) {
                    MotionEvent.TOOL_TYPE_STYLUS -> true
                    MotionEvent.TOOL_TYPE_MOUSE -> true
                    else -> false
                }
            }

            /**
             * Returns the amount of distance the pointer moved since the historical record at the
             * [since] index.
             */
            private fun distanceMoved(
                event: MotionEvent,
                since: Int = 0,
            ): Float {
                return if (event.historySize > 0) {
                    sqrt(
                        (event.y - event.getHistoricalY(since)).pow(2) +
                            (event.x - event.getHistoricalX(since)).pow(2)
                    )
                } else {
                    0f
                }
            }
        }
        }
    }
    }