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

Commit 216c0eed authored by Tony Wickham's avatar Tony Wickham Committed by android-build-merger
Browse files

Merge "Decouple recents view from window while swiping up" into ub-launcher3-qt-dev

am: 0cc53e7f

Change-Id: I35b6985c50af31debac49fcc5c4714216acd9786
parents 4f5503e1 0cc53e7f
Loading
Loading
Loading
Loading
+26 −1
Original line number Diff line number Diff line
@@ -16,14 +16,15 @@
package com.android.quickstep;

import static android.view.View.TRANSLATION_Y;

import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_DAMPING_RATIO;
import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_STIFFNESS;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.WindowTransformSwipeHandler.RECENTS_ATTACH_DURATION;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -177,6 +178,8 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
        return new AnimationFactory() {
            private Animator mShelfAnim;
            private ShelfAnimState mShelfState;
            private Animator mAttachToWindowAnim;
            private boolean mIsAttachedToWindow;

            @Override
            public void createActivityController(long transitionLength) {
@@ -221,6 +224,28 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
                mShelfAnim.setDuration(duration);
                mShelfAnim.start();
            }

            @Override
            public void setRecentsAttachedToAppWindow(boolean attached, boolean animate) {
                if (mIsAttachedToWindow == attached && animate) {
                    return;
                }
                mIsAttachedToWindow = attached;
                if (mAttachToWindowAnim != null) {
                    mAttachToWindowAnim.cancel();
                }
                mAttachToWindowAnim = ObjectAnimator.ofFloat(activity.getOverviewPanel(),
                        RecentsView.CONTENT_ALPHA, attached ? 1 : 0);
                mAttachToWindowAnim.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        mAttachToWindowAnim = null;
                    }
                });
                mAttachToWindowAnim.setInterpolator(ACCEL_DEACCEL);
                mAttachToWindowAnim.setDuration(animate ? RECENTS_ATTACH_DURATION : 0);
                mAttachToWindowAnim.start();
            }
        };
    }

+1 −0
Original line number Diff line number Diff line
@@ -267,6 +267,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
                        mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
                                || isLikelyToStartNewTask);
                        mMotionPauseDetector.addPosition(displacement, ev.getEventTime());
                        mInteractionHandler.setIsLikelyToStartNewTask(isLikelyToStartNewTask);
                    }
                }
                break;
+85 −8
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
@@ -111,6 +112,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
        implements SwipeAnimationListener, OnApplyWindowInsetsListener {
    private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();

    private static final Rect TEMP_RECT = new Rect();

    private static final String[] STATE_NAMES = DEBUG_STATES ? new String[16] : null;

    private static int getFlagForIndex(int index, String name) {
@@ -162,22 +165,23 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
            STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED;

    enum GestureEndTarget {
        HOME(1, STATE_SCALED_CONTROLLER_HOME, true, false, ContainerType.WORKSPACE),
        HOME(1, STATE_SCALED_CONTROLLER_HOME, true, false, ContainerType.WORKSPACE, false),

        RECENTS(1, STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
                | STATE_SCREENSHOT_VIEW_SHOWN, true, false, ContainerType.TASKSWITCHER),
                | STATE_SCREENSHOT_VIEW_SHOWN, true, false, ContainerType.TASKSWITCHER, true),

        NEW_TASK(0, STATE_START_NEW_TASK, false, true, ContainerType.APP),
        NEW_TASK(0, STATE_START_NEW_TASK, false, true, ContainerType.APP, true),

        LAST_TASK(0, STATE_RESUME_LAST_TASK, false, true, ContainerType.APP);
        LAST_TASK(0, STATE_RESUME_LAST_TASK, false, true, ContainerType.APP, false);

        GestureEndTarget(float endShift, int endState, boolean isLauncher, boolean canBeContinued,
                int containerType) {
                int containerType, boolean recentsAttachedToAppWindow) {
            this.endShift = endShift;
            this.endState = endState;
            this.isLauncher = isLauncher;
            this.canBeContinued = canBeContinued;
            this.containerType = containerType;
            this.recentsAttachedToAppWindow = recentsAttachedToAppWindow;
        }

        /** 0 is app, 1 is overview */
@@ -190,6 +194,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
        public final boolean canBeContinued;
        /** Used to log where the user ended up after the gesture ends */
        public final int containerType;
        /** Whether RecentsView should be attached to the window as we animate to this target */
        public final boolean recentsAttachedToAppWindow;
    }

    public static final long MAX_SWIPE_DURATION = 350;
@@ -202,6 +208,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
    private static final String SCREENSHOT_CAPTURED_EVT = "ScreenshotCaptured";

    private static final long SHELF_ANIM_DURATION = 120;
    public static final long RECENTS_ATTACH_DURATION = 300;

    /**
     * Used as the page index for logging when we return to the last task at the end of the gesture.
@@ -254,6 +261,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
    private int mLogAction = Touch.SWIPE;
    private int mLogDirection = Direction.UP;
    private PointF mDownPos;
    private boolean mIsLikelyToStartNewTask;

    private final RecentsAnimationWrapper mRecentsAnimationWrapper;

@@ -437,6 +445,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
                mAnimationFactory = mActivityControlHelper.prepareRecentsUI(mActivity,
                        mWasLauncherAlreadyVisible, true,
                        this::onAnimatorPlaybackControllerCreated);
                maybeUpdateRecentsAttachedState(false /* animate */);
            };
            if (mWasLauncherAlreadyVisible) {
                // Launcher is visible, but might be about to stop. Thus, if we prepare recents
@@ -541,10 +550,65 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
        setShelfState(isPaused ? PEEK : HIDE, FAST_OUT_SLOW_IN, SHELF_ANIM_DURATION);
    }

    public void maybeUpdateRecentsAttachedState() {
        maybeUpdateRecentsAttachedState(true /* animate */);
    }

    /**
     * Determines whether to show or hide RecentsView. The window is always
     * synchronized with its corresponding TaskView in RecentsView, so if
     * RecentsView is shown, it will appear to be attached to the window.
     *
     * Note this method has no effect unless the navigation mode is NO_BUTTON.
     */
    private void maybeUpdateRecentsAttachedState(boolean animate) {
        if (mMode != Mode.NO_BUTTON || mRecentsView == null) {
            return;
        }
        RemoteAnimationTargetCompat runningTaskTarget = mRecentsAnimationWrapper.targetSet == null
                ? null
                : mRecentsAnimationWrapper.targetSet.findTask(mRunningTaskId);
        final boolean recentsAttachedToAppWindow;
        int runningTaskIndex = mRecentsView.getRunningTaskIndex();
        if (mContinuingLastGesture) {
            recentsAttachedToAppWindow = true;
            animate = false;
        } else if (runningTaskTarget != null && isNotInRecents(runningTaskTarget)) {
            // The window is going away so make sure recents is always visible in this case.
            recentsAttachedToAppWindow = true;
            animate = false;
        } else {
            if (mGestureEndTarget != null) {
                recentsAttachedToAppWindow = mGestureEndTarget.recentsAttachedToAppWindow;
            } else {
                recentsAttachedToAppWindow = mIsShelfPeeking || mIsLikelyToStartNewTask;
            }
            if (animate) {
                // Only animate if an adjacent task view is visible on screen.
                TaskView adjacentTask1 = mRecentsView.getTaskViewAt(runningTaskIndex + 1);
                TaskView adjacentTask2 = mRecentsView.getTaskViewAt(runningTaskIndex - 1);
                animate = (adjacentTask1 != null && adjacentTask1.getGlobalVisibleRect(TEMP_RECT))
                        || (adjacentTask2 != null && adjacentTask2.getGlobalVisibleRect(TEMP_RECT));
            }
        }
        mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
    }

    public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) {
        if (mIsLikelyToStartNewTask != isLikelyToStartNewTask) {
            mIsLikelyToStartNewTask = isLikelyToStartNewTask;
            maybeUpdateRecentsAttachedState();
        }
    }

    @UiThread
    public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, long duration) {
        mAnimationFactory.setShelfState(shelfState, interpolator, duration);
        boolean wasShelfPeeking = mIsShelfPeeking;
        mIsShelfPeeking = shelfState == PEEK;
        if (mIsShelfPeeking != wasShelfPeeking) {
            maybeUpdateRecentsAttachedState();
        }
        if (mRecentsView != null && shelfState.shouldPreformHaptic) {
            mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
                    HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
@@ -872,6 +936,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
            Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) {
        mGestureEndTarget = target;

        maybeUpdateRecentsAttachedState();

        if (mGestureEndTarget == HOME) {
            HomeAnimationFactory homeAnimFactory;
            if (mActivity != null) {
@@ -905,8 +971,15 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
            windowAnim.start(velocityPxPerMs);
            mLauncherTransitionController = null;
        } else {
            Animator windowAnim = mCurrentShift.animateToValue(start, end);
            ValueAnimator windowAnim = mCurrentShift.animateToValue(start, end);
            windowAnim.setDuration(duration).setInterpolator(interpolator);
            windowAnim.addUpdateListener(valueAnimator -> {
                if (mRecentsView != null && mRecentsView.getVisibility() != View.VISIBLE) {
                    // Views typically don't compute scroll when invisible as an optimization,
                    // but in our case we need to since the window offset depends on the scroll.
                    mRecentsView.computeScroll();
                }
            });
            windowAnim.addListener(new AnimationSuccessListener() {
                @Override
                public void onAnimationSuccess(Animator animator) {
@@ -1180,10 +1253,14 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
    }

    public static float getHiddenTargetAlpha(RemoteAnimationTargetCompat app, Float expectedAlpha) {
        if (!(app.isNotInRecents
                || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME)) {
        if (!isNotInRecents(app)) {
            return 0;
        }
        return expectedAlpha;
    }

    private static boolean isNotInRecents(RemoteAnimationTargetCompat app) {
        return app.isNotInRecents
                || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
    }
}
+11 −4
Original line number Diff line number Diff line
@@ -27,6 +27,10 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Interpolator;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;

import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.AnimatorPlaybackController;
@@ -37,10 +41,6 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.function.BiPredicate;
import java.util.function.Consumer;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;

/**
 * Utility class which abstracts out the logical differences between Launcher and RecentsActivity.
 */
@@ -122,6 +122,13 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {

        default void setShelfState(ShelfAnimState animState, Interpolator interpolator,
                long duration) { }

        /**
         * @param attached Whether to show RecentsView alongside the app window. If false, recents
         *                 will be hidden by some property we can animate, e.g. alpha.
         * @param animate Whether to animate recents to/from its new attached state.
         */
        default void setRecentsAttachedToAppWindow(boolean attached, boolean animate) { }
    }

    interface HomeAnimationFactory {