Merge "User-resize pip to normal bounds when (un)folding" into tm-qpr-dev am: 8664c9501c
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20161485 Change-Id: Ic8e62e8d6918a22e3b7aac32f8097820186a7af9 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -745,6 +745,15 @@ public class PipController implements PipTransitionController.PipTransitionCallb
|
|||||||
// Directly move PiP to its final destination bounds without animation.
|
// Directly move PiP to its final destination bounds without animation.
|
||||||
mPipTaskOrganizer.scheduleFinishResizePip(postChangeBounds);
|
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 {
|
} else {
|
||||||
updateDisplayLayout.run();
|
updateDisplayLayout.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ public class PipResizeGestureHandler {
|
|||||||
private final Rect mDisplayBounds = new Rect();
|
private final Rect mDisplayBounds = new Rect();
|
||||||
private final Function<Rect, Rect> mMovementBoundsSupplier;
|
private final Function<Rect, Rect> mMovementBoundsSupplier;
|
||||||
private final Runnable mUpdateMovementBoundsRunnable;
|
private final Runnable mUpdateMovementBoundsRunnable;
|
||||||
|
private final Consumer<Rect> mUpdateResizeBoundsCallback;
|
||||||
|
|
||||||
private int mDelta;
|
private int mDelta;
|
||||||
private float mTouchSlop;
|
private float mTouchSlop;
|
||||||
@@ -137,6 +138,13 @@ public class PipResizeGestureHandler {
|
|||||||
mPhonePipMenuController = menuActivityController;
|
mPhonePipMenuController = menuActivityController;
|
||||||
mPipUiEventLogger = pipUiEventLogger;
|
mPipUiEventLogger = pipUiEventLogger;
|
||||||
mPinchResizingAlgorithm = new PipPinchResizingAlgorithm();
|
mPinchResizingAlgorithm = new PipPinchResizingAlgorithm();
|
||||||
|
|
||||||
|
mUpdateResizeBoundsCallback = (rect) -> {
|
||||||
|
mUserResizeBounds.set(rect);
|
||||||
|
mMotionHelper.synchronizePinnedStackBounds();
|
||||||
|
mUpdateMovementBoundsRunnable.run();
|
||||||
|
resetState();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init() {
|
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() {
|
private void finishResize() {
|
||||||
if (!mLastResizeBounds.isEmpty()) {
|
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
|
// 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.
|
// position correctly. Drag-resize does not need to move, so just finalize resize.
|
||||||
if (mOngoingPinchToResize) {
|
if (mOngoingPinchToResize) {
|
||||||
@@ -526,24 +569,23 @@ public class PipResizeGestureHandler {
|
|||||||
|| mLastResizeBounds.height() >= PINCH_RESIZE_AUTO_MAX_RATIO * mMaxSize.y) {
|
|| mLastResizeBounds.height() >= PINCH_RESIZE_AUTO_MAX_RATIO * mMaxSize.y) {
|
||||||
resizeRectAboutCenter(mLastResizeBounds, mMaxSize.x, mMaxSize.y);
|
resizeRectAboutCenter(mLastResizeBounds, mMaxSize.x, mMaxSize.y);
|
||||||
}
|
}
|
||||||
final int leftEdge = mLastResizeBounds.left;
|
|
||||||
final Rect movementBounds =
|
// get the current movement bounds
|
||||||
mPipBoundsAlgorithm.getMovementBounds(mLastResizeBounds);
|
final Rect movementBounds = mPipBoundsAlgorithm
|
||||||
final int fromLeft = Math.abs(leftEdge - movementBounds.left);
|
.getMovementBounds(mLastResizeBounds);
|
||||||
final int fromRight = Math.abs(movementBounds.right - leftEdge);
|
|
||||||
// The PIP will be snapped to either the right or left edge, so calculate which one
|
// snap mLastResizeBounds to the correct edge based on movement bounds
|
||||||
// is closest to the current position.
|
snapToMovementBoundsEdge(mLastResizeBounds, movementBounds);
|
||||||
final int newLeft = fromLeft < fromRight
|
|
||||||
? movementBounds.left : movementBounds.right;
|
|
||||||
mLastResizeBounds.offsetTo(newLeft, mLastResizeBounds.top);
|
|
||||||
final float snapFraction = mPipBoundsAlgorithm.getSnapFraction(
|
final float snapFraction = mPipBoundsAlgorithm.getSnapFraction(
|
||||||
mLastResizeBounds, movementBounds);
|
mLastResizeBounds, movementBounds);
|
||||||
mPipBoundsAlgorithm.applySnapFraction(mLastResizeBounds, snapFraction);
|
mPipBoundsAlgorithm.applySnapFraction(mLastResizeBounds, snapFraction);
|
||||||
mPipTaskOrganizer.scheduleAnimateResizePip(startBounds, mLastResizeBounds,
|
mPipTaskOrganizer.scheduleAnimateResizePip(startBounds, mLastResizeBounds,
|
||||||
PINCH_RESIZE_SNAP_DURATION, mAngle, callback);
|
PINCH_RESIZE_SNAP_DURATION, mAngle, mUpdateResizeBoundsCallback);
|
||||||
} else {
|
} else {
|
||||||
mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds,
|
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;
|
final float magnetRadiusPercent = (float) mLastResizeBounds.width() / mMinSize.x / 2.f;
|
||||||
mPipDismissTargetHandler
|
mPipDismissTargetHandler
|
||||||
|
|||||||
@@ -824,6 +824,16 @@ public class PipTouchHandler {
|
|||||||
return mPipResizeGestureHandler.getUserResizeBounds();
|
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.
|
* Gesture controlling normal movement of the PIP.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.wm.shell.pip.phone;
|
package com.android.wm.shell.pip.phone;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
import static junit.framework.Assert.assertTrue;
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
@@ -55,6 +56,7 @@ import org.mockito.MockitoAnnotations;
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
@TestableLooper.RunWithLooper(setAsMainLooper = true)
|
@TestableLooper.RunWithLooper(setAsMainLooper = true)
|
||||||
public class PipResizeGestureHandlerTest extends ShellTestCase {
|
public class PipResizeGestureHandlerTest extends ShellTestCase {
|
||||||
|
private static final float DEFAULT_SNAP_FRACTION = 2.0f;
|
||||||
private static final int STEP_SIZE = 40;
|
private static final int STEP_SIZE = 40;
|
||||||
private final MotionEvent.PointerProperties[] mPp = new MotionEvent.PointerProperties[2];
|
private final MotionEvent.PointerProperties[] mPp = new MotionEvent.PointerProperties[2];
|
||||||
|
|
||||||
@@ -196,6 +198,51 @@ public class PipResizeGestureHandlerTest extends ShellTestCase {
|
|||||||
< mPipBoundsState.getBounds().width());
|
< 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) {
|
private MotionEvent obtainMotionEvent(int action, int topLeft, int bottomRight) {
|
||||||
final MotionEvent.PointerCoords[] pc = new MotionEvent.PointerCoords[2];
|
final MotionEvent.PointerCoords[] pc = new MotionEvent.PointerCoords[2];
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user