Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a9156a05 authored by James O'Leary's avatar James O'Leary
Browse files

Compose overscroll gesture updates

Two changes for the latest Compose prototype:
1. Pass the identity of the underlying app to the Overscroll plugin.
2. Enable the Compose gesture over an app when there's a Recents extra
card plugin active (otherwise the current app won't count as the
rightmost one).

Some changes to the gesture:
- Angle decreased from 35° to 25° to remove overlap with
Assistant gesture
- Distance increased from 8 to 110 dp. 110 dp is 2x the Assistant
gesture and roughly the same as scrubbing into an app from Home.
- Fling detection added; uses same distance threshold, 110 dp.
- If a touch was recognized as another gesture, the touch will not be
reinterpreted as a Compose gesture, no matter what touch movement occurs
- Fixes issue where Assistant + Compose could both be triggered
- Fixes issue where scrubbing apps to the left, then back to the right,
would bring in Compose. i.e. if a touch down + touch movement starts
bringing in Assistant UI elements, then, the user moves their touch
below the Assistant angle, the Compose gesture will not start
being recognized
- Gesture length required for fling lowered from 110 dp to 40 dp, per
tuning with PM.

Bug: b/146508473
Change-Id: I414573d1a92684d1d992837a5f1df522346ec211
parent c7d601e9
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -484,7 +484,9 @@ public class TouchInteractionService extends Service implements PluginListener<O
                base = new AssistantInputConsumer(this, newGestureState, base, mInputMonitorCompat);
                base = new AssistantInputConsumer(this, newGestureState, base, mInputMonitorCompat);
            }
            }


            if (mOverscrollPlugin != null) {
            if (FeatureFlags.ENABLE_QUICK_CAPTURE_GESTURE.get()
                    && (mOverscrollPlugin != null)
                    && mOverscrollPlugin.isActive()) {
                // Put the overscroll gesture as higher priority than the Assistant or base gestures
                // Put the overscroll gesture as higher priority than the Assistant or base gestures
                base = new OverscrollInputConsumer(this, newGestureState, base, mInputMonitorCompat,
                base = new OverscrollInputConsumer(this, newGestureState, base, mInputMonitorCompat,
                        mOverscrollPlugin);
                        mOverscrollPlugin);
+70 −7
Original line number Original line Diff line number Diff line
@@ -26,14 +26,17 @@ import static com.android.launcher3.Utilities.squaredHypot;


import android.content.Context;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.PointF;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewConfiguration;


import androidx.annotation.Nullable;
import androidx.annotation.Nullable;


import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.quickstep.GestureState;
import com.android.quickstep.GestureState;
import com.android.quickstep.InputConsumer;
import com.android.quickstep.InputConsumer;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.plugins.OverscrollPlugin;
import com.android.systemui.plugins.OverscrollPlugin;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.InputMonitorCompat;
@@ -47,12 +50,12 @@ public class OverscrollInputConsumer<T extends BaseDraggingActivity> extends Del


    private static final String TAG = "OverscrollInputConsumer";
    private static final String TAG = "OverscrollInputConsumer";


    private static final int ANGLE_THRESHOLD = 35; // Degrees

    private final PointF mDownPos = new PointF();
    private final PointF mDownPos = new PointF();
    private final PointF mLastPos = new PointF();
    private final PointF mLastPos = new PointF();
    private final PointF mStartDragPos = new PointF();
    private final PointF mStartDragPos = new PointF();
    private final int mAngleThreshold;


    private final float mFlingThresholdPx;
    private int mActivePointerId = -1;
    private int mActivePointerId = -1;
    private boolean mPassedSlop = false;
    private boolean mPassedSlop = false;


@@ -60,19 +63,28 @@ public class OverscrollInputConsumer<T extends BaseDraggingActivity> extends Del


    private final Context mContext;
    private final Context mContext;
    private final GestureState mGestureState;
    private final GestureState mGestureState;
    @Nullable private final OverscrollPlugin mPlugin;
    @Nullable
    private final OverscrollPlugin mPlugin;
    private final GestureDetector mGestureDetector;


    private RecentsView mRecentsView;
    private RecentsView mRecentsView;


    public OverscrollInputConsumer(Context context, GestureState gestureState,
    public OverscrollInputConsumer(Context context, GestureState gestureState,
            InputConsumer delegate, InputMonitorCompat inputMonitor, OverscrollPlugin plugin) {
            InputConsumer delegate, InputMonitorCompat inputMonitor, OverscrollPlugin plugin) {
        super(delegate, inputMonitor);
        super(delegate, inputMonitor);

        mAngleThreshold = context.getResources()
                .getInteger(R.integer.assistant_gesture_corner_deg_threshold);
        mFlingThresholdPx = context.getResources()
            .getDimension(R.dimen.gestures_overscroll_fling_threshold);
        mContext = context;
        mContext = context;
        mGestureState = gestureState;
        mGestureState = gestureState;
        mPlugin = plugin;
        mPlugin = plugin;


        float slop = ViewConfiguration.get(context).getScaledTouchSlop();
        float slop = ViewConfiguration.get(context).getScaledTouchSlop();

        mSquaredSlop = slop * slop;
        mSquaredSlop = slop * slop;
        mGestureDetector = new GestureDetector(context, new FlingGestureListener());


        gestureState.getActivityInterface().createActivityInitListener(this::onActivityInit)
        gestureState.getActivityInterface().createActivityInitListener(this::onActivityInit)
                .register();
                .register();
@@ -139,21 +151,29 @@ public class OverscrollInputConsumer<T extends BaseDraggingActivity> extends Del


                        mPassedSlop = true;
                        mPassedSlop = true;
                        mStartDragPos.set(mLastPos.x, mLastPos.y);
                        mStartDragPos.set(mLastPos.x, mLastPos.y);

                        if (isOverscrolled()) {
                        if (isOverscrolled()) {
                            setActive(ev);
                            setActive(ev);

                            if (mPlugin != null) {
                                mPlugin.onTouchStart(getDeviceState(), getUnderlyingActivity());
                            }
                        } else {
                        } else {
                            mState = STATE_DELEGATE_ACTIVE;
                            mState = STATE_DELEGATE_ACTIVE;
                        }
                        }
                    }
                    }
                }
                }


                if (mPassedSlop && mState != STATE_DELEGATE_ACTIVE && isOverscrolled()
                        && mPlugin != null) {
                    mPlugin.onTouchTraveled(getDistancePx());
                }

                break;
                break;
            }
            }
            case ACTION_CANCEL:
            case ACTION_CANCEL:
            case ACTION_UP:
            case ACTION_UP:
                if (mState != STATE_DELEGATE_ACTIVE && mPassedSlop && mPlugin != null) {
                if (mState != STATE_DELEGATE_ACTIVE && mPassedSlop && mPlugin != null) {
                    mPlugin.onOverscroll(getDeviceState());
                    mPlugin.onTouchEnd(getDistancePx());
                }
                }


                mPassedSlop = false;
                mPassedSlop = false;
@@ -161,6 +181,10 @@ public class OverscrollInputConsumer<T extends BaseDraggingActivity> extends Del
                break;
                break;
        }
        }


        if (mState != STATE_DELEGATE_ACTIVE) {
            mGestureDetector.onTouchEvent(ev);
        }

        if (mState != STATE_ACTIVE) {
        if (mState != STATE_ACTIVE) {
            mDelegate.onMotionEvent(ev);
            mDelegate.onMotionEvent(ev);
        }
        }
@@ -168,12 +192,19 @@ public class OverscrollInputConsumer<T extends BaseDraggingActivity> extends Del


    private boolean isOverscrolled() {
    private boolean isOverscrolled() {
        // Make sure there isn't an app to quick switch to on our right
        // Make sure there isn't an app to quick switch to on our right
        boolean atRightMostApp = (mRecentsView == null || mRecentsView.getRunningTaskIndex() <= 0);
        int maxIndex = 0;
        if ((mRecentsView instanceof LauncherRecentsView)
                && ((LauncherRecentsView) mRecentsView).hasRecentsExtraCard()) {
            maxIndex = 1;
        }

        boolean atRightMostApp = (mRecentsView == null
                || mRecentsView.getRunningTaskIndex() <= maxIndex);


        // Check if the gesture is within our angle threshold of horizontal
        // Check if the gesture is within our angle threshold of horizontal
        float deltaY = Math.abs(mLastPos.y - mDownPos.y);
        float deltaY = Math.abs(mLastPos.y - mDownPos.y);
        float deltaX = mDownPos.x - mLastPos.x; // Positive if this is a gesture to the left
        float deltaX = mDownPos.x - mLastPos.x; // Positive if this is a gesture to the left
        boolean angleInBounds = Math.toDegrees(Math.atan2(deltaY, deltaX)) < ANGLE_THRESHOLD;
        boolean angleInBounds = Math.toDegrees(Math.atan2(deltaY, deltaX)) < mAngleThreshold;


        return atRightMostApp && angleInBounds;
        return atRightMostApp && angleInBounds;
    }
    }
@@ -193,4 +224,36 @@ public class OverscrollInputConsumer<T extends BaseDraggingActivity> extends Del


        return deviceState;
        return deviceState;
    }
    }

    private int getDistancePx() {
        return (int) Math.hypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y);
    }

    private String getUnderlyingActivity() {
        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);
        }
    }
}
}
+5 −0
Original line number Original line Diff line number Diff line
@@ -377,6 +377,11 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements StateL
        addView(mRecentsExtraViewContainer, 0);
        addView(mRecentsExtraViewContainer, 0);
    }
    }


    @Override
    public boolean hasRecentsExtraCard() {
        return mRecentsExtraViewContainer != null;
    }

    @Override
    @Override
    public void setContentAlpha(float alpha) {
    public void setContentAlpha(float alpha) {
        super.setContentAlpha(alpha);
        super.setContentAlpha(alpha);
+5 −0
Original line number Original line Diff line number Diff line
@@ -830,6 +830,11 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl


    public abstract void startHome();
    public abstract void startHome();


    /** `true` if there is a +1 space available in overview. */
    public boolean hasRecentsExtraCard() {
        return false;
    }

    public void reset() {
    public void reset() {
        setCurrentTask(-1);
        setCurrentTask(-1);
        mIgnoreResetTaskId = -1;
        mIgnoreResetTaskId = -1;
+3 −0
Original line number Original line Diff line number Diff line
@@ -77,4 +77,7 @@


    <!-- Distance to move elements when swiping up to go home from launcher -->
    <!-- Distance to move elements when swiping up to go home from launcher -->
    <dimen name="home_pullback_distance">28dp</dimen>
    <dimen name="home_pullback_distance">28dp</dimen>

    <!-- Overscroll Gesture -->
    <dimen name="gestures_overscroll_fling_threshold">40dp</dimen>
</resources>
</resources>
Loading