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

Commit 104b2de2 authored by Ben Lin's avatar Ben Lin
Browse files

Add stash support for PIP.

Bug: 165793553
Test: adb shell cmd device_config put systemui pip_stashing true
Test: Drag PIP Window to outside of display and see it stashed
Change-Id: I59e5475162cd3353e2bcbdf38bd5c5a22561a578
parent 07ca993a
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -394,6 +394,11 @@ public final class SystemUiDeviceConfigFlags {
     */
    public static final String PIP_PINCH_RESIZE = "pip_pinch_resize";

    /**
     * (boolean) Whether to enable stashing for PIP.
     */
    public static final String PIP_STASHING = "pip_stashing";

    /**
     * (float) Bottom height in DP for Back Gesture.
     */
+28 −3
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
    private static final int EXPAND_STACK_TO_MENU_DURATION = 250;
    private static final int LEAVE_PIP_DURATION = 300;
    private static final int SHIFT_DURATION = 300;
    private static final float STASH_RATIO = 0.25f;

    /** Friction to use for PIP when it moves via physics fling animations. */
    private static final float DEFAULT_FRICTION = 2f;
@@ -120,6 +121,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
    /** FlingConfig instances provided to PhysicsAnimator for fling gestures. */
    private PhysicsAnimator.FlingConfig mFlingConfigX;
    private PhysicsAnimator.FlingConfig mFlingConfigY;
    /** FlingConfig instances proviced to PhysicsAnimator for stashing. */
    private PhysicsAnimator.FlingConfig mStashConfigX;

    /** SpringConfig to use for fling-then-spring animations. */
    private final PhysicsAnimator.SpringConfig mSpringConfig =
@@ -383,6 +386,21 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
    void flingToSnapTarget(
            float velocityX, float velocityY,
            @Nullable Runnable updateAction, @Nullable Runnable endAction) {
        movetoTarget(velocityX, velocityY, updateAction, endAction, false /* isStash */);
    }

    /**
     * Stash PiP to the closest edge.
     */
    void stashToEdge(
            float velocityX, float velocityY,
            @Nullable Runnable updateAction, @Nullable Runnable endAction) {
        movetoTarget(velocityX, velocityY, updateAction, endAction, true /* isStash */);
    }

    private void movetoTarget(
            float velocityX, float velocityY,
            @Nullable Runnable updateAction, @Nullable Runnable endAction, boolean isStash) {
        // If we're flinging to a snap target now, we're not springing to catch up to the touch
        // location now.
        mSpringingToTouch = false;
@@ -391,8 +409,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
                .spring(FloatProperties.RECT_WIDTH, mBounds.width(), mSpringConfig)
                .spring(FloatProperties.RECT_HEIGHT, mBounds.height(), mSpringConfig)
                .flingThenSpring(
                        FloatProperties.RECT_X, velocityX, mFlingConfigX, mSpringConfig,
                        true /* flingMustReachMinOrMax */)
                        FloatProperties.RECT_X, velocityX, isStash ? mStashConfigX : mFlingConfigX,
                        mSpringConfig, true /* flingMustReachMinOrMax */)
                .flingThenSpring(
                        FloatProperties.RECT_Y, velocityY, mFlingConfigY, mSpringConfig)
                .withEndActions(endAction);
@@ -402,7 +420,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
                    (target, values) -> updateAction.run());
        }

        final float xEndValue = velocityX < 0 ? mMovementBounds.left : mMovementBounds.right;
        final float offset = ((float) mBounds.width()) * (1.0f - STASH_RATIO);
        final float leftEdge = isStash ? mMovementBounds.left - offset : mMovementBounds.left;
        final float rightEdge = isStash ?  mMovementBounds.right + offset : mMovementBounds.right;

        final float xEndValue = velocityX < 0 ? leftEdge : rightEdge;
        final float estimatedFlingYEndValue =
                PhysicsAnimator.estimateFlingEndValue(
                        mTemporaryBounds.top, velocityY, mFlingConfigY);
@@ -506,6 +528,9 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
                DEFAULT_FRICTION, mMovementBounds.left, mMovementBounds.right);
        mFlingConfigY = new PhysicsAnimator.FlingConfig(
                DEFAULT_FRICTION, mMovementBounds.top, mMovementBounds.bottom);
        final float offset = ((float) mBounds.width()) * (1.0f - STASH_RATIO);
        mStashConfigX = new PhysicsAnimator.FlingConfig(
                DEFAULT_FRICTION, mMovementBounds.left - offset, mMovementBounds.right + offset);
    }

    /**
+39 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.pip.phone;

import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_STASHING;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE;
import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_FULL;
@@ -33,6 +34,7 @@ import android.graphics.Rect;
import android.graphics.drawable.TransitionDrawable;
import android.os.Handler;
import android.os.RemoteException;
import android.provider.DeviceConfig;
import android.util.Log;
import android.util.Size;
import android.view.Gravity;
@@ -101,6 +103,13 @@ public class PipTouchHandler {
    private final AccessibilityManager mAccessibilityManager;
    private boolean mShowPipMenuOnAnimationEnd = false;

    /**
     * Whether PIP stash is enabled or not. When enabled, if at the time of fling-release the
     * PIP bounds is outside the left/right edge of the screen, it will be shown in "stashed" mode,
     * where PIP will only show partially.
     */
    private boolean mEnableStash = false;

    /**
     * MagnetizedObject wrapper for PIP. This allows the magnetic target library to locate and move
     * PIP.
@@ -306,6 +315,22 @@ public class PipTouchHandler {
        });

        mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView);

        mEnableStash = DeviceConfig.getBoolean(
                DeviceConfig.NAMESPACE_SYSTEMUI,
                PIP_STASHING,
                /* defaultValue = */ false);
        deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
                context.getMainExecutor(),
                new DeviceConfig.OnPropertiesChangedListener() {
                    @Override
                    public void onPropertiesChanged(DeviceConfig.Properties properties) {
                        if (properties.getKeyset().contains(PIP_STASHING)) {
                            mEnableStash = properties.getBoolean(
                                    PIP_STASHING, /* defaultValue = */ false);
                        }
                    }
                });
    }

    private void reloadResources() {
@@ -986,9 +1011,20 @@ public class PipTouchHandler {

                // Reset the touch state on up before the fling settles
                mTouchState.reset();
                final Rect animatingBounds = mMotionHelper.getPossiblyAnimatingBounds();
                // If User releases the PIP window while it's out of the display bounds, put
                // PIP into stashed mode.
                if (mEnableStash
                        && (animatingBounds.right > mPipBoundsHandler.getDisplayBounds().right
                        || animatingBounds.left < mPipBoundsHandler.getDisplayBounds().left)) {
                    mMotionHelper.stashToEdge(vel.x, vel.y,
                            PipTouchHandler.this::updateDismissFraction /* updateAction */,
                            this::flingEndAction /* endAction */);
                } else {
                    mMotionHelper.flingToSnapTarget(vel.x, vel.y,
                            PipTouchHandler.this::updateDismissFraction /* updateAction */,
                            this::flingEndAction /* endAction */);
                }
            } else if (mTouchState.isDoubleTap()) {
                // Expand to fullscreen if this is a double tap
                // the PiP should be frozen until the transition ends