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

Commit 23135f2d authored by Qijing Yao's avatar Qijing Yao Committed by Android (Google) Code Review
Browse files

Merge "Defer drag indicator removal until window drop transition ends" into main

parents 78a94767 9160446e
Loading
Loading
Loading
Loading
+64 −77
Original line number Diff line number Diff line
@@ -18,8 +18,8 @@ package com.android.wm.shell.common
import android.app.ActivityManager.RunningTaskInfo
import android.graphics.RectF
import android.view.SurfaceControl
import android.window.DesktopExperienceFlags
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.shared.annotations.ShellDesktopThread
import com.android.wm.shell.shared.desktopmode.DesktopState

/**
@@ -30,10 +30,8 @@ class MultiDisplayDragMoveIndicatorController(
    private val displayController: DisplayController,
    private val rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer,
    private val indicatorSurfaceFactory: MultiDisplayDragMoveIndicatorSurface.Factory,
    @ShellDesktopThread private val desktopExecutor: ShellExecutor,
    private val desktopState: DesktopState,
) {
    @ShellDesktopThread
    private val dragIndicators =
        mutableMapOf<Int, MutableMap<Int, MultiDisplayDragMoveIndicatorSurface>>()

@@ -43,9 +41,6 @@ class MultiDisplayDragMoveIndicatorController(
     * [taskInfo] based on [boundsDp] on the destination displays ([displayIds]) as the dragged
     * window moves. [transactionSupplier] provides a [SurfaceControl.Transaction] for applying
     * changes to the indicator surfaces.
     *
     * It is executed on the [desktopExecutor] to prevent blocking the main thread and avoid jank,
     * as creating and manipulating surfaces can be expensive.
     */
    fun onDragMove(
        boundsDp: RectF,
@@ -56,9 +51,8 @@ class MultiDisplayDragMoveIndicatorController(
        displayIds: Set<Int>,
        transactionSupplier: () -> SurfaceControl.Transaction,
    ) {
        desktopExecutor.execute {
        val startDisplayDpi =
                displayController.getDisplayLayout(startDisplayId)?.densityDpi() ?: return@execute
            displayController.getDisplayLayout(startDisplayId)?.densityDpi() ?: return
        val transaction = transactionSupplier()
        for (displayId in displayIds) {
            if (
@@ -98,8 +92,7 @@ class MultiDisplayDragMoveIndicatorController(
                )

            // Get or create the inner map for the current task.
                val dragIndicatorsForTask =
                    dragIndicators.getOrPut(taskInfo.taskId) { mutableMapOf() }
            val dragIndicatorsForTask = dragIndicators.getOrPut(taskInfo.taskId) { mutableMapOf() }
            dragIndicatorsForTask[displayId]?.also { existingIndicator ->
                existingIndicator.relayout(boundsPx, transaction, visibility)
            }
@@ -119,25 +112,19 @@ class MultiDisplayDragMoveIndicatorController(
        }
        transaction.apply()
    }
    }

    /**
     * Called when the drag ends. Disposes of the drag move indicator surfaces associated with the
     * given [taskId]. [transactionSupplier] provides a [SurfaceControl.Transaction] for applying
     * changes to the indicator surfaces.
     *
     * It is executed on the [desktopExecutor] to ensure that any pending `onDragMove` operations
     * have completed before disposing of the surfaces.
     * given [taskId] and applies the surface changes with the provided [transaction].
     */
    fun onDragEnd(taskId: Int, transactionSupplier: () -> SurfaceControl.Transaction) {
        desktopExecutor.execute {
    fun onDragEnd(taskId: Int, transaction: SurfaceControl.Transaction) {
        dragIndicators
            .remove(taskId)
            ?.values
            ?.takeIf { it.isNotEmpty() }
            ?.let { indicators ->
                    val transaction = transactionSupplier()
                indicators.forEach { indicator -> indicator.dispose(transaction) }
                if (!DesktopExperienceFlags.ENABLE_WINDOW_DROP_SMOOTH_TRANSITION.isTrue) {
                    transaction.apply()
                }
            }
+8 −7
Original line number Diff line number Diff line
@@ -126,7 +126,6 @@ import com.android.wm.shell.desktopmode.DesktopTasksTransitionObserver;
import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.desktopmode.DisplayDisconnectTransitionHandler;
import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler;
import com.android.wm.shell.desktopmode.DragToDisplayTransitionHandler;
import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler;
import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler;
import com.android.wm.shell.desktopmode.OverviewToDesktopTransitionObserver;
@@ -137,6 +136,7 @@ import com.android.wm.shell.desktopmode.SpringDragToDesktopTransitionHandler;
import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler;
import com.android.wm.shell.desktopmode.VisualIndicatorUpdateScheduler;
import com.android.wm.shell.desktopmode.WindowDecorCaptionRepository;
import com.android.wm.shell.desktopmode.WindowDragTransitionHandler;
import com.android.wm.shell.desktopmode.compatui.SystemModalsTransitionHandler;
import com.android.wm.shell.desktopmode.data.DesktopRepositoryInitializer;
import com.android.wm.shell.desktopmode.data.DesktopRepositoryInitializerImpl;
@@ -921,7 +921,7 @@ public abstract class WMShellModule {
            Optional<DesksTransitionObserver> desksTransitionObserver,
            UserProfileContexts userProfileContexts,
            DesktopModeCompatPolicy desktopModeCompatPolicy,
            DragToDisplayTransitionHandler dragToDisplayTransitionHandler,
            WindowDragTransitionHandler windowDragTransitionHandler,
            DesktopModeMoveToDisplayTransitionHandler moveToDisplayTransitionHandler,
            HomeIntentProvider homeIntentProvider,
            DesktopState desktopState,
@@ -969,7 +969,7 @@ public abstract class WMShellModule {
                desksTransitionObserver.get(),
                userProfileContexts,
                desktopModeCompatPolicy,
                dragToDisplayTransitionHandler,
                windowDragTransitionHandler,
                moveToDisplayTransitionHandler,
                homeIntentProvider,
                desktopState,
@@ -1160,8 +1160,10 @@ public abstract class WMShellModule {

    @WMSingleton
    @Provides
    static DragToDisplayTransitionHandler provideDragToDisplayTransitionHandler() {
        return new DragToDisplayTransitionHandler();
    static WindowDragTransitionHandler provideWindowDragTransitionHandler(
            MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController
    ) {
        return new WindowDragTransitionHandler(multiDisplayDragMoveIndicatorController);
    }

    @WMSingleton
@@ -1288,12 +1290,11 @@ public abstract class WMShellModule {
            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
            MultiDisplayDragMoveIndicatorSurface.Factory
                multiDisplayDragMoveIndicatorSurfaceFactory,
            @ShellDesktopThread ShellExecutor desktopExecutor,
            DesktopState desktopState
    ) {
        return new MultiDisplayDragMoveIndicatorController(
                displayController, rootTaskDisplayAreaOrganizer,
                multiDisplayDragMoveIndicatorSurfaceFactory, desktopExecutor, desktopState);
                multiDisplayDragMoveIndicatorSurfaceFactory, desktopState);
    }

    @WMSingleton
+13 −9
Original line number Diff line number Diff line
@@ -243,7 +243,7 @@ class DesktopTasksController(
    private val desksTransitionObserver: DesksTransitionObserver,
    private val userProfileContexts: UserProfileContexts,
    private val desktopModeCompatPolicy: DesktopModeCompatPolicy,
    private val dragToDisplayTransitionHandler: DragToDisplayTransitionHandler,
    private val windowDragTransitionHandler: WindowDragTransitionHandler,
    private val moveToDisplayTransitionHandler: DesktopModeMoveToDisplayTransitionHandler,
    private val homeIntentProvider: HomeIntentProvider,
    private val desktopState: DesktopState,
@@ -5041,6 +5041,7 @@ class DesktopTasksController(
     *   task bounds or just task leash)
     * @param validDragArea the bounds of where the task can be dragged within the display.
     * @param dragStartBounds the bounds of the task before starting dragging.
     * @return true if caller needs to clear the window drag indicators by itself.
     */
    fun onDragPositioningEnd(
        taskInfo: RunningTaskInfo,
@@ -5051,17 +5052,19 @@ class DesktopTasksController(
        validDragArea: Rect,
        dragStartBounds: Rect,
        motionEvent: MotionEvent,
    ) {
    ): Boolean {
        if (taskInfo.configuration.windowConfiguration.windowingMode != WINDOWING_MODE_FREEFORM) {
            return
            return true
        }

        val indicator = getVisualIndicator() ?: return
        val indicator = getVisualIndicator() ?: return true
        val indicatorType =
            indicator.updateIndicatorType(
                displayId,
                PointF(inputCoordinate.x, currentDragBounds.top.toFloat()),
            )

        var needDragIndicatorCleanup = true
        when (indicatorType) {
            IndicatorType.TO_FULLSCREEN_INDICATOR -> {
                val shouldMaximizeWhenDragToTopEdge =
@@ -5137,10 +5140,10 @@ class DesktopTasksController(
                        startBounds = currentDragBounds,
                        endBounds = dragStartBounds,
                    )
                    return
                    return true
                }

                val newDisplayId = motionEvent.getDisplayId()
                val newDisplayId = motionEvent.displayId
                val displayAreaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(newDisplayId)
                val isCrossDisplayDrag =
                    DesktopExperienceFlags.ENABLE_CONNECTED_DISPLAYS_WINDOW_DRAG.isTrue() &&
@@ -5166,7 +5169,7 @@ class DesktopTasksController(
                        taskInfo,
                        newDisplayId,
                        constrainedBounds,
                        dragToDisplayTransitionHandler,
                        windowDragTransitionHandler,
                        enterReason = EnterReason.APP_HANDLE_DRAG,
                    )
                } else {
@@ -5174,10 +5177,10 @@ class DesktopTasksController(
                    // leash
                    val wct = WindowContainerTransaction()
                    wct.setBounds(taskInfo.token, destinationBounds)
                    transitions.startTransition(TRANSIT_CHANGE, wct, /* handler= */ null)
                    transitions.startTransition(TRANSIT_CHANGE, wct, windowDragTransitionHandler)
                }

                releaseVisualIndicator()
                needDragIndicatorCleanup = false
            }
            IndicatorType.TO_DESKTOP_INDICATOR -> {
                throw IllegalArgumentException(
@@ -5190,6 +5193,7 @@ class DesktopTasksController(
        taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(
            doesAnyTaskRequireTaskbarRounding(taskInfo.displayId)
        )
        return needDragIndicatorCleanup
    }

    /**
+13 −1
Original line number Diff line number Diff line
@@ -17,13 +17,17 @@ package com.android.wm.shell.desktopmode

import android.os.IBinder
import android.view.SurfaceControl
import android.window.DesktopExperienceFlags
import android.window.TransitionInfo
import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
import com.android.wm.shell.common.MultiDisplayDragMoveIndicatorController
import com.android.wm.shell.transition.Transitions

/** Handles the transition to drag a window to another display by dragging the caption. */
class DragToDisplayTransitionHandler : Transitions.TransitionHandler {
class WindowDragTransitionHandler(
    private val multiDisplayDragMoveIndicatorController: MultiDisplayDragMoveIndicatorController
) : Transitions.TransitionHandler {
    override fun handleRequest(
        transition: IBinder,
        request: TransitionRequestInfo,
@@ -48,6 +52,14 @@ class DragToDisplayTransitionHandler : Transitions.TransitionHandler {
            finishTransaction
                .setWindowCrop(sc, endBounds.width(), endBounds.height())
                .setPosition(sc, endPosition.x.toFloat(), endPosition.y.toFloat())
            if (DesktopExperienceFlags.ENABLE_WINDOW_DROP_SMOOTH_TRANSITION.isTrue) {
                change.taskInfo?.let { taskInfo ->
                    multiDisplayDragMoveIndicatorController.onDragEnd(
                        taskInfo.taskId,
                        finishTransaction,
                    )
                }
            }
        }

        startTransaction.apply()
+14 −6
Original line number Diff line number Diff line
@@ -1564,12 +1564,20 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                    // Tasks bounds haven't actually been updated (only its leash), so pass to
                    // DesktopTasksController to allow secondary transformations (i.e. snap resizing
                    // or transforming to fullscreen) before setting new task bounds.
                    final boolean needDragIndicatorCleanup =
                            mDesktopTasksController.onDragPositioningEnd(
                            taskInfo, decoration.getTaskSurface(),
                            e.getDisplayId(),
                            new PointF(e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx)),
                                    taskInfo, decoration.getTaskSurface(), e.getDisplayId(),
                                    new PointF(e.getRawX(dragPointerIdx),
                                            e.getRawY(dragPointerIdx)),
                                    newTaskBounds, decoration.calculateValidDragArea(),
                                    new Rect(mOnDragStartInitialBounds), e);
                    if (DesktopExperienceFlags.ENABLE_WINDOW_DROP_SMOOTH_TRANSITION.isTrue()) {
                        if (needDragIndicatorCleanup) {
                            mMultiDisplayDragMoveIndicatorController.onDragEnd(taskInfo.taskId,
                                    mTransactionFactory.get());
                        }
                    }

                    if (touchingButton) {
                        // We need the input event to not be consumed here to end the ripple
                        // effect on the touched button. We will reset drag state in the ensuing
Loading