Move logic that overrides MotionPauseDetector to callers
There are 2 conditions that we force the MotionPauseDetector to treat
the motion as not paused:
1. If we haven't passed a small displacement (48dp before, 36dp now)
2. If we have moved mostly orthogonally
These existed soley for the OtherActivityInputConsumer case, because
1. We only need the displacement requirement to make room for the
peeking shelf, which doesn't exist in other cases (it's already there on
home for example)
2. We can only move orthogonally for quick switch, which again doesn't
exist for other users of MotionPauseDetector.
So now instead of checking min displacement and orthogonal distance
inside MotionPauseDetector, we let callers setDisallowPause()
before adding positions to their MotionPauseDetector.
The only user visible change is that you no longer have to swipe up 48dp
before we allow pause to overview from home. This also paves the way to
using the same logic that determines to disallowPause to also detach
recents from the window while swiping up from an app.
Bug: 129985827
Change-Id: Ie690aa314da3260aff2209341a29638604f9501c
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
index bab215b..6358109 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
@@ -28,6 +28,7 @@
import android.animation.AnimatorSet;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
+import android.view.ViewConfiguration;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
@@ -44,12 +45,14 @@
private static final long PEEK_ANIM_DURATION = 100;
private final MotionPauseDetector mMotionPauseDetector;
+ private final float mMotionPauseMinDisplacement;
private AnimatorSet mPeekAnim;
public FlingAndHoldTouchController(Launcher l) {
super(l, false /* allowDragToOverview */);
mMotionPauseDetector = new MotionPauseDetector(l);
+ mMotionPauseMinDisplacement = ViewConfiguration.get(l).getScaledTouchSlop();
}
@Override
@@ -98,7 +101,8 @@
@Override
public boolean onDrag(float displacement, MotionEvent event) {
- mMotionPauseDetector.addPosition(displacement, 0, event.getEventTime());
+ mMotionPauseDetector.setDisallowPause(-displacement < mMotionPauseMinDisplacement);
+ mMotionPauseDetector.addPosition(displacement, event.getEventTime());
return super.onDrag(displacement, event);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java
index abd7c03..a76ecd5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java
@@ -21,14 +21,14 @@
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE_NOOP;
+
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPLEFT;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPRIGHT;
+import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE;
+import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE_NOOP;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.NAVBAR;
import android.animation.ValueAnimator;
-import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.PointF;
@@ -40,10 +40,10 @@
import android.view.MotionEvent;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.systemui.shared.recents.ISystemUiProxy;
-import com.android.launcher3.R;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.NavigationBarCompat;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
index 03af92d..78cc166 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
@@ -21,9 +21,9 @@
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.INVALID_POINTER_ID;
+import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
-import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -45,6 +45,9 @@
import android.view.ViewConfiguration;
import android.view.WindowManager;
+import androidx.annotation.UiThread;
+
+import com.android.launcher3.R;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
@@ -62,8 +65,6 @@
import java.util.function.Consumer;
-import androidx.annotation.UiThread;
-
/**
* Input consumer for handling events originating from an activity other than Launcher
*/
@@ -90,6 +91,7 @@
private final Consumer<OtherActivityInputConsumer> mOnCompleteCallback;
private final MotionPauseDetector mMotionPauseDetector;
+ private final float mMotionPauseMinDisplacement;
private VelocityTracker mVelocityTracker;
private WindowTransformSwipeHandler mInteractionHandler;
@@ -107,8 +109,9 @@
// Slop used to determine when we say that the gesture has started.
private boolean mPassedTouchSlop;
- // TODO: Start displacement should have both x and y
+ // Might be displacement in X or Y, depending on the direction we are swiping from the nav bar.
private float mStartDisplacement;
+ private float mStartDisplacementX;
private Handler mMainThreadHandler;
private Runnable mCancelRecentsAnimationRunnable = () -> {
@@ -131,6 +134,8 @@
mMode = SysUINavigationMode.getMode(base);
mMotionPauseDetector = new MotionPauseDetector(base);
+ mMotionPauseMinDisplacement = base.getResources().getDimension(
+ R.dimen.motion_pause_detector_min_displacement_from_app);
mOnCompleteCallback = onCompleteCallback;
mVelocityTracker = VelocityTracker.obtain();
mInputMonitorCompat = inputMonitorCompat;
@@ -219,6 +224,7 @@
}
mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
float displacement = getDisplacement(ev);
+ float displacementX = mLastPos.x - mDownPos.x;
if (!mPassedDragSlop) {
if (!mIsDeferredDownTarget) {
@@ -227,13 +233,13 @@
if (Math.abs(displacement) > mDragSlop) {
mPassedDragSlop = true;
mStartDisplacement = displacement;
+ mStartDisplacementX = displacementX;
}
}
}
if (!mPassedTouchSlop) {
- if (Math.hypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y) >=
- mTouchSlop) {
+ if (Math.hypot(displacementX, mLastPos.y - mDownPos.y) >= mTouchSlop) {
mPassedTouchSlop = true;
if (mIsDeferredDownTarget) {
@@ -244,6 +250,7 @@
if (!mPassedDragSlop) {
mPassedDragSlop = true;
mStartDisplacement = displacement;
+ mStartDisplacementX = displacementX;
}
notifyGestureStarted();
}
@@ -254,12 +261,12 @@
mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
if (mMode == Mode.NO_BUTTON) {
- boolean isLandscape = isNavBarOnLeft() || isNavBarOnRight();
- float orthogonalDisplacement = !isLandscape
- ? ev.getX() - mDownPos.x
- : ev.getY() - mDownPos.y;
- mMotionPauseDetector.addPosition(displacement, orthogonalDisplacement,
- ev.getEventTime());
+ float horizontalDist = Math.abs(displacementX - mStartDisplacementX);
+ float upDist = -(displacement - mStartDisplacement);
+ boolean isLikelyToStartNewTask = horizontalDist > upDist;
+ mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
+ || isLikelyToStartNewTask);
+ mMotionPauseDetector.addPosition(displacement, ev.getEventTime());
}
}
break;
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 13a0435..32f312f 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -38,7 +38,7 @@
<dimen name="motion_pause_detector_speed_very_slow">0.0285dp</dimen>
<dimen name="motion_pause_detector_speed_somewhat_fast">0.285dp</dimen>
<dimen name="motion_pause_detector_speed_fast">0.5dp</dimen>
- <dimen name="motion_pause_detector_min_displacement">48dp</dimen>
+ <dimen name="motion_pause_detector_min_displacement_from_app">36dp</dimen>
<!-- Launcher app transition -->
<dimen name="content_trans_y">50dp</dimen>
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index ae5f390..4b24a2f 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -38,28 +38,26 @@
private final float mSpeedVerySlow;
private final float mSpeedSomewhatFast;
private final float mSpeedFast;
- private final float mMinDisplacementForPause;
private final Alarm mForcePauseTimeout;
private Long mPreviousTime = null;
private Float mPreviousPosition = null;
private Float mPreviousVelocity = null;
- private TotalDisplacement mTotalDisplacement = new TotalDisplacement();
private Float mFirstPosition = null;
- private Float mFirstOrthogonalPosition = null;
private OnMotionPauseListener mOnMotionPauseListener;
private boolean mIsPaused;
// Bias more for the first pause to make it feel extra responsive.
private boolean mHasEverBeenPaused;
+ /** @see #setDisallowPause(boolean) */
+ private boolean mDisallowPause;
public MotionPauseDetector(Context context) {
Resources res = context.getResources();
mSpeedVerySlow = res.getDimension(R.dimen.motion_pause_detector_speed_very_slow);
mSpeedSomewhatFast = res.getDimension(R.dimen.motion_pause_detector_speed_somewhat_fast);
mSpeedFast = res.getDimension(R.dimen.motion_pause_detector_speed_fast);
- mMinDisplacementForPause = res.getDimension(R.dimen.motion_pause_detector_min_displacement);
mForcePauseTimeout = new Alarm();
mForcePauseTimeout.setOnAlarmListener(alarm -> updatePaused(true /* isPaused */));
}
@@ -73,28 +71,30 @@
}
/**
+ * @param disallowPause If true, we will not detect any pauses until this is set to false again.
+ */
+ public void setDisallowPause(boolean disallowPause) {
+ mDisallowPause = disallowPause;
+ updatePaused(false);
+ }
+
+ /**
* Computes velocity and acceleration to determine whether the motion is paused.
* @param position The x or y component of the motion being tracked.
- * @param orthogonalPosition The x or y component (opposite of {@param position}) of the motion.
*
* TODO: Use historical positions as well, e.g. {@link MotionEvent#getHistoricalY(int, int)}.
*/
- public void addPosition(float position, float orthogonalPosition, long time) {
+ public void addPosition(float position, long time) {
if (mFirstPosition == null) {
mFirstPosition = position;
}
- if (mFirstOrthogonalPosition == null) {
- mFirstOrthogonalPosition = orthogonalPosition;
- }
mForcePauseTimeout.setAlarm(FORCE_PAUSE_TIMEOUT);
if (mPreviousTime != null && mPreviousPosition != null) {
long changeInTime = Math.max(1, time - mPreviousTime);
float changeInPosition = position - mPreviousPosition;
float velocity = changeInPosition / changeInTime;
if (mPreviousVelocity != null) {
- mTotalDisplacement.set(Math.abs(position - mFirstPosition),
- Math.abs(orthogonalPosition - mFirstOrthogonalPosition));
- checkMotionPaused(velocity, mPreviousVelocity, mTotalDisplacement);
+ checkMotionPaused(velocity, mPreviousVelocity);
}
mPreviousVelocity = velocity;
}
@@ -102,8 +102,7 @@
mPreviousPosition = position;
}
- private void checkMotionPaused(float velocity, float prevVelocity,
- TotalDisplacement totalDisplacement) {
+ private void checkMotionPaused(float velocity, float prevVelocity) {
float speed = Math.abs(velocity);
float previousSpeed = Math.abs(prevVelocity);
boolean isPaused;
@@ -125,16 +124,13 @@
}
}
}
- boolean passedMinDisplacement = totalDisplacement.primary >= mMinDisplacementForPause;
- boolean isDisplacementOrthogonal = totalDisplacement.orthogonal > totalDisplacement.primary;
- if (!passedMinDisplacement || isDisplacementOrthogonal) {
- mForcePauseTimeout.cancelAlarm();
- isPaused = false;
- }
updatePaused(isPaused);
}
private void updatePaused(boolean isPaused) {
+ if (mDisallowPause) {
+ isPaused = false;
+ }
if (mIsPaused != isPaused) {
mIsPaused = isPaused;
if (mIsPaused) {
@@ -151,8 +147,6 @@
mPreviousPosition = null;
mPreviousVelocity = null;
mFirstPosition = null;
- mFirstOrthogonalPosition = null;
- mTotalDisplacement.set(0, 0);
setOnMotionPauseListener(null);
mIsPaused = mHasEverBeenPaused = false;
mForcePauseTimeout.cancelAlarm();
@@ -165,18 +159,4 @@
public interface OnMotionPauseListener {
void onMotionPauseChanged(boolean isPaused);
}
-
- /**
- * Contains the displacement from the first tracked position,
- * along both the primary and orthogonal axes.
- */
- private class TotalDisplacement {
- public float primary;
- public float orthogonal;
-
- public void set(float primaryDisplacement, float orthogonalDisplacement) {
- this.primary = primaryDisplacement;
- this.orthogonal = orthogonalDisplacement;
- }
- }
}