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

Commit b818c6e7 authored by Maryam Dehaini's avatar Maryam Dehaini Committed by Android (Google) Code Review
Browse files

Merge "Set position during TRANSIT_ENTER_DESKTOP_MODE transition" into udc-qpr-dev

parents 0a296745 ee7406fa
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import com.android.wm.shell.sysui.ShellSharedConstants
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.util.KtProtoLog
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator
import java.io.PrintWriter
import java.util.concurrent.Executor
import java.util.function.Consumer
@@ -204,7 +205,11 @@ class DesktopTasksController(
     * Moves a single task to freeform and sets the taskBounds to the passed in bounds,
     * startBounds
     */
    fun moveToFreeform(taskInfo: RunningTaskInfo, startBounds: Rect) {
    fun moveToFreeform(
            taskInfo: RunningTaskInfo,
            startBounds: Rect,
            dragToDesktopValueAnimator: MoveToDesktopAnimator
    ) {
        KtProtoLog.v(
            WM_SHELL_DESKTOP_MODE,
            "DesktopTasksController: moveToFreeform with bounds taskId=%d",
@@ -216,8 +221,8 @@ class DesktopTasksController(
        wct.setBounds(taskInfo.token, startBounds)

        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            enterDesktopTaskTransitionHandler.startTransition(
                    Transitions.TRANSIT_ENTER_FREEFORM, wct, mOnAnimationFinishedCallback)
            enterDesktopTaskTransitionHandler.startMoveToFreeformAnimation(wct,
                    dragToDesktopValueAnimator, mOnAnimationFinishedCallback)
        } else {
            shellTaskOrganizer.applyTransaction(wct)
        }
@@ -270,7 +275,7 @@ class DesktopTasksController(
     * Move a task to fullscreen after being dragged from fullscreen and released back into
     * status bar area
     */
    fun cancelMoveToFreeform(task: RunningTaskInfo, position: Point) {
    fun cancelMoveToFreeform(task: RunningTaskInfo, moveToDesktopAnimator: MoveToDesktopAnimator) {
        KtProtoLog.v(
            WM_SHELL_DESKTOP_MODE,
            "DesktopTasksController: cancelMoveToFreeform taskId=%d",
@@ -280,8 +285,8 @@ class DesktopTasksController(
        wct.setBounds(task.token, null)

        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            enterDesktopTaskTransitionHandler.startCancelMoveToDesktopMode(
                wct, position) { t ->
            enterDesktopTaskTransitionHandler.startCancelMoveToDesktopMode(wct,
                    moveToDesktopAnimator) { t ->
                val callbackWCT = WindowContainerTransaction()
                visualIndicator?.releaseVisualIndicator(t)
                visualIndicator = null
+61 −12
Original line number Diff line number Diff line
@@ -22,9 +22,10 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.IBinder;
import android.util.Slog;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.TransitionInfo;
@@ -35,6 +36,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator;

import java.util.ArrayList;
import java.util.List;
@@ -47,18 +49,17 @@ import java.util.function.Supplier;
 */
public class EnterDesktopTaskTransitionHandler implements Transitions.TransitionHandler {

    private static final String TAG = "EnterDesktopTaskTransitionHandler";
    private final Transitions mTransitions;
    private final Supplier<SurfaceControl.Transaction> mTransactionSupplier;

    // The size of the screen during drag relative to the fullscreen size
    public static final float DRAG_FREEFORM_SCALE = 0.4f;
    // The size of the screen after drag relative to the fullscreen size
    public static final float FINAL_FREEFORM_SCALE = 0.6f;
    public static final int FREEFORM_ANIMATION_DURATION = 336;

    private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();
    private Point mPosition;
    private Consumer<SurfaceControl.Transaction> mOnAnimationFinishedCallback;
    private MoveToDesktopAnimator mMoveToDesktopAnimator;

    public EnterDesktopTaskTransitionHandler(
            Transitions transitions) {
@@ -86,16 +87,31 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition
        mPendingTransitionTokens.add(token);
    }

    /**
     * Starts Transition of type TRANSIT_ENTER_FREEFORM
     * @param wct WindowContainerTransaction for transition
     * @param moveToDesktopAnimator Animator that shrinks and positions task during two part move
     *                              to desktop animation
     * @param onAnimationEndCallback to be called after animation
     */
    public void startMoveToFreeformAnimation(@NonNull WindowContainerTransaction wct,
            @NonNull MoveToDesktopAnimator moveToDesktopAnimator,
            Consumer<SurfaceControl.Transaction> onAnimationEndCallback) {
        mMoveToDesktopAnimator = moveToDesktopAnimator;
        startTransition(Transitions.TRANSIT_ENTER_FREEFORM, wct, onAnimationEndCallback);
    }

    /**
     * Starts Transition of type TRANSIT_CANCEL_ENTERING_DESKTOP_MODE
     * @param wct WindowContainerTransaction for transition
     * @param position Position of task when transition is triggered
     * @param moveToDesktopAnimator Animator that shrinks and positions task during two part move
     *                              to desktop animation
     * @param onAnimationEndCallback to be called after animation
     */
    public void startCancelMoveToDesktopMode(@NonNull WindowContainerTransaction wct,
            Point position,
            MoveToDesktopAnimator moveToDesktopAnimator,
            Consumer<SurfaceControl.Transaction> onAnimationEndCallback) {
        mPosition = position;
        mMoveToDesktopAnimator = moveToDesktopAnimator;
        startTransition(Transitions.TRANSIT_CANCEL_ENTERING_DESKTOP_MODE, wct,
                onAnimationEndCallback);
    }
@@ -145,9 +161,23 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition
            // to null and we don't require an animation
            final SurfaceControl sc = change.getLeash();
            startT.setWindowCrop(sc, null);

            if (mMoveToDesktopAnimator == null
                    || mMoveToDesktopAnimator.getTaskId() != change.getTaskInfo().taskId) {
                Slog.e(TAG, "No animator available for this transition");
                return false;
            }

            // Calculate and set position of the task
            final PointF position = mMoveToDesktopAnimator.getPosition();
            startT.setPosition(sc, position.x, position.y);
            finishT.setPosition(sc, position.x, position.y);

            startT.apply();

            mTransitions.getMainExecutor().execute(
                    () -> finishCallback.onTransitionFinished(null, null));

            return true;
        }

@@ -162,12 +192,18 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition
                    endBounds.height());
            startT.apply();

            // End the animation that shrinks the window when task is first dragged from fullscreen
            if (mMoveToDesktopAnimator != null) {
                mMoveToDesktopAnimator.endAnimator();
            }

            // We want to find the scale of the current bounds relative to the end bounds. The
            // task is currently scaled to DRAG_FREEFORM_SCALE and the final bounds will be
            // scaled to FINAL_FREEFORM_SCALE. So, it is scaled to
            // DRAG_FREEFORM_SCALE / FINAL_FREEFORM_SCALE relative to the freeform bounds
            final ValueAnimator animator =
                    ValueAnimator.ofFloat(DRAG_FREEFORM_SCALE / FINAL_FREEFORM_SCALE, 1f);
                    ValueAnimator.ofFloat(
                            MoveToDesktopAnimator.DRAG_FREEFORM_SCALE / FINAL_FREEFORM_SCALE, 1f);
            animator.setDuration(FREEFORM_ANIMATION_DURATION);
            final SurfaceControl.Transaction t = mTransactionSupplier.get();
            animator.addUpdateListener(animation -> {
@@ -199,8 +235,7 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition
        }

        if (type == Transitions.TRANSIT_CANCEL_ENTERING_DESKTOP_MODE
                && taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
                && mPosition != null) {
                && taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
            // This Transition animates a task to fullscreen after being dragged from the status
            // bar and then released back into the status bar area
            final SurfaceControl sc = change.getLeash();
@@ -210,13 +245,27 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition
                    .setWindowCrop(sc, endBounds.width(), endBounds.height())
                    .apply();

            if (mMoveToDesktopAnimator == null
                    || mMoveToDesktopAnimator.getTaskId() != change.getTaskInfo().taskId) {
                Slog.e(TAG, "No animator available for this transition");
                return false;
            }

            // End the animation that shrinks the window when task is first dragged from fullscreen
            mMoveToDesktopAnimator.endAnimator();

            final ValueAnimator animator = new ValueAnimator();
            animator.setFloatValues(DRAG_FREEFORM_SCALE, 1f);
            animator.setFloatValues(MoveToDesktopAnimator.DRAG_FREEFORM_SCALE, 1f);
            animator.setDuration(FREEFORM_ANIMATION_DURATION);
            final SurfaceControl.Transaction t = mTransactionSupplier.get();

            // Get position of the task
            final float x = mMoveToDesktopAnimator.getPosition().x;
            final float y = mMoveToDesktopAnimator.getPosition().y;

            animator.addUpdateListener(animation -> {
                final float scale = (float) animation.getAnimatedValue();
                t.setPosition(sc, mPosition.x * (1 - scale), mPosition.y * (1 - scale))
                t.setPosition(sc, x * (1 - scale), y * (1 - scale))
                        .setScale(sc, scale, scale)
                        .show(sc)
                        .apply();
+18 −36
Original line number Diff line number Diff line
@@ -24,9 +24,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;

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.desktopmode.EnterDesktopTaskTransitionHandler.DRAG_FREEFORM_SCALE;
import static com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FINAL_FREEFORM_SCALE;
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;
@@ -112,9 +112,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {

    private SplitScreenController mSplitScreenController;

    private ValueAnimator mDragToDesktopValueAnimator;
    private MoveToDesktopAnimator mMoveToDesktopAnimator;
    private final Rect mDragToDesktopAnimationStartBounds = new Rect();
    private boolean mDragToDesktopAnimationStarted;

    public DesktopModeWindowDecorViewModel(
            Context context,
@@ -233,7 +232,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            removeTaskFromEventReceiver(oldTaskInfo.displayId);
            incrementEventReceiverTasks(taskInfo.displayId);
        }

        decoration.relayout(taskInfo);
    }

@@ -599,7 +597,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            }
            case MotionEvent.ACTION_UP: {
                if (relevantDecor == null) {
                    mDragToDesktopAnimationStarted = false;
                    mMoveToDesktopAnimator = null;
                    mTransitionDragActive = false;
                    return;
                }
@@ -613,14 +611,14 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                        } else if (DesktopModeStatus.isProto1Enabled()) {
                            mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true));
                        }
                        mDragToDesktopAnimationStarted = false;
                        mMoveToDesktopAnimator = null;
                        return;
                    } else if (mDragToDesktopAnimationStarted) {
                        Point position = new Point((int) ev.getX(), (int) ev.getY());
                    } else if (mMoveToDesktopAnimator != null) {
                        relevantDecor.incrementRelayoutBlock();
                        mDesktopTasksController.ifPresent(
                                c -> c.cancelMoveToFreeform(relevantDecor.mTaskInfo, position));
                        mDragToDesktopAnimationStarted = false;
                                c -> c.cancelMoveToFreeform(relevantDecor.mTaskInfo,
                                        mMoveToDesktopAnimator));
                        mMoveToDesktopAnimator = null;
                        return;
                    }
                }
@@ -640,21 +638,19 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                    final int statusBarHeight = getStatusBarHeight(
                            relevantDecor.mTaskInfo.displayId);
                    if (ev.getY() > statusBarHeight) {
                        if (!mDragToDesktopAnimationStarted) {
                            mDragToDesktopAnimationStarted = true;
                        if (mMoveToDesktopAnimator == null) {
                            mMoveToDesktopAnimator = new MoveToDesktopAnimator(
                                    mDragToDesktopAnimationStartBounds, relevantDecor.mTaskInfo,
                                    relevantDecor.mTaskSurface);
                            mDesktopTasksController.ifPresent(
                                    c -> c.moveToFreeform(relevantDecor.mTaskInfo,
                                            mDragToDesktopAnimationStartBounds));
                            startAnimation(relevantDecor);
                                            mDragToDesktopAnimationStartBounds,
                                            mMoveToDesktopAnimator));
                            mMoveToDesktopAnimator.startAnimation();
                        }
                    }
                    if (mDragToDesktopAnimationStarted) {
                        Transaction t = mTransactionFactory.get();
                        float width = (float) mDragToDesktopValueAnimator.getAnimatedValue()
                                * mDragToDesktopAnimationStartBounds.width();
                        float x = ev.getX() - (width / 2);
                        t.setPosition(relevantDecor.mTaskSurface, x, ev.getY());
                        t.apply();
                    if (mMoveToDesktopAnimator != null) {
                        mMoveToDesktopAnimator.updatePosition(ev);
                    }
                }
                break;
@@ -662,7 +658,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {

            case MotionEvent.ACTION_CANCEL: {
                mTransitionDragActive = false;
                mDragToDesktopAnimationStarted = false;
                mMoveToDesktopAnimator = null;
            }
        }
    }
@@ -729,20 +725,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        animator.start();
    }

    private void startAnimation(@NonNull DesktopModeWindowDecoration focusedDecor) {
        mDragToDesktopValueAnimator = ValueAnimator.ofFloat(1f, DRAG_FREEFORM_SCALE);
        mDragToDesktopValueAnimator.setDuration(FREEFORM_ANIMATION_DURATION);
        final Transaction t = mTransactionFactory.get();
        mDragToDesktopValueAnimator.addUpdateListener(animation -> {
            final float animatorValue = (float) animation.getAnimatedValue();
            SurfaceControl sc = focusedDecor.mTaskSurface;
            t.setScale(sc, animatorValue, animatorValue);
            t.apply();
        });

        mDragToDesktopValueAnimator.start();
    }

    @Nullable
    private DesktopModeWindowDecoration getRelevantWindowDecor(MotionEvent ev) {
        if (mSplitScreenController != null && mSplitScreenController.isSplitScreenVisible()) {
+72 −0
Original line number Diff line number Diff line
package com.android.wm.shell.windowdecor

import android.animation.ValueAnimator
import android.app.ActivityManager.RunningTaskInfo
import android.graphics.PointF
import android.graphics.Rect
import android.view.MotionEvent
import android.view.SurfaceControl

/**
 * Creates an animator to shrink and position task after a user drags a fullscreen task from
 * the top of the screen to transition it into freeform and before the user releases the task. The
 * MoveToDesktopAnimator object also holds information about the state of the task that are
 * accessed by the EnterDesktopTaskTransitionHandler.
 */
class MoveToDesktopAnimator @JvmOverloads constructor(
        private val startBounds: Rect,
        private val taskInfo: RunningTaskInfo,
        private val taskSurface: SurfaceControl,
        private val transactionFactory: () -> SurfaceControl.Transaction =
                SurfaceControl::Transaction
) {
    companion object {
        // The size of the screen during drag relative to the fullscreen size
        const val DRAG_FREEFORM_SCALE: Float = 0.4f
        const val ANIMATION_DURATION = 336
    }

    private val animatedTaskWidth
        get() = dragToDesktopAnimator.animatedValue as Float * startBounds.width()
    private val dragToDesktopAnimator: ValueAnimator = ValueAnimator.ofFloat(1f,
            DRAG_FREEFORM_SCALE)
            .setDuration(ANIMATION_DURATION.toLong())
            .apply {
                val t = SurfaceControl.Transaction()
                addUpdateListener { animation ->
                    val animatorValue = animation.animatedValue as Float
                    t.setScale(taskSurface, animatorValue, animatorValue)
                            .apply()
                }
            }

    val taskId get() = taskInfo.taskId
    val position: PointF = PointF(0.0f, 0.0f)

    /**
     * Starts the animation that scales the task down.
     */
    fun startAnimation() {
        dragToDesktopAnimator.start()
    }

    /**
     * Uses the position of the motion event and the current scale of the task as defined by the
     * ValueAnimator to update the local position variable and set the task surface's position
     */
    fun updatePosition(ev: MotionEvent) {
        position.x = ev.x - animatedTaskWidth / 2
        position.y = ev.y

        val t = transactionFactory()
        t.setPosition(taskSurface, position.x, position.y)
        t.apply()
    }

    /**
     * Ends the animation, setting the scale and position to the final animation value
     */
    fun endAnimator() {
        dragToDesktopAnimator.end()
    }
}
 No newline at end of file
+13 −3
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.verify;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.WindowConfiguration;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.IBinder;
import android.view.SurfaceControl;
@@ -41,6 +42,7 @@ import androidx.test.filters.SmallTest;

import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator;

import junit.framework.AssertionFailedError;

@@ -73,6 +75,10 @@ public class EnterDesktopTaskTransitionHandlerTest {
    ShellExecutor mExecutor;
    @Mock
    SurfaceControl mSurfaceControl;
    @Mock
    MoveToDesktopAnimator mMoveToDesktopAnimator;
    @Mock
    PointF mPosition;

    private EnterDesktopTaskTransitionHandler mEnterDesktopTaskTransitionHandler;

@@ -82,6 +88,7 @@ public class EnterDesktopTaskTransitionHandlerTest {

        doReturn(mExecutor).when(mTransitions).getMainExecutor();
        doReturn(mAnimationT).when(mTransactionFactory).get();
        doReturn(mPosition).when(mMoveToDesktopAnimator).getPosition();

        mEnterDesktopTaskTransitionHandler = new EnterDesktopTaskTransitionHandler(mTransitions,
                mTransactionFactory);
@@ -89,12 +96,15 @@ public class EnterDesktopTaskTransitionHandlerTest {

    @Test
    public void testEnterFreeformAnimation() {
        final int transitionType = Transitions.TRANSIT_ENTER_FREEFORM;
        final int taskId = 1;
        WindowContainerTransaction wct = new WindowContainerTransaction();
        doReturn(mToken).when(mTransitions)
                .startTransition(transitionType, wct, mEnterDesktopTaskTransitionHandler);
        mEnterDesktopTaskTransitionHandler.startTransition(transitionType, wct, null);
                .startTransition(Transitions.TRANSIT_ENTER_FREEFORM, wct,
                        mEnterDesktopTaskTransitionHandler);
        doReturn(taskId).when(mMoveToDesktopAnimator).getTaskId();

        mEnterDesktopTaskTransitionHandler.startMoveToFreeformAnimation(wct,
                mMoveToDesktopAnimator, null);

        TransitionInfo.Change change =
                createChange(WindowManager.TRANSIT_CHANGE, taskId, WINDOWING_MODE_FREEFORM);