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

Commit 6292565f authored by Ben Lin's avatar Ben Lin Committed by Android (Google) Code Review
Browse files

Merge changes If42d4470,Ia0b701b7 into sc-dev

* changes:
  PiP: Add tap-to-unstash function.
  PiP: Allow stashing via dropping on the edge.
parents 98d8a3a9 eded2ac4
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -424,6 +424,12 @@ public final class SystemUiDeviceConfigFlags {
     */
    public static final String PIP_STASHING = "pip_stashing";

    /**
     * (float) The threshold velocity to cause PiP to be stashed when flinging from one edge to the
     * other.
     */
    public static final String PIP_STASH_MINIMUM_VELOCITY_THRESHOLD = "pip_velocity_threshold";

    /**
     * (float) Bottom height in DP for Back Gesture.
     */
+8 −1
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Debug;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.Choreographer;
@@ -62,6 +61,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,

    private static final int SHRINK_STACK_FROM_MENU_DURATION = 250;
    private static final int EXPAND_STACK_TO_MENU_DURATION = 250;
    private static final int UNSTASH_DURATION = 250;
    private static final int LEAVE_PIP_DURATION = 300;
    private static final int SHIFT_DURATION = 300;

@@ -481,6 +481,13 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
        }
    }

    /**
     * Animates the PiP from stashed state into un-stashed, popping it out from the edge.
     */
    void animateToUnStashedBounds(Rect unstashedBounds) {
        resizeAndAnimatePipUnchecked(unstashedBounds, UNSTASH_DURATION);
    }

    /**
     * Animates the PiP to offset it from the IME or shelf.
     */
+73 −19
Original line number Diff line number Diff line
@@ -17,7 +17,9 @@
package com.android.wm.shell.pip.phone;

import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_STASHING;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_STASH_MINIMUM_VELOCITY_THRESHOLD;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
import static com.android.wm.shell.pip.PipBoundsState.STASH_TYPE_NONE;
import static com.android.wm.shell.pip.phone.PhonePipMenuController.MENU_STATE_CLOSE;
import static com.android.wm.shell.pip.phone.PhonePipMenuController.MENU_STATE_FULL;
import static com.android.wm.shell.pip.phone.PhonePipMenuController.MENU_STATE_NONE;
@@ -61,9 +63,8 @@ import java.util.function.Consumer;
 */
public class PipTouchHandler {
    private static final String TAG = "PipTouchHandler";

    private static final float STASH_MINIMUM_VELOCITY_X = 3000.f;
    private static final float MINIMUM_SIZE_PERCENT = 0.4f;
    private static final float DEFAULT_STASH_VELOCITY_THRESHOLD = 18000.f;

    // Allow PIP to resize to a slightly bigger state upon touch
    private final boolean mEnableResize;
@@ -86,6 +87,8 @@ public class PipTouchHandler {
     */
    private boolean mEnableStash = true;

    private float mStashVelocityThreshold;

    // The reference inset bounds, used to determine the dismiss fraction
    private final Rect mInsetBounds = new Rect();
    private int mExpandedShortestEdgeSize;
@@ -175,9 +178,17 @@ public class PipTouchHandler {
        mPipDismissTargetHandler = new PipDismissTargetHandler(context, pipUiEventLogger,
                mMotionHelper, mainExecutor);
        mTouchState = new PipTouchState(ViewConfiguration.get(context),
                () -> mMenuController.showMenuWithPossibleDelay(MENU_STATE_FULL,
                        mPipBoundsState.getBounds(), true /* allowMenuTimeout */, willResizeMenu(),
                        shouldShowResizeHandle()),
                () -> {
                    if (mPipBoundsState.isStashed()) {
                        animateToUnStashedState();
                        mPipBoundsState.setStashed(STASH_TYPE_NONE);
                    } else {
                        mMenuController.showMenuWithPossibleDelay(MENU_STATE_FULL,
                                mPipBoundsState.getBounds(), true /* allowMenuTimeout */,
                                willResizeMenu(),
                                shouldShowResizeHandle());
                    }
                },
                menuController::hideMenu,
                mainExecutor);

@@ -204,6 +215,19 @@ public class PipTouchHandler {
                                PIP_STASHING, /* defaultValue = */ true);
                    }
                });
        mStashVelocityThreshold = DeviceConfig.getFloat(
                DeviceConfig.NAMESPACE_SYSTEMUI,
                PIP_STASH_MINIMUM_VELOCITY_THRESHOLD,
                DEFAULT_STASH_VELOCITY_THRESHOLD);
        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
                mainExecutor,
                properties -> {
                    if (properties.getKeyset().contains(PIP_STASH_MINIMUM_VELOCITY_THRESHOLD)) {
                        mStashVelocityThreshold = properties.getFloat(
                                PIP_STASH_MINIMUM_VELOCITY_THRESHOLD,
                                DEFAULT_STASH_VELOCITY_THRESHOLD);
                    }
                });
    }

    private void reloadResources() {
@@ -709,6 +733,17 @@ public class PipTouchHandler {
        mSavedSnapFraction = -1f;
    }

    private void animateToUnStashedState() {
        final Rect pipBounds = mPipBoundsState.getBounds();
        final boolean onLeftEdge = pipBounds.left < mPipBoundsState.getDisplayBounds().left;
        final Rect unStashedBounds = new Rect(0, pipBounds.top, 0, pipBounds.bottom);
        unStashedBounds.left = onLeftEdge ? mInsetBounds.left
                : mInsetBounds.right - pipBounds.width();
        unStashedBounds.right = onLeftEdge ? mInsetBounds.left + pipBounds.width()
                : mInsetBounds.right;
        mMotionHelper.animateToUnStashedBounds(unStashedBounds);
    }

    /**
     * @return the motion helper.
     */
@@ -772,7 +807,7 @@ public class PipTouchHandler {
            }

            if (touchState.startedDragging()) {
                mPipBoundsState.setStashed(PipBoundsState.STASH_TYPE_NONE);
                mPipBoundsState.setStashed(STASH_TYPE_NONE);
                mSavedSnapFraction = -1f;
                mPipDismissTargetHandler.showDismissTargetMaybe();
            }
@@ -825,14 +860,8 @@ public class PipTouchHandler {

                // Reset the touch state on up before the fling settles
                mTouchState.reset();
                // If user flings the PIP window above the minimum velocity, stash PIP.
                // Only allow stashing to the edge if the user starts dragging the PIP from that
                // edge.
                if (mEnableStash && !mPipBoundsState.isStashed()
                        && ((vel.x > STASH_MINIMUM_VELOCITY_X
                        && mDownSavedFraction > 1f && mDownSavedFraction < 2f)
                        || (vel.x < -STASH_MINIMUM_VELOCITY_X
                        && mDownSavedFraction > 3f && mDownSavedFraction < 4f))) {
                        && shouldStash(vel, getPossiblyMotionBounds())) {
                    mMotionHelper.stashToEdge(vel.x, this::stashEndAction /* endAction */);
                } else {
                    mMotionHelper.flingToSnapTarget(vel.x, vel.y,
@@ -857,13 +886,18 @@ public class PipTouchHandler {
                    setTouchEnabled(false);
                    mMotionHelper.expandLeavePip();
                }
            } else if (mMenuState != MENU_STATE_FULL && !mPipBoundsState.isStashed()) {
            } else if (mMenuState != MENU_STATE_FULL) {
                if (!mTouchState.isWaitingForDoubleTap()) {
                    // User has stalled long enough for this not to be a drag or a double tap, just
                    // expand the menu
                    if (mPipBoundsState.isStashed()) {
                        animateToUnStashedState();
                        mPipBoundsState.setStashed(STASH_TYPE_NONE);
                    } else {
                        // User has stalled long enough for this not to be a drag or a double tap,
                        // just expand the menu
                        mMenuController.showMenu(MENU_STATE_FULL, mPipBoundsState.getBounds(),
                                true /* allowMenuTimeout */, willResizeMenu(),
                                shouldShowResizeHandle());
                    }
                } else {
                    // Next touch event _may_ be the second tap for the double-tap, schedule a
                    // fallback runnable to trigger the menu if no touch event occurs before the
@@ -894,6 +928,26 @@ public class PipTouchHandler {
                mPipExclusionBoundsChangeListener.get().accept(new Rect());
            }
        }

        private boolean shouldStash(PointF vel, Rect motionBounds) {
            // If user flings the PIP window above the minimum velocity, stash PIP.
            // Only allow stashing to the edge if the user starts dragging the PIP from the
            // opposite edge.
            final boolean stashFromFlingToEdge = ((vel.x < -mStashVelocityThreshold
                    && mDownSavedFraction > 1f && mDownSavedFraction < 2f)
                    || (vel.x > mStashVelocityThreshold
                    && mDownSavedFraction > 3f && mDownSavedFraction < 4f));

            // If User releases the PIP window while it's out of the display bounds, put
            // PIP into stashed mode.
            final int offset = motionBounds.width() / 2;
            final boolean stashFromDroppingOnEdge =
                    (motionBounds.right > mPipBoundsState.getDisplayBounds().right + offset
                            || motionBounds.left
                            < mPipBoundsState.getDisplayBounds().left - offset);

            return stashFromFlingToEdge || stashFromDroppingOnEdge;
        }
    }

    void setPipExclusionBoundsChangeListener(Consumer<Rect> pipExclusionBoundsChangeListener) {