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

Commit fc934955 authored by Daichi Hirono's avatar Daichi Hirono
Browse files

Move task to fullscreen on default display

This CL handles moving a task to the default display when using the
move-to-next-display shortcut in projected mode.

When the shortcut is used to move a task from an external display
to the default display, the task will now transition to fullscreen
mode.

Bug: 424748132
Test: DesktopTasksControllerTest
Flag: com.android.window.flags.move_to_next_display_shortcut_with_projected_mode
Change-Id: I059c0844f1b3faf90ddc111d1872552ba077fe24
parent a9995ca9
Loading
Loading
Loading
Loading
+73 −43
Original line number Diff line number Diff line
@@ -2031,6 +2031,14 @@ class DesktopTasksController(
    /** Move task to the next display which can host desktop tasks. */
    fun moveToNextDesktopDisplay(taskId: Int, enterReason: EnterReason) =
        moveToNextDisplay(taskId, enterReason) { displayId ->
            if (
                DesktopExperienceFlags.MOVE_TO_NEXT_DISPLAY_SHORTCUT_WITH_PROJECTED_MODE.isTrue &&
                    desktopState.isProjectedMode() &&
                    displayId == DEFAULT_DISPLAY
            ) {
                logD("moveToNextDesktopDisplay: Moving to default display during projected mode.")
                return@moveToNextDisplay true
            }
            if (!desktopState.isDesktopModeSupportedOnDisplay(displayId)) {
                logD(
                    "moveToNextDesktopDisplay: Skip displayId=$displayId as desktop mode " +
@@ -2137,6 +2145,28 @@ class DesktopTasksController(
            return
        }

        val activationRunnable: RunOnTransitStart?
        val deactivationRunnable: RunOnTransitStart?

        if (
            DesktopExperienceFlags.MOVE_TO_NEXT_DISPLAY_SHORTCUT_WITH_PROJECTED_MODE.isTrue &&
                desktopState.isProjectedMode() &&
                displayId == DEFAULT_DISPLAY
        ) {
            logV("moveToDisplay: moving task to default display during projected mode")
            activationRunnable = null
            deactivationRunnable =
                addMoveToFullscreenChanges(
                    wct,
                    task,
                    willExitDesktop(
                        triggerTaskId = task.taskId,
                        displayId = task.displayId,
                        forceExitDesktop = false,
                    ),
                    displayId,
                )
        } else {
            val destinationDeskId = taskRepository.getDefaultDeskId(displayId)
            if (destinationDeskId == null) {
                logW("moveToDisplay: desk not found for display: $displayId")
@@ -2161,9 +2191,8 @@ class DesktopTasksController(
                wct.reparent(task.token, displayAreaInfo.token, /* onTop= */ true)
            }

        val activationRunnable =
            activationRunnable =
                addDeskActivationChanges(destinationDeskId, wct, task, enterReason = enterReason)

            val sourceDisplayId = task.displayId
            val sourceDeskId = taskRepository.getDeskIdForTask(task.taskId)
            val shouldExitDesktopIfNeeded =
@@ -2171,7 +2200,7 @@ class DesktopTasksController(
                    DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue
            val isLastTask =
                sourceDeskId?.let { taskRepository.isOnlyTaskInDesk(task.taskId, it) } ?: false
        val deactivationRunnable =
            deactivationRunnable =
                if (shouldExitDesktopIfNeeded) {
                    performDesktopExitCleanupIfNeeded(
                        taskId = task.taskId,
@@ -2185,6 +2214,7 @@ class DesktopTasksController(
                } else {
                    null
                }
        }
        if (DesktopExperienceFlags.ENABLE_DISPLAY_FOCUS_IN_SHELL_TRANSITIONS.isTrue) {
            // Bring the destination display to top with includingParents=true, so that the
            // destination display gains the display focus, which makes the top task in the display
+36 −0
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ import com.android.window.flags.Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP
import com.android.window.flags.Flags.FLAG_ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT
import com.android.window.flags.Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND
import com.android.window.flags.Flags.FLAG_ENABLE_PER_DISPLAY_DESKTOP_WALLPAPER_ACTIVITY
import com.android.window.flags.Flags.FLAG_MOVE_TO_NEXT_DISPLAY_SHORTCUT_WITH_PROJECTED_MODE
import com.android.wm.shell.MockToken
import com.android.wm.shell.R
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
@@ -4165,6 +4166,41 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(anyBoolean())
    }

    @Test
    @EnableFlags(
        FLAG_ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT,
        FLAG_MOVE_TO_NEXT_DISPLAY_SHORTCUT_WITH_PROJECTED_MODE,
    )
    fun moveToNextDesktopDisplay_projectedMode_movesToFullscreenOnDefaultDisplay() {
        // Setup state where a desktop task is running on a secondary display while the device is in
        // projected mode
        desktopState.isProjected = true
        whenever(rootTaskDisplayAreaOrganizer.displayIds)
            .thenReturn(intArrayOf(DEFAULT_DISPLAY, SECOND_DISPLAY))
        val defaultDisplayArea = DisplayAreaInfo(MockToken().token(), DEFAULT_DISPLAY, 0)
        whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY))
            .thenReturn(defaultDisplayArea)
        taskRepository.addDesk(displayId = SECOND_DISPLAY, deskId = SECOND_DISPLAY)
        val task = setUpFreeformTask(displayId = SECOND_DISPLAY)

        controller.moveToNextDesktopDisplay(task.taskId, EnterReason.UNKNOWN_ENTER)

        val wct =
            getLatestWct(
                type = TRANSIT_CHANGE,
                handlerClass = DesktopModeMoveToDisplayTransitionHandler::class.java,
            )

        // Verify that the task is reparented to the default display and set to fullscreen mode
        val hierarchyOp =
            wct.hierarchyOps.find { it.container == task.token.asBinder() && it.isReparent }
        assertNotNull(hierarchyOp)
        assertThat(hierarchyOp.newParent).isEqualTo(defaultDisplayArea.token.asBinder())
        val configChange = wct.changes[task.token.asBinder()]
        assertNotNull(configChange)
        assertThat(configChange.windowingMode).isEqualTo(WINDOWING_MODE_FULLSCREEN)
    }

    private fun moveToNextDesktopDisplay_moveIifDesktopModeSupportedOnDestination(
        isDesktopModeSupportedOnDestination: Boolean
    ) {