Loading packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt +122 −61 Original line number Diff line number Diff line Loading @@ -381,6 +381,13 @@ object KeyguardBottomAreaViewBinder { return when (event?.actionMasked) { MotionEvent.ACTION_DOWN -> 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 = view .animate() Loading @@ -388,43 +395,40 @@ object KeyguardBottomAreaViewBinder { .scaleY(PRESSED_SCALE) .setDuration(longPressDurationMs) .withEndAction { view.setOnClickListener { 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) dispatchClick(viewModel.configKey) cancel() } } true } else { false } MotionEvent.ACTION_MOVE -> { if (event.historySize > 0) { val distance = sqrt( (event.y - event.getHistoricalY(0)).pow(2) + (event.x - event.getHistoricalX(0)).pow(2) ) if (distance > ViewConfiguration.getTouchSlop()) { if (!isUsingAccurateTool(event)) { // Moving too far while performing a long-press gesture cancels that // gesture. val distanceMoved = distanceMoved(event) if (distanceMoved > ViewConfiguration.getTouchSlop()) { cancel() } } true } 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( onAnimationEnd = if (event.eventTime - event.downTime < longPressDurationMs) { Loading Loading @@ -457,6 +461,7 @@ object KeyguardBottomAreaViewBinder { null } ) } true } MotionEvent.ACTION_CANCEL -> { Loading @@ -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) { longPressAnimator?.cancel() longPressAnimator = null Loading @@ -475,6 +502,40 @@ object KeyguardBottomAreaViewBinder { companion object { 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 } } } } Loading Loading
packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt +122 −61 Original line number Diff line number Diff line Loading @@ -381,6 +381,13 @@ object KeyguardBottomAreaViewBinder { return when (event?.actionMasked) { MotionEvent.ACTION_DOWN -> 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 = view .animate() Loading @@ -388,43 +395,40 @@ object KeyguardBottomAreaViewBinder { .scaleY(PRESSED_SCALE) .setDuration(longPressDurationMs) .withEndAction { view.setOnClickListener { 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) dispatchClick(viewModel.configKey) cancel() } } true } else { false } MotionEvent.ACTION_MOVE -> { if (event.historySize > 0) { val distance = sqrt( (event.y - event.getHistoricalY(0)).pow(2) + (event.x - event.getHistoricalX(0)).pow(2) ) if (distance > ViewConfiguration.getTouchSlop()) { if (!isUsingAccurateTool(event)) { // Moving too far while performing a long-press gesture cancels that // gesture. val distanceMoved = distanceMoved(event) if (distanceMoved > ViewConfiguration.getTouchSlop()) { cancel() } } true } 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( onAnimationEnd = if (event.eventTime - event.downTime < longPressDurationMs) { Loading Loading @@ -457,6 +461,7 @@ object KeyguardBottomAreaViewBinder { null } ) } true } MotionEvent.ACTION_CANCEL -> { Loading @@ -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) { longPressAnimator?.cancel() longPressAnimator = null Loading @@ -475,6 +502,40 @@ object KeyguardBottomAreaViewBinder { companion object { 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 } } } } Loading