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

Commit f9362ad6 authored by Gustav Sennton's avatar Gustav Sennton
Browse files

Update taskbar rounding when dragging or resizing desktop task.

If a maximized Desktop task is resized the Taskbar should be updated to
not be rounded. With this CL we trigger taskbar rounding once during
desktop task drag/resizing the first time a "move" is registered.

Bug: 431993211
Flag: EXEMPT bugfix
Test: MultiDisplayVeiledResizeTaskPositionerTest
Change-Id: Ia842deaf4a3ec42a495ab1e8b98a1f83912443ef
parent d67a95f3
Loading
Loading
Loading
Loading
+36 −26
Original line number Diff line number Diff line
@@ -2558,7 +2558,7 @@ class DesktopTasksController(
        }

        val shouldRestoreToSnap =
            isMaximized && isTaskSnappedToHalfScreen(taskInfo, destinationBounds)
            isMaximized && isTaskSnappedToHalfScreen(taskInfo.displayId, destinationBounds)

        logD("willMaximize = %s", willMaximize)
        logD("shouldRestoreToSnap = %s", shouldRestoreToSnap)
@@ -2622,21 +2622,42 @@ class DesktopTasksController(
        )
    }

    private fun isMaximizedToStableBoundsEdges(
        taskInfo: RunningTaskInfo,
        stableBounds: Rect,
    ): Boolean {
        val currentTaskBounds = taskInfo.configuration.windowConfiguration.bounds
        return isTaskBoundsEqual(currentTaskBounds, stableBounds)
    private fun isMaximizedToStableBoundsEdges(displayId: Int, taskBounds: Rect): Boolean {
        val displayLayout = displayController.getDisplayLayout(displayId) ?: return false
        val stableBounds = Rect().also { displayLayout.getStableBounds(it) }
        return isTaskBoundsEqual(taskBounds, stableBounds)
    }

    /** Returns if current task bound is snapped to half screen */
    private fun isTaskSnappedToHalfScreen(
        taskInfo: RunningTaskInfo,
        taskBounds: Rect = taskInfo.configuration.windowConfiguration.bounds,
    ): Boolean =
        getSnapBounds(taskInfo.displayId, SnapPosition.LEFT) == taskBounds ||
            getSnapBounds(taskInfo.displayId, SnapPosition.RIGHT) == taskBounds
    private fun isTaskSnappedToHalfScreen(displayId: Int, taskBounds: Rect): Boolean =
        getSnapBounds(displayId, SnapPosition.LEFT) == taskBounds ||
            getSnapBounds(displayId, SnapPosition.RIGHT) == taskBounds

    /**
     * Update the rounding state of the taskbar on the given display, based on the task with ID
     * [taskId] having bounds [newBounds].
     */
    fun updateTaskbarRoundingOnTaskResize(displayId: Int, taskId: Int, newBounds: Rect) {
        val otherTasksRequireTaskbarRounding =
            doesAnyTaskRequireTaskbarRounding(
                displayId,
                shellController.currentUserId,
                excludeTaskId = taskId,
            )
        val resizedTaskRequiresTaskbarRounding =
            doesTaskRequireTaskbarRounding(displayId, newBounds)
        taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(
            otherTasksRequireTaskbarRounding || resizedTaskRequiresTaskbarRounding
        )
    }

    private fun doesTaskRequireTaskbarRounding(displayId: Int, taskBounds: Rect): Boolean {
        val isSnappedToHalfScreen = isTaskSnappedToHalfScreen(displayId, taskBounds)
        val isMaximizedToBothEdges = isMaximizedToStableBoundsEdges(displayId, taskBounds)
        logD("isTaskSnappedToHalfScreen(taskInfo) = %s", isSnappedToHalfScreen)
        logD("isMaximizedToStableBoundsEdges(taskInfo, stableBounds) = %s", isMaximizedToBothEdges)
        return isSnappedToHalfScreen || isMaximizedToBothEdges
    }

    @VisibleForTesting
    fun doesAnyTaskRequireTaskbarRounding(
@@ -2652,21 +2673,10 @@ class DesktopTasksController(
                .filterNot { taskId -> taskId == excludeTaskId }
                .any { taskId ->
                    val taskInfo = shellTaskOrganizer.getRunningTaskInfo(taskId) ?: return false
                    val displayLayout = displayController.getDisplayLayout(taskInfo.displayId)
                    val stableBounds = Rect().also { displayLayout?.getStableBounds(it) }
                    logD("taskInfo = %s", taskInfo)
                    logD(
                        "isTaskSnappedToHalfScreen(taskInfo) = %s",
                        isTaskSnappedToHalfScreen(taskInfo),
                    )
                    logD(
                        "isMaximizedToStableBoundsEdges(taskInfo, stableBounds) = %s",
                        isMaximizedToStableBoundsEdges(taskInfo, stableBounds),
                    )
                    isTaskSnappedToHalfScreen(taskInfo) ||
                        isMaximizedToStableBoundsEdges(taskInfo, stableBounds)
                    val taskBounds = taskInfo.configuration.windowConfiguration.bounds
                    doesTaskRequireTaskbarRounding(displayId, taskBounds)
                }

        logD("doesAnyTaskRequireTaskbarRounding = %s", doesAnyTaskRequireTaskbarRounding)
        return doesAnyTaskRequireTaskbarRounding
    }
+6 −3
Original line number Diff line number Diff line
@@ -2288,7 +2288,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                mMainHandler,
                mMultiDisplayDragMoveIndicatorController,
                mShellDesktopState,
                mDesktopConfig);
                mDesktopConfig,
                mDesktopTasksController);
        windowDecoration.setTaskDragResizer(taskPositioner);

        final DesktopModeTouchEventListener touchEventListener =
@@ -2632,7 +2633,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                Handler handler,
                MultiDisplayDragMoveIndicatorController multiDisplayDragMoveIndicatorController,
                DesktopState desktopState,
                DesktopConfig desktopConfig) {
                DesktopConfig desktopConfig,
                DesktopTasksController desktopTasksController) {
            final TaskPositioner taskPositioner = desktopConfig.isVeiledResizeEnabled()
                    // TODO(b/383632995): Update when the flag is launched.
                    ? (DesktopExperienceFlags.ENABLE_CONNECTED_DISPLAYS_WINDOW_DRAG.isTrue()
@@ -2644,7 +2646,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                            interactionJankMonitor,
                            handler,
                            multiDisplayDragMoveIndicatorController,
                            desktopState)
                            desktopState,
                            desktopTasksController)
                        : new VeiledResizeTaskPositioner(
                            taskOrganizer,
                            windowDecoration,
+17 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.MultiDisplayDragMoveBoundsCalculator
import com.android.wm.shell.common.MultiDisplayDragMoveIndicatorController
import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.shared.annotations.ShellMainThread
import com.android.wm.shell.shared.desktopmode.DesktopState
import com.android.wm.shell.transition.Transitions
@@ -57,6 +58,7 @@ class MultiDisplayVeiledResizeTaskPositioner(
    @ShellMainThread private val handler: Handler,
    private val multiDisplayDragMoveIndicatorController: MultiDisplayDragMoveIndicatorController,
    private val desktopState: DesktopState,
    private val desktopTasksController: DesktopTasksController,
) : TaskPositioner, Transitions.TransitionHandler, DisplayController.OnDisplaysChangedListener {

    private val dragEventListeners =
@@ -76,6 +78,7 @@ class MultiDisplayVeiledResizeTaskPositioner(
    private var isResizingOrAnimatingResize = false
    @Surface.Rotation private var rotation = 0
    private var startDisplayId = 0
    private var hasMoved = false
    private val displayIds = mutableSetOf<Int>()

    constructor(
@@ -87,6 +90,7 @@ class MultiDisplayVeiledResizeTaskPositioner(
        @ShellMainThread handler: Handler,
        multiDisplayDragMoveIndicatorController: MultiDisplayDragMoveIndicatorController,
        desktopState: DesktopState,
        desktopTasksController: DesktopTasksController,
    ) : this(
        taskOrganizer,
        windowDecoration,
@@ -97,6 +101,7 @@ class MultiDisplayVeiledResizeTaskPositioner(
        handler,
        multiDisplayDragMoveIndicatorController,
        desktopState,
        desktopTasksController,
    )

    init {
@@ -110,6 +115,7 @@ class MultiDisplayVeiledResizeTaskPositioner(
            windowDecoration.taskInfo.configuration.windowConfiguration.bounds
        )
        repositionStartPoint[x] = y
        hasMoved = false
        if (isResizing) {
            // Capture CUJ for re-sizing window in DW mode.
            interactionJankMonitor.begin(
@@ -219,6 +225,17 @@ class MultiDisplayVeiledResizeTaskPositioner(
            t.setFrameTimeline(Choreographer.getInstance().vsyncId)
            t.apply()
        }
        if (!hasMoved) {
            // Update taskbar rounding once the drag/resize has registered a move event - in case
            // the moved task is no longer maximized. Only call this once per resize/drag so we
            // don't call into Launcher with each drag/resize frame to try to update the taskbar.
            desktopTasksController.updateTaskbarRoundingOnTaskResize(
                displayId,
                windowDecoration.taskInfo.taskId,
                Rect(repositionTaskBounds),
            )
            hasMoved = true
        }
        return Rect(repositionTaskBounds)
    }

+1 −0
Original line number Diff line number Diff line
@@ -297,6 +297,7 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() {
                    any(),
                    any(),
                    any(),
                    any(),
                )
            )
            .thenReturn(mockTaskPositioner)
+54 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayLayout
import com.android.wm.shell.common.MultiDisplayDragMoveIndicatorController
import com.android.wm.shell.common.MultiDisplayTestUtil.TestDisplay
import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.shared.desktopmode.FakeDesktopState
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.transition.Transitions.TransitionFinishCallback
@@ -97,6 +98,7 @@ class MultiDisplayVeiledResizeTaskPositionerTest : ShellTestCase() {
    private val mockSurfaceControl = mock<SurfaceControl>()
    private val mockMultiDisplayDragMoveIndicatorController =
        mock<MultiDisplayDragMoveIndicatorController>()
    private val mockDesktopTasksController = mock<DesktopTasksController>()
    private lateinit var resources: TestableResources
    private lateinit var spyDisplayLayout0: DisplayLayout
    private lateinit var spyDisplayLayout1: DisplayLayout
@@ -171,6 +173,7 @@ class MultiDisplayVeiledResizeTaskPositionerTest : ShellTestCase() {
                mainHandler,
                mockMultiDisplayDragMoveIndicatorController,
                desktopState,
                mockDesktopTasksController,
            )
    }

@@ -620,6 +623,57 @@ class MultiDisplayVeiledResizeTaskPositionerTest : ShellTestCase() {
        verify(spyDisplayLayout1, times(1)).getStableBounds(any())
    }

    @Test
    fun testDragResize_moved_updatesTaskbarRounding() = runOnUiThread {
        val moveBounds = Rect(STARTING_BOUNDS)
        moveBounds.union(moveBounds.right + 100, moveBounds.bottom + 100)
        taskPositioner.onDragPositioningStart(
            CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
            DISPLAY_ID_0,
            STARTING_BOUNDS.right.toFloat(),
            STARTING_BOUNDS.bottom.toFloat(),
        )

        taskPositioner.onDragPositioningMove(
            DISPLAY_ID_0,
            moveBounds.right.toFloat(),
            moveBounds.bottom.toFloat(),
        )

        verify(mockDesktopTasksController)
            .updateTaskbarRoundingOnTaskResize(DISPLAY_ID_0, TASK_ID, moveBounds)
    }

    @Test
    fun testDragResize_movedSeveralTimes_updatesTaskbarRoundingOnce() = runOnUiThread {
        val firstmoveBounds = Rect(STARTING_BOUNDS)
        firstmoveBounds.union(firstmoveBounds.right + 100, firstmoveBounds.bottom + 100)
        val secondMoveBounds = Rect(firstmoveBounds)
        secondMoveBounds.union(secondMoveBounds.right + 100, secondMoveBounds.bottom + 100)
        taskPositioner.onDragPositioningStart(
            CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM,
            DISPLAY_ID_0,
            STARTING_BOUNDS.right.toFloat(),
            STARTING_BOUNDS.bottom.toFloat(),
        )

        taskPositioner.onDragPositioningMove(
            DISPLAY_ID_0,
            firstmoveBounds.right.toFloat(),
            firstmoveBounds.bottom.toFloat(),
        )
        taskPositioner.onDragPositioningMove(
            DISPLAY_ID_0,
            secondMoveBounds.right.toFloat() + 100,
            secondMoveBounds.bottom.toFloat() + 100,
        )

        verify(mockDesktopTasksController)
            .updateTaskbarRoundingOnTaskResize(DISPLAY_ID_0, TASK_ID, firstmoveBounds)
        verify(mockDesktopTasksController, never())
            .updateTaskbarRoundingOnTaskResize(DISPLAY_ID_0, TASK_ID, secondMoveBounds)
    }

    @Test
    fun testClose() = runOnUiThread {
        verify(mockDisplayController, times(1)).addDisplayWindowListener(eq(taskPositioner))