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

Commit fb5c7f5b authored by Ben Lin's avatar Ben Lin Committed by Android (Google) Code Review
Browse files

Merge "Re-implement pinch-to-resize gesture."

parents 7ea661f1 014f2975
Loading
Loading
Loading
Loading
+37 −13
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ public class PipAnimationController {
    public static final int TRANSITION_DIRECTION_LEAVE_PIP = 3;
    public static final int TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN = 4;
    public static final int TRANSITION_DIRECTION_REMOVE_STACK = 5;
    public static final int TRANSITION_DIRECTION_SNAP_AFTER_RESIZE = 6;

    @IntDef(prefix = { "TRANSITION_DIRECTION_" }, value = {
            TRANSITION_DIRECTION_NONE,
@@ -61,7 +62,8 @@ public class PipAnimationController {
            TRANSITION_DIRECTION_TO_PIP,
            TRANSITION_DIRECTION_LEAVE_PIP,
            TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN,
            TRANSITION_DIRECTION_REMOVE_STACK
            TRANSITION_DIRECTION_REMOVE_STACK,
            TRANSITION_DIRECTION_SNAP_AFTER_RESIZE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface TransitionDirection {}
@@ -109,13 +111,27 @@ public class PipAnimationController {
    }

    @SuppressWarnings("unchecked")
    /**
     * Construct and return an animator that animates from the {@param startBounds} to the
     * {@param endBounds} with the given {@param direction}. If {@param direction} is type
     * {@link ANIM_TYPE_BOUNDS}, then {@param sourceHintRect} will be used to animate
     * in a better, more smooth manner.
     *
     * In the case where one wants to start animation during an intermediate animation (for example,
     * if the user is currently doing a pinch-resize, and upon letting go now PiP needs to animate
     * to the correct snap fraction region), then provide the base bounds, which is current PiP
     * leash bounds before transformation/any animation. This is so when we try to construct
     * the different transformation matrices for the animation, we are constructing this based off
     * the PiP original bounds, rather than the {@param startBounds}, which is post-transformed.
     */
    @VisibleForTesting
    public PipTransitionAnimator getAnimator(SurfaceControl leash, Rect startBounds, Rect endBounds,
            Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction) {
    public PipTransitionAnimator getAnimator(SurfaceControl leash, Rect baseBounds,
            Rect startBounds, Rect endBounds, Rect sourceHintRect,
            @PipAnimationController.TransitionDirection int direction) {
        if (mCurrentAnimator == null) {
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofBounds(leash, startBounds, endBounds, sourceHintRect,
                            direction));
                    PipTransitionAnimator.ofBounds(leash, startBounds, startBounds, endBounds,
                            sourceHintRect, direction));
        } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
                && mCurrentAnimator.isRunning()) {
            // If we are still animating the fade into pip, then just move the surface and ensure
@@ -130,8 +146,8 @@ public class PipAnimationController {
        } else {
            mCurrentAnimator.cancel();
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofBounds(leash, startBounds, endBounds, sourceHintRect,
                            direction));
                    PipTransitionAnimator.ofBounds(leash, baseBounds, startBounds, endBounds,
                            sourceHintRect, direction));
        }
        return mCurrentAnimator;
    }
@@ -180,6 +196,7 @@ public class PipAnimationController {
        private final @AnimationType int mAnimationType;
        private final Rect mDestinationBounds = new Rect();

        private T mBaseValue;
        protected T mCurrentValue;
        protected T mStartValue;
        private T mEndValue;
@@ -190,10 +207,11 @@ public class PipAnimationController {
        private @TransitionDirection int mTransitionDirection;

        private PipTransitionAnimator(SurfaceControl leash, @AnimationType int animationType,
                Rect destinationBounds, T startValue, T endValue) {
                Rect destinationBounds, T baseValue, T startValue, T endValue) {
            mLeash = leash;
            mAnimationType = animationType;
            mDestinationBounds.set(destinationBounds);
            mBaseValue = baseValue;
            mStartValue = startValue;
            mEndValue = endValue;
            addListener(this);
@@ -263,6 +281,10 @@ public class PipAnimationController {
            return mStartValue;
        }

        T getBaseValue() {
            return mBaseValue;
        }

        @VisibleForTesting
        public T getEndValue() {
            return mEndValue;
@@ -334,7 +356,7 @@ public class PipAnimationController {
        static PipTransitionAnimator<Float> ofAlpha(SurfaceControl leash,
                Rect destinationBounds, float startValue, float endValue) {
            return new PipTransitionAnimator<Float>(leash, ANIM_TYPE_ALPHA,
                    destinationBounds, startValue, endValue) {
                    destinationBounds, startValue, startValue, endValue) {
                @Override
                void applySurfaceControlTransaction(SurfaceControl leash,
                        SurfaceControl.Transaction tx, float fraction) {
@@ -367,7 +389,7 @@ public class PipAnimationController {
        }

        static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash,
                Rect startValue, Rect endValue, Rect sourceHintRect,
                Rect baseValue, Rect startValue, Rect endValue, Rect sourceHintRect,
                @PipAnimationController.TransitionDirection int direction) {
            // Just for simplicity we'll interpolate between the source rect hint insets and empty
            // insets to calculate the window crop
@@ -375,7 +397,7 @@ public class PipAnimationController {
            if (isOutPipDirection(direction)) {
                initialSourceValue = new Rect(endValue);
            } else {
                initialSourceValue = new Rect(startValue);
                initialSourceValue = new Rect(baseValue);
            }

            final Rect sourceHintRectInsets;
@@ -391,22 +413,24 @@ public class PipAnimationController {

            // construct new Rect instances in case they are recycled
            return new PipTransitionAnimator<Rect>(leash, ANIM_TYPE_BOUNDS,
                    endValue, new Rect(startValue), new Rect(endValue)) {
                    endValue, new Rect(baseValue), new Rect(startValue), new Rect(endValue)) {
                private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect());
                private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect());

                @Override
                void applySurfaceControlTransaction(SurfaceControl leash,
                        SurfaceControl.Transaction tx, float fraction) {
                    final Rect base = getBaseValue();
                    final Rect start = getStartValue();
                    final Rect end = getEndValue();
                    Rect bounds = mRectEvaluator.evaluate(fraction, start, end);
                    setCurrentValue(bounds);
                    if (inScaleTransition() || sourceHintRect == null) {

                        if (isOutPipDirection(direction)) {
                            getSurfaceTransactionHelper().scale(tx, leash, end, bounds);
                        } else {
                            getSurfaceTransactionHelper().scale(tx, leash, start, bounds);
                            getSurfaceTransactionHelper().scale(tx, leash, base, bounds);
                        }
                    } else {
                        final Rect insets;
+19 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTI
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_NONE;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_REMOVE_STACK;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_SAME;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_SNAP_AFTER_RESIZE;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
import static com.android.wm.shell.pip.PipAnimationController.isInPipDirection;
import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection;
@@ -814,6 +815,20 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
                TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback);
    }

    /**
     * Animates resizing of the pinned stack given the duration and start bounds.
     * This is used when the starting bounds is not the current PiP bounds.
     */
    public void scheduleAnimateResizePip(Rect fromBounds, Rect toBounds, int duration,
            Consumer<Rect> updateBoundsCallback) {
        if (mShouldDeferEnteringPip) {
            Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
            return;
        }
        scheduleAnimateResizePip(fromBounds, toBounds, null /* sourceHintRect */,
                TRANSITION_DIRECTION_SNAP_AFTER_RESIZE, duration, updateBoundsCallback);
    }

    private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
            Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction,
            int durationMs, Consumer<Rect> updateBoundsCallback) {
@@ -1073,8 +1088,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
            Log.w(TAG, "Abort animation, invalid leash");
            return;
        }
        Rect baseBounds = direction == TRANSITION_DIRECTION_SNAP_AFTER_RESIZE
                ? mPipBoundsState.getBounds() : currentBounds;
        mPipAnimationController
                .getAnimator(mLeash, currentBounds, destinationBounds, sourceHintRect, direction)
                .getAnimator(mLeash, baseBounds, currentBounds, destinationBounds, sourceHintRect,
                        direction)
                .setTransitionDirection(direction)
                .setPipAnimationCallback(mPipAnimationCallback)
                .setDuration(durationMs)
+123 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.wm.shell.pip.phone;

import android.graphics.Point;
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();
    /**
     * 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.
     */
    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));

        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)));
            }
            // 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)));
            }
        } 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)));
            }
            // 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)));
            }
        }

        // 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;
        }

        TMP_RECT.set(currentPipBounds.centerX() - width / 2,
                currentPipBounds.centerY() - height / 2,
                currentPipBounds.centerX() + width / 2,
                currentPipBounds.centerY() + height / 2);
        return TMP_RECT;
    }
}
+121 −101

File changed.

Preview size limit exceeded, changes collapsed.

+5 −0
Original line number Diff line number Diff line
@@ -470,6 +470,11 @@ public class PipTouchHandler {
            return true;
        }

        if (mPipResizeGestureHandler.hasOngoingGesture()) {
            mPipDismissTargetHandler.hideDismissTargetMaybe();
            return true;
        }

        if ((ev.getAction() == MotionEvent.ACTION_DOWN || mTouchState.isUserInteracting())
                && mPipDismissTargetHandler.maybeConsumeMotionEvent(ev)) {
            // If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event
Loading