diff options
4 files changed, 55 insertions, 4 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index 00494611420d..e1b198c4217a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -379,6 +379,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, } } + public SurfaceControl getSurfaceControl() { + return mLeash; + } + private void setBoundsStateForEntry(ComponentName componentName, PictureInPictureParams params, ActivityInfo activityInfo) { mPipBoundsState.setBoundsStateForEntry(componentName, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java index c26b686f91fb..1da9577fe49a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java @@ -26,8 +26,10 @@ import android.graphics.Rect; import android.graphics.drawable.TransitionDrawable; import android.view.Gravity; import android.view.MotionEvent; +import android.view.SurfaceControl; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.view.WindowManager; import android.widget.FrameLayout; @@ -47,7 +49,7 @@ import kotlin.Unit; /** * Handler of all Magnetized Object related code for PiP. */ -public class PipDismissTargetHandler { +public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListener { /* The multiplier to apply scale the target size by when applying the magnetic field radius */ private static final float MAGNETIC_FIELD_RADIUS_MULTIPLIER = 1.25f; @@ -92,6 +94,9 @@ public class PipDismissTargetHandler { private int mDismissAreaHeight; private float mMagneticFieldRadiusPercent = 1f; + private SurfaceControl mTaskLeash; + private boolean mHasDismissTargetSurface; + private final Context mContext; private final PipMotionHelper mMotionHelper; private final PipUiEventLogger mPipUiEventLogger; @@ -167,6 +172,14 @@ public class PipDismissTargetHandler { mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView); } + @Override + public boolean onPreDraw() { + mTargetViewContainer.getViewTreeObserver().removeOnPreDrawListener(this); + mHasDismissTargetSurface = true; + updateDismissTargetLayer(); + return true; + } + /** * Potentially start consuming future motion events if PiP is currently near the magnetized * object. @@ -207,12 +220,31 @@ public class PipDismissTargetHandler { * MAGNETIC_FIELD_RADIUS_MULTIPLIER)); } + public void setTaskLeash(SurfaceControl taskLeash) { + mTaskLeash = taskLeash; + } + + private void updateDismissTargetLayer() { + if (!mHasDismissTargetSurface || mTaskLeash == null) { + // No dismiss target surface, can just return + return; + } + + // Put the dismiss target behind the task + SurfaceControl.Transaction t = new SurfaceControl.Transaction(); + t.setRelativeLayer(mTargetViewContainer.getViewRootImpl().getSurfaceControl(), + mTaskLeash, -1); + t.apply(); + } + /** Adds the magnetic target view to the WindowManager so it's ready to be animated in. */ public void createOrUpdateDismissTarget() { if (!mTargetViewContainer.isAttachedToWindow()) { mMagneticTargetAnimator.cancel(); mTargetViewContainer.setVisibility(View.INVISIBLE); + mTargetViewContainer.getViewTreeObserver().removeOnPreDrawListener(this); + mHasDismissTargetSurface = false; try { mWindowManager.addView(mTargetViewContainer, getDismissTargetLayoutParams()); @@ -259,9 +291,9 @@ public class PipDismissTargetHandler { createOrUpdateDismissTarget(); if (mTargetViewContainer.getVisibility() != View.VISIBLE) { - mTargetView.setTranslationY(mTargetViewContainer.getHeight()); mTargetViewContainer.setVisibility(View.VISIBLE); + mTargetViewContainer.getViewTreeObserver().addOnPreDrawListener(this); // Cancel in case we were in the middle of animating it out. mMagneticTargetAnimator.cancel(); 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 15e7f07a1f6c..604ebc08f42e 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 @@ -40,6 +40,7 @@ import android.view.Choreographer; import androidx.dynamicanimation.animation.AnimationHandler; import androidx.dynamicanimation.animation.AnimationHandler.FrameCallbackScheduler; +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; @@ -71,6 +72,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, /** Friction to use for PIP when it moves via physics fling animations. */ private static final float DEFAULT_FRICTION = 1.9f; + /** How much of the dismiss circle size to use when scaling down PIP. **/ + private static final float DISMISS_CIRCLE_PERCENT = 0.85f; private final Context mContext; private final PipTaskOrganizer mPipTaskOrganizer; @@ -296,9 +299,17 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, boolean flung, Function0<Unit> after) { final PointF targetCenter = target.getCenterOnScreen(); - final float desiredWidth = getBounds().width() / 2; - final float desiredHeight = getBounds().height() / 2; + // PIP should fit in the circle + final float dismissCircleSize = mContext.getResources().getDimensionPixelSize( + R.dimen.dismiss_circle_size); + final float width = getBounds().width(); + final float height = getBounds().height(); + final float ratio = width / height; + + // Width should be a little smaller than the circle size. + final float desiredWidth = dismissCircleSize * DISMISS_CIRCLE_PERCENT; + final float desiredHeight = desiredWidth / ratio; final float destinationX = targetCenter.x - (desiredWidth / 2f); final float destinationY = targetCenter.y - (desiredHeight / 2f); 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 f0ea4653c245..b1086c575f49 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 @@ -75,6 +75,7 @@ public class PipTouchHandler { private final @NonNull PipBoundsState mPipBoundsState; private final PipUiEventLogger mPipUiEventLogger; private final PipDismissTargetHandler mPipDismissTargetHandler; + private final PipTaskOrganizer mPipTaskOrganizer; private final ShellExecutor mMainExecutor; private PipResizeGestureHandler mPipResizeGestureHandler; @@ -173,6 +174,7 @@ public class PipTouchHandler { mAccessibilityManager = context.getSystemService(AccessibilityManager.class); mPipBoundsAlgorithm = pipBoundsAlgorithm; mPipBoundsState = pipBoundsState; + mPipTaskOrganizer = pipTaskOrganizer; mMenuController = menuController; mPipUiEventLogger = pipUiEventLogger; mFloatingContentCoordinator = floatingContentCoordinator; @@ -799,6 +801,7 @@ public class PipTouchHandler { mMovementWithinDismiss = touchState.getDownTouchPosition().y >= mPipBoundsState.getMovementBounds().bottom; mMotionHelper.setSpringingToTouch(false); + mPipDismissTargetHandler.setTaskLeash(mPipTaskOrganizer.getSurfaceControl()); // If the menu is still visible then just poke the menu // so that it will timeout after the user stops touching it @@ -847,6 +850,7 @@ public class PipTouchHandler { @Override public boolean onUp(PipTouchState touchState) { mPipDismissTargetHandler.hideDismissTargetMaybe(); + mPipDismissTargetHandler.setTaskLeash(null); if (!touchState.isUserInteracting()) { return false; |