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

Commit a12648b4 authored by Maryam Dehaini's avatar Maryam Dehaini
Browse files

Control resize veil in transition handlers using listener

Creates a VeiledResizeAnimationListener that is passed to transition
handlers that animate the resize veil. DesktopModeWindowDecorViewModel
implements this listener in order to know when to show, resize, or hide
the resize veil.

Test: Trigger drag to desktop, toggle, and enter desktop transitions
Bug: 323884646

Change-Id: Ife93959125db5d347e3abad131d303b3e03c397d
parent c3c62274
Loading
Loading
Loading
Loading
+14 −24
Original line number Diff line number Diff line
@@ -70,8 +70,8 @@ import com.android.wm.shell.sysui.ShellSharedConstants
import com.android.wm.shell.transition.OneShotRemoteHandler
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 com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener
import java.io.PrintWriter
import java.util.concurrent.Executor
import java.util.function.Consumer
@@ -175,6 +175,12 @@ class DesktopTasksController(
        )
    }

    fun setOnTaskResizeAnimationListener(listener: OnTaskResizeAnimationListener) {
        toggleResizeDesktopTaskTransitionHandler.setOnTaskResizeAnimationListener(listener)
        enterDesktopTaskTransitionHandler.setOnTaskResizeAnimationListener(listener)
        dragToDesktopTransitionHandler.setOnTaskResizeAnimatorListener(listener)
    }

    /** Setter needed to avoid cyclic dependency. */
    fun setSplitScreenController(controller: SplitScreenController) {
        splitScreenController = controller
@@ -236,12 +242,11 @@ class DesktopTasksController(

    /** Move a task with given `taskId` to desktop */
    fun moveToDesktop(
            decor: DesktopModeWindowDecoration,
            taskId: Int,
            wct: WindowContainerTransaction = WindowContainerTransaction()
    ) {
        shellTaskOrganizer.getRunningTaskInfo(taskId)?.let {
            task -> moveToDesktop(decor, task, wct)
            task -> moveToDesktop(task, wct)
        }
    }

@@ -283,7 +288,6 @@ class DesktopTasksController(
     * Move a task to desktop
     */
    fun moveToDesktop(
            decor: DesktopModeWindowDecoration,
            task: RunningTaskInfo,
            wct: WindowContainerTransaction = WindowContainerTransaction()
    ) {
@@ -298,7 +302,7 @@ class DesktopTasksController(
        addMoveToDesktopChanges(wct, task)

        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            enterDesktopTaskTransitionHandler.moveToDesktop(wct, decor)
            enterDesktopTaskTransitionHandler.moveToDesktop(wct)
        } else {
            shellTaskOrganizer.applyTransaction(wct)
        }
@@ -311,7 +315,6 @@ class DesktopTasksController(
    fun startDragToDesktop(
            taskInfo: RunningTaskInfo,
            dragToDesktopValueAnimator: MoveToDesktopAnimator,
            windowDecor: DesktopModeWindowDecoration
    ) {
        KtProtoLog.v(
                WM_SHELL_DESKTOP_MODE,
@@ -320,8 +323,7 @@ class DesktopTasksController(
        )
        dragToDesktopTransitionHandler.startDragToDesktopTransition(
                taskInfo.taskId,
                dragToDesktopValueAnimator,
                windowDecor
                dragToDesktopValueAnimator
        )
    }

@@ -522,7 +524,7 @@ class DesktopTasksController(
    }

    /** Quick-resizes a desktop task, toggling between the stable bounds and the default bounds. */
    fun toggleDesktopTaskSize(taskInfo: RunningTaskInfo, windowDecor: DesktopModeWindowDecoration) {
    fun toggleDesktopTaskSize(taskInfo: RunningTaskInfo) {
        val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return

        val stableBounds = Rect()
@@ -543,11 +545,7 @@ class DesktopTasksController(

        val wct = WindowContainerTransaction().setBounds(taskInfo.token, destinationBounds)
        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            toggleResizeDesktopTaskTransitionHandler.startTransition(
                wct,
                taskInfo.taskId,
                windowDecor
            )
            toggleResizeDesktopTaskTransitionHandler.startTransition(wct)
        } else {
            shellTaskOrganizer.applyTransaction(wct)
        }
@@ -558,11 +556,7 @@ class DesktopTasksController(
     *
     * @param position the portion of the screen (RIGHT or LEFT) we want to snap the task to.
     */
    fun snapToHalfScreen(
            taskInfo: RunningTaskInfo,
            windowDecor: DesktopModeWindowDecoration,
            position: SnapPosition
    ) {
    fun snapToHalfScreen(taskInfo: RunningTaskInfo, position: SnapPosition) {
        val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return

        val stableBounds = Rect()
@@ -592,11 +586,7 @@ class DesktopTasksController(

        val wct = WindowContainerTransaction().setBounds(taskInfo.token, destinationBounds)
        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            toggleResizeDesktopTaskTransitionHandler.startTransition(
                    wct,
                    taskInfo.taskId,
                    windowDecor
            )
            toggleResizeDesktopTaskTransitionHandler.startTransition(wct)
        } else {
            shellTaskOrganizer.applyTransaction(wct)
        }
+13 −10
Original line number Diff line number Diff line
@@ -34,9 +34,9 @@ import com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_END_DRAG
import com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP
import com.android.wm.shell.transition.Transitions.TransitionHandler
import com.android.wm.shell.util.KtProtoLog
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator
import com.android.wm.shell.windowdecor.MoveToDesktopAnimator.Companion.DRAG_FREEFORM_SCALE
import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener
import java.util.function.Supplier

/**
@@ -69,6 +69,7 @@ class DragToDesktopTransitionHandler(
    private var dragToDesktopStateListener: DragToDesktopStateListener? = null
    private var splitScreenController: SplitScreenController? = null
    private var transitionState: TransitionState? = null
    private lateinit var onTaskResizeAnimationListener: OnTaskResizeAnimationListener

    /** Whether a drag-to-desktop transition is in progress. */
    val inProgress: Boolean
@@ -84,6 +85,10 @@ class DragToDesktopTransitionHandler(
        splitScreenController = controller
    }

    fun setOnTaskResizeAnimatorListener(listener: OnTaskResizeAnimationListener) {
        onTaskResizeAnimationListener = listener
    }

    /**
     * Starts a transition that performs a transient launch of Home so that Home is brought to the
     * front while still keeping the currently focused task that is being dragged resumed. This
@@ -96,7 +101,6 @@ class DragToDesktopTransitionHandler(
    fun startDragToDesktopTransition(
            taskId: Int,
            dragToDesktopAnimator: MoveToDesktopAnimator,
            windowDecoration: DesktopModeWindowDecoration
    ) {
        if (inProgress) {
            KtProtoLog.v(
@@ -128,14 +132,12 @@ class DragToDesktopTransitionHandler(
            TransitionState.FromSplit(
                    draggedTaskId = taskId,
                    dragAnimator = dragToDesktopAnimator,
                    windowDecoration = windowDecoration,
                    startTransitionToken = startTransitionToken
            )
        } else {
            TransitionState.FromFullscreen(
                    draggedTaskId = taskId,
                    dragAnimator = dragToDesktopAnimator,
                    windowDecoration = windowDecoration,
                    startTransitionToken = startTransitionToken
            )
        }
@@ -405,7 +407,7 @@ class DragToDesktopTransitionHandler(
            // 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.
            state.windowDecoration.showResizeVeil(t, animStartBounds)
            onTaskResizeAnimationListener.onAnimationStart(state.draggedTaskId, t, animStartBounds)
            finishCallback.onTransitionFinished(null /* wct */)

            // Because the task surface was scaled down during the drag, we must use the animated
@@ -429,11 +431,15 @@ class DragToDesktopTransitionHandler(
                                        animBounds.height()
                                )
                            }
                            state.windowDecoration.updateResizeVeil(tx, animBounds)
                            onTaskResizeAnimationListener.onBoundsChange(
                                    state.draggedTaskId,
                                    tx,
                                    animBounds
                            )
                        }
                        addListener(object : AnimatorListenerAdapter() {
                            override fun onAnimationEnd(animation: Animator) {
                                state.windowDecoration.hideResizeVeil()
                                onTaskResizeAnimationListener.onAnimationEnd(state.draggedTaskId)
                                startTransitionFinishCb.onTransitionFinished(null /* null */)
                                clearState()
                            }
@@ -576,7 +582,6 @@ class DragToDesktopTransitionHandler(
    sealed class TransitionState {
        abstract val draggedTaskId: Int
        abstract val dragAnimator: MoveToDesktopAnimator
        abstract val windowDecoration: DesktopModeWindowDecoration
        abstract val startTransitionToken: IBinder
        abstract var startTransitionFinishCb: Transitions.TransitionFinishCallback?
        abstract var startTransitionFinishTransaction: SurfaceControl.Transaction?
@@ -589,7 +594,6 @@ class DragToDesktopTransitionHandler(
        data class FromFullscreen(
                override val draggedTaskId: Int,
                override val dragAnimator: MoveToDesktopAnimator,
                override val windowDecoration: DesktopModeWindowDecoration,
                override val startTransitionToken: IBinder,
                override var startTransitionFinishCb: Transitions.TransitionFinishCallback? = null,
                override var startTransitionFinishTransaction: SurfaceControl.Transaction? = null,
@@ -603,7 +607,6 @@ class DragToDesktopTransitionHandler(
        data class FromSplit(
                override val draggedTaskId: Int,
                override val dragAnimator: MoveToDesktopAnimator,
                override val windowDecoration: DesktopModeWindowDecoration,
                override val startTransitionToken: IBinder,
                override var startTransitionFinishCb: Transitions.TransitionFinishCallback? = null,
                override var startTransitionFinishTransaction: SurfaceControl.Transaction? = null,
+15 −14
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration;
import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener;

import java.util.ArrayList;
import java.util.List;
@@ -59,8 +59,8 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition
    public static final int FREEFORM_ANIMATION_DURATION = 336;

    private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();
    private DesktopModeWindowDecoration mDesktopModeWindowDecoration;

    private OnTaskResizeAnimationListener mOnTaskResizeAnimationListener;
    public EnterDesktopTaskTransitionHandler(
            Transitions transitions) {
        this(transitions, SurfaceControl.Transaction::new);
@@ -73,14 +73,15 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition
        mTransactionSupplier = supplier;
    }

    void setOnTaskResizeAnimationListener(OnTaskResizeAnimationListener listener) {
        mOnTaskResizeAnimationListener =  listener;
    }

    /**
     * Starts Transition of type TRANSIT_MOVE_TO_DESKTOP
     * @param wct WindowContainerTransaction for transition
     * @param decor {@link DesktopModeWindowDecoration} of task being animated
     */
    public void moveToDesktop(@NonNull WindowContainerTransaction wct,
            DesktopModeWindowDecoration decor) {
        mDesktopModeWindowDecoration = decor;
    public void moveToDesktop(@NonNull WindowContainerTransaction wct) {
        final IBinder token = mTransitions.startTransition(TRANSIT_MOVE_TO_DESKTOP, wct, this);
        mPendingTransitionTokens.add(token);
    }
@@ -136,18 +137,18 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition
            @NonNull TransitionInfo.Change change,
            @NonNull SurfaceControl.Transaction startT,
            @NonNull Transitions.TransitionFinishCallback finishCallback) {
        if (mDesktopModeWindowDecoration == null) {
            Slog.e(TAG, "Window Decoration is not available for this transition");
        final SurfaceControl leash = change.getLeash();
        final Rect startBounds = change.getStartAbsBounds();
        final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
        if (mOnTaskResizeAnimationListener == null) {
            Slog.e(TAG, "onTaskResizeAnimationListener is not available for this transition");
            return false;
        }

        final SurfaceControl leash = change.getLeash();
        final Rect startBounds = change.getStartAbsBounds();
        startT.setPosition(leash, startBounds.left, startBounds.top)
                .setWindowCrop(leash, startBounds.width(), startBounds.height())
                .show(leash);
        mDesktopModeWindowDecoration.showResizeVeil(startT, startBounds);

        mOnTaskResizeAnimationListener.onAnimationStart(taskInfo.taskId, startT, startBounds);
        final ValueAnimator animator = ValueAnimator.ofObject(new RectEvaluator(),
                change.getStartAbsBounds(), change.getEndAbsBounds());
        animator.setDuration(FREEFORM_ANIMATION_DURATION);
@@ -157,12 +158,12 @@ public class EnterDesktopTaskTransitionHandler implements Transitions.Transition
            t.setPosition(leash, animationValue.left, animationValue.top)
                    .setWindowCrop(leash, animationValue.width(), animationValue.height())
                    .show(leash);
            mDesktopModeWindowDecoration.updateResizeVeil(t, animationValue);
            mOnTaskResizeAnimationListener.onBoundsChange(taskInfo.taskId, t, animationValue);
        });
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mDesktopModeWindowDecoration.hideResizeVeil();
                mOnTaskResizeAnimationListener.onAnimationEnd(taskInfo.taskId);
                mTransitions.getMainExecutor().execute(
                        () -> finishCallback.onTransitionFinished(null));
            }
+14 −15
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.animation.RectEvaluator
import android.animation.ValueAnimator
import android.graphics.Rect
import android.os.IBinder
import android.util.SparseArray
import android.view.SurfaceControl
import android.view.WindowManager.TRANSIT_CHANGE
import android.window.TransitionInfo
@@ -30,7 +29,7 @@ import android.window.WindowContainerTransaction
import androidx.core.animation.addListener
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE
import com.android.wm.shell.windowdecor.DesktopModeWindowDecoration
import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener
import java.util.function.Supplier

/** Handles the animation of quick resizing of desktop tasks. */
@@ -40,7 +39,7 @@ class ToggleResizeDesktopTaskTransitionHandler(
) : Transitions.TransitionHandler {

    private val rectEvaluator = RectEvaluator(Rect())
    private val taskToDecorationMap = SparseArray<DesktopModeWindowDecoration>()
    private lateinit var onTaskResizeAnimationListener: OnTaskResizeAnimationListener

    private var boundsAnimator: Animator? = null

@@ -49,13 +48,12 @@ class ToggleResizeDesktopTaskTransitionHandler(
    ) : this(transitions, Supplier { SurfaceControl.Transaction() })

    /** Starts a quick resize transition. */
    fun startTransition(
        wct: WindowContainerTransaction,
        taskId: Int,
        windowDecoration: DesktopModeWindowDecoration
    ) {
    fun startTransition(wct: WindowContainerTransaction) {
        transitions.startTransition(TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE, wct, this)
        taskToDecorationMap.put(taskId, windowDecoration)
    }

    fun setOnTaskResizeAnimationListener(listener: OnTaskResizeAnimationListener) {
        onTaskResizeAnimationListener = listener
    }

    override fun startAnimation(
@@ -70,9 +68,6 @@ class ToggleResizeDesktopTaskTransitionHandler(
        val taskId = checkNotNull(change.taskInfo).taskId
        val startBounds = change.startAbsBounds
        val endBounds = change.endAbsBounds
        val windowDecor =
            taskToDecorationMap.removeReturnOld(taskId)
                ?: throw IllegalStateException("Window decoration not found for task $taskId")

        val tx = transactionSupplier.get()
        boundsAnimator?.cancel()
@@ -90,7 +85,11 @@ class ToggleResizeDesktopTaskTransitionHandler(
                                )
                                .setWindowCrop(leash, startBounds.width(), startBounds.height())
                                .show(leash)
                            windowDecor.showResizeVeil(startTransaction, startBounds)
                            onTaskResizeAnimationListener.onAnimationStart(
                                    taskId,
                                    startTransaction,
                                    startBounds
                            )
                        },
                        onEnd = {
                            finishTransaction
@@ -101,7 +100,7 @@ class ToggleResizeDesktopTaskTransitionHandler(
                                )
                                .setWindowCrop(leash, endBounds.width(), endBounds.height())
                                .show(leash)
                            windowDecor.hideResizeVeil()
                            onTaskResizeAnimationListener.onAnimationEnd(taskId)
                            finishCallback.onTransitionFinished(null)
                            boundsAnimator = null
                        }
@@ -111,7 +110,7 @@ class ToggleResizeDesktopTaskTransitionHandler(
                        tx.setPosition(leash, rect.left.toFloat(), rect.top.toFloat())
                            .setWindowCrop(leash, rect.width(), rect.height())
                            .show(leash)
                        windowDecor.updateResizeVeil(tx, rect)
                        onTaskResizeAnimationListener.onBoundsChange(taskId, tx, rect)
                    }
                    start()
                }
+37 −9
Original line number Diff line number Diff line
@@ -211,6 +211,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        mShellCommandHandler.addDumpCallback(this::dump, this);
        mDisplayInsetsController.addInsetsChangedListener(mContext.getDisplayId(),
                new DesktopModeOnInsetsChangedListener());
        mDesktopTasksController.ifPresent(c -> c.setOnTaskResizeAnimationListener(
                new DeskopModeOnTaskResizeAnimationListener()));
    }

    @Override
@@ -356,7 +358,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                    // App sometimes draws before the insets from WindowDecoration#relayout have
                    // been added, so they must be added here
                    mWindowDecorByTaskId.get(mTaskId).addCaptionInset(wct);
                    mDesktopTasksController.get().moveToDesktop(decoration, mTaskId, wct);
                    mDesktopTasksController.get().moveToDesktop(mTaskId, wct);
                    closeOtherSplitTask(mTaskId);
                }
                decoration.closeHandleMenu();
@@ -387,25 +389,23 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                    return;
                }
                final RunningTaskInfo taskInfo = decoration.mTaskInfo;
                mDesktopTasksController.ifPresent(c -> c.toggleDesktopTaskSize(
                        taskInfo, decoration));
                mDesktopTasksController.ifPresent(c -> c.toggleDesktopTaskSize(taskInfo));
                decoration.closeHandleMenu();
            } else if (id == R.id.maximize_menu_maximize_button) {
                final RunningTaskInfo taskInfo = decoration.mTaskInfo;
                mDesktopTasksController.ifPresent(c -> c.toggleDesktopTaskSize(
                        taskInfo, mWindowDecorByTaskId.get(taskInfo.taskId)));
                mDesktopTasksController.ifPresent(c -> c.toggleDesktopTaskSize(taskInfo));
                decoration.closeHandleMenu();
                decoration.closeMaximizeMenu();
            } else if (id == R.id.maximize_menu_snap_left_button) {
                final RunningTaskInfo taskInfo = decoration.mTaskInfo;
                mDesktopTasksController.ifPresent(c -> c.snapToHalfScreen(
                        taskInfo, mWindowDecorByTaskId.get(taskInfo.taskId), SnapPosition.LEFT));
                        taskInfo, SnapPosition.LEFT));
                decoration.closeHandleMenu();
                decoration.closeMaximizeMenu();
            } else if (id == R.id.maximize_menu_snap_right_button) {
                final RunningTaskInfo taskInfo = decoration.mTaskInfo;
                mDesktopTasksController.ifPresent(c -> c.snapToHalfScreen(
                        taskInfo, mWindowDecorByTaskId.get(taskInfo.taskId), SnapPosition.RIGHT));
                        taskInfo, SnapPosition.RIGHT));
                decoration.closeHandleMenu();
                decoration.closeMaximizeMenu();
            }
@@ -558,7 +558,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
            }
            mDesktopTasksController.ifPresent(c -> {
                final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
                c.toggleDesktopTaskSize(decoration.mTaskInfo, decoration);
                c.toggleDesktopTaskSize(decoration.mTaskInfo);
            });
            return true;
        }
@@ -761,7 +761,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                                    relevantDecor.mTaskInfo, relevantDecor.mTaskSurface);
                            mDesktopTasksController.ifPresent(
                                    c -> c.startDragToDesktop(relevantDecor.mTaskInfo,
                                            mMoveToDesktopAnimator, relevantDecor));
                                            mMoveToDesktopAnimator));
                        }
                    }
                    if (mMoveToDesktopAnimator != null) {
@@ -1020,6 +1020,34 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        pw.println(innerPrefix + "mWindowDecorByTaskId=" + mWindowDecorByTaskId);
    }

    private class DeskopModeOnTaskResizeAnimationListener
            implements OnTaskResizeAnimationListener {
        @Override
        public void onAnimationStart(int taskId, Transaction t, Rect bounds) {
            final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
            if (decoration == null)  {
                t.apply();
                return;
            }
            decoration.showResizeVeil(t, bounds);
        }

        @Override
        public void onBoundsChange(int taskId, Transaction t, Rect bounds) {
            final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
            if (decoration == null) return;
            decoration.updateResizeVeil(t, bounds);
        }

        @Override
        public void onAnimationEnd(int taskId) {
            final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
            if (decoration == null) return;
            decoration.hideResizeVeil();
        }
    }


    private class DragStartListenerImpl
            implements DragPositioningCallbackUtility.DragStartListener {
        @Override
Loading