Merge changes If42d4470,Ia0b701b7 into sc-dev

* changes:
  PiP: Add tap-to-unstash function.
  PiP: Allow stashing via dropping on the edge.
This commit is contained in:
Ben Lin
2021-02-02 19:27:55 +00:00
committed by Android (Google) Code Review
3 changed files with 87 additions and 20 deletions

View File

@@ -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.
*/

View File

@@ -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.
*/

View File

@@ -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
mMenuController.showMenu(MENU_STATE_FULL, mPipBoundsState.getBounds(),
true /* allowMenuTimeout */, willResizeMenu(),
shouldShowResizeHandle());
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) {