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

This commit is contained in:
Ale Nijamkin
2023-02-03 20:22:01 +00:00
committed by Android (Google) Code Review

View File

@@ -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
}
}
} }
} }