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

Commit e3830462 authored by Youkichi Hosoi's avatar Youkichi Hosoi
Browse files

DesktopMode: Implement method to toggle fullscreen state of focused task

The method will be called when the fullscreen key is pressed, and:
1. Move focused desktop tasks into fullscreen mode.
2. Move focused fullscreen tasks into desktop mode.
3. Move focused split screen tasks into fullscreen mode.

Bug: 396483171
Test: atest WMShellUnitTests:DesktopTasksControllerTest
Flag: com.android.window.flags.toggle_fullscreen_state_via_fullscreen_key

Change-Id: I94db978e27c5560291c6be0d3fbf1c974a54d388
parent 4b0ed5a4
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -61,6 +61,10 @@ public interface DesktopMode {
    /** Called when requested to go to split screen from the current focused desktop app. */
    void moveFocusedTaskToStageSplit(int displayId, boolean leftOrTop);

    /** Called when requested to toggle the fullscreen state of the focused app. */
    void toggleFocusedTaskFullscreenState(
            int displayId, DesktopModeTransitionSource transitionSource);

    /**
     * Register a listener that will receive callbacks about desktop-first state. Once it's
     * registered, the listener immediately receives the current state.
+64 −15
Original line number Diff line number Diff line
@@ -443,19 +443,7 @@ class DesktopTasksController(
        when (allFocusedTasks.size) {
            0 -> return
            // Full screen case
            1 -> {
                if (
                    desktopModeCompatPolicy.shouldDisableDesktopEntryPoints(
                        allFocusedTasks.single()
                    )
                ) {
                    return
                }
                moveTaskToDefaultDeskAndActivate(
                    allFocusedTasks.single().taskId,
                    transitionSource = transitionSource,
                )
            }
            1 -> moveFullscreenTaskToDesktop(allFocusedTasks.single(), transitionSource)
            // Split-screen case where there are two focused tasks, then we find the child
            // task to move to desktop.
            2 -> {
@@ -477,6 +465,36 @@ class DesktopTasksController(
        }
    }

    /**
     * Toggles the focused task's fullscreen state. A desktop task or a split screen task is moved
     * into fullscreen mode, while a fullscreen task is moved into desktop mode.
     */
    fun toggleFocusedTaskFullscreenState(
        displayId: Int,
        userId: Int = shellController.currentUserId,
        transitionSource: DesktopModeTransitionSource,
    ) {
        getFocusedDesktopTask(displayId = displayId, userId = userId)?.let {
            // Desktop -> Fullscreen.
            moveDesktopTaskToFullscreen(it, displayId, transitionSource)
            return
        }
        val allFocusedTasks = getFocusedNonDesktopTasks(displayId = displayId, userId = userId)
        when (allFocusedTasks.size) {
            0 -> {}
            // Fullscreen -> Desktop.
            1 -> moveFullscreenTaskToDesktop(allFocusedTasks.single(), transitionSource)
            // Split screen -> Fullscreen (the active split screen app is moved into fullscreen).
            2 -> splitScreenController.goToFullscreenFromSplit()
            else ->
                logW(
                    "DesktopTasksController: Cannot toggle fullscreen state, expected less " +
                        "than 3 focused tasks but found %d",
                    allFocusedTasks.size,
                )
        }
    }

    /**
     * Returns all focused tasks in full screen or split screen mode in [displayId] excluding home
     * activity and desk roots.
@@ -502,6 +520,25 @@ class DesktopTasksController(
    private fun getSplitFocusedTask(task1: RunningTaskInfo, task2: RunningTaskInfo) =
        if (task1.taskId == task2.parentTaskId) task2 else task1

    /** Moves a desktop task into fullscreen mode. */
    private fun moveDesktopTaskToFullscreen(
        task: RunningTaskInfo,
        displayId: Int,
        transitionSource: DesktopModeTransitionSource,
    ) {
        snapEventHandler.removeTaskIfTiled(displayId, task.taskId)
        moveToFullscreenWithAnimation(task, task.positionInParent, transitionSource)
    }

    /** Moves a fullscreen task into desktop mode. */
    private fun moveFullscreenTaskToDesktop(
        task: RunningTaskInfo,
        transitionSource: DesktopModeTransitionSource,
    ) {
        if (desktopModeCompatPolicy.shouldDisableDesktopEntryPoints(task)) return
        moveTaskToDefaultDeskAndActivate(task.taskId, transitionSource = transitionSource)
    }

    @Deprecated("Use isDisplayDesktopFirst() instead.", ReplaceWith("isDisplayDesktopFirst()"))
    private fun isDesktopFirstLegacy(displayId: Int): Boolean {
        if (DesktopExperienceFlags.ENABLE_DESKTOP_FIRST_BASED_DEFAULT_TO_DESKTOP_BUGFIX.isTrue) {
@@ -1861,8 +1898,7 @@ class DesktopTasksController(
        transitionSource: DesktopModeTransitionSource,
    ) {
        getFocusedDesktopTask(displayId = displayId, userId = userId)?.let {
            snapEventHandler.removeTaskIfTiled(displayId, it.taskId)
            moveToFullscreenWithAnimation(it, it.positionInParent, transitionSource)
            moveDesktopTaskToFullscreen(it, displayId, transitionSource)
        }
    }

@@ -6008,6 +6044,19 @@ class DesktopTasksController(
            }
        }

        override fun toggleFocusedTaskFullscreenState(
            displayId: Int,
            transitionSource: DesktopModeTransitionSource,
        ) {
            logV("toggleFocusedTaskFullscreenState")
            mainExecutor.execute {
                this@DesktopTasksController.toggleFocusedTaskFullscreenState(
                    displayId = displayId,
                    transitionSource = transitionSource,
                )
            }
        }

        override fun registerDesktopFirstListener(listener: DesktopFirstListener) {
            logV("registerDesktopFirstListener")
            if (desktopFirstListenerManager.isEmpty) {
+96 −0
Original line number Diff line number Diff line
@@ -7787,6 +7787,102 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        assertThat(fullscreenReorderIndex).isGreaterThan(homeReorderIndex)
    }
    @Test
    fun toggleFocusedTaskFullscreenState_desktopTaskIsMovedToFullscreen() {
        val task1 = setUpFreeformTask()
        val task2 = setUpFreeformTask()
        val task3 = setUpFreeformTask()
        task1.isFocused = false
        task2.isFocused = true
        task3.isFocused = false
        controller.toggleFocusedTaskFullscreenState(DEFAULT_DISPLAY, transitionSource = UNKNOWN)
        val wct = getLatestExitDesktopWct()
        assertThat(wct.changes[task2.token.asBinder()]?.windowingMode)
            .isEqualTo(WINDOWING_MODE_UNDEFINED) // inherited FULLSCREEN
    }
    @Test
    @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun toggleFocusedTaskFullscreenState_fullscreenTaskIsMovedToDesktop_multiDesksDisabled() {
        val task1 = setUpFullscreenTask()
        val task2 = setUpFullscreenTask()
        val task3 = setUpFullscreenTask()
        task1.isFocused = true
        task2.isFocused = false
        task3.isFocused = false
        controller.toggleFocusedTaskFullscreenState(DEFAULT_DISPLAY, transitionSource = UNKNOWN)
        val wct = getLatestEnterDesktopWct()
        assertThat(wct.changes[task1.token.asBinder()]?.windowingMode)
            .isEqualTo(WINDOWING_MODE_FREEFORM)
    }
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun toggleFocusedTaskFullscreenState_fullscreenTaskIsMovedToDesktop_multiDesksEnabled() =
        testScope.runTest {
            val task1 = setUpFullscreenTask()
            val task2 = setUpFullscreenTask()
            val task3 = setUpFullscreenTask()
            task1.isFocused = true
            task2.isFocused = false
            task3.isFocused = false
            controller.toggleFocusedTaskFullscreenState(DEFAULT_DISPLAY, transitionSource = UNKNOWN)
            runCurrent()
            val wct = getLatestEnterDesktopWct()
            verify(desksOrganizer).moveTaskToDesk(wct, deskId = 0, task1)
        }
    @Test
    @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun toggleFocusedTaskFullscreenState_splitScreenTaskIsMovedToFullscreen_multiDesksDisabled() {
        val task1 = setUpSplitScreenTask()
        val task2 = setUpFullscreenTask()
        val task3 = setUpFullscreenTask()
        val task4 = setUpSplitScreenTask()
        task1.isFocused = true
        task2.isFocused = false
        task3.isFocused = false
        task4.isFocused = true
        task4.parentTaskId = task1.taskId
        controller.toggleFocusedTaskFullscreenState(DEFAULT_DISPLAY, transitionSource = UNKNOWN)
        verifyEnterDesktopWCTNotExecuted()
        verify(splitScreenController).goToFullscreenFromSplit()
    }
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun toggleFocusedTaskFullscreenState_splitScreenTaskIsMovedToFullscreen_multiDesksEnabled() =
        testScope.runTest {
            val task1 = setUpSplitScreenTask()
            val task2 = setUpFullscreenTask()
            val task3 = setUpFullscreenTask()
            val task4 = setUpSplitScreenTask()
            task1.isFocused = true
            task2.isFocused = false
            task3.isFocused = false
            task4.isFocused = true
            task4.parentTaskId = task1.taskId
            controller.toggleFocusedTaskFullscreenState(DEFAULT_DISPLAY, transitionSource = UNKNOWN)
            runCurrent()
            verifyEnterDesktopWCTNotExecuted()
            verify(splitScreenController).goToFullscreenFromSplit()
        }
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION)
    @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)