Check horizontal touch slop for non-vertical flings
Flag: com.android.launcher3.enable_gesture_nav_horizontal_touch_slop
Fixes: 394364217
Test: Tested overview gesture with slight horizontal fling at the end
Change-Id: Ifb716b58486dd0bfadee467978b85150525af333
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index c564594..9aee58f 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -653,3 +653,13 @@
description: "Enable more grid scale options on the launcher for desktop experience"
bug: "375491272"
}
+
+flag {
+ name: "enable_gesture_nav_horizontal_touch_slop"
+ namespace: "launcher"
+ description: "Enables horizontal touch slop checking in non-vertical fling navigation gestures"
+ bug: "394364217"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 23b8e36..0566f09 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -31,6 +31,7 @@
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.Flags.enableAdditionalHomeAnimations;
+import static com.android.launcher3.Flags.enableGestureNavHorizontalTouchSlop;
import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
import static com.android.launcher3.Flags.msdlFeedback;
import static com.android.launcher3.PagedView.INVALID_PAGE;
@@ -1104,7 +1105,12 @@
public void onGestureCancelled() {
updateDisplacement(0);
mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED);
- handleNormalGestureEnd(0, false, new PointF(), true /* isCancel */);
+ handleNormalGestureEnd(
+ /* endVelocityPxPerMs= */ 0,
+ /* isFling= */ false,
+ /* velocityPxPerMs= */ new PointF(),
+ /* isCancel= */ true,
+ /* horizontalTouchSlopPassed= */ false);
}
/**
@@ -1113,7 +1119,8 @@
* @param velocityPxPerMs The x and y components of the velocity when the gesture ends.
*/
@UiThread
- public void onGestureEnded(float endVelocityPxPerMs, PointF velocityPxPerMs) {
+ public void onGestureEnded(
+ float endVelocityPxPerMs, PointF velocityPxPerMs, boolean horizontalTouchSlopPassed) {
float flingThreshold = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_threshold_speed);
boolean isFling = mGestureStarted && !mIsMotionPaused
@@ -1126,7 +1133,11 @@
mLogDirectionUpOrLeft = velocityPxPerMs.x < 0;
}
Runnable handleNormalGestureEndCallback = () -> handleNormalGestureEnd(
- endVelocityPxPerMs, isFling, velocityPxPerMs, /* isCancel= */ false);
+ endVelocityPxPerMs,
+ isFling,
+ velocityPxPerMs,
+ /* isCancel= */ false,
+ horizontalTouchSlopPassed);
if (mRecentsView != null) {
mRecentsView.runOnPageScrollsInitialized(handleNormalGestureEndCallback);
} else {
@@ -1259,7 +1270,11 @@
}
private GestureEndTarget calculateEndTarget(
- PointF velocityPxPerMs, float endVelocityPxPerMs, boolean isFlingY, boolean isCancel) {
+ PointF velocityPxPerMs,
+ float endVelocityPxPerMs,
+ boolean isFlingY,
+ boolean isCancel,
+ boolean horizontalTouchSlopPassed) {
ActiveGestureProtoLogProxy.logOnCalculateEndTarget(
dpiFromPx(velocityPxPerMs.x),
dpiFromPx(velocityPxPerMs.y),
@@ -1276,7 +1291,7 @@
} else if (isFlingY) {
endTarget = calculateEndTargetForFlingY(velocityPxPerMs, endVelocityPxPerMs);
} else {
- endTarget = calculateEndTargetForNonFling(velocityPxPerMs);
+ endTarget = calculateEndTargetForNonFling(velocityPxPerMs, horizontalTouchSlopPassed);
}
if (mDeviceState.isOverviewDisabled() && endTarget == RECENTS) {
@@ -1314,12 +1329,14 @@
return willGoToNewTask ? NEW_TASK : HOME;
}
- private GestureEndTarget calculateEndTargetForNonFling(PointF velocity) {
+ private GestureEndTarget calculateEndTargetForNonFling(
+ PointF velocity, boolean horizontalTouchSlopPassed) {
final boolean isScrollingToNewTask = isScrollingToNewTask();
// Fully gestural mode.
final boolean isFlingX = Math.abs(velocity.x) > mContext.getResources()
- .getDimension(R.dimen.quickstep_fling_threshold_speed);
+ .getDimension(R.dimen.quickstep_fling_threshold_speed)
+ && (!enableGestureNavHorizontalTouchSlop() || horizontalTouchSlopPassed);
if (isScrollingToNewTask && isFlingX) {
// Flinging towards new task takes precedence over mIsMotionPaused (which only
// checks y-velocity).
@@ -1359,11 +1376,15 @@
@UiThread
private void handleNormalGestureEnd(
- float endVelocityPxPerMs, boolean isFling, PointF velocityPxPerMs, boolean isCancel) {
+ float endVelocityPxPerMs,
+ boolean isFling,
+ PointF velocityPxPerMs,
+ boolean isCancel,
+ boolean horizontalTouchSlopPassed) {
long duration = MAX_SWIPE_DURATION;
float currentShift = mCurrentShift.value;
final GestureEndTarget endTarget = calculateEndTarget(
- velocityPxPerMs, endVelocityPxPerMs, isFling, isCancel);
+ velocityPxPerMs, endVelocityPxPerMs, isFling, isCancel, horizontalTouchSlopPassed);
// Set the state, but don't notify until the animation completes
mGestureState.setEndTarget(endTarget, false /* isAtomic */);
mAnimationFactory.setEndTarget(endTarget);
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
index 6bd3400..984f390 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
@@ -435,7 +435,11 @@
logShowOverviewFrom(command.type)
containerInterface.runOnInitBackgroundStateUI {
Log.d(TAG, "recents animation started - onInitBackgroundStateUI: $command")
- interactionHandler.onGestureEnded(0f, PointF())
+ interactionHandler.onGestureEnded(
+ 0f,
+ PointF(),
+ /* horizontalTouchSlopPassed= */ false,
+ )
}
command.removeListener(this)
}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 5963a7c..7cae5b8 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -483,7 +483,8 @@
: velocityYPxPerMs;
mInteractionHandler.updateDisplacement(getDisplacement(ev) - mStartDisplacement);
mInteractionHandler.onGestureEnded(velocityPxPerMs,
- new PointF(velocityXPxPerMs, velocityYPxPerMs));
+ new PointF(velocityXPxPerMs, velocityYPxPerMs),
+ Math.abs(mDownPos.x - mLastPos.x) > mTouchSlop);
}
} else {
// Since we start touch tracking on DOWN, we may reach this state without actually
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java
index 0c74610..6fbbd59 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java
@@ -364,7 +364,7 @@
float xVelocityPxPerMs = isQuickSwitch ? 100 : 0;
float yVelocityPxPerMs = isQuickSwitch ? 0 : -100;
swipeHandler.onGestureEnded(
- yVelocityPxPerMs, new PointF(xVelocityPxPerMs, yVelocityPxPerMs));
+ yVelocityPxPerMs, new PointF(xVelocityPxPerMs, yVelocityPxPerMs), isQuickSwitch);
swipeHandler.onCalculateEndTarget();
runOnMainSync(swipeHandler::onSettledOnEndTarget);
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt
index 35f1218..5661dcf 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt
@@ -116,14 +116,14 @@
@Test
fun goHomeFromAppByTrackpad_updateEduStats() {
gestureState.setTrackpadGestureType(GestureState.TrackpadGestureType.THREE_FINGER)
- underTest.onGestureEnded(flingSpeed, PointF())
+ underTest.onGestureEnded(flingSpeed, PointF(), /* horizontalTouchSlopPassed= */ false)
verify(systemUiProxy)
.updateContextualEduStats(/* isTrackpadGesture= */ eq(true), eq(GestureType.HOME))
}
@Test
fun goHomeFromAppByTouch_updateEduStats() {
- underTest.onGestureEnded(flingSpeed, PointF())
+ underTest.onGestureEnded(flingSpeed, PointF(), /* horizontalTouchSlopPassed= */ false)
verify(systemUiProxy)
.updateContextualEduStats(/* isTrackpadGesture= */ eq(false), eq(GestureType.HOME))
}