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

Commit 08805831 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Polish the back to home gesture animation to match the spec." into tm-dev am: cf806451

parents 4e2dcdac cf806451
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -244,8 +244,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
        mDragLayerAlpha = mDragLayer.getAlphaProperty(ALPHA_INDEX_TRANSITIONS);
        mHandler = new Handler(Looper.getMainLooper());
        mDeviceProfile = mLauncher.getDeviceProfile();
        mBackAnimationController = new LauncherBackAnimationController(
                mDeviceProfile, mLauncher, this);
        mBackAnimationController = new LauncherBackAnimationController(mLauncher, this);

        Resources res = mLauncher.getResources();
        mContentScale = res.getFloat(R.dimen.content_scale);
@@ -1441,6 +1440,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
                }
            };
            anim.addOnUpdateListener(runner);
        } else {
            // If no floating icon or widget is present, animate the to the default window
            // target rect.
            anim.addOnUpdateListener(new SpringAnimRunner(targets, targetRect, windowTargetBounds));
        }

        // Use a fixed velocity to start the animation.
+77 −49
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
@@ -33,11 +34,12 @@ import android.util.MathUtils;
import android.util.Pair;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.window.BackEvent;
import android.window.IOnBackInvokedCallback;

import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -62,34 +64,36 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
 *
 */
public class LauncherBackAnimationController {
    private static final int CANCEL_TRANSITION_DURATION = 150;
    private static final int CANCEL_TRANSITION_DURATION = 233;
    private static final float MIN_WINDOW_SCALE = 0.7f;
    private static final String TAG = "LauncherBackAnimationController";
    private final DeviceProfile mDeviceProfile;
    private final QuickstepTransitionManager mQuickstepTransitionManager;
    private final Matrix mTransformMatrix = new Matrix();
    private final RectF mTargetRectF = new RectF();
    private final RectF mStartRectF = new RectF();
    /** The window position at the beginning of the back animation. */
    private final Rect mStartRect = new Rect();
    /** The window position when the back gesture is cancelled. */
    private final RectF mCancelRect = new RectF();
    /** The current window position. */
    private final RectF mCurrentRect = new RectF();
    private final BaseQuickstepLauncher mLauncher;
    private final int mWindowScaleMarginX;
    private final int mWindowScaleMarginY;
    /** Max window translation in the Y axis. */
    private final int mWindowMaxDeltaY;
    private final float mWindowScaleEndCornerRadius;
    private final float mWindowScaleStartCornerRadius;
    private final Interpolator mCancelInterpolator;
    private final PointF mInitialTouchPos = new PointF();

    private RemoteAnimationTargetCompat mBackTarget;
    private SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
    private boolean mSpringAnimationInProgress = false;
    private boolean mAnimatorSetInProgress = false;
    @BackEvent.SwipeEdge
    private int mSwipeEdge;
    private float mBackProgress = 0;
    private boolean mBackInProgress = false;

    public LauncherBackAnimationController(
            DeviceProfile deviceProfile,
            BaseQuickstepLauncher launcher,
            QuickstepTransitionManager quickstepTransitionManager) {
        mDeviceProfile = deviceProfile;
        mLauncher = launcher;
        mQuickstepTransitionManager = quickstepTransitionManager;
        mWindowScaleEndCornerRadius = QuickStepContract.supportsRoundedCornersOnWindows(
@@ -100,8 +104,10 @@ public class LauncherBackAnimationController {
        mWindowScaleStartCornerRadius = QuickStepContract.getWindowCornerRadius(mLauncher);
        mWindowScaleMarginX = mLauncher.getResources().getDimensionPixelSize(
                R.dimen.swipe_back_window_scale_x_margin);
        mWindowScaleMarginY = mLauncher.getResources().getDimensionPixelSize(
                R.dimen.swipe_back_window_scale_y_margin);
        mWindowMaxDeltaY = mLauncher.getResources().getDimensionPixelSize(
                R.dimen.swipe_back_window_max_delta_y);
        mCancelInterpolator =
                AnimationUtils.loadInterpolator(mLauncher, R.interpolator.back_cancel);
    }

    /**
@@ -136,7 +142,7 @@ public class LauncherBackAnimationController {
                        if (!mBackInProgress) {
                            startBack(backEvent);
                        } else {
                            updateBackProgress(mBackProgress);
                            updateBackProgress(mBackProgress, backEvent);
                        }
                    }

@@ -145,11 +151,13 @@ public class LauncherBackAnimationController {
    }

    private void resetPositionAnimated() {
        ValueAnimator cancelAnimator = ValueAnimator.ofFloat(mBackProgress, 0);
        ValueAnimator cancelAnimator = ValueAnimator.ofFloat(0, 1);
        mCancelRect.set(mCurrentRect);
        cancelAnimator.setDuration(CANCEL_TRANSITION_DURATION);
        cancelAnimator.setInterpolator(mCancelInterpolator);
        cancelAnimator.addUpdateListener(
                animation -> {
                    updateBackProgress((float) animation.getAnimatedValue());
                    updateCancelProgress((float) animation.getAnimatedValue());
                });
        cancelAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
@@ -179,50 +187,70 @@ public class LauncherBackAnimationController {
        mTransaction.show(appTarget.leash).apply();
        mTransaction.setAnimationTransaction();
        mBackTarget = new RemoteAnimationTargetCompat(appTarget);
        mSwipeEdge = backEvent.getSwipeEdge();
        float screenWidth = mDeviceProfile.widthPx;
        float screenHeight = mDeviceProfile.heightPx;
        float targetHeight = screenHeight - 2 * mWindowScaleMarginY;
        float targetWidth = targetHeight * screenWidth / screenHeight;
        float left;
        if (mSwipeEdge == BackEvent.EDGE_LEFT) {
            left = screenWidth - targetWidth - mWindowScaleMarginX;
        } else {
            left = mWindowScaleMarginX;
        }
        float top = mWindowScaleMarginY;
        mInitialTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY());

        // TODO(b/218916755): Offset start rectangle in multiwindow mode.
        mStartRectF.set(0, 0, screenWidth, screenHeight);
        mTargetRectF.set(left, top, targetWidth + left, targetHeight + top);
        mStartRect.set(mBackTarget.windowConfiguration.getMaxBounds());
    }

    private void updateBackProgress(float progress) {
    private void updateBackProgress(float progress, BackEvent event) {
        if (mBackTarget == null) {
            return;
        }
        float screenWidth = mStartRect.width();
        float screenHeight = mStartRect.height();
        float dX = Math.abs(event.getTouchX() - mInitialTouchPos.x);
        // The 'follow width' is the width of the window if it completely matches
        // the gesture displacement.
        float followWidth = screenWidth - dX;
        // The 'progress width' is the width of the window if it strictly linearly interpolates
        // to minimum scale base on progress.
        float progressWidth = MathUtils.lerp(1, MIN_WINDOW_SCALE, progress) * screenWidth;
        // The final width is derived from interpolating between the follow with and progress width
        // using gesture progress.
        float width = MathUtils.lerp(followWidth, progressWidth, progress);
        float height = screenHeight / screenWidth * width;
        float deltaYRatio = (event.getTouchY() - mInitialTouchPos.y) / screenHeight;
        // Base the window movement in the Y axis on the touch movement in the Y axis.
        float deltaY = (float) Math.sin(deltaYRatio * Math.PI * 0.5f) * mWindowMaxDeltaY;
        // Move the window along the Y axis.
        float top = (screenHeight - height) * 0.5f + deltaY;
        // Move the window along the X axis.
        float left = event.getSwipeEdge() == BackEvent.EDGE_RIGHT
                ? progress * mWindowScaleMarginX
                : screenWidth - progress * mWindowScaleMarginX - width;

        mCurrentRect.set(left, top, left + width, top + height);
        float cornerRadius = Utilities.mapRange(
                progress, mWindowScaleStartCornerRadius, mWindowScaleEndCornerRadius);
        applyTransform(mCurrentRect, cornerRadius);
    }

    private void updateCancelProgress(float progress) {
        if (mBackTarget == null) {
            return;
        }
        mCurrentRect.set(
                MathUtils.lerp(mStartRectF.left, mTargetRectF.left, progress),
                MathUtils.lerp(mStartRectF.top, mTargetRectF.top, progress),
                MathUtils.lerp(mStartRectF.right, mTargetRectF.right, progress),
                MathUtils.lerp(mStartRectF.bottom, mTargetRectF.bottom, progress));
        SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder builder =
                new SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder(mBackTarget.leash);
                MathUtils.lerp(mCancelRect.left, mStartRect.left, progress),
                MathUtils.lerp(mCancelRect.top, mStartRect.top, progress),
                MathUtils.lerp(mCancelRect.right, mStartRect.right, progress),
                MathUtils.lerp(mCancelRect.bottom, mStartRect.bottom, progress));

        Rect currentRect = new Rect();
        mCurrentRect.round(currentRect);
        float cornerRadius = Utilities.mapRange(
                progress, mWindowScaleEndCornerRadius, mWindowScaleStartCornerRadius);
        applyTransform(mCurrentRect, cornerRadius);
    }

        // Scale the target window to match the currentRectF.
        final float scale = mCurrentRect.width() / mStartRectF.width();
    /** Transform the target window to match the target rect. */
    private void applyTransform(RectF targetRect, float cornerRadius) {
        SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder builder =
                new SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder(mBackTarget.leash);
        final float scale = targetRect.width() / mStartRect.width();
        mTransformMatrix.reset();
        mTransformMatrix.setScale(scale, scale);
        mTransformMatrix.postTranslate(mCurrentRect.left, mCurrentRect.top);
        Rect startRect = new Rect();
        mStartRectF.round(startRect);
        float cornerRadius = Utilities.mapRange(
                progress, mWindowScaleStartCornerRadius, mWindowScaleEndCornerRadius);
        mTransformMatrix.postTranslate(targetRect.left, targetRect.top);
        builder.withMatrix(mTransformMatrix)
                .withWindowCrop(startRect)
                .withWindowCrop(mStartRect)
                .withCornerRadius(cornerRadius);
        SyncRtSurfaceTransactionApplierCompat.SurfaceParams surfaceParams = builder.build();

@@ -263,11 +291,11 @@ public class LauncherBackAnimationController {
        mBackTarget = null;
        mBackInProgress = false;
        mBackProgress = 0;
        mSwipeEdge = BackEvent.EDGE_LEFT;
        mTransformMatrix.reset();
        mTargetRectF.setEmpty();
        mCancelRect.setEmpty();
        mCurrentRect.setEmpty();
        mStartRectF.setEmpty();
        mStartRect.setEmpty();
        mInitialTouchPos.set(0, 0);
        mAnimatorSetInProgress = false;
        mSpringAnimationInProgress = false;
        SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.getNoCreate();
+24 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2022, 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.
*/
-->

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:controlX1="0.2"
    android:controlY1="0"
    android:controlX2="0"
    android:controlY2="1"/>
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -166,6 +166,6 @@

    <!-- Swipe back to home related -->
    <dimen name="swipe_back_window_scale_x_margin">10dp</dimen>
    <dimen name="swipe_back_window_scale_y_margin">80dp</dimen>
    <dimen name="swipe_back_window_max_delta_y">160dp</dimen>
    <dimen name="swipe_back_window_corner_radius">40dp</dimen>
</resources>