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

Commit 87a79200 authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Fix some issues with pinch to resize" into sc-dev

parents 5225e0ea 59415ea4
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -94,11 +94,14 @@ public class PipSurfaceTransactionHelper {
    public PipSurfaceTransactionHelper scale(SurfaceControl.Transaction tx, SurfaceControl leash,
            Rect sourceBounds, Rect destinationBounds, float degrees) {
        mTmpSourceRectF.set(sourceBounds);
        // We want the matrix to position the surface relative to the screen coordinates so offset
        // the source to 0,0
        mTmpSourceRectF.offsetTo(0, 0);
        mTmpDestinationRectF.set(destinationBounds);
        mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
        mTmpTransform.postRotate(degrees);
        tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
                .setPosition(leash, mTmpDestinationRectF.left, mTmpDestinationRectF.top);
        mTmpTransform.postRotate(degrees,
                mTmpDestinationRectF.centerX(), mTmpDestinationRectF.centerY());
        tx.setMatrix(leash, mTmpTransform, mTmpFloat9);
        return this;
    }

+99 −95
Original line number Diff line number Diff line
@@ -16,111 +16,115 @@
package com.android.wm.shell.pip.phone;

import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;

/**
 * Helper class to calculate the new size given two-fingers pinch to resize.
 */
public class PipPinchResizingAlgorithm {
    private static final Rect TMP_RECT = new Rect();

    private static final int PINCH_RESIZE_MAX_ANGLE_ROTATION = 45;
    private static final float OVERROTATE_DAMP_FACTOR = 0.4f;
    private static final float ANGLE_THRESHOLD = 5f;

    private final PointF mTmpDownVector = new PointF();
    private final PointF mTmpLastVector = new PointF();
    private final PointF mTmpDownCentroid = new PointF();
    private final PointF mTmpLastCentroid = new PointF();

    /**
     * Given inputs and requirements and current PiP bounds, return the new size.
     *
     * @param x0 x-coordinate of the primary input.
     * @param y0 y-coordinate of the primary input.
     * @param x1 x-coordinate of the secondary input.
     * @param y1 y-coordinate of the secondary input.
     * @param downx0 x-coordinate of the original down point of the primary input.
     * @param downy0 y-coordinate of the original down ponit of the primary input.
     * @param downx1 x-coordinate of the original down point of the secondary input.
     * @param downy1 y-coordinate of the original down point of the secondary input.
     * @param currentPipBounds current PiP bounds.
     * @param minVisibleWidth minimum visible width.
     * @param minVisibleHeight minimum visible height.
     * @param maxSize max size.
     * @return The new resized PiP bounds, sharing the same center.
     * Updates {@param resizeBoundsOut} with the new bounds of the PIP, and returns the angle in
     * degrees that the PIP should be rotated.
     */
    public static Rect pinchResize(float x0, float y0, float x1, float y1,
            float downx0, float downy0, float downx1, float downy1, Rect currentPipBounds,
            int minVisibleWidth, int minVisibleHeight, Point maxSize) {

        int width = currentPipBounds.width();
        int height = currentPipBounds.height();
        int left = currentPipBounds.left;
        int top = currentPipBounds.top;
        int right = currentPipBounds.right;
        int bottom = currentPipBounds.bottom;
        final float aspect = (float) width / (float) height;
        final int widthDelta = Math.round(Math.abs(x0 - x1) - Math.abs(downx0 - downx1));
        final int heightDelta = Math.round(Math.abs(y0 - y1) - Math.abs(downy0 - downy1));
        final int dx = (int) ((x0 - downx0 + x1 - downx1) / 2);
        final int dy = (int) ((y0 - downy0 + y1 - downy1) / 2);

        width = Math.max(minVisibleWidth, Math.min(width + widthDelta, maxSize.x));
        height = Math.max(minVisibleHeight, Math.min(height + heightDelta, maxSize.y));

        // Calculate 2 rectangles fulfilling all requirements for either X or Y being the major
        // drag axis. What ever is producing the bigger rectangle will be chosen.
        int width1;
        int width2;
        int height1;
        int height2;
        if (aspect > 1.0f) {
            // 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);
            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)));
    public float calculateBoundsAndAngle(PointF downPoint, PointF downSecondPoint,
            PointF lastPoint, PointF lastSecondPoint, Point minSize, Point maxSize,
            Rect initialBounds, Rect resizeBoundsOut) {
        float downDist = (float) Math.hypot(downSecondPoint.x - downPoint.x,
                downSecondPoint.y - downPoint.y);
        float dist = (float) Math.hypot(lastSecondPoint.x - lastPoint.x,
                lastSecondPoint.y - lastPoint.y);
        float minScale = getMinScale(initialBounds, minSize);
        float maxScale = getMaxScale(initialBounds, maxSize);
        float scale = Math.max(minScale, Math.min(maxScale, dist / downDist));

        // Scale the bounds by the change in distance between the points
        resizeBoundsOut.set(initialBounds);
        scaleRectAboutCenter(resizeBoundsOut, scale);

        // Translate by the centroid movement
        getCentroid(downPoint, downSecondPoint, mTmpDownCentroid);
        getCentroid(lastPoint, lastSecondPoint, mTmpLastCentroid);
        resizeBoundsOut.offset((int) (mTmpLastCentroid.x - mTmpDownCentroid.x),
                (int) (mTmpLastCentroid.y - mTmpDownCentroid.y));

        // Calculate the angle
        mTmpDownVector.set(downSecondPoint.x - downPoint.x,
                downSecondPoint.y - downPoint.y);
        mTmpLastVector.set(lastSecondPoint.x - lastPoint.x,
                lastSecondPoint.y - lastPoint.y);
        float angle = (float) Math.atan2(cross(mTmpDownVector, mTmpLastVector),
                dot(mTmpDownVector, mTmpLastVector));
        return constrainRotationAngle((float) Math.toDegrees(angle));
    }
            // 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);
            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)));

    private float getMinScale(Rect bounds, Point minSize) {
        return Math.max((float) minSize.x / bounds.width(), (float) minSize.y / bounds.height());
    }
        } 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);
            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)));

    private float getMaxScale(Rect bounds, Point maxSize) {
        return Math.min((float) maxSize.x / bounds.width(), (float) maxSize.y / bounds.height());
    }
            // 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);
            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)));

    private float constrainRotationAngle(float angle) {
        // Remove some degrees so that user doesn't immediately start rotating until a threshold
        return Math.signum(angle) * Math.max(0, (Math.abs(dampedRotate(angle)) - ANGLE_THRESHOLD));
    }

    /**
     * Given the current rotation angle, dampen it so that as it approaches the maximum angle,
     * dampen it.
     */
    private float dampedRotate(float amount) {
        if (Float.compare(amount, 0) == 0) return 0;

        float f = amount / PINCH_RESIZE_MAX_ANGLE_ROTATION;
        f = f / (Math.abs(f)) * (overRotateInfluenceCurve(Math.abs(f)));

        // Clamp this factor, f, to -1 < f < 1
        if (Math.abs(f) >= 1) {
            f /= Math.abs(f);
        }
        return OVERROTATE_DAMP_FACTOR * f * PINCH_RESIZE_MAX_ANGLE_ROTATION;
    }

    /**
     * Returns a value that corresponds to y = (f - 1)^3 + 1.
     */
    private float overRotateInfluenceCurve(float f) {
        f -= 1.0f;
        return f * f * f + 1.0f;
    }

    private void getCentroid(PointF p1, PointF p2, PointF centroidOut) {
        centroidOut.set((p2.x + p1.x) / 2, (p2.y + p1.y) / 2);
    }

        // Use the bigger of the two rectangles if the major change was positive, otherwise
        // do the opposite.
        final boolean grows = width > (right - left) || height > (bottom - top);
        if (grows == (width1 * height1 > width2 * height2)) {
            width = width1;
            height = height1;
        } else {
            width = width2;
            height = height2;
    private float dot(PointF p1, PointF p2) {
        return p1.x * p2.x + p1.y * p2.y;
    }

        TMP_RECT.set(currentPipBounds.centerX() - width / 2,
                currentPipBounds.centerY() - height / 2,
                currentPipBounds.centerX() + width / 2,
                currentPipBounds.centerY() + height / 2);
        TMP_RECT.offset(dx, dy);
        return TMP_RECT;
    private float cross(PointF p1, PointF p2) {
        return p1.x * p2.y - p1.y * p2.x;
    }

    private void scaleRectAboutCenter(Rect r, float scale) {
        if (scale != 1.0f) {
            int cx = r.centerX();
            int cy = r.centerY();
            r.offset(-cx, -cy);
            r.scale(scale);
            r.offset(cx, cy);
        }
    }
}
+51 −130
Original line number Diff line number Diff line
@@ -63,10 +63,7 @@ public class PipResizeGestureHandler {

    private static final String TAG = "PipResizeGestureHandler";
    private static final int PINCH_RESIZE_SNAP_DURATION = 250;
    private static final int PINCH_RESIZE_MAX_ANGLE_ROTATION = 45;
    private static final float PINCH_RESIZE_AUTO_MAX_RATIO = 0.9f;
    private static final float OVERROTATE_DAMP_FACTOR = 0.4f;
    private static final float ANGLE_THRESHOLD = 5f;

    private final Context mContext;
    private final PipBoundsAlgorithm mPipBoundsAlgorithm;
@@ -75,17 +72,20 @@ public class PipResizeGestureHandler {
    private final PipTaskOrganizer mPipTaskOrganizer;
    private final PhonePipMenuController mPhonePipMenuController;
    private final PipUiEventLogger mPipUiEventLogger;
    private final PipPinchResizingAlgorithm mPinchResizingAlgorithm;
    private final int mDisplayId;
    private final ShellExecutor mMainExecutor;
    private final Region mTmpRegion = new Region();

    private final PointF mDownPoint = new PointF();
    private final PointF mDownSecondaryPoint = new PointF();
    private final PointF mDownSecondPoint = new PointF();
    private final PointF mLastPoint = new PointF();
    private final PointF mLastSecondPoint = new PointF();
    private final Point mMaxSize = new Point();
    private final Point mMinSize = new Point();
    private final Rect mLastResizeBounds = new Rect();
    private final Rect mUserResizeBounds = new Rect();
    private final Rect mLastDownBounds = new Rect();
    private final Rect mDownBounds = new Rect();
    private final Rect mDragCornerSize = new Rect();
    private final Rect mTmpTopLeftCorner = new Rect();
    private final Rect mTmpTopRightCorner = new Rect();
@@ -103,11 +103,7 @@ public class PipResizeGestureHandler {
    private boolean mIsEnabled;
    private boolean mEnablePinchResize;
    private boolean mIsSysUiStateValid;
    // For drag-resize
    private boolean mThresholdCrossed;
    // For pinch-resize
    private boolean mThresholdCrossed0;
    private boolean mThresholdCrossed1;
    private boolean mOngoingPinchToResize = false;
    private float mAngle = 0;
    int mFirstIndex = -1;
@@ -135,6 +131,7 @@ public class PipResizeGestureHandler {
        mUpdateMovementBoundsRunnable = updateMovementBoundsRunnable;
        mPhonePipMenuController = menuActivityController;
        mPipUiEventLogger = pipUiEventLogger;
        mPinchResizingAlgorithm = new PipPinchResizingAlgorithm();
    }

    public void init() {
@@ -294,6 +291,10 @@ public class PipResizeGestureHandler {
        return mEnablePinchResize;
    }

    public boolean isResizing() {
        return mAllowGesture;
    }

    public boolean willStartResizeGesture(MotionEvent ev) {
        if (isInValidSysUiState()) {
            switch (ev.getActionMasked()) {
@@ -362,6 +363,7 @@ public class PipResizeGestureHandler {
        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
            mFirstIndex = -1;
            mSecondIndex = -1;
            mAllowGesture = false;
            finishResize();
        }

@@ -371,14 +373,16 @@ public class PipResizeGestureHandler {

        if (action == MotionEvent.ACTION_POINTER_DOWN) {
            if (mFirstIndex == -1 && mSecondIndex == -1) {
                mAllowGesture = true;
                mFirstIndex = 0;
                mSecondIndex = 1;
                mDownPoint.set(ev.getRawX(mFirstIndex), ev.getRawY(mFirstIndex));
                mDownSecondaryPoint.set(ev.getRawX(mSecondIndex), ev.getRawY(mSecondIndex));
                mDownSecondPoint.set(ev.getRawX(mSecondIndex), ev.getRawY(mSecondIndex));
                mDownBounds.set(mPipBoundsState.getBounds());


                mLastDownBounds.set(mPipBoundsState.getBounds());
                mLastResizeBounds.set(mLastDownBounds);
                mLastPoint.set(mDownPoint);
                mLastSecondPoint.set(mLastSecondPoint);
                mLastResizeBounds.set(mDownBounds);
            }
        }

@@ -391,131 +395,34 @@ public class PipResizeGestureHandler {
            float y0 = ev.getRawY(mFirstIndex);
            float x1 = ev.getRawX(mSecondIndex);
            float y1 = ev.getRawY(mSecondIndex);
            mLastPoint.set(x0, y0);
            mLastSecondPoint.set(x1, y1);

            double hypot0 = Math.hypot(x0 - mDownPoint.x, y0 - mDownPoint.y);
            double hypot1 = Math.hypot(x1 - mDownSecondaryPoint.x, y1 - mDownSecondaryPoint.y);
            // Capture inputs
            if (hypot0 > mTouchSlop && !mThresholdCrossed0) {
                mInputMonitor.pilferPointers();
                mThresholdCrossed0 = true;
                // Reset the down to begin resizing from this point
                mDownPoint.set(x0, y0);
            }
            if (hypot1 > mTouchSlop && !mThresholdCrossed1) {
            if (!mThresholdCrossed
                    && (distanceBetween(mDownSecondPoint, mLastSecondPoint) > mTouchSlop
                            || distanceBetween(mDownPoint, mLastPoint) > mTouchSlop)) {
                mInputMonitor.pilferPointers();
                mThresholdCrossed1 = true;
                mThresholdCrossed = true;
                // Reset the down to begin resizing from this point
                mDownSecondaryPoint.set(x1, y1);
                mDownPoint.set(mLastPoint);
                mDownSecondPoint.set(mLastSecondPoint);
            }
            if (mThresholdCrossed0 || mThresholdCrossed1) {

            if (mThresholdCrossed) {
                if (mPhonePipMenuController.isMenuVisible()) {
                    mPhonePipMenuController.hideMenu();
                }

                x0 = mThresholdCrossed0 ? x0 : mDownPoint.x;
                y0 = mThresholdCrossed0 ? y0 : mDownPoint.y;
                x1 = mThresholdCrossed1 ? x1 : mDownSecondaryPoint.x;
                y1 = mThresholdCrossed1 ? y1 : mDownSecondaryPoint.y;

                final Rect originalPipBounds = mPipBoundsState.getBounds();
                int focusX = (int) originalPipBounds.centerX();
                int focusY = (int) originalPipBounds.centerY();

                float down0X = mDownPoint.x;
                float down0Y = mDownPoint.y;
                float down1X = mDownSecondaryPoint.x;
                float down1Y = mDownSecondaryPoint.y;

                float angle = 0;
                if (down0X > focusX && down0Y < focusY && down1X < focusX && down1Y > focusY) {
                    // Top right + Bottom left pinch to zoom.
                    angle = calculateRotationAngle(mLastResizeBounds.centerX(),
                            mLastResizeBounds.centerY(), x0, y0, x1, y1, true);
                } else if (down1X > focusX && down1Y < focusY
                        && down0X < focusX && down0Y > focusY) {
                    // Top right + Bottom left pinch to zoom.
                    angle = calculateRotationAngle(mLastResizeBounds.centerX(),
                            mLastResizeBounds.centerY(), x1, y1, x0, y0, true);
                } else if (down0X < focusX && down0Y < focusY
                        && down1X > focusX && down1Y > focusY) {
                    // Top left + bottom right pinch to zoom.
                    angle = calculateRotationAngle(mLastResizeBounds.centerX(),
                            mLastResizeBounds.centerY(), x0, y0, x1, y1, false);
                } else if (down1X < focusX && down1Y < focusY
                        && down0X > focusX && down0Y > focusY) {
                    // Top left + bottom right pinch to zoom.
                    angle = calculateRotationAngle(mLastResizeBounds.centerX(),
                            mLastResizeBounds.centerY(), x1, y1, x0, y0, false);
                }
                mAngle = angle;

                mLastResizeBounds.set(PipPinchResizingAlgorithm.pinchResize(x0, y0, x1, y1,
                        mDownPoint.x, mDownPoint.y, mDownSecondaryPoint.x, mDownSecondaryPoint.y,
                        originalPipBounds, mMinSize.x, mMinSize.y, mMaxSize));

                mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds, mLastResizeBounds,
                        (float) -mAngle, null);
                mPipBoundsState.setHasUserResizedPip(true);
            }
        }
    }

    private float calculateRotationAngle(int pivotX, int pivotY, float topX, float topY,
            float bottomX, float bottomY, boolean positive) {

        // The base angle is the angle formed by taking the angle between the center horizontal
        // and one of the corners.
        double baseAngle = Math.toDegrees(Math.atan2(Math.abs(mLastResizeBounds.top - pivotY),
                Math.abs(mLastResizeBounds.right - pivotX)));

        double angle0 = mThresholdCrossed0
                ? Math.toDegrees(Math.atan2(pivotY - topY, topX - pivotX)) : baseAngle;
        double angle1 = mThresholdCrossed0
                ? Math.toDegrees(Math.atan2(pivotY - bottomY, bottomX - pivotX)) : baseAngle;


        if (positive) {
            angle1 = angle1 < 0 ? 180 + angle1 : angle1 - 180;
        } else {
            angle0 = angle0 < 0 ? -angle0 - 180 : 180 - angle0;
            angle1 = -angle1;
        }

        // Calculate the percentage difference of [0, 90] compare to the base angle.
        double diff0 = (Math.max(-90, Math.min(angle0, 90)) - baseAngle) / 90;
        double diff1 = (Math.max(-90, Math.min(angle1, 90)) - baseAngle) / 90;

        final float angle =
                (float) (diff0 + diff1) / 2 * PINCH_RESIZE_MAX_ANGLE_ROTATION * (positive ? 1 : -1);

        // Remove some degrees so that user doesn't immediately start rotating until a threshold
        return angle / Math.abs(angle)
                * Math.max(0, (Math.abs(dampedRotate(angle)) - ANGLE_THRESHOLD));
    }

    /**
     * Given the current rotation angle, dampen it so that as it approaches the maximum angle,
     * dampen it.
     */
    private float dampedRotate(float amount) {
        if (Float.compare(amount, 0) == 0) return 0;
                mAngle = mPinchResizingAlgorithm.calculateBoundsAndAngle(mDownPoint,
                        mDownSecondPoint, mLastPoint, mLastSecondPoint, mMinSize, mMaxSize,
                        mDownBounds, mLastResizeBounds);

        float f = amount / PINCH_RESIZE_MAX_ANGLE_ROTATION;
        f = f / (Math.abs(f)) * (overRotateInfluenceCurve(Math.abs(f)));

        // Clamp this factor, f, to -1 < f < 1
        if (Math.abs(f) >= 1) {
            f /= Math.abs(f);
                mPipTaskOrganizer.scheduleUserResizePip(mDownBounds, mLastResizeBounds,
                        mAngle, null);
                mPipBoundsState.setHasUserResizedPip(true);
            }
        return OVERROTATE_DAMP_FACTOR * f * PINCH_RESIZE_MAX_ANGLE_ROTATION;
        }

    /**
     * Returns a value that corresponds to y = (f - 1)^3 + 1.
     */
    private float overRotateInfluenceCurve(float f) {
        f -= 1.0f;
        return f * f * f + 1.0f;
    }

    private void onDragCornerResize(MotionEvent ev) {
@@ -529,7 +436,7 @@ public class PipResizeGestureHandler {
            if (mAllowGesture) {
                setCtrlType((int) x, (int) y);
                mDownPoint.set(x, y);
                mLastDownBounds.set(mPipBoundsState.getBounds());
                mDownBounds.set(mPipBoundsState.getBounds());
            }
            if (!currentPipBounds.contains((int) ev.getX(), (int) ev.getY())
                    && mPhonePipMenuController.isMenuVisible()) {
@@ -560,11 +467,11 @@ public class PipResizeGestureHandler {
                        mLastResizeBounds.set(TaskResizingAlgorithm.resizeDrag(x, y,
                                mDownPoint.x, mDownPoint.y, currentPipBounds, mCtrlType, mMinSize.x,
                                mMinSize.y, mMaxSize, true,
                                mLastDownBounds.width() > mLastDownBounds.height()));
                                mDownBounds.width() > mDownBounds.height()));
                        mPipBoundsAlgorithm.transformBoundsToAspectRatio(mLastResizeBounds,
                                mPipBoundsState.getAspectRatio(), false /* useCurrentMinEdgeSize */,
                                true /* useCurrentSize */);
                        mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds, mLastResizeBounds,
                        mPipTaskOrganizer.scheduleUserResizePip(mDownBounds, mLastResizeBounds,
                                null);
                        mPipBoundsState.setHasUserResizedPip(true);
                    }
@@ -593,12 +500,12 @@ public class PipResizeGestureHandler {
                // If user resize is pretty close to max size, just auto resize to max.
                if (mLastResizeBounds.width() >= PINCH_RESIZE_AUTO_MAX_RATIO * mMaxSize.x
                        || mLastResizeBounds.height() >= PINCH_RESIZE_AUTO_MAX_RATIO * mMaxSize.y) {
                    mLastResizeBounds.set(0, 0, mMaxSize.x, mMaxSize.y);
                    resizeRectAboutCenter(mLastResizeBounds, mMaxSize.x, mMaxSize.y);
                }
                final float snapFraction = mPipBoundsAlgorithm.getSnapFraction(mLastResizeBounds);
                mPipBoundsAlgorithm.applySnapFraction(mLastResizeBounds, snapFraction);
                mPipTaskOrganizer.scheduleAnimateResizePip(startBounds, mLastResizeBounds,
                        PINCH_RESIZE_SNAP_DURATION, -mAngle, callback);
                        PINCH_RESIZE_SNAP_DURATION, mAngle, callback);
            } else {
                mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds,
                        PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE, callback);
@@ -642,6 +549,20 @@ public class PipResizeGestureHandler {
        mOhmOffset = offset;
    }

    private float distanceBetween(PointF p1, PointF p2) {
        return (float) Math.hypot(p2.x - p1.x, p2.y - p1.y);
    }

    private void resizeRectAboutCenter(Rect rect, int w, int h) {
        int cx = rect.centerX();
        int cy = rect.centerY();
        int l = cx - w / 2;
        int r = l + w;
        int t = cy - h / 2;
        int b = t + h;
        rect.set(l, t, r, b);
    }

    public void dump(PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
        pw.println(prefix + TAG);
+1 −1
Original line number Diff line number Diff line
@@ -664,7 +664,7 @@ public class PipTouchHandler {
        } else if (menuState == MENU_STATE_NONE && mMenuState == MENU_STATE_FULL) {
            // Try and restore the PiP to the closest edge, using the saved snap fraction
            // if possible
            if (resize) {
            if (resize && !mPipResizeGestureHandler.isResizing()) {
                if (mDeferResizeToNormalBoundsUntilRotation == -1) {
                    // This is a very special case: when the menu is expanded and visible,
                    // navigating to another activity can trigger auto-enter PiP, and if the