Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8664c950 authored by Ikram Gabiyev's avatar Ikram Gabiyev Committed by Android (Google) Code Review
Browse files

Merge "User-resize pip to normal bounds when (un)folding" into tm-qpr-dev

parents 087c3d19 862c902a
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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();
        }
+61 −19
Original line number Diff line number Diff line
@@ -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
+10 −0
Original line number Diff line number Diff line
@@ -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.
     */
+47 −0
Original line number Diff line number Diff line
@@ -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++) {