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

Commit dd0112e1 authored by Jorge Gil's avatar Jorge Gil
Browse files

[26/N] Desks: Apply desk activation logic when moving task to next display

Consolidates activation logic regardless of multi-desks being enabled
when moving a task to the desktop of another display. Prior to this
change, the target desk only got desk activation changes with the flag
enabled. Activation in this context means:
- Home/Wallpaper go to front to cover existing non-desktop windows (e.g.
  if something was fullscreen in the target display)
- Existing inactive desktop tasks are brought to front to join the task
  moving to the desktop in the new display
- The task moving to the new desktop/display may put the # of desktop
  tasks over the task-limit, so minimization logic needs to be applied.

So with this change all that is applied even with multi-desks disabled
(which fixes pre-existing bugs), and allows the activation logic in the
moveToDisplay() function to be simplified to calling
addDeskActivationChanges(), which already internally handles multi-desk
flag differences.

Bug: 362720497
Flag: com.android.window.flags.enable_desktop_windowing_mode
Flag: com.android.window.flags.enable_move_to_next_display_shortcut
Flag: com.android.window.flags.enable_multiple_desktops_backend
Test: open a couple of freeform apps in an external display, move one to
fullscreen. Then, move a task from the internal display to the external
display and verify:
 1) The fullscreen task is no longer visible
 2) Wallpaper is visible in the background
 3) Existing desktop tasks are visible
 4) Going over the limit minimizes some of the existing tasks from (3)

Change-Id: I5c9ddf8c3de52ddc948c847036feed195e639c80
parent 45dc6eaa
Loading
Loading
Loading
Loading
+12 −14
Original line number Diff line number Diff line
@@ -1317,12 +1317,13 @@ class DesktopTasksController(
            applyFreeformDisplayChange(wct, task, displayId)
        }

        val activationRunnable: RunOnTransitStart?
        if (DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue) {
            desksOrganizer.moveTaskToDesk(wct, destinationDeskId, task)
            prepareForDeskActivation(displayId, wct)
            desksOrganizer.activateDesk(wct, destinationDeskId)
            activationRunnable = { transition ->
        } else {
            wct.reparent(task.token, displayAreaInfo.token, /* onTop= */ true)
        }
        addDeskActivationChanges(destinationDeskId, wct)
        val activationRunnable: RunOnTransitStart = { transition ->
            desksTransitionObserver.addPendingTransition(
                DeskTransition.ActiveDeskWithTask(
                    token = transition,
@@ -1332,10 +1333,7 @@ class DesktopTasksController(
                )
            )
        }
        } else {
            wct.reparent(task.token, displayAreaInfo.token, /* onTop= */ true)
            activationRunnable = null
        }

        if (Flags.enableDisplayFocusInShellTransitions()) {
            // 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
+102 −0
Original line number Diff line number Diff line
@@ -2780,6 +2780,73 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        assertThat(taskChange.includingParents()).isTrue()
    }

    @Test
    @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun moveToNextDisplay_toDesktopInOtherDisplay_bringsExistingTasksToFront() {
        val transition = Binder()
        val sourceDeskId = 0
        val targetDeskId = 2
        taskRepository.addDesk(displayId = SECOND_DISPLAY, deskId = targetDeskId)
        taskRepository.setDeskInactive(deskId = targetDeskId)
        // Set up two display ids
        whenever(rootTaskDisplayAreaOrganizer.displayIds)
            .thenReturn(intArrayOf(DEFAULT_DISPLAY, SECOND_DISPLAY))
        // Create a mock for the target display area: second display
        val secondDisplayArea = DisplayAreaInfo(MockToken().token(), SECOND_DISPLAY, 0)
        whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(SECOND_DISPLAY))
            .thenReturn(secondDisplayArea)
        whenever(transitions.startTransition(eq(TRANSIT_CHANGE), any(), anyOrNull()))
            .thenReturn(transition)
        val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = sourceDeskId)
        val task2 = setUpFreeformTask(displayId = SECOND_DISPLAY, deskId = targetDeskId)

        controller.moveToNextDisplay(task1.taskId)

        // Existing desktop task in the target display is moved to front.
        val wct = getLatestTransition()
        wct.assertReorder(task2.token, /* toTop= */ true)
    }

    @Test
    @EnableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
        Flags.FLAG_ENABLE_PER_DISPLAY_DESKTOP_WALLPAPER_ACTIVITY,
        Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER,
    )
    @DisableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun moveToNextDisplay_toDesktopInOtherDisplay_movesHomeAndWallpaperToFront() {
        val homeTask = setUpHomeTask(displayId = SECOND_DISPLAY)
        whenever(desktopWallpaperActivityTokenProvider.getToken(SECOND_DISPLAY))
            .thenReturn(wallpaperToken)
        val transition = Binder()
        val sourceDeskId = 0
        val targetDeskId = 2
        taskRepository.addDesk(displayId = SECOND_DISPLAY, deskId = targetDeskId)
        taskRepository.setDeskInactive(deskId = targetDeskId)
        // Set up two display ids
        whenever(rootTaskDisplayAreaOrganizer.displayIds)
            .thenReturn(intArrayOf(DEFAULT_DISPLAY, SECOND_DISPLAY))
        // Create a mock for the target display area: second display
        val secondDisplayArea = DisplayAreaInfo(MockToken().token(), SECOND_DISPLAY, 0)
        whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(SECOND_DISPLAY))
            .thenReturn(secondDisplayArea)
        whenever(transitions.startTransition(eq(TRANSIT_CHANGE), any(), anyOrNull()))
            .thenReturn(transition)
        val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = sourceDeskId)

        controller.moveToNextDisplay(task1.taskId)

        // Home / Wallpaper should be moved to front as the background of desktop tasks, otherwise
        // fullscreen (non-desktop) tasks could remain visible.
        val wct = getLatestTransition()
        val homeReorderIndex = wct.indexOfReorder(homeTask, toTop = true)
        val wallpaperReorderIndex = wct.indexOfReorder(wallpaperToken, toTop = true)
        assertThat(homeReorderIndex).isNotEqualTo(-1)
        assertThat(wallpaperReorderIndex).isNotEqualTo(-1)
        // Wallpaper last, to be in front of Home.
        assertThat(wallpaperReorderIndex).isGreaterThan(homeReorderIndex)
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_MULTIPLE_DESKTOPS_BACKEND)
    fun moveToNextDisplay_toDeskInOtherDisplay_movesToDeskAndActivates() {
@@ -2853,6 +2920,35 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            )
    }

    @Test
    fun moveToNextDisplay_movingToDesktop_sendsTaskbarRoundingUpdate() {
        val transition = Binder()
        val sourceDeskId = 1
        val targetDeskId = 2
        taskRepository.addDesk(displayId = SECOND_DISPLAY, deskId = targetDeskId)
        taskRepository.setDeskInactive(deskId = targetDeskId)
        // Set up two display ids
        whenever(rootTaskDisplayAreaOrganizer.displayIds)
            .thenReturn(intArrayOf(DEFAULT_DISPLAY, SECOND_DISPLAY))
        // Create a mock for the target display area: second display
        val secondDisplayArea = DisplayAreaInfo(MockToken().token(), SECOND_DISPLAY, 0)
        whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(SECOND_DISPLAY))
            .thenReturn(secondDisplayArea)
        whenever(transitions.startTransition(eq(TRANSIT_CHANGE), any(), anyOrNull()))
            .thenReturn(transition)

        val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY, deskId = sourceDeskId)
        taskRepository.addTaskToDesk(
            displayId = DEFAULT_DISPLAY,
            deskId = sourceDeskId,
            taskId = task.taskId,
            isVisible = true,
        )
        controller.moveToNextDisplay(task.taskId)

        verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(anyBoolean())
    }

    @Test
    fun getTaskWindowingMode() {
        val fullscreenTask = setUpFullscreenTask()
@@ -6786,6 +6882,12 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        return arg.lastValue
    }

    private fun getLatestTransition(): WindowContainerTransaction {
        val arg = argumentCaptor<WindowContainerTransaction>()
        verify(transitions).startTransition(any(), arg.capture(), anyOrNull())
        return arg.lastValue
    }

    private fun getLatestEnterDesktopWct(): WindowContainerTransaction {
        val arg = argumentCaptor<WindowContainerTransaction>()
        verify(enterDesktopTransitionHandler).moveToDesktop(arg.capture(), any())