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

Commit 06927c22 authored by Joshua Tsuji's avatar Joshua Tsuji
Browse files

Fix PIP snapping to incorrect location.

animateToClosestSnapTarget is no longer used, we always use flingToSnapTarget now. If velocity is low/zero, the fling animation will end and a spring animation will spring it to the nearest allowable location.

This also incorporates a fix to PhysicsAnimator (cl/296316037) to more accurately decide if a fling is strong enough to reach the other side of the screen. This fixes an issue where pushing PIP off-screen and then very gently moving it back on screen caused it to jump to the other side of the screen.

Fixes: 154937295
Test: manual
Change-Id: I6f0284195bcb802f4cdd58cc06457023dcf63aa1
parent 6dfbdb3e
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -327,15 +327,6 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
        startBoundsAnimator(xEndValue /* toX */, estimatedFlingYEndValue /* toY */);
    }

    /**
     * Animates the PiP to the closest snap target.
     */
    void animateToClosestSnapTarget() {
        final Rect newBounds = new Rect();
        mSnapAlgorithm.snapRectToClosestEdge(mBounds, mMovementBounds, newBounds);
        animateToBounds(newBounds, mSpringConfig);
    }

    /**
     * Animates PIP to the provided bounds, using physics animations and the given spring
     * configuration
+3 −8
Original line number Diff line number Diff line
@@ -885,7 +885,6 @@ public class PipTouchHandler {

            final PointF vel = touchState.getVelocity();
            final float velocity = PointF.length(vel.x, vel.y);
            final boolean isFling = velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond();

            if (touchState.isDragging()) {
                Runnable endAction = null;
@@ -900,13 +899,9 @@ public class PipTouchHandler {
                    endAction = mMenuController::hideMenu;
                }

                if (isFling) {
                mMotionHelper.flingToSnapTarget(vel.x, vel.y,
                        PipTouchHandler.this::updateDismissFraction /* updateAction */,
                        endAction /* endAction */);
                } else {
                    mMotionHelper.animateToClosestSnapTarget();
                }
            } else if (mTouchState.isDoubleTap()) {
                // Expand to fullscreen if this is a double tap
                // the PiP should be frozen until the transition ends
+21 −4
Original line number Diff line number Diff line
@@ -311,10 +311,25 @@ class PhysicsAnimator<T> private constructor (val target: T) {
        val springConfigCopy = springConfig.copy()
        val toAtLeast = if (startVelocity < 0) flingConfig.min else flingConfig.max

        // If the fling needs to reach min/max, calculate the velocity required to do so and use
        // that if the provided start velocity is not sufficient.
        if (flingMustReachMinOrMax &&
                toAtLeast != -Float.MAX_VALUE && toAtLeast != Float.MAX_VALUE) {
        if (flingMustReachMinOrMax && isValidValue(toAtLeast)) {
            val currentValue = property.getValue(target)
            val flingTravelDistance =
                    startVelocity / (flingConfig.friction * FLING_FRICTION_SCALAR_MULTIPLIER)
            val projectedFlingEndValue = currentValue + flingTravelDistance
            val midpoint = (flingConfig.min + flingConfig.max) / 2

            // If fling velocity is too low to push the target past the midpoint between min and
            // max, then spring back towards the nearest edge, starting with the current velocity.
            if ((startVelocity < 0 && projectedFlingEndValue > midpoint) ||
                    (startVelocity > 0 && projectedFlingEndValue < midpoint)) {
                val toPosition =
                        if (projectedFlingEndValue < midpoint) flingConfig.min else flingConfig.max
                if (isValidValue(toPosition)) {
                    return spring(property, toPosition, startVelocity, springConfig)
                }
            }

            // Projected fling end value is past the midpoint, so fling forward.
            val distanceToDestination = toAtLeast - property.getValue(target)

            // The minimum velocity required for the fling to end up at the given destination,
@@ -345,6 +360,8 @@ class PhysicsAnimator<T> private constructor (val target: T) {
        return this
    }

    private fun isValidValue(value: Float) = value < Float.MAX_VALUE && value > -Float.MAX_VALUE

    /**
     * Adds a listener that will be called whenever any property on the animated object is updated.
     * This will be called on every animation frame, with the current value of the animated object