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

Commit dd1d40ef authored by Ben Lin's avatar Ben Lin
Browse files

PiP pinch-to-resize: add double-tap to max/min size.

Per spec, max size would be the biggest possible bounds within the
movement bounds (displayWidth - 2 * insetWidth), and min size would be
40% of the width.

This also fixes the issue of portrait PiP not resizing correctly due to
wrong math being done in the resize algorithm.

Bug: 166478885
Test: Double-tap on PiP
Change-Id: I2e239d23a0e2519c0b482005614a1faddb1f808a
parent 60a993de
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Size;
import android.view.DisplayInfo;
@@ -59,6 +60,8 @@ public final class PipBoundsState {
    private final @NonNull Rect mExpandedBounds = new Rect();
    private final @NonNull Rect mNormalMovementBounds = new Rect();
    private final @NonNull Rect mExpandedMovementBounds = new Rect();
    private final Point mMaxSize = new Point();
    private final Point mMinSize = new Point();
    private final @NonNull Context mContext;
    private float mAspectRatio;
    private int mStashedState = STASH_TYPE_NONE;
@@ -151,6 +154,24 @@ public final class PipBoundsState {
        mExpandedMovementBounds.set(bounds);
    }

    /** Sets the max possible size for resize. */
    public void setMaxSize(int width, int height) {
        mMaxSize.set(width, height);
    }

    /** Sets the min possible size for resize. */
    public void setMinSize(int width, int height) {
        mMinSize.set(width, height);
    }

    public Point getMaxSize() {
        return mMaxSize;
    }

    public Point getMinSize() {
        return mMinSize;
    }

    /** Returns the expanded movement bounds. */
    @NonNull
    public Rect getExpandedMovementBounds() {
+4 −4
Original line number Diff line number Diff line
@@ -85,21 +85,21 @@ public class PipPinchResizingAlgorithm {
        } else {
            // Assuming that the width is our target we calculate the height.
            width1 = Math.max(minVisibleWidth, Math.min(maxSize.x, width));
            height1 = Math.round((float) width1 * aspect);
            height1 = Math.round((float) width1 / aspect);
            if (height1 < minVisibleHeight) {
                // If the resulting height is too small we adjust to the minimal size.
                height1 = minVisibleHeight;
                width1 = Math.max(minVisibleWidth,
                        Math.min(maxSize.x, Math.round((float) height1 / aspect)));
                        Math.min(maxSize.x, Math.round((float) height1 * aspect)));
            }
            // Assuming that the height is our target we calculate the width.
            height2 = Math.max(minVisibleHeight, Math.min(maxSize.y, height));
            width2 = Math.round((float) height2 / aspect);
            width2 = Math.round((float) height2 * aspect);
            if (width2 < minVisibleWidth) {
                // If the resulting width is too small we adjust to the minimal size.
                width2 = minVisibleWidth;
                height2 = Math.max(minVisibleHeight,
                        Math.min(maxSize.y, Math.round((float) width2 * aspect)));
                        Math.min(maxSize.y, Math.round((float) width2 / aspect)));
            }
        }

+63 −14
Original line number Diff line number Diff line
@@ -359,9 +359,13 @@ public class PipTouchHandler {
                mPipBoundsState.getExpandedBounds(), insetBounds, expandedMovementBounds,
                bottomOffset);

        if (mPipResizeGestureHandler.isUsingPinchToZoom()) {
            updatePinchResizeSizeConstraints(insetBounds, normalBounds, aspectRatio);
        } else {
            mPipResizeGestureHandler.updateMinSize(normalBounds.width(), normalBounds.height());
            mPipResizeGestureHandler.updateMaxSize(mPipBoundsState.getExpandedBounds().width(),
                    mPipBoundsState.getExpandedBounds().height());
        }

        // The extra offset does not really affect the movement bounds, but are applied based on the
        // current state (ime showing, or shelf offset) when we need to actually shift
@@ -430,6 +434,30 @@ public class PipTouchHandler {
        }
    }

    private void updatePinchResizeSizeConstraints(Rect insetBounds, Rect normalBounds,
            float aspectRatio) {
        final int shorterLength = Math.min(mPipBoundsState.getDisplayBounds().width(),
                mPipBoundsState.getDisplayBounds().height());
        final int padding = insetBounds.left;
        final int minWidth, minHeight, maxWidth, maxHeight;
        if (aspectRatio > 1f) {
            minWidth = (int) Math.min(normalBounds.width(), shorterLength * 0.4);
            minHeight = (int) (minWidth / aspectRatio);
            maxWidth = (int) Math.max(normalBounds.width(), shorterLength - 2 * padding);
            maxHeight = (int) (maxWidth / aspectRatio);
        } else {
            minHeight = (int) Math.min(normalBounds.height(), shorterLength * 0.4);
            minWidth = (int) (minHeight * aspectRatio);
            maxHeight = (int) Math.max(normalBounds.height(), shorterLength - 2 * padding);
            maxWidth = (int) (maxHeight * aspectRatio);
        }

        mPipResizeGestureHandler.updateMinSize(minWidth, minHeight);
        mPipResizeGestureHandler.updateMaxSize(maxWidth, maxHeight);
        mPipBoundsState.setMaxSize(maxWidth, maxHeight);
        mPipBoundsState.setMinSize(minWidth, minHeight);
    }

    /**
     * TODO Add appropriate description
     */
@@ -640,13 +668,36 @@ public class PipTouchHandler {
        }
    }

    private void animateToExpandedState(Runnable callback) {
        Rect expandedBounds = new Rect(mPipBoundsState.getExpandedBounds());
        mSavedSnapFraction = mMotionHelper.animateToExpandedState(expandedBounds,
                mPipBoundsState.getMovementBounds(), mPipBoundsState.getExpandedMovementBounds(),
    private void animateToMaximizedState(Runnable callback) {
        Rect maxMovementBounds = new Rect();
        Rect maxBounds = new Rect(0, 0, mPipBoundsState.getMaxSize().x,
                mPipBoundsState.getMaxSize().y);
        mPipBoundsAlgorithm.getMovementBounds(maxBounds, mInsetBounds, maxMovementBounds,
                mIsImeShowing ? mImeHeight : 0);
        mSavedSnapFraction = mMotionHelper.animateToExpandedState(maxBounds,
                mPipBoundsState.getMovementBounds(), maxMovementBounds,
                callback);
    }

    private void animateToMinimizedState() {
        animateToUnexpandedState(new Rect(0, 0, mPipBoundsState.getMinSize().x,
                mPipBoundsState.getMinSize().y));
    }

    private void animateToExpandedState(Runnable callback) {
        mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds());
        final Rect currentBounds = mPipBoundsState.getBounds();
        final Rect expandedBounds = mPipBoundsState.getExpandedBounds();
        Rect finalExpandedBounds = new Rect(expandedBounds.width() > expandedBounds.width()
                        && expandedBounds.height() > expandedBounds.height()
                        ? currentBounds : expandedBounds);
        Rect restoredMovementBounds = new Rect();
        mPipBoundsAlgorithm.getMovementBounds(finalExpandedBounds,
                mInsetBounds, restoredMovementBounds, mIsImeShowing ? mImeHeight : 0);
        mSavedSnapFraction = mMotionHelper.animateToExpandedState(finalExpandedBounds,
                mPipBoundsState.getMovementBounds(), restoredMovementBounds, callback);
    }

    private void animateToUnexpandedState(Rect restoreBounds) {
        Rect restoredMovementBounds = new Rect();
        mPipBoundsAlgorithm.getMovementBounds(restoreBounds,
@@ -789,17 +840,15 @@ public class PipTouchHandler {
                // If using pinch to zoom, double-tap functions as resizing between max/min size
                if (mPipResizeGestureHandler.isUsingPinchToZoom()) {
                    final boolean toExpand = mPipBoundsState.getBounds().width()
                            < mPipBoundsState.getExpandedBounds().width()
                            < mPipBoundsState.getMaxSize().x
                            && mPipBoundsState.getBounds().height()
                            < mPipBoundsState.getExpandedBounds().height();
                    mPipResizeGestureHandler.setUserResizeBounds(toExpand
                            ? mPipBoundsState.getExpandedBounds()
                            : mPipBoundsState.getNormalBounds());
                            < mPipBoundsState.getMaxSize().y;
                    if (toExpand) {
                        animateToExpandedState(null);
                        animateToMaximizedState(null);
                    } else {
                        animateToUnexpandedState(mPipBoundsState.getNormalBounds());
                        animateToMinimizedState();
                    }
                    mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds());
                } else {
                    // Expand to fullscreen if this is a double tap
                    // the PiP should be frozen until the transition ends