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

Commit e461db8a authored by Mady Mellor's avatar Mady Mellor Committed by Android (Google) Code Review
Browse files

Merge "Update PIP minimize to edge gesture"

parents 1457cdcc 3b10dcd2
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ public class PipSnapAlgorithm {
    private int mOrientation = Configuration.ORIENTATION_UNDEFINED;

    private final int mMinimizedVisibleSize;
    private boolean mIsMinimized;

    public PipSnapAlgorithm(Context context) {
        mContext = context;
@@ -75,6 +76,13 @@ public class PipSnapAlgorithm {
        calculateSnapTargets();
    }

    /**
     * Sets the PIP's minimized state.
     */
    public void setMinimized(boolean isMinimized) {
        mIsMinimized = isMinimized;
    }

    /**
     * Enables snapping to the closest edge.
     */
@@ -251,8 +259,7 @@ public class PipSnapAlgorithm {
        final int boundedTop = Math.max(movementBounds.top, Math.min(movementBounds.bottom,
                stackBounds.top));
        boundsOut.set(stackBounds);
        if (stackBounds.left < movementBounds.left ||
                stackBounds.left > movementBounds.right) {
        if (mIsMinimized) {
            boundsOut.offsetTo(boundedLeft, boundsOut.top);
            return;
        }
+52 −103
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ public class PipTouchHandler implements TunerService.Tunable {
    private static final int MINIMIZE_STACK_MAX_DURATION = 200;

    // The fraction of the stack width that the user has to drag offscreen to minimize the PIP
    private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.15f;
    private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.2f;

    private final Context mContext;
    private final IActivityManager mActivityManager;
@@ -183,7 +183,7 @@ public class PipTouchHandler implements TunerService.Tunable {
        mTouchState = new PipTouchState(mViewConfig);
        mFlingAnimationUtils = new FlingAnimationUtils(context, 2f);
        mGestures = new PipTouchGesture[] {
                mDragToDismissGesture, mTapThroughGesture, mMinimizeGesture, mDefaultMovementGesture
                mDragToDismissGesture, mDefaultMovementGesture
        };
        mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler());
        registerInputConsumer();
@@ -231,6 +231,7 @@ public class PipTouchHandler implements TunerService.Tunable {

    public void onMinimizedStateChanged(boolean isMinimized) {
        mIsMinimized = isMinimized;
        mSnapAlgorithm.setMinimized(isMinimized);
    }

    public void onSnapToEdgeStateChanged(boolean isSnapToEdge) {
@@ -298,14 +299,13 @@ public class PipTouchHandler implements TunerService.Tunable {
    }

    /**
     * @return whether the current touch state is a horizontal drag offscreen.
     * @return whether the current touch state places the pip partially offscreen.
     */
    private boolean isDraggingOffscreen(PipTouchState touchState) {
        PointF lastDelta = touchState.getLastTouchDelta();
        PointF downDelta = touchState.getDownTouchDelta();
        float left = mPinnedStackBounds.left + lastDelta.x;
        return !(mBoundedPinnedStackBounds.left <= left && left <= mBoundedPinnedStackBounds.right)
                && Math.abs(downDelta.x) > Math.abs(downDelta.y);
        return !(mBoundedPinnedStackBounds.left <= left && left <= mBoundedPinnedStackBounds.right);
    }

    /**
@@ -429,7 +429,7 @@ public class PipTouchHandler implements TunerService.Tunable {
                mUpdatePinnedStackBoundsListener);
        mPinnedStackBoundsAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
            public void onAnimationStart(Animator animation) {
                mMenuController.hideMenu();
            }
        });
@@ -589,116 +589,23 @@ public class PipTouchHandler implements TunerService.Tunable {

    /**** Gestures ****/

    /**
     * Gesture controlling dragging the PIP slightly offscreen to minimize it.
     */
    private PipTouchGesture mMinimizeGesture = new PipTouchGesture() {
        @Override
        boolean onMove(PipTouchState touchState) {
            if (mEnableMinimizing) {
                boolean isDraggingOffscreen = isDraggingOffscreen(touchState);
                if (touchState.startedDragging() && isDraggingOffscreen) {
                    // Reset the minimized state once we drag horizontally
                    setMinimizedState(false);
                }

                if (touchState.allowDraggingOffscreen() && isDraggingOffscreen) {
                    // Move the pinned stack, but ignore the vertical movement
                    float left = mPinnedStackBounds.left + touchState.getLastTouchDelta().x;
                    mTmpBounds.set(mPinnedStackBounds);
                    mTmpBounds.offsetTo((int) left, mPinnedStackBounds.top);
                    if (!mTmpBounds.equals(mPinnedStackBounds)) {
                        mPinnedStackBounds.set(mTmpBounds);
                        mMotionHelper.resizeToBounds(mPinnedStackBounds);
                    }
                    return true;
                } else if (mIsMinimized && touchState.isDragging()) {
                    // Move the pinned stack, but ignore the horizontal movement
                    PointF lastDelta = touchState.getLastTouchDelta();
                    float top = mPinnedStackBounds.top + lastDelta.y;
                    top = Math.max(mBoundedPinnedStackBounds.top, Math.min(
                            mBoundedPinnedStackBounds.bottom, top));
                    mTmpBounds.set(mPinnedStackBounds);
                    mTmpBounds.offsetTo(mPinnedStackBounds.left, (int) top);
                    movePinnedStack(mTmpBounds);
                    return true;
                }
            }
            return false;
        }

        @Override
        public boolean onUp(PipTouchState touchState) {
            if (mEnableMinimizing) {
                if (touchState.isDragging()) {
                    if (isDraggingOffscreen(touchState)) {
                        if (shouldMinimizedPinnedStack()) {
                            setMinimizedState(true);
                            animateToClosestMinimizedTarget();
                            return true;
                        }
                    } else if (mIsMinimized) {
                        PointF vel = touchState.getVelocity();
                        if (vel.length() > mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
                            flingToMinimizedSnapTarget(vel.y);
                        } else {
                            animateToClosestMinimizedTarget();
                        }
                        return true;
                    }
                } else if (mIsMinimized) {
                    setMinimizedState(false);
                    animateToClosestSnapTarget();
                    return true;
                }
            }
            return false;
        }
    };

    /**
     * Gesture controlling tapping on the PIP to show an overlay.
     */
    private PipTouchGesture mTapThroughGesture = new PipTouchGesture() {
        @Override
        boolean onMove(PipTouchState touchState) {
            return false;
        }

        @Override
        public boolean onUp(PipTouchState touchState) {
            if (!touchState.isDragging() && !mIsMinimized && !mIsTappingThrough) {
                mMenuController.showMenu();
                mIsTappingThrough = true;
                return true;
            }
            return false;
        }
    };

    /**
     * Gesture controlling normal movement of the PIP.
     */
    private PipTouchGesture mDefaultMovementGesture = new PipTouchGesture() {
        @Override
        boolean onMove(PipTouchState touchState) {
            if (touchState.startedDragging()) {
                // For now, once the user has started a drag that the other gestures have not
                // intercepted, disallow those gestures from intercepting again to drag offscreen
                touchState.setDisallowDraggingOffscreen();
            }

            if (touchState.isDragging()) {
                // Move the pinned stack freely
                PointF lastDelta = touchState.getLastTouchDelta();
                float left = mPinnedStackBounds.left + lastDelta.x;
                float top = mPinnedStackBounds.top + lastDelta.y;
                if (!DEBUG_ALLOW_OUT_OF_BOUNDS_STACK) {
                if (!touchState.allowDraggingOffscreen()) {
                    left = Math.max(mBoundedPinnedStackBounds.left, Math.min(
                            mBoundedPinnedStackBounds.right, left));
                }
                top = Math.max(mBoundedPinnedStackBounds.top, Math.min(
                        mBoundedPinnedStackBounds.bottom, top));
                }
                mTmpBounds.set(mPinnedStackBounds);
                mTmpBounds.offsetTo((int) left, (int) top);
                movePinnedStack(mTmpBounds);
@@ -711,16 +618,58 @@ public class PipTouchHandler implements TunerService.Tunable {
        public boolean onUp(PipTouchState touchState) {
            if (touchState.isDragging()) {
                PointF vel = mTouchState.getVelocity();
                float velocity = PointF.length(vel.x, vel.y);
                if (!mIsMinimized && (shouldMinimizedPinnedStack()
                        || isHorizontalFlingTowardsCurrentEdge(vel))) {
                    // Pip should be minimized
                    setMinimizedState(true);
                    animateToClosestMinimizedTarget();
                    return true;
                }
                if (mIsMinimized) {
                    // If we're dragging and it wasn't a minimize gesture
                    // then we shouldn't be minimized.
                    setMinimizedState(false);
                }

                final float velocity = PointF.length(vel.x, vel.y);
                if (velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
                    flingToSnapTarget(velocity, vel.x, vel.y);
                } else {
                    animateToClosestSnapTarget();
                }
            } else if (mIsMinimized) {
                // This was a tap, so no longer minimized
                animateToClosestSnapTarget();
                setMinimizedState(false);
            } else if (!mIsTappingThrough) {
                mMenuController.showMenu();
                mIsTappingThrough = true;
            } else {
                expandPinnedStackToFullscreen();
            }
            return true;
        }
    };

    /**
     * @return whether the gesture ending in the {@param vel} is fast enough to be a fling towards
     *         the same edge the PIP is on. Used to identify a minimize gesture.
     */
    private boolean isHorizontalFlingTowardsCurrentEdge(PointF vel) {
        final boolean isHorizontal = Math.abs(vel.x) > Math.abs(vel.y);
        final boolean isFling = PointF.length(vel.x, vel.y) > mFlingAnimationUtils
                .getMinVelocityPxPerSecond();
        final boolean towardsCurrentEdge = onEdge(true /* left */) && vel.x < 0
                || onEdge(false /* right */) && vel.x > 0;
        return towardsCurrentEdge && isHorizontal && isFling;
    }

    private boolean onEdge(boolean checkLeft) {
        if (checkLeft) {
            return mPinnedStackBounds.left <= mBoundedPinnedStackBounds.left;
        } else {
            return mPinnedStackBounds.right >= mBoundedPinnedStackBounds.right
                    + mPinnedStackBounds.width();
        }
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ class PinnedStackController {
        public void setIsMinimized(final boolean isMinimized) {
            mHandler.post(() -> {
                mIsMinimized = isMinimized;
                mSnapAlgorithm.setMinimized(isMinimized);
            });
        }