Merge "User-resize pip to normal bounds when (un)folding" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
8664c9501c
@@ -745,6 +745,15 @@ public class PipController implements PipTransitionController.PipTransitionCallb
|
||||
// Directly move PiP to its final destination bounds without animation.
|
||||
mPipTaskOrganizer.scheduleFinishResizePip(postChangeBounds);
|
||||
}
|
||||
|
||||
// if the pip window size is beyond allowed bounds user resize to normal bounds
|
||||
if (mPipBoundsState.getBounds().width() < mPipBoundsState.getMinSize().x
|
||||
|| mPipBoundsState.getBounds().width() > mPipBoundsState.getMaxSize().x
|
||||
|| mPipBoundsState.getBounds().height() < mPipBoundsState.getMinSize().y
|
||||
|| mPipBoundsState.getBounds().height() > mPipBoundsState.getMaxSize().y) {
|
||||
mTouchHandler.userResizeTo(mPipBoundsState.getNormalBounds(), snapFraction);
|
||||
}
|
||||
|
||||
} else {
|
||||
updateDisplayLayout.run();
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ public class PipResizeGestureHandler {
|
||||
private final Rect mDisplayBounds = new Rect();
|
||||
private final Function<Rect, Rect> mMovementBoundsSupplier;
|
||||
private final Runnable mUpdateMovementBoundsRunnable;
|
||||
private final Consumer<Rect> mUpdateResizeBoundsCallback;
|
||||
|
||||
private int mDelta;
|
||||
private float mTouchSlop;
|
||||
@@ -137,6 +138,13 @@ public class PipResizeGestureHandler {
|
||||
mPhonePipMenuController = menuActivityController;
|
||||
mPipUiEventLogger = pipUiEventLogger;
|
||||
mPinchResizingAlgorithm = new PipPinchResizingAlgorithm();
|
||||
|
||||
mUpdateResizeBoundsCallback = (rect) -> {
|
||||
mUserResizeBounds.set(rect);
|
||||
mMotionHelper.synchronizePinnedStackBounds();
|
||||
mUpdateMovementBoundsRunnable.run();
|
||||
resetState();
|
||||
};
|
||||
}
|
||||
|
||||
public void init() {
|
||||
@@ -508,15 +516,50 @@ public class PipResizeGestureHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private void snapToMovementBoundsEdge(Rect bounds, Rect movementBounds) {
|
||||
final int leftEdge = bounds.left;
|
||||
|
||||
|
||||
final int fromLeft = Math.abs(leftEdge - movementBounds.left);
|
||||
final int fromRight = Math.abs(movementBounds.right - leftEdge);
|
||||
|
||||
// The PIP will be snapped to either the right or left edge, so calculate which one
|
||||
// is closest to the current position.
|
||||
final int newLeft = fromLeft < fromRight
|
||||
? movementBounds.left : movementBounds.right;
|
||||
|
||||
bounds.offsetTo(newLeft, mLastResizeBounds.top);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the pip window and updates user-resized bounds.
|
||||
*
|
||||
* @param bounds target bounds to resize to
|
||||
* @param snapFraction snap fraction to apply after resizing
|
||||
*/
|
||||
void userResizeTo(Rect bounds, float snapFraction) {
|
||||
Rect finalBounds = new Rect(bounds);
|
||||
|
||||
// get the current movement bounds
|
||||
final Rect movementBounds = mPipBoundsAlgorithm.getMovementBounds(finalBounds);
|
||||
|
||||
// snap the target bounds to the either left or right edge, by choosing the closer one
|
||||
snapToMovementBoundsEdge(finalBounds, movementBounds);
|
||||
|
||||
// apply the requested snap fraction onto the target bounds
|
||||
mPipBoundsAlgorithm.applySnapFraction(finalBounds, snapFraction);
|
||||
|
||||
// resize from current bounds to target bounds without animation
|
||||
mPipTaskOrganizer.scheduleUserResizePip(mPipBoundsState.getBounds(), finalBounds, null);
|
||||
// set the flag that pip has been resized
|
||||
mPipBoundsState.setHasUserResizedPip(true);
|
||||
|
||||
// finish the resize operation and update the state of the bounds
|
||||
mPipTaskOrganizer.scheduleFinishResizePip(finalBounds, mUpdateResizeBoundsCallback);
|
||||
}
|
||||
|
||||
private void finishResize() {
|
||||
if (!mLastResizeBounds.isEmpty()) {
|
||||
final Consumer<Rect> callback = (rect) -> {
|
||||
mUserResizeBounds.set(mLastResizeBounds);
|
||||
mMotionHelper.synchronizePinnedStackBounds();
|
||||
mUpdateMovementBoundsRunnable.run();
|
||||
resetState();
|
||||
};
|
||||
|
||||
// Pinch-to-resize needs to re-calculate snap fraction and animate to the snapped
|
||||
// position correctly. Drag-resize does not need to move, so just finalize resize.
|
||||
if (mOngoingPinchToResize) {
|
||||
@@ -526,24 +569,23 @@ public class PipResizeGestureHandler {
|
||||
|| mLastResizeBounds.height() >= PINCH_RESIZE_AUTO_MAX_RATIO * mMaxSize.y) {
|
||||
resizeRectAboutCenter(mLastResizeBounds, mMaxSize.x, mMaxSize.y);
|
||||
}
|
||||
final int leftEdge = mLastResizeBounds.left;
|
||||
final Rect movementBounds =
|
||||
mPipBoundsAlgorithm.getMovementBounds(mLastResizeBounds);
|
||||
final int fromLeft = Math.abs(leftEdge - movementBounds.left);
|
||||
final int fromRight = Math.abs(movementBounds.right - leftEdge);
|
||||
// The PIP will be snapped to either the right or left edge, so calculate which one
|
||||
// is closest to the current position.
|
||||
final int newLeft = fromLeft < fromRight
|
||||
? movementBounds.left : movementBounds.right;
|
||||
mLastResizeBounds.offsetTo(newLeft, mLastResizeBounds.top);
|
||||
|
||||
// get the current movement bounds
|
||||
final Rect movementBounds = mPipBoundsAlgorithm
|
||||
.getMovementBounds(mLastResizeBounds);
|
||||
|
||||
// snap mLastResizeBounds to the correct edge based on movement bounds
|
||||
snapToMovementBoundsEdge(mLastResizeBounds, movementBounds);
|
||||
|
||||
final float snapFraction = mPipBoundsAlgorithm.getSnapFraction(
|
||||
mLastResizeBounds, movementBounds);
|
||||
mPipBoundsAlgorithm.applySnapFraction(mLastResizeBounds, snapFraction);
|
||||
mPipTaskOrganizer.scheduleAnimateResizePip(startBounds, mLastResizeBounds,
|
||||
PINCH_RESIZE_SNAP_DURATION, mAngle, callback);
|
||||
PINCH_RESIZE_SNAP_DURATION, mAngle, mUpdateResizeBoundsCallback);
|
||||
} else {
|
||||
mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds,
|
||||
PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE, callback);
|
||||
PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE,
|
||||
mUpdateResizeBoundsCallback);
|
||||
}
|
||||
final float magnetRadiusPercent = (float) mLastResizeBounds.width() / mMinSize.x / 2.f;
|
||||
mPipDismissTargetHandler
|
||||
|
||||
@@ -824,6 +824,16 @@ public class PipTouchHandler {
|
||||
return mPipResizeGestureHandler.getUserResizeBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the pip window and updates user resized bounds
|
||||
*
|
||||
* @param bounds target bounds to resize to
|
||||
* @param snapFraction snap fraction to apply after resizing
|
||||
*/
|
||||
void userResizeTo(Rect bounds, float snapFraction) {
|
||||
mPipResizeGestureHandler.userResizeTo(bounds, snapFraction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gesture controlling normal movement of the PIP.
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.wm.shell.pip.phone;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -55,6 +56,7 @@ import org.mockito.MockitoAnnotations;
|
||||
@SmallTest
|
||||
@TestableLooper.RunWithLooper(setAsMainLooper = true)
|
||||
public class PipResizeGestureHandlerTest extends ShellTestCase {
|
||||
private static final float DEFAULT_SNAP_FRACTION = 2.0f;
|
||||
private static final int STEP_SIZE = 40;
|
||||
private final MotionEvent.PointerProperties[] mPp = new MotionEvent.PointerProperties[2];
|
||||
|
||||
@@ -196,6 +198,51 @@ public class PipResizeGestureHandlerTest extends ShellTestCase {
|
||||
< mPipBoundsState.getBounds().width());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserResizeTo() {
|
||||
// resizing the bounds to normal bounds at first
|
||||
mPipResizeGestureHandler.userResizeTo(mPipBoundsState.getNormalBounds(),
|
||||
DEFAULT_SNAP_FRACTION);
|
||||
|
||||
assertPipBoundsUserResizedTo(mPipBoundsState.getNormalBounds());
|
||||
|
||||
verify(mPipTaskOrganizer, times(1))
|
||||
.scheduleUserResizePip(any(), any(), any());
|
||||
|
||||
verify(mPipTaskOrganizer, times(1))
|
||||
.scheduleFinishResizePip(any(), any());
|
||||
|
||||
// bounds with max size
|
||||
final Rect maxBounds = new Rect(0, 0, mPipBoundsState.getMaxSize().x,
|
||||
mPipBoundsState.getMaxSize().y);
|
||||
|
||||
// resizing the bounds to maximum bounds the second time
|
||||
mPipResizeGestureHandler.userResizeTo(maxBounds, DEFAULT_SNAP_FRACTION);
|
||||
|
||||
assertPipBoundsUserResizedTo(maxBounds);
|
||||
|
||||
// another call to scheduleUserResizePip() and scheduleFinishResizePip() makes
|
||||
// the total number of invocations 2 for each method
|
||||
verify(mPipTaskOrganizer, times(2))
|
||||
.scheduleUserResizePip(any(), any(), any());
|
||||
|
||||
verify(mPipTaskOrganizer, times(2))
|
||||
.scheduleFinishResizePip(any(), any());
|
||||
}
|
||||
|
||||
private void assertPipBoundsUserResizedTo(Rect bounds) {
|
||||
// check user-resized bounds
|
||||
assertEquals(mPipResizeGestureHandler.getUserResizeBounds().width(), bounds.width());
|
||||
assertEquals(mPipResizeGestureHandler.getUserResizeBounds().height(), bounds.height());
|
||||
|
||||
// check if the bounds are the same
|
||||
assertEquals(mPipBoundsState.getBounds().width(), bounds.width());
|
||||
assertEquals(mPipBoundsState.getBounds().height(), bounds.height());
|
||||
|
||||
// a flag should be set to indicate pip has been resized by the user
|
||||
assertTrue(mPipBoundsState.hasUserResizedPip());
|
||||
}
|
||||
|
||||
private MotionEvent obtainMotionEvent(int action, int topLeft, int bottomRight) {
|
||||
final MotionEvent.PointerCoords[] pc = new MotionEvent.PointerCoords[2];
|
||||
for (int i = 0; i < 2; i++) {
|
||||
|
||||
Reference in New Issue
Block a user