Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +11 −14 Original line number Diff line number Diff line Loading @@ -1779,13 +1779,6 @@ class DesktopTasksController( val activationRunnable = addDeskActivationChanges(destinationDeskId, wct, task) 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 // gains the global focus. wct.reorder(task.token, /* onTop= */ true, /* includingParents= */ true) } val sourceDisplayId = task.displayId val sourceDeskId = taskRepository.getDeskIdForTask(task.taskId) val shouldExitDesktopIfNeeded = Loading @@ -1799,15 +1792,20 @@ class DesktopTasksController( displayId = sourceDisplayId, wct = wct, forceToFullscreen = false, // TODO: b/371096166 - Temporary turing home relaunch off to prevent home // stealing // display focus. Remove shouldEndUpAtHome = false when home focus handling // with connected display is implemented in wm core. shouldEndUpAtHome = false, ) } 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 // gains the global focus. This must be done after performDesktopExitCleanupIfNeeded. // The method launches Launcher on the source display when the last task is moved, which // brings the source display to the top. Calling reorder after // performDesktopExitCleanupIfNeeded ensures that the destination display becomes the // top (focused) display. wct.reorder(task.token, /* onTop= */ true, /* includingParents= */ true) } val transition = transitions.startTransition( TRANSIT_CHANGE, Loading Loading @@ -2415,7 +2413,6 @@ class DesktopTasksController( displayId: Int, wct: WindowContainerTransaction, forceToFullscreen: Boolean, shouldEndUpAtHome: Boolean = true, ): RunOnTransitStart? { if (!willExitDesktop(taskId, displayId, forceToFullscreen)) { return null Loading @@ -2427,7 +2424,7 @@ class DesktopTasksController( deskId = deskId, displayId = displayId, willExitDesktop = true, shouldEndUpAtHome = shouldEndUpAtHome, shouldEndUpAtHome = true, ) } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +47 −12 Original line number Diff line number Diff line Loading @@ -3558,18 +3558,19 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY) controller.moveToNextDisplay(task.taskId) val taskChange = val wct = getLatestWct( type = TRANSIT_CHANGE, handlerClass = DesktopModeMoveToDisplayTransitionHandler::class.java, ) .hierarchyOps .find { it.container == task.token.asBinder() && it.type == HIERARCHY_OP_TYPE_REORDER } assertNotNull(taskChange) assertThat(taskChange.toTop).isTrue() assertThat(taskChange.includingParents()).isTrue() wct.assertReorderAt( // Reorder should be the last change so that other hierarchyOps do not change the // display focus after moving the destination display top. index = wct.hierarchyOps.size - 1, task, toTop = true, includingParents = true, ) } @Test Loading Loading @@ -3776,6 +3777,29 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() ) } @Test @EnableFlags( FLAG_ENABLE_DISPLAY_FOCUS_IN_SHELL_TRANSITIONS, FLAG_ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT, ) fun moveToNextDisplay_resetLauncherOnSourceDisplay() { taskRepository.addDesk(displayId = SECOND_DISPLAY, deskId = SECOND_DISPLAY) // Set up two display ids whenever(rootTaskDisplayAreaOrganizer.displayIds) .thenReturn(intArrayOf(DEFAULT_DISPLAY, SECOND_DISPLAY)) val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY) controller.moveToNextDisplay(task.taskId) val wct = getLatestWct( type = TRANSIT_CHANGE, handlerClass = DesktopModeMoveToDisplayTransitionHandler::class.java, ) wct.assertPendingIntent(launchHomeIntent(DEFAULT_DISPLAY)) wct.assertPendingIntentActivityOptionsLaunchDisplayId(DEFAULT_DISPLAY) } @Test fun moveToNextDisplay_movingToDesktop_sendsTaskbarRoundingUpdate() { val transition = Binder() Loading Loading @@ -10129,12 +10153,14 @@ private fun WindowContainerTransaction.assertReorderAt( index: Int, task: RunningTaskInfo, toTop: Boolean? = null, includingParents: Boolean? = null, ) { assertIndexInBounds(index) val op = hierarchyOps[index] assertThat(op.type).isEqualTo(HIERARCHY_OP_TYPE_REORDER) assertThat(op.container).isEqualTo(task.token.asBinder()) toTop?.let { assertThat(op.toTop).isEqualTo(it) } includingParents?.let { assertThat(op.includingParents()).isEqualTo(it) } } private fun WindowContainerTransaction.assertReorderAt( Loading Loading @@ -10198,7 +10224,8 @@ private fun WindowContainerTransaction.hasRemoveAt(index: Int, token: WindowCont private fun WindowContainerTransaction.assertPendingIntent(intent: Intent) { assertHop { hop -> hop.type == HIERARCHY_OP_TYPE_PENDING_INTENT && hop.pendingIntent?.intent?.component == intent.component hop.pendingIntent?.intent?.component == intent.component && hop.pendingIntent?.intent?.categories == intent.categories } } Loading @@ -10217,6 +10244,14 @@ private fun WindowContainerTransaction.assertPendingIntentAt(index: Int, intent: assertThat(op.pendingIntent?.intent?.categories).isEqualTo(intent.categories) } private fun WindowContainerTransaction.assertPendingIntentActivityOptionsLaunchDisplayId( displayId: Int ) { assertHop { hop -> hop.launchOptions != null && ActivityOptions(hop.launchOptions).launchDisplayId == displayId } } private fun WindowContainerTransaction.assertPendingIntentActivityOptionsLaunchDisplayIdAt( index: Int, displayId: Int, Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +11 −14 Original line number Diff line number Diff line Loading @@ -1779,13 +1779,6 @@ class DesktopTasksController( val activationRunnable = addDeskActivationChanges(destinationDeskId, wct, task) 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 // gains the global focus. wct.reorder(task.token, /* onTop= */ true, /* includingParents= */ true) } val sourceDisplayId = task.displayId val sourceDeskId = taskRepository.getDeskIdForTask(task.taskId) val shouldExitDesktopIfNeeded = Loading @@ -1799,15 +1792,20 @@ class DesktopTasksController( displayId = sourceDisplayId, wct = wct, forceToFullscreen = false, // TODO: b/371096166 - Temporary turing home relaunch off to prevent home // stealing // display focus. Remove shouldEndUpAtHome = false when home focus handling // with connected display is implemented in wm core. shouldEndUpAtHome = false, ) } 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 // gains the global focus. This must be done after performDesktopExitCleanupIfNeeded. // The method launches Launcher on the source display when the last task is moved, which // brings the source display to the top. Calling reorder after // performDesktopExitCleanupIfNeeded ensures that the destination display becomes the // top (focused) display. wct.reorder(task.token, /* onTop= */ true, /* includingParents= */ true) } val transition = transitions.startTransition( TRANSIT_CHANGE, Loading Loading @@ -2415,7 +2413,6 @@ class DesktopTasksController( displayId: Int, wct: WindowContainerTransaction, forceToFullscreen: Boolean, shouldEndUpAtHome: Boolean = true, ): RunOnTransitStart? { if (!willExitDesktop(taskId, displayId, forceToFullscreen)) { return null Loading @@ -2427,7 +2424,7 @@ class DesktopTasksController( deskId = deskId, displayId = displayId, willExitDesktop = true, shouldEndUpAtHome = shouldEndUpAtHome, shouldEndUpAtHome = true, ) } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +47 −12 Original line number Diff line number Diff line Loading @@ -3558,18 +3558,19 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY) controller.moveToNextDisplay(task.taskId) val taskChange = val wct = getLatestWct( type = TRANSIT_CHANGE, handlerClass = DesktopModeMoveToDisplayTransitionHandler::class.java, ) .hierarchyOps .find { it.container == task.token.asBinder() && it.type == HIERARCHY_OP_TYPE_REORDER } assertNotNull(taskChange) assertThat(taskChange.toTop).isTrue() assertThat(taskChange.includingParents()).isTrue() wct.assertReorderAt( // Reorder should be the last change so that other hierarchyOps do not change the // display focus after moving the destination display top. index = wct.hierarchyOps.size - 1, task, toTop = true, includingParents = true, ) } @Test Loading Loading @@ -3776,6 +3777,29 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase() ) } @Test @EnableFlags( FLAG_ENABLE_DISPLAY_FOCUS_IN_SHELL_TRANSITIONS, FLAG_ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT, ) fun moveToNextDisplay_resetLauncherOnSourceDisplay() { taskRepository.addDesk(displayId = SECOND_DISPLAY, deskId = SECOND_DISPLAY) // Set up two display ids whenever(rootTaskDisplayAreaOrganizer.displayIds) .thenReturn(intArrayOf(DEFAULT_DISPLAY, SECOND_DISPLAY)) val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY) controller.moveToNextDisplay(task.taskId) val wct = getLatestWct( type = TRANSIT_CHANGE, handlerClass = DesktopModeMoveToDisplayTransitionHandler::class.java, ) wct.assertPendingIntent(launchHomeIntent(DEFAULT_DISPLAY)) wct.assertPendingIntentActivityOptionsLaunchDisplayId(DEFAULT_DISPLAY) } @Test fun moveToNextDisplay_movingToDesktop_sendsTaskbarRoundingUpdate() { val transition = Binder() Loading Loading @@ -10129,12 +10153,14 @@ private fun WindowContainerTransaction.assertReorderAt( index: Int, task: RunningTaskInfo, toTop: Boolean? = null, includingParents: Boolean? = null, ) { assertIndexInBounds(index) val op = hierarchyOps[index] assertThat(op.type).isEqualTo(HIERARCHY_OP_TYPE_REORDER) assertThat(op.container).isEqualTo(task.token.asBinder()) toTop?.let { assertThat(op.toTop).isEqualTo(it) } includingParents?.let { assertThat(op.includingParents()).isEqualTo(it) } } private fun WindowContainerTransaction.assertReorderAt( Loading Loading @@ -10198,7 +10224,8 @@ private fun WindowContainerTransaction.hasRemoveAt(index: Int, token: WindowCont private fun WindowContainerTransaction.assertPendingIntent(intent: Intent) { assertHop { hop -> hop.type == HIERARCHY_OP_TYPE_PENDING_INTENT && hop.pendingIntent?.intent?.component == intent.component hop.pendingIntent?.intent?.component == intent.component && hop.pendingIntent?.intent?.categories == intent.categories } } Loading @@ -10217,6 +10244,14 @@ private fun WindowContainerTransaction.assertPendingIntentAt(index: Int, intent: assertThat(op.pendingIntent?.intent?.categories).isEqualTo(intent.categories) } private fun WindowContainerTransaction.assertPendingIntentActivityOptionsLaunchDisplayId( displayId: Int ) { assertHop { hop -> hop.launchOptions != null && ActivityOptions(hop.launchOptions).launchDisplayId == displayId } } private fun WindowContainerTransaction.assertPendingIntentActivityOptionsLaunchDisplayIdAt( index: Int, displayId: Int, Loading