diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 1d85e9fceac9c..b87a642a8dc78 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -57,6 +57,9 @@
4dp
0dp
+
+ 32dp
+
24dp
50dp
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
index d0ab31dd72c89..fc523aef9d16b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
@@ -37,6 +37,7 @@ public final class PipBoundsState {
private final @NonNull Rect mBounds = new Rect();
private float mAspectRatio;
+ private boolean mIsStashed;
private PipReentryState mPipReentryState;
private ComponentName mLastPipComponentName;
private final DisplayInfo mDisplayInfo = new DisplayInfo();
@@ -54,6 +55,20 @@ public final class PipBoundsState {
return new Rect(mBounds);
}
+ /**
+ * Dictate where PiP currently should be stashed or not.
+ */
+ public void setStashed(boolean isStashed) {
+ mIsStashed = isStashed;
+ }
+
+ /**
+ * Whether PiP is stashed or not.
+ */
+ public boolean isStashed() {
+ return mIsStashed;
+ }
+
public void setAspectRatio(float aspectRatio) {
mAspectRatio = aspectRatio;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
index 9240b3f41ff4b..9247c683a0820 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
@@ -33,6 +33,7 @@ import androidx.dynamicanimation.animation.AnimationHandler;
import androidx.dynamicanimation.animation.AnimationHandler.FrameCallbackScheduler;
import androidx.dynamicanimation.animation.SpringForce;
+import com.android.wm.shell.R;
import com.android.wm.shell.animation.FloatProperties;
import com.android.wm.shell.animation.PhysicsAnimator;
import com.android.wm.shell.common.FloatingContentCoordinator;
@@ -60,7 +61,6 @@ 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;
@@ -94,6 +94,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
/** The destination bounds to which PIP is animating. */
private final Rect mAnimatingToBounds = new Rect();
+ private int mStashOffset = 0;
+
/** Coordinator instance for resolving conflicts with other floating content. */
private FloatingContentCoordinator mFloatingContentCoordinator;
@@ -189,6 +191,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
mPipTaskOrganizer.registerPipTransitionCallback(mPipTransitionCallback);
mTemporaryBoundsPhysicsAnimator.setCustomAnimationHandler(
mSfAnimationHandlerThreadLocal.get());
+ reloadResources();
mResizePipUpdateListener = (target, values) -> {
if (!mTemporaryBounds.isEmpty()) {
@@ -198,6 +201,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
};
}
+ void reloadResources() {
+ mStashOffset = mContext.getResources()
+ .getDimensionPixelSize(R.dimen.pip_stash_offset);
+ }
+
@NonNull
@Override
public Rect getFloatingBoundsOnScreen() {
@@ -414,9 +422,10 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
FloatProperties.RECT_Y, velocityY, mFlingConfigY, mSpringConfig)
.withEndActions(endAction);
- final float offset = ((float) getBounds().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 leftEdge = isStash ? mStashOffset - mPipBoundsState.getBounds().width()
+ : mMovementBounds.left;
+ final float rightEdge = isStash ? mPipBoundsState.getDisplayBounds().right - mStashOffset
+ : mMovementBounds.right;
final float xEndValue = velocityX < 0 ? leftEdge : rightEdge;
final float estimatedFlingYEndValue =
@@ -524,9 +533,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) getBounds().width()) * (1.0f - STASH_RATIO);
mStashConfigX = new PhysicsAnimator.FlingConfig(
- DEFAULT_FRICTION, mMovementBounds.left - offset, mMovementBounds.right + offset);
+ DEFAULT_FRICTION, mStashOffset - mPipBoundsState.getBounds().width(),
+ mPipBoundsState.getDisplayBounds().right - mStashOffset);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index ef3875597aa28..f3d8c7b0f5982 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -47,6 +47,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.policy.TaskResizingAlgorithm;
import com.android.wm.shell.R;
import com.android.wm.shell.pip.PipBoundsHandler;
+import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipUiEventLogger;
@@ -67,6 +68,7 @@ public class PipResizeGestureHandler {
private final Context mContext;
private final PipBoundsHandler mPipBoundsHandler;
private final PipMotionHelper mMotionHelper;
+ private final PipBoundsState mPipBoundsState;
private final int mDisplayId;
private final Executor mMainExecutor;
private final ScaleGestureDetector mScaleGestureDetector;
@@ -107,13 +109,15 @@ public class PipResizeGestureHandler {
private int mCtrlType;
public PipResizeGestureHandler(Context context, PipBoundsHandler pipBoundsHandler,
- PipMotionHelper motionHelper, PipTaskOrganizer pipTaskOrganizer,
- Function movementBoundsSupplier, Runnable updateMovementBoundsRunnable,
- PipUiEventLogger pipUiEventLogger, PipMenuActivityController menuActivityController) {
+ PipBoundsState pipBoundsState, PipMotionHelper motionHelper,
+ PipTaskOrganizer pipTaskOrganizer, Function movementBoundsSupplier,
+ Runnable updateMovementBoundsRunnable, PipUiEventLogger pipUiEventLogger,
+ PipMenuActivityController menuActivityController) {
mContext = context;
mDisplayId = context.getDisplayId();
mMainExecutor = context.getMainExecutor();
mPipBoundsHandler = pipBoundsHandler;
+ mPipBoundsState = pipBoundsState;
mMotionHelper = motionHelper;
mPipTaskOrganizer = pipTaskOrganizer;
mMovementBoundsSupplier = movementBoundsSupplier;
@@ -263,6 +267,11 @@ public class PipResizeGestureHandler {
}
private void onInputEvent(InputEvent ev) {
+ // Don't allow resize when PiP is stashed.
+ if (mPipBoundsState.isStashed()) {
+ return;
+ }
+
if (ev instanceof MotionEvent) {
if (mUsingPinchToZoom) {
mScaleGestureDetector.onTouchEvent((MotionEvent) ev);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index e95e4a07ed922..d820e772d490b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -179,8 +179,8 @@ public class PipTouchHandler {
mMotionHelper = new PipMotionHelper(mContext, pipBoundsState, pipTaskOrganizer,
mMenuController, mPipBoundsHandler.getSnapAlgorithm(), floatingContentCoordinator);
mPipResizeGestureHandler =
- new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper,
- pipTaskOrganizer, this::getMovementBounds,
+ new PipResizeGestureHandler(context, pipBoundsHandler, pipBoundsState,
+ mMotionHelper, pipTaskOrganizer, this::getMovementBounds,
this::updateMovementBounds, pipUiEventLogger, menuController);
mPipDismissTargetHandler = new PipDismissTargetHandler(context, pipUiEventLogger,
mMotionHelper, mHandler);
@@ -221,6 +221,7 @@ public class PipTouchHandler {
R.dimen.pip_expanded_shortest_edge_size);
mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
mPipDismissTargetHandler.updateMagneticTargetSize();
+ mMotionHelper.reloadResources();
}
private boolean shouldShowResizeHandle() {
@@ -463,7 +464,7 @@ public class PipTouchHandler {
}
MotionEvent ev = (MotionEvent) inputEvent;
- if (mPipResizeGestureHandler.willStartResizeGesture(ev)) {
+ if (!mPipBoundsState.isStashed() && mPipResizeGestureHandler.willStartResizeGesture(ev)) {
// Initialize the touch state for the gesture, but immediately reset to invalidate the
// gesture
mTouchState.onTouchEvent(ev);
@@ -553,6 +554,8 @@ public class PipTouchHandler {
}
}
+ shouldDeliverToMenu |= !mPipBoundsState.isStashed();
+
// Deliver the event to PipMenuActivity to handle button click if the menu has shown.
if (shouldDeliverToMenu) {
final MotionEvent cloneEvent = MotionEvent.obtain(ev);
@@ -715,7 +718,7 @@ public class PipTouchHandler {
// If the menu is still visible then just poke the menu
// so that it will timeout after the user stops touching it
- if (mMenuState != MENU_STATE_NONE) {
+ if (mMenuState != MENU_STATE_NONE && !mPipBoundsState.isStashed()) {
mMenuController.pokeMenu();
}
}
@@ -727,6 +730,7 @@ public class PipTouchHandler {
}
if (touchState.startedDragging()) {
+ mPipBoundsState.setStashed(false);
mSavedSnapFraction = -1f;
mPipDismissTargetHandler.showDismissTargetMaybe();
}
@@ -785,12 +789,13 @@ public class PipTouchHandler {
if (mEnableStash
&& (animatingBounds.right > mPipBoundsState.getDisplayBounds().right
|| animatingBounds.left < mPipBoundsState.getDisplayBounds().left)) {
+ mPipBoundsState.setStashed(true);
mMotionHelper.stashToEdge(vel.x, vel.y, this::flingEndAction /* endAction */);
} else {
mMotionHelper.flingToSnapTarget(vel.x, vel.y,
this::flingEndAction /* endAction */);
}
- } else if (mTouchState.isDoubleTap()) {
+ } else if (mTouchState.isDoubleTap() && !mPipBoundsState.isStashed()) {
// If using pinch to zoom, double-tap functions as resizing between max/min size
if (mPipResizeGestureHandler.isUsingPinchToZoom()) {
final boolean toExpand =
@@ -809,7 +814,7 @@ public class PipTouchHandler {
setTouchEnabled(false);
mMotionHelper.expandLeavePip();
}
- } else if (mMenuState != MENU_STATE_FULL) {
+ } else if (mMenuState != MENU_STATE_FULL && !mPipBoundsState.isStashed()) {
if (!mTouchState.isWaitingForDoubleTap()) {
// User has stalled long enough for this not to be a drag or a double tap, just
// expand the menu