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

Commit 2f663508 authored by Matt Sziklay's avatar Matt Sziklay Committed by Android (Google) Code Review
Browse files

Merge "Combine bounds change and move-to-center animations." into main

parents c8d77cfb dafa4517
Loading
Loading
Loading
Loading
+31 −50
Original line number Diff line number Diff line
@@ -369,58 +369,41 @@ class DragToDesktopTransitionHandler(
            val startBounds = draggedTaskChange.startAbsBounds
            val endBounds = draggedTaskChange.endAbsBounds

            // TODO(b/301106941): Instead of forcing-finishing the animation that scales the
            //  surface down and then starting another that scales it back up to the final size,
            //  blend the two animations.
            state.dragAnimator.endAnimator()
            // Using [DRAG_FREEFORM_SCALE] to calculate animated width/height is possible because
            // it is known that the animation scale is finished because the animation was
            // force-ended above. This won't be true when the two animations are blended.
            val animStartWidth = (startBounds.width() * DRAG_FREEFORM_SCALE).toInt()
            val animStartHeight = (startBounds.height() * DRAG_FREEFORM_SCALE).toInt()
            // Using end bounds here to find the left/top also assumes the center animation has
            // finished and the surface is placed exactly in the center of the screen which matches
            // the end/default bounds of the now freeform task.
            val animStartLeft = endBounds.centerX() - (animStartWidth / 2)
            val animStartTop = endBounds.centerY() - (animStartHeight / 2)
            val animStartBounds = Rect(
                    animStartLeft,
                    animStartTop,
                    animStartLeft + animStartWidth,
                    animStartTop + animStartHeight
            // Pause any animation that may be currently playing; we will use the relevant
            // details of that animation here.
            state.dragAnimator.cancelAnimator()
            // We still apply scale to task bounds; as we animate the bounds to their
            // end value, animate scale to 1.
            val startScale = state.dragAnimator.scale
            val startPosition = state.dragAnimator.position
            val unscaledStartWidth = startBounds.width()
            val unscaledStartHeight = startBounds.height()
            val unscaledStartBounds = Rect(
                startPosition.x.toInt(),
                startPosition.y.toInt(),
                startPosition.x.toInt() + unscaledStartWidth,
                startPosition.y.toInt() + unscaledStartHeight
            )


            dragToDesktopStateListener?.onCommitToDesktopAnimationStart(t)
            t.apply {
                setScale(draggedTaskLeash, 1f, 1f)
                setPosition(
                        draggedTaskLeash,
                        animStartBounds.left.toFloat(),
                        animStartBounds.top.toFloat()
                )
                setWindowCrop(
                        draggedTaskLeash,
                        animStartBounds.width(),
                        animStartBounds.height()
                )
            }
            // Accept the merge by applying the merging transaction (applied by #showResizeVeil)
            // and finish callback. Show the veil and position the task at the first frame before
            // starting the final animation.
            onTaskResizeAnimationListener.onAnimationStart(state.draggedTaskId, t, animStartBounds)
            onTaskResizeAnimationListener.onAnimationStart(state.draggedTaskId, t,
                unscaledStartBounds)
            finishCallback.onTransitionFinished(null /* wct */)

            // Because the task surface was scaled down during the drag, we must use the animated
            // bounds instead of the [startAbsBounds].
            val tx: SurfaceControl.Transaction = transactionSupplier.get()
            ValueAnimator.ofObject(rectEvaluator, animStartBounds, endBounds)
            ValueAnimator.ofObject(rectEvaluator, unscaledStartBounds, endBounds)
                    .setDuration(DRAG_TO_DESKTOP_FINISH_ANIM_DURATION_MS)
                    .apply {
                        addUpdateListener { animator ->
                            val animBounds = animator.animatedValue as Rect
                            val animFraction = animator.animatedFraction
                            // Progress scale from starting value to 1 as animation plays.
                            val animScale = startScale + animFraction * (1 - startScale)
                            tx.apply {
                                setScale(draggedTaskLeash, 1f, 1f)
                                setScale(draggedTaskLeash, animScale, animScale)
                                setPosition(
                                     draggedTaskLeash,
                                     animBounds.left.toFloat(),
@@ -493,10 +476,8 @@ class DragToDesktopTransitionHandler(
        val draggedTaskChange = state.draggedTaskChange
                ?: throw IllegalStateException("Expected non-null task change")
        val sc = draggedTaskChange.leash
        // TODO(b/301106941): Don't end the animation and start one to scale it back, merge them
        //  instead.
        // End the animation that shrinks the window when task is first dragged from fullscreen
        dragToDesktopAnimator.endAnimator()
        // Pause the animation that shrinks the window when task is first dragged from fullscreen
        dragToDesktopAnimator.cancelAnimator()
        // Then animate the scaled window back to its original bounds.
        val x: Float = dragToDesktopAnimator.position.x
        val y: Float = dragToDesktopAnimator.position.y
+6 −70
Original line number Diff line number Diff line
@@ -33,16 +33,8 @@ import static android.view.WindowInsets.Type.statusBars;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.compatui.AppCompatUtils.isSingleTopActivityTranslucent;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR;
import static com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FREEFORM_ANIMATION_DURATION;
import static com.android.wm.shell.windowdecor.MoveToDesktopAnimator.DRAG_FREEFORM_SCALE;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;

import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
@@ -858,26 +850,18 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            }
            case MotionEvent.ACTION_UP: {
                if (mTransitionDragActive) {
                    final DesktopModeVisualIndicator.IndicatorType indicatorType =
                    mDesktopTasksController.updateVisualIndicator(relevantDecor.mTaskInfo,
                            relevantDecor.mTaskSurface, ev.getRawX(), ev.getRawY());
                    mTransitionDragActive = false;
                    if (indicatorType == TO_DESKTOP_INDICATOR
                            || indicatorType == TO_SPLIT_LEFT_INDICATOR
                            || indicatorType == TO_SPLIT_RIGHT_INDICATOR) {
                        if (DesktopModeStatus.isEnabled()) {
                            animateToDesktop(relevantDecor, ev);
                        }
                        mMoveToDesktopAnimator = null;
                        return;
                    } else if (mMoveToDesktopAnimator != null) {
                    if (mMoveToDesktopAnimator != null) {
                        // Though this isn't a hover event, we need to update handle's hover state
                        // as it likely will change.
                        relevantDecor.updateHoverAndPressStatus(ev);
                        mDesktopTasksController.onDragPositioningEndThroughStatusBar(
                                new PointF(ev.getRawX(), ev.getRawY()),
                                relevantDecor.mTaskInfo,
                                calculateFreeformBounds(ev.getDisplayId(), DRAG_FREEFORM_SCALE));
                                calculateFreeformBounds(ev.getDisplayId(),
                                        DesktopTasksController.DESKTOP_MODE_INITIAL_BOUNDS_SCALE));
                        mMoveToDesktopAnimator = null;
                        return;
                    } else {
@@ -946,54 +930,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                (int) (screenHeight * (adjustmentPercentage + scale)));
    }

    /**
     * Blocks relayout until transition is finished and transitions to Desktop
     */
    private void animateToDesktop(DesktopModeWindowDecoration relevantDecor,
            MotionEvent ev) {
        centerAndMoveToDesktopWithAnimation(relevantDecor, ev);
    }

    /**
     * Animates a window to the center, grows to freeform size, and transitions to Desktop Mode.
     * @param relevantDecor the window decor of the task to be animated
     * @param ev the motion event that triggers the animation
     * TODO(b/315527000): This animation needs to be adjusted to allow snap left/right cases.
     *  Currently fullscreen -> split snap still animates to center screen before readjusting.
     */
    private void centerAndMoveToDesktopWithAnimation(DesktopModeWindowDecoration relevantDecor,
            MotionEvent ev) {
        ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
        animator.setDuration(FREEFORM_ANIMATION_DURATION);
        final SurfaceControl sc = relevantDecor.mTaskSurface;
        final Rect endBounds = calculateFreeformBounds(ev.getDisplayId(), DRAG_FREEFORM_SCALE);
        final Transaction t = mTransactionFactory.get();
        final float diffX = endBounds.centerX() - ev.getRawX();
        final float diffY = endBounds.top - ev.getRawY();
        final float startingX = ev.getRawX() - DRAG_FREEFORM_SCALE
                * mDragToDesktopAnimationStartBounds.width() / 2;

        animator.addUpdateListener(animation -> {
            final float animatorValue = (float) animation.getAnimatedValue();
            final float x = startingX + diffX * animatorValue;
            final float y = ev.getRawY() + diffY * animatorValue;
            t.setPosition(sc, x, y);
            t.apply();
        });
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mDesktopTasksController.onDragPositioningEndThroughStatusBar(
                        new PointF(ev.getRawX(), ev.getRawY()),
                        relevantDecor.mTaskInfo,
                        calculateFreeformBounds(ev.getDisplayId(),
                                DesktopTasksController
                                        .DESKTOP_MODE_INITIAL_BOUNDS_SCALE));
            }
        });
        animator.start();
    }

    @Nullable
    private DesktopModeWindowDecoration getRelevantWindowDecor(MotionEvent ev) {
        final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
+7 −6
Original line number Diff line number Diff line
@@ -31,15 +31,16 @@ class MoveToDesktopAnimator @JvmOverloads constructor(

    private val animatedTaskWidth
        get() = dragToDesktopAnimator.animatedValue as Float * startBounds.width()
    val scale: Float
        get() = dragToDesktopAnimator.animatedValue as Float
    private val dragToDesktopAnimator: ValueAnimator = ValueAnimator.ofFloat(1f,
            DRAG_FREEFORM_SCALE)
            .setDuration(ANIMATION_DURATION.toLong())
            .apply {
                val t = SurfaceControl.Transaction()
                val cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)
                addUpdateListener { animation ->
                    val animatorValue = animation.animatedValue as Float
                    t.setScale(taskSurface, animatorValue, animatorValue)
                addUpdateListener {
                    t.setScale(taskSurface, scale, scale)
                            .setCornerRadius(taskSurface, cornerRadius)
                            .apply()
                }
@@ -90,9 +91,9 @@ class MoveToDesktopAnimator @JvmOverloads constructor(
    }

    /**
     * Ends the animation, setting the scale and position to the final animation value
     * Cancels the animation, intended to be used when another animator will take over.
     */
    fun endAnimator() {
        dragToDesktopAnimator.end()
    fun cancelAnimator() {
        dragToDesktopAnimator.cancel()
    }
}
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -190,7 +190,7 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
        handler.cancelDragToDesktopTransition()

        // Cancel animation should run since it had already started.
        verify(dragAnimator).endAnimator()
        verify(dragAnimator).cancelAnimator()
    }

    @Test