Merge "Revert "Compose gesture integrated fully into Launcher"" into ub-launcher3-rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
ac327df55c
+1
-2
@@ -26,7 +26,6 @@ import static android.view.MotionEvent.INVALID_POINTER_ID;
|
||||
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
|
||||
import static com.android.launcher3.Utilities.squaredHypot;
|
||||
import static com.android.launcher3.util.TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS;
|
||||
import static com.android.quickstep.GestureState.STATE_OVERSCROLL_WINDOW_CREATED;
|
||||
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
|
||||
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
|
||||
|
||||
@@ -431,6 +430,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
|
||||
@Override
|
||||
public boolean allowInterceptByParent() {
|
||||
return !mPassedPilferInputSlop || mGestureState.hasState(STATE_OVERSCROLL_WINDOW_CREATED);
|
||||
return !mPassedPilferInputSlop;
|
||||
}
|
||||
}
|
||||
|
||||
+56
-101
@@ -24,11 +24,9 @@ import static android.view.MotionEvent.ACTION_UP;
|
||||
|
||||
import static com.android.launcher3.Utilities.squaredHypot;
|
||||
|
||||
import static java.lang.Math.abs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PointF;
|
||||
import android.util.Log;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
@@ -46,31 +44,24 @@ import com.android.systemui.shared.system.InputMonitorCompat;
|
||||
* Input consumer for handling events to pass to an {@code OverscrollPlugin}.
|
||||
*/
|
||||
public class OverscrollInputConsumer extends DelegateInputConsumer {
|
||||
|
||||
private static final String TAG = "OverscrollInputConsumer";
|
||||
private static final boolean DEBUG_LOGS_ENABLED = false;
|
||||
private static void debugPrint(String log) {
|
||||
if (DEBUG_LOGS_ENABLED) {
|
||||
Log.v(TAG, log);
|
||||
}
|
||||
}
|
||||
|
||||
private final PointF mDownPos = new PointF();
|
||||
private final PointF mLastPos = new PointF();
|
||||
private final PointF mStartDragPos = new PointF();
|
||||
private final int mAngleThreshold;
|
||||
|
||||
private final int mFlingDistanceThresholdPx;
|
||||
private final int mFlingVelocityThresholdPx;
|
||||
private final float mFlingThresholdPx;
|
||||
private int mActivePointerId = -1;
|
||||
private boolean mPassedSlop = false;
|
||||
// True if we set ourselves as active, meaning we no longer pass events to the delegate.
|
||||
private boolean mPassedActiveThreshold = false;
|
||||
private final float mSquaredActiveThreshold;
|
||||
|
||||
private final float mSquaredSlop;
|
||||
|
||||
private final GestureState mGestureState;
|
||||
@Nullable
|
||||
private final OverscrollPlugin mPlugin;
|
||||
private final GestureDetector mGestureDetector;
|
||||
|
||||
@Nullable
|
||||
private RecentsView mRecentsView;
|
||||
@@ -81,19 +72,15 @@ public class OverscrollInputConsumer extends DelegateInputConsumer {
|
||||
|
||||
mAngleThreshold = context.getResources()
|
||||
.getInteger(R.integer.assistant_gesture_corner_deg_threshold);
|
||||
mFlingDistanceThresholdPx = (int) context.getResources()
|
||||
.getDimension(R.dimen.gestures_overscroll_fling_threshold);
|
||||
mFlingVelocityThresholdPx = ViewConfiguration.get(context).getScaledMinimumFlingVelocity();
|
||||
mFlingThresholdPx = context.getResources()
|
||||
.getDimension(R.dimen.gestures_overscroll_fling_threshold);
|
||||
mGestureState = gestureState;
|
||||
mPlugin = plugin;
|
||||
|
||||
float slop = ViewConfiguration.get(context).getScaledTouchSlop();
|
||||
|
||||
mSquaredSlop = slop * slop;
|
||||
|
||||
float dragThreshold = (int) context.getResources()
|
||||
.getDimension(R.dimen.gestures_overscroll_drag_threshold);
|
||||
mSquaredActiveThreshold = dragThreshold * dragThreshold;
|
||||
mGestureDetector = new GestureDetector(context, new FlingGestureListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,27 +90,12 @@ public class OverscrollInputConsumer extends DelegateInputConsumer {
|
||||
|
||||
@Override
|
||||
public void onMotionEvent(MotionEvent ev) {
|
||||
if (mPlugin == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ev.getActionMasked()) {
|
||||
case ACTION_DOWN: {
|
||||
if (mPlugin.blockOtherGestures()) {
|
||||
// When an Activity is visible, blocking other gestures prevents the Activity
|
||||
// from disappearing upon ACTION_DOWN in the navigation bar. (it will reappear
|
||||
// on ACTION_MOVE or ACTION_UP)
|
||||
debugPrint("Becoming active on ACTION_DOWN");
|
||||
if (mState != STATE_ACTIVE) {
|
||||
setActive(ev);
|
||||
}
|
||||
}
|
||||
mActivePointerId = ev.getPointerId(0);
|
||||
mDownPos.set(ev.getX(), ev.getY());
|
||||
mLastPos.set(mDownPos);
|
||||
mPlugin.onTouchEvent(ev, getHorizontalDistancePx(), getVerticalDistancePx(),
|
||||
(int) Math.sqrt(mSquaredActiveThreshold), mFlingDistanceThresholdPx,
|
||||
mFlingVelocityThresholdPx, getDeviceState(), getUnderlyingActivity());
|
||||
|
||||
break;
|
||||
}
|
||||
case ACTION_POINTER_DOWN: {
|
||||
@@ -159,82 +131,53 @@ public class OverscrollInputConsumer extends DelegateInputConsumer {
|
||||
}
|
||||
mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
|
||||
|
||||
float squaredDist = squaredHypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y);
|
||||
|
||||
|
||||
|
||||
if (!mPassedSlop) {
|
||||
// Normal gesture, ensure we pass the slop before we start tracking the gesture
|
||||
if (squaredDist > mSquaredSlop) {
|
||||
debugPrint("passed slop");
|
||||
if (squaredHypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y)
|
||||
> mSquaredSlop) {
|
||||
|
||||
mPassedSlop = true;
|
||||
mStartDragPos.set(mLastPos.x, mLastPos.y);
|
||||
if (isOverscrolled()) {
|
||||
debugPrint("setting STATE_OVERSCROLL_WINDOW_CREATED");
|
||||
mGestureState.setState(GestureState.STATE_OVERSCROLL_WINDOW_CREATED);
|
||||
if (!mPlugin.allowsUnderlyingActivityOverscroll()
|
||||
&& (mState != STATE_ACTIVE)) {
|
||||
debugPrint("setting active gesture handler to overscroll to "
|
||||
+ "prevent losing active touch when Activity starts");
|
||||
setActive(ev);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debugPrint("Not past slop");
|
||||
}
|
||||
}
|
||||
|
||||
if (mPassedSlop && !mPassedActiveThreshold && isOverscrolled()) {
|
||||
if ((squaredDist > mSquaredActiveThreshold)) {
|
||||
debugPrint("Past slop and past threshold, set active");
|
||||
|
||||
mPassedActiveThreshold = true;
|
||||
if (mState != STATE_ACTIVE) {
|
||||
setActive(ev);
|
||||
|
||||
if (mPlugin != null) {
|
||||
mPlugin.onTouchStart(getDeviceState(), getUnderlyingActivity());
|
||||
}
|
||||
} else {
|
||||
mState = STATE_DELEGATE_ACTIVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mPassedSlop && mState != STATE_DELEGATE_ACTIVE && isOverscrolled()) {
|
||||
debugPrint("Relaying touch event");
|
||||
mPlugin.onTouchEvent(ev, getHorizontalDistancePx(), getVerticalDistancePx(),
|
||||
(int) Math.sqrt(mSquaredActiveThreshold), mFlingDistanceThresholdPx,
|
||||
mFlingVelocityThresholdPx, getDeviceState(), getUnderlyingActivity());
|
||||
if (mPassedSlop && mState != STATE_DELEGATE_ACTIVE && isOverscrolled()
|
||||
&& mPlugin != null) {
|
||||
mPlugin.onTouchTraveled(getDistancePx());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ACTION_CANCEL:
|
||||
case ACTION_UP:
|
||||
if (mPassedSlop && isOverscrolled()) {
|
||||
mPlugin.onTouchEvent(ev, getHorizontalDistancePx(), getVerticalDistancePx(),
|
||||
(int) Math.sqrt(mSquaredActiveThreshold), mFlingDistanceThresholdPx,
|
||||
mFlingVelocityThresholdPx, getDeviceState(), getUnderlyingActivity());
|
||||
if (mState != STATE_DELEGATE_ACTIVE && mPassedSlop && mPlugin != null) {
|
||||
mPlugin.onTouchEnd(getDistancePx());
|
||||
}
|
||||
|
||||
mPassedSlop = false;
|
||||
mPassedActiveThreshold = false;
|
||||
mState = STATE_INACTIVE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mState != STATE_DELEGATE_ACTIVE) {
|
||||
mGestureDetector.onTouchEvent(ev);
|
||||
}
|
||||
|
||||
if (mState != STATE_ACTIVE) {
|
||||
mDelegate.onMotionEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isOverscrolled() {
|
||||
if (mPlugin.blockOtherGestures()) {
|
||||
// When an Activity is visible, this `InputConsumer` immediately becomes
|
||||
// the active gesture handler to prevent the Activity from disappearing on TOUCH_DOWN
|
||||
// in the navbar.
|
||||
//
|
||||
// Returning `true` ensures that case will still result in touches being handled,
|
||||
// instead of dropping touches until the gesture reaches the thresholds calculated
|
||||
// below.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mRecentsView == null) {
|
||||
BaseDraggingActivity activity = mGestureState.getActivityInterface()
|
||||
.getCreatedActivity();
|
||||
@@ -253,10 +196,9 @@ public class OverscrollInputConsumer extends DelegateInputConsumer {
|
||||
|| mRecentsView.getRunningTaskIndex() <= maxIndex);
|
||||
|
||||
// Check if the gesture is within our angle threshold of horizontal
|
||||
float deltaY = abs(mLastPos.y - mDownPos.y);
|
||||
float deltaX = abs(mDownPos.x - mLastPos.x);
|
||||
|
||||
boolean angleInBounds = (Math.toDegrees(Math.atan2(deltaY, deltaX)) < mAngleThreshold);
|
||||
float deltaY = Math.abs(mLastPos.y - mDownPos.y);
|
||||
float deltaX = mDownPos.x - mLastPos.x; // Positive if this is a gesture to the left
|
||||
boolean angleInBounds = Math.toDegrees(Math.atan2(deltaY, deltaX)) < mAngleThreshold;
|
||||
|
||||
return atRightMostApp && angleInBounds;
|
||||
}
|
||||
@@ -277,22 +219,35 @@ public class OverscrollInputConsumer extends DelegateInputConsumer {
|
||||
return deviceState;
|
||||
}
|
||||
|
||||
private int getHorizontalDistancePx() {
|
||||
return (int) (mLastPos.x - mDownPos.x);
|
||||
}
|
||||
|
||||
private int getVerticalDistancePx() {
|
||||
return (int) (mLastPos.y - mDownPos.y);
|
||||
private int getDistancePx() {
|
||||
return (int) Math.hypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y);
|
||||
}
|
||||
|
||||
private String getUnderlyingActivity() {
|
||||
// Overly defensive, got guidance on code review that something in the chain of
|
||||
// `mGestureState.getRunningTask().topActivity` can be null and thus cause a null pointer
|
||||
// exception to be thrown, but we aren't sure which part can be null.
|
||||
if ((mGestureState == null) || (mGestureState.getRunningTask() == null)
|
||||
|| (mGestureState.getRunningTask().topActivity == null)) {
|
||||
return "";
|
||||
}
|
||||
return mGestureState.getRunningTask().topActivity.flattenToString();
|
||||
}
|
||||
|
||||
private class FlingGestureListener extends GestureDetector.SimpleOnGestureListener {
|
||||
@Override
|
||||
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||
if (isValidAngle(velocityX, -velocityY)
|
||||
&& getDistancePx() >= mFlingThresholdPx
|
||||
&& mState != STATE_DELEGATE_ACTIVE) {
|
||||
|
||||
if (mPlugin != null) {
|
||||
mPlugin.onFling(-velocityX);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isValidAngle(float deltaX, float deltaY) {
|
||||
float angle = (float) Math.toDegrees(Math.atan2(deltaY, deltaX));
|
||||
// normalize so that angle is measured clockwise from horizontal in the bottom right
|
||||
// corner and counterclockwise from horizontal in the bottom left corner
|
||||
|
||||
angle = angle > 90 ? 180 - angle : angle;
|
||||
return (angle < mAngleThreshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,6 @@
|
||||
|
||||
<!-- Overscroll Gesture -->
|
||||
<dimen name="gestures_overscroll_fling_threshold">40dp</dimen>
|
||||
<dimen name="gestures_overscroll_drag_threshold">136dp</dimen>
|
||||
|
||||
<!-- Tips Gesture Tutorial -->
|
||||
<dimen name="gesture_tutorial_title_margin_start_end">40dp</dimen>
|
||||
|
||||
@@ -106,10 +106,6 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
||||
public static final int STATE_RECENTS_ANIMATION_ENDED =
|
||||
getFlagForIndex("STATE_RECENTS_ANIMATION_ENDED");
|
||||
|
||||
// Called when we create an overscroll window when swiping right to left on the most recent app
|
||||
public static final int STATE_OVERSCROLL_WINDOW_CREATED =
|
||||
getFlagForIndex("STATE_OVERSCROLL_WINDOW_CREATED");
|
||||
|
||||
// Called when RecentsView stops scrolling and settles on a TaskView.
|
||||
public static final int STATE_RECENTS_SCROLLING_FINISHED =
|
||||
getFlagForIndex("STATE_RECENTS_SCROLLING_FINISHED");
|
||||
|
||||
@@ -110,9 +110,6 @@ public final class FeatureFlags {
|
||||
public static final BooleanFlag ENABLE_QUICK_CAPTURE_GESTURE = getDebugFlag(
|
||||
"ENABLE_QUICK_CAPTURE_GESTURE", true, "Swipe from right to left to quick capture");
|
||||
|
||||
public static final BooleanFlag ENABLE_QUICK_CAPTURE_WINDOW = getDebugFlag(
|
||||
"ENABLE_QUICK_CAPTURE_WINDOW", false, "Use window to host quick capture");
|
||||
|
||||
public static final BooleanFlag FORCE_LOCAL_OVERSCROLL_PLUGIN = getDebugFlag(
|
||||
"FORCE_LOCAL_OVERSCROLL_PLUGIN", false,
|
||||
"Use a launcher-provided OverscrollPlugin if available");
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.android.systemui.plugins;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.systemui.plugins.annotations.ProvidesInterface;
|
||||
|
||||
/**
|
||||
@@ -30,7 +28,7 @@ import com.android.systemui.plugins.annotations.ProvidesInterface;
|
||||
public interface OverscrollPlugin extends Plugin {
|
||||
|
||||
String ACTION = "com.android.systemui.action.PLUGIN_LAUNCHER_OVERSCROLL";
|
||||
int VERSION = 4;
|
||||
int VERSION = 3;
|
||||
|
||||
String DEVICE_STATE_LOCKED = "Locked";
|
||||
String DEVICE_STATE_LAUNCHER = "Launcher";
|
||||
@@ -43,33 +41,33 @@ public interface OverscrollPlugin extends Plugin {
|
||||
boolean isActive();
|
||||
|
||||
/**
|
||||
* Called when a touch has been recognized as an overscroll gesture.
|
||||
* @param horizontalDistancePx Horizontal distance from the last finger location to the finger
|
||||
* location when it first touched the screen.
|
||||
* @param verticalDistancePx Horizontal distance from the last finger location to the finger
|
||||
* location when it first touched the screen.
|
||||
* @param thresholdPx Minimum distance for gesture.
|
||||
* @param flingDistanceThresholdPx Minimum distance for gesture by fling.
|
||||
* @param flingVelocityThresholdPx Minimum velocity for gesture by fling.
|
||||
* Called when a touch is down and has been recognized as an overscroll gesture.
|
||||
* A call of this method will always result in `onTouchUp` being called, and possibly
|
||||
* `onFling` as well.
|
||||
*
|
||||
* @param deviceState String representing the current device state
|
||||
* @param underlyingActivity String representing the currently active Activity
|
||||
*/
|
||||
void onTouchEvent(MotionEvent event,
|
||||
int horizontalDistancePx,
|
||||
int verticalDistancePx,
|
||||
int thresholdPx,
|
||||
int flingDistanceThresholdPx,
|
||||
int flingVelocityThresholdPx,
|
||||
String deviceState,
|
||||
String underlyingActivity);
|
||||
void onTouchStart(String deviceState, String underlyingActivity);
|
||||
|
||||
/**
|
||||
* @return `true` if overscroll gesture handling should override all other gestures.
|
||||
* Called when a touch that was previously recognized has moved.
|
||||
*
|
||||
* @param px distance between the position of touch on this update and the position of the
|
||||
* touch when it was initially recognized.
|
||||
*/
|
||||
boolean blockOtherGestures();
|
||||
void onTouchTraveled(int px);
|
||||
|
||||
/**
|
||||
* @return `true` if the overscroll gesture can pan the underlying app.
|
||||
* Called when a touch that was previously recognized has ended.
|
||||
*
|
||||
* @param px distance between the position of touch on this update and the position of the
|
||||
* touch when it was initially recognized.
|
||||
*/
|
||||
boolean allowsUnderlyingActivityOverscroll();
|
||||
void onTouchEnd(int px);
|
||||
|
||||
/**
|
||||
* Called when the user starts Compose with a fling. `onTouchUp` will also be called.
|
||||
*/
|
||||
void onFling(float velocity);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user