Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt +3 −2 Original line number Diff line number Diff line Loading @@ -57,7 +57,7 @@ class DesktopModeShellCommandHandler(private val controller: DesktopTasksControl return false } if (!Flags.enableMultipleDesktopsBackend()) { return controller.moveTaskToDesktop(taskId, transitionSource = UNKNOWN) return controller.moveTaskToDefaultDeskAndActivate(taskId, transitionSource = UNKNOWN) } if (args.size < 3) { pw.println("Error: desk id should be provided as arguments") Loading @@ -70,8 +70,9 @@ class DesktopModeShellCommandHandler(private val controller: DesktopTasksControl pw.println("Error: desk id should be an integer") return false } controller.moveTaskToDesk(taskId = taskId, deskId = deskId, transitionSource = UNKNOWN) pw.println("Not implemented.") return false return true } private fun runMoveToNextDisplay(args: Array<String>, pw: PrintWriter): Boolean { Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt +78 −43 Original line number Diff line number Diff line Loading @@ -236,25 +236,32 @@ class DesktopRepository( * TODO: b/389960283 - add explicit [deskId] argument. */ fun addTask(displayId: Int, taskId: Int, isVisible: Boolean) { addOrMoveFreeformTaskToTop(displayId, taskId) addActiveTask(displayId, taskId) updateTask(displayId, taskId, isVisible) val activeDesk = checkNotNull(desktopData.getDefaultDesk(displayId)) { "Expected desk in display: $displayId" } addTaskToDesk(displayId = displayId, deskId = activeDesk.deskId, taskId = taskId, isVisible) } /** * Adds task with [taskId] to the list of active tasks on [displayId]'s active desk. * * TODO: b/389960283 - add explicit [deskId] argument. */ private fun addActiveTask(displayId: Int, taskId: Int) { val activeDesk = desktopData.getDefaultDesk(displayId) checkNotNull(activeDesk) { "Expected desk in display: $displayId" } fun addTaskToDesk(displayId: Int, deskId: Int, taskId: Int, isVisible: Boolean) { addOrMoveTaskToTopOfDesk(displayId = displayId, deskId = deskId, taskId = taskId) addActiveTaskToDesk(displayId = displayId, deskId = deskId, taskId = taskId) updateTaskInDesk( displayId = displayId, deskId = deskId, taskId = taskId, isVisible = isVisible, ) } // Removes task if it is active on another desk excluding [activeDesk]. removeActiveTask(taskId, excludedDeskId = activeDesk.deskId) private fun addActiveTaskToDesk(displayId: Int, deskId: Int, taskId: Int) { val desk = checkNotNull(desktopData.getDesk(deskId)) { "Did not find desk: $deskId" } if (activeDesk.activeTasks.add(taskId)) { logD("Adds active task=%d displayId=%d deskId=%d", taskId, displayId, activeDesk.deskId) // Removes task if it is active on another desk excluding this desk. removeActiveTask(taskId, excludedDeskId = deskId) if (desk.activeTasks.add(taskId)) { logD("Adds active task=%d displayId=%d deskId=%d", taskId, displayId, deskId) updateActiveTasksListeners(displayId) } } Loading Loading @@ -405,10 +412,10 @@ class DesktopRepository( emptySet() } /** Removes task from visible tasks of all displays except [excludedDisplayId]. */ private fun removeVisibleTask(taskId: Int, excludedDisplayId: Int? = null) { /** Removes task from visible tasks of all desks except [excludedDeskId]. */ private fun removeVisibleTask(taskId: Int, excludedDeskId: Int? = null) { desktopData.forAllDesks { displayId, desk -> if (displayId != excludedDisplayId && desk.visibleTasks.remove(taskId)) { if (desk.deskId != excludedDeskId && desk.visibleTasks.remove(taskId)) { notifyVisibleTaskListeners(displayId, desk.visibleTasks.size) } } Loading @@ -423,30 +430,58 @@ class DesktopRepository( * TODO: b/389960283 - add explicit [deskId] argument. */ fun updateTask(displayId: Int, taskId: Int, isVisible: Boolean) { logD("updateTask taskId=%d, displayId=%d, isVisible=%b", taskId, displayId, isVisible) val validDisplayId = if (displayId == INVALID_DISPLAY) { // When a task vanishes it doesn't have a displayId. Find the display of the task. getDisplayIdForTask(taskId) } else { displayId } if (validDisplayId == null) { logW("No display id found for task: taskId=%d", taskId) return } val desk = checkNotNull(desktopData.getDefaultDesk(validDisplayId)) { "Expected a desk in display: $validDisplayId" } updateTaskInDesk( displayId = validDisplayId, deskId = desk.deskId, taskId = taskId, isVisible, ) } private fun updateTaskInDesk(displayId: Int, deskId: Int, taskId: Int, isVisible: Boolean) { check(displayId != INVALID_DISPLAY) { "Display must be valid" } logD( "updateTaskInDesk taskId=%d, deskId=%d, displayId=%d, isVisible=%b", taskId, deskId, displayId, isVisible, ) if (isVisible) { // If task is visible, remove it from any other display besides [displayId]. removeVisibleTask(taskId, excludedDisplayId = displayId) } else if (displayId == INVALID_DISPLAY) { // Task has vanished. Check which display to remove the task from. removeVisibleTask(taskId) return // If task is visible, remove it from any other desk besides [deskId]. removeVisibleTask(taskId, excludedDeskId = deskId) } val prevCount = getVisibleTaskCount(displayId) val desk = checkNotNull(desktopData.getDesk(deskId)) { "Did not find desk: $deskId" } val prevCount = getVisibleTaskCountInDesk(deskId) if (isVisible) { desktopData.getDefaultDesk(displayId)?.visibleTasks?.add(taskId) ?: error("Expected non-null desk in display $displayId") desk.visibleTasks.add(taskId) unminimizeTask(displayId, taskId) } else { desktopData.getDefaultDesk(displayId)?.visibleTasks?.remove(taskId) desk.visibleTasks.remove(taskId) } val newCount = getVisibleTaskCount(displayId) val newCount = getVisibleTaskCount(deskId) if (prevCount != newCount) { logD( "Update task visibility taskId=%d visible=%b displayId=%d", "Update task visibility taskId=%d visible=%b deskId=%d displayId=%d", taskId, isVisible, deskId, displayId, ) logD("VisibleTaskCount has changed from %d to %d", prevCount, newCount) Loading Loading @@ -606,33 +641,32 @@ class DesktopRepository( /** * Gets number of visible freeform tasks on given [displayId]'s active desk. * * TODO: b/389960283 - add explicit [deskId] argument. * TODO: b/389960283 - migrate callers to [getVisibleTaskCountInDesk]. */ fun getVisibleTaskCount(displayId: Int): Int = (desktopData.getActiveDesk(displayId)?.visibleTasks?.size ?: 0).also { logD("getVisibleTaskCount=$it") } /** Gets the number of visible tasks on the given desk. */ fun getVisibleTaskCountInDesk(deskId: Int): Int = desktopData.getDesk(deskId)?.visibleTasks?.size ?: 0 /** * Adds task (or moves if it already exists) to the top of the ordered list. * * Unminimizes the task if it is minimized. * * TODO: b/389960283 - add explicit [deskId] argument. */ private fun addOrMoveFreeformTaskToTop(displayId: Int, taskId: Int) { val desk = getDefaultDesk(displayId) ?: error("Expected a desk in display: $displayId") logD( "Add or move task to top: display=%d taskId=%d deskId=%d", taskId, displayId, desk.deskId, ) private fun addOrMoveTaskToTopOfDesk(displayId: Int, deskId: Int, taskId: Int) { val desk = desktopData.getDesk(deskId) ?: error("Could not find desk: $deskId") logD("addOrMoveTaskToTopOfDesk: display=%d deskId=%d taskId=%d", displayId, deskId, taskId) desktopData.forAllDesks { _, desk1 -> desk1.freeformTasksInZOrder.remove(taskId) } desk.freeformTasksInZOrder.add(0, taskId) // TODO: double check minimization logic. // Unminimize the task if it is minimized. unminimizeTask(displayId, taskId) if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue()) { // TODO: can probably just update the desk. updatePersistentRepository(displayId) } } Loading @@ -648,6 +682,7 @@ class DesktopRepository( // mark it as minimized. getDisplayIdForTask(taskId)?.let { minimizeTask(it, taskId) } ?: logW("Minimize task: No display id found for task: taskId=%d", taskId) return } else { logD("Minimize Task: display=%d, task=%d", displayId, taskId) desktopData.getActiveDesk(displayId)?.minimizedTasks?.add(taskId) Loading Loading @@ -680,7 +715,7 @@ class DesktopRepository( private fun getDisplayIdForTask(taskId: Int): Int? { var displayForTask: Int? = null desktopData.forAllDesks { displayId, desk -> if (taskId in desk.freeformTasksInZOrder) { if (taskId in desk.activeTasks) { displayForTask = displayId } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +118 −15 Original line number Diff line number Diff line Loading @@ -357,15 +357,15 @@ class DesktopTasksController( 0 -> return // Full screen case 1 -> moveRunningTaskToDesktop( allFocusedTasks.single(), moveTaskToDefaultDeskAndActivate( allFocusedTasks.single().taskId, transitionSource = transitionSource, ) // Split-screen case where there are two focused tasks, then we find the child // task to move to desktop. 2 -> moveRunningTaskToDesktop( getSplitFocusedTask(allFocusedTasks[0], allFocusedTasks[1]), moveTaskToDefaultDeskAndActivate( getSplitFocusedTask(allFocusedTasks[0], allFocusedTasks[1]).taskId, transitionSource = transitionSource, ) else -> Loading Loading @@ -428,7 +428,7 @@ class DesktopTasksController( /** Moves task to desktop mode if task is running, else launches it in desktop mode. */ @JvmOverloads fun moveTaskToDesktop( fun moveTaskToDefaultDeskAndActivate( taskId: Int, wct: WindowContainerTransaction = WindowContainerTransaction(), transitionSource: DesktopModeTransitionSource, Loading @@ -436,7 +436,49 @@ class DesktopTasksController( callback: IMoveToDesktopCallback? = null, ): Boolean { val runningTask = shellTaskOrganizer.getRunningTaskInfo(taskId) if (runningTask == null) { val backgroundTask = recentTasksController?.findTaskInBackground(taskId) if (runningTask == null && backgroundTask == null) { logW("moveTaskToDefaultDeskAndActivate taskId=%d not found", taskId) return false } // TODO(342378842): Instead of using default display, support multiple displays val displayId = runningTask?.displayId ?: DEFAULT_DISPLAY val deskId = checkNotNull(taskRepository.getDefaultDeskId(displayId)) { "Expected a default desk to exist" } return moveTaskToDesk( taskId = taskId, deskId = deskId, wct = wct, transitionSource = transitionSource, remoteTransition = remoteTransition, ) } /** Moves task to desktop mode if task is running, else launches it in desktop mode. */ fun moveTaskToDesk( taskId: Int, deskId: Int, wct: WindowContainerTransaction = WindowContainerTransaction(), transitionSource: DesktopModeTransitionSource, remoteTransition: RemoteTransition? = null, callback: IMoveToDesktopCallback? = null, ): Boolean { val runningTask = shellTaskOrganizer.getRunningTaskInfo(taskId) if (runningTask != null) { moveRunningTaskToDesk( task = runningTask, deskId = deskId, wct = wct, transitionSource = transitionSource, remoteTransition = remoteTransition, callback = callback, ) } val backgroundTask = recentTasksController?.findTaskInBackground(taskId) if (backgroundTask != null) { // TODO: b/391484662 - add support for |deskId|. return moveBackgroundTaskToDesktop( taskId, wct, Loading @@ -445,8 +487,8 @@ class DesktopTasksController( callback, ) } moveRunningTaskToDesktop(runningTask, wct, transitionSource, remoteTransition, callback) return true logW("moveTaskToDesk taskId=%d not found", taskId) return false } private fun moveBackgroundTaskToDesktop( Loading Loading @@ -500,8 +542,9 @@ class DesktopTasksController( } /** Moves a running task to desktop. */ fun moveRunningTaskToDesktop( private fun moveRunningTaskToDesk( task: RunningTaskInfo, deskId: Int, wct: WindowContainerTransaction = WindowContainerTransaction(), transitionSource: DesktopModeTransitionSource, remoteTransition: RemoteTransition? = null, Loading @@ -511,20 +554,49 @@ class DesktopTasksController( logW("Cannot enter desktop for taskId %d, ineligible top activity found", task.taskId) return } logV("moveRunningTaskToDesktop taskId=%d", task.taskId) val displayId = taskRepository.getDisplayForDesk(deskId) logV( "moveRunningTaskToDesk taskId=%d deskId=%d displayId=%d", task.taskId, deskId, displayId, ) exitSplitIfApplicable(wct, task) val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( wct = wct, displayId = task.displayId, displayId = displayId, excludeTaskId = task.taskId, reason = DesktopImmersiveController.ExitReason.TASK_LAUNCH, ) // Bring other apps to front first val taskIdToMinimize = if (Flags.enableMultipleDesktopsBackend()) { // Activate the desk first. prepareForDeskActivation(displayId, wct) desksOrganizer.activateDesk(wct, deskId) if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue()) { // TODO: 362720497 - do non-running tasks need to be restarted with // |wct#startTask|? } taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate( doesAnyTaskRequireTaskbarRounding(displayId) ) // TODO: 362720497 - activating a desk with the intention to move a new task to it // means we may need to minimize something in the activating desk. Do so here // similar // to how it's done in #bringDesktopAppsToFrontBeforeShowingNewTask instead of // returning null. null } else { // Bring other apps to front first. bringDesktopAppsToFrontBeforeShowingNewTask(task.displayId, wct, task.taskId) } if (Flags.enableMultipleDesktopsBackend()) { prepareMoveTaskToDesk(wct, task, deskId) } else { addMoveToDesktopChanges(wct, task) } val transition: IBinder if (remoteTransition != null) { Loading @@ -543,6 +615,18 @@ class DesktopTasksController( addPendingMinimizeTransition(transition, it, MinimizeReason.TASK_LIMIT) } exitResult.asExit()?.runOnTransitionStart?.invoke(transition) if (Flags.enableMultipleDesktopsBackend()) { desksTransitionObserver.addPendingTransition( DeskTransition.ActiveDeskWithTask( token = transition, displayId = displayId, deskId = deskId, enterTaskId = task.taskId, ) ) } else { taskRepository.setActiveDesk(displayId = displayId, deskId = deskId) } } private fun invokeCallbackToOverview(transition: IBinder, callback: IMoveToDesktopCallback?) { Loading Loading @@ -2152,6 +2236,7 @@ class DesktopTasksController( * different [displayId] if the task should be moved to a different display. */ @VisibleForTesting @Deprecated("Deprecated with multiple desks", ReplaceWith("prepareMoveTaskToDesk()")) fun addMoveToDesktopChanges( wct: WindowContainerTransaction, taskInfo: RunningTaskInfo, Loading Loading @@ -2179,6 +2264,24 @@ class DesktopTasksController( } } private fun prepareMoveTaskToDesk( wct: WindowContainerTransaction, taskInfo: RunningTaskInfo, deskId: Int, ) { if (!Flags.enableMultipleDesktopsBackend()) return val displayId = taskRepository.getDisplayForDesk(deskId) val displayLayout = displayController.getDisplayLayout(displayId) ?: return val initialBounds = getInitialBounds(displayLayout, taskInfo, displayId) if (canChangeTaskPosition(taskInfo)) { wct.setBounds(taskInfo.token, initialBounds) } desksOrganizer.moveTaskToDesk(wct, deskId = deskId, task = taskInfo) if (useDesktopOverrideDensity()) { wct.setDensityDpi(taskInfo.token, DESKTOP_DENSITY_OVERRIDE) } } /** * Apply changes to move a freeform task from one display to another, which includes handling * density changes between displays. Loading Loading @@ -3173,7 +3276,7 @@ class DesktopTasksController( callback: IMoveToDesktopCallback?, ) { executeRemoteCallWithTaskPermission(controller, "moveTaskToDesktop") { c -> c.moveTaskToDesktop( c.moveTaskToDefaultDeskAndActivate( taskId, transitionSource = transitionSource, remoteTransition = remoteTransition, Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DeskTransition.kt +8 −0 Original line number Diff line number Diff line Loading @@ -34,4 +34,12 @@ sealed class DeskTransition { /** A transition to activate a desk in its display. */ data class ActivateDesk(override val token: IBinder, val displayId: Int, val deskId: Int) : DeskTransition() /** A transition to activate a desk by moving an outside task to it. */ data class ActiveDeskWithTask( override val token: IBinder, val displayId: Int, val deskId: Int, val enterTaskId: Int, ) : DeskTransition() } libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DesksTransitionObserver.kt +20 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,26 @@ class DesksTransitionObserver( ) } } is DeskTransition.ActiveDeskWithTask -> { val withTask = info.changes.find { change -> change.taskInfo?.taskId == deskTransition.enterTaskId && change.taskInfo?.isVisibleRequested == true && desksOrganizer.getDeskAtEnd(change) == deskTransition.deskId } withTask?.let { desktopRepository.setActiveDesk( displayId = deskTransition.displayId, deskId = deskTransition.deskId, ) desktopRepository.addTaskToDesk( displayId = deskTransition.displayId, deskId = deskTransition.deskId, taskId = deskTransition.enterTaskId, isVisible = true, ) } } } } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeShellCommandHandler.kt +3 −2 Original line number Diff line number Diff line Loading @@ -57,7 +57,7 @@ class DesktopModeShellCommandHandler(private val controller: DesktopTasksControl return false } if (!Flags.enableMultipleDesktopsBackend()) { return controller.moveTaskToDesktop(taskId, transitionSource = UNKNOWN) return controller.moveTaskToDefaultDeskAndActivate(taskId, transitionSource = UNKNOWN) } if (args.size < 3) { pw.println("Error: desk id should be provided as arguments") Loading @@ -70,8 +70,9 @@ class DesktopModeShellCommandHandler(private val controller: DesktopTasksControl pw.println("Error: desk id should be an integer") return false } controller.moveTaskToDesk(taskId = taskId, deskId = deskId, transitionSource = UNKNOWN) pw.println("Not implemented.") return false return true } private fun runMoveToNextDisplay(args: Array<String>, pw: PrintWriter): Boolean { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt +78 −43 Original line number Diff line number Diff line Loading @@ -236,25 +236,32 @@ class DesktopRepository( * TODO: b/389960283 - add explicit [deskId] argument. */ fun addTask(displayId: Int, taskId: Int, isVisible: Boolean) { addOrMoveFreeformTaskToTop(displayId, taskId) addActiveTask(displayId, taskId) updateTask(displayId, taskId, isVisible) val activeDesk = checkNotNull(desktopData.getDefaultDesk(displayId)) { "Expected desk in display: $displayId" } addTaskToDesk(displayId = displayId, deskId = activeDesk.deskId, taskId = taskId, isVisible) } /** * Adds task with [taskId] to the list of active tasks on [displayId]'s active desk. * * TODO: b/389960283 - add explicit [deskId] argument. */ private fun addActiveTask(displayId: Int, taskId: Int) { val activeDesk = desktopData.getDefaultDesk(displayId) checkNotNull(activeDesk) { "Expected desk in display: $displayId" } fun addTaskToDesk(displayId: Int, deskId: Int, taskId: Int, isVisible: Boolean) { addOrMoveTaskToTopOfDesk(displayId = displayId, deskId = deskId, taskId = taskId) addActiveTaskToDesk(displayId = displayId, deskId = deskId, taskId = taskId) updateTaskInDesk( displayId = displayId, deskId = deskId, taskId = taskId, isVisible = isVisible, ) } // Removes task if it is active on another desk excluding [activeDesk]. removeActiveTask(taskId, excludedDeskId = activeDesk.deskId) private fun addActiveTaskToDesk(displayId: Int, deskId: Int, taskId: Int) { val desk = checkNotNull(desktopData.getDesk(deskId)) { "Did not find desk: $deskId" } if (activeDesk.activeTasks.add(taskId)) { logD("Adds active task=%d displayId=%d deskId=%d", taskId, displayId, activeDesk.deskId) // Removes task if it is active on another desk excluding this desk. removeActiveTask(taskId, excludedDeskId = deskId) if (desk.activeTasks.add(taskId)) { logD("Adds active task=%d displayId=%d deskId=%d", taskId, displayId, deskId) updateActiveTasksListeners(displayId) } } Loading Loading @@ -405,10 +412,10 @@ class DesktopRepository( emptySet() } /** Removes task from visible tasks of all displays except [excludedDisplayId]. */ private fun removeVisibleTask(taskId: Int, excludedDisplayId: Int? = null) { /** Removes task from visible tasks of all desks except [excludedDeskId]. */ private fun removeVisibleTask(taskId: Int, excludedDeskId: Int? = null) { desktopData.forAllDesks { displayId, desk -> if (displayId != excludedDisplayId && desk.visibleTasks.remove(taskId)) { if (desk.deskId != excludedDeskId && desk.visibleTasks.remove(taskId)) { notifyVisibleTaskListeners(displayId, desk.visibleTasks.size) } } Loading @@ -423,30 +430,58 @@ class DesktopRepository( * TODO: b/389960283 - add explicit [deskId] argument. */ fun updateTask(displayId: Int, taskId: Int, isVisible: Boolean) { logD("updateTask taskId=%d, displayId=%d, isVisible=%b", taskId, displayId, isVisible) val validDisplayId = if (displayId == INVALID_DISPLAY) { // When a task vanishes it doesn't have a displayId. Find the display of the task. getDisplayIdForTask(taskId) } else { displayId } if (validDisplayId == null) { logW("No display id found for task: taskId=%d", taskId) return } val desk = checkNotNull(desktopData.getDefaultDesk(validDisplayId)) { "Expected a desk in display: $validDisplayId" } updateTaskInDesk( displayId = validDisplayId, deskId = desk.deskId, taskId = taskId, isVisible, ) } private fun updateTaskInDesk(displayId: Int, deskId: Int, taskId: Int, isVisible: Boolean) { check(displayId != INVALID_DISPLAY) { "Display must be valid" } logD( "updateTaskInDesk taskId=%d, deskId=%d, displayId=%d, isVisible=%b", taskId, deskId, displayId, isVisible, ) if (isVisible) { // If task is visible, remove it from any other display besides [displayId]. removeVisibleTask(taskId, excludedDisplayId = displayId) } else if (displayId == INVALID_DISPLAY) { // Task has vanished. Check which display to remove the task from. removeVisibleTask(taskId) return // If task is visible, remove it from any other desk besides [deskId]. removeVisibleTask(taskId, excludedDeskId = deskId) } val prevCount = getVisibleTaskCount(displayId) val desk = checkNotNull(desktopData.getDesk(deskId)) { "Did not find desk: $deskId" } val prevCount = getVisibleTaskCountInDesk(deskId) if (isVisible) { desktopData.getDefaultDesk(displayId)?.visibleTasks?.add(taskId) ?: error("Expected non-null desk in display $displayId") desk.visibleTasks.add(taskId) unminimizeTask(displayId, taskId) } else { desktopData.getDefaultDesk(displayId)?.visibleTasks?.remove(taskId) desk.visibleTasks.remove(taskId) } val newCount = getVisibleTaskCount(displayId) val newCount = getVisibleTaskCount(deskId) if (prevCount != newCount) { logD( "Update task visibility taskId=%d visible=%b displayId=%d", "Update task visibility taskId=%d visible=%b deskId=%d displayId=%d", taskId, isVisible, deskId, displayId, ) logD("VisibleTaskCount has changed from %d to %d", prevCount, newCount) Loading Loading @@ -606,33 +641,32 @@ class DesktopRepository( /** * Gets number of visible freeform tasks on given [displayId]'s active desk. * * TODO: b/389960283 - add explicit [deskId] argument. * TODO: b/389960283 - migrate callers to [getVisibleTaskCountInDesk]. */ fun getVisibleTaskCount(displayId: Int): Int = (desktopData.getActiveDesk(displayId)?.visibleTasks?.size ?: 0).also { logD("getVisibleTaskCount=$it") } /** Gets the number of visible tasks on the given desk. */ fun getVisibleTaskCountInDesk(deskId: Int): Int = desktopData.getDesk(deskId)?.visibleTasks?.size ?: 0 /** * Adds task (or moves if it already exists) to the top of the ordered list. * * Unminimizes the task if it is minimized. * * TODO: b/389960283 - add explicit [deskId] argument. */ private fun addOrMoveFreeformTaskToTop(displayId: Int, taskId: Int) { val desk = getDefaultDesk(displayId) ?: error("Expected a desk in display: $displayId") logD( "Add or move task to top: display=%d taskId=%d deskId=%d", taskId, displayId, desk.deskId, ) private fun addOrMoveTaskToTopOfDesk(displayId: Int, deskId: Int, taskId: Int) { val desk = desktopData.getDesk(deskId) ?: error("Could not find desk: $deskId") logD("addOrMoveTaskToTopOfDesk: display=%d deskId=%d taskId=%d", displayId, deskId, taskId) desktopData.forAllDesks { _, desk1 -> desk1.freeformTasksInZOrder.remove(taskId) } desk.freeformTasksInZOrder.add(0, taskId) // TODO: double check minimization logic. // Unminimize the task if it is minimized. unminimizeTask(displayId, taskId) if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue()) { // TODO: can probably just update the desk. updatePersistentRepository(displayId) } } Loading @@ -648,6 +682,7 @@ class DesktopRepository( // mark it as minimized. getDisplayIdForTask(taskId)?.let { minimizeTask(it, taskId) } ?: logW("Minimize task: No display id found for task: taskId=%d", taskId) return } else { logD("Minimize Task: display=%d, task=%d", displayId, taskId) desktopData.getActiveDesk(displayId)?.minimizedTasks?.add(taskId) Loading Loading @@ -680,7 +715,7 @@ class DesktopRepository( private fun getDisplayIdForTask(taskId: Int): Int? { var displayForTask: Int? = null desktopData.forAllDesks { displayId, desk -> if (taskId in desk.freeformTasksInZOrder) { if (taskId in desk.activeTasks) { displayForTask = displayId } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +118 −15 Original line number Diff line number Diff line Loading @@ -357,15 +357,15 @@ class DesktopTasksController( 0 -> return // Full screen case 1 -> moveRunningTaskToDesktop( allFocusedTasks.single(), moveTaskToDefaultDeskAndActivate( allFocusedTasks.single().taskId, transitionSource = transitionSource, ) // Split-screen case where there are two focused tasks, then we find the child // task to move to desktop. 2 -> moveRunningTaskToDesktop( getSplitFocusedTask(allFocusedTasks[0], allFocusedTasks[1]), moveTaskToDefaultDeskAndActivate( getSplitFocusedTask(allFocusedTasks[0], allFocusedTasks[1]).taskId, transitionSource = transitionSource, ) else -> Loading Loading @@ -428,7 +428,7 @@ class DesktopTasksController( /** Moves task to desktop mode if task is running, else launches it in desktop mode. */ @JvmOverloads fun moveTaskToDesktop( fun moveTaskToDefaultDeskAndActivate( taskId: Int, wct: WindowContainerTransaction = WindowContainerTransaction(), transitionSource: DesktopModeTransitionSource, Loading @@ -436,7 +436,49 @@ class DesktopTasksController( callback: IMoveToDesktopCallback? = null, ): Boolean { val runningTask = shellTaskOrganizer.getRunningTaskInfo(taskId) if (runningTask == null) { val backgroundTask = recentTasksController?.findTaskInBackground(taskId) if (runningTask == null && backgroundTask == null) { logW("moveTaskToDefaultDeskAndActivate taskId=%d not found", taskId) return false } // TODO(342378842): Instead of using default display, support multiple displays val displayId = runningTask?.displayId ?: DEFAULT_DISPLAY val deskId = checkNotNull(taskRepository.getDefaultDeskId(displayId)) { "Expected a default desk to exist" } return moveTaskToDesk( taskId = taskId, deskId = deskId, wct = wct, transitionSource = transitionSource, remoteTransition = remoteTransition, ) } /** Moves task to desktop mode if task is running, else launches it in desktop mode. */ fun moveTaskToDesk( taskId: Int, deskId: Int, wct: WindowContainerTransaction = WindowContainerTransaction(), transitionSource: DesktopModeTransitionSource, remoteTransition: RemoteTransition? = null, callback: IMoveToDesktopCallback? = null, ): Boolean { val runningTask = shellTaskOrganizer.getRunningTaskInfo(taskId) if (runningTask != null) { moveRunningTaskToDesk( task = runningTask, deskId = deskId, wct = wct, transitionSource = transitionSource, remoteTransition = remoteTransition, callback = callback, ) } val backgroundTask = recentTasksController?.findTaskInBackground(taskId) if (backgroundTask != null) { // TODO: b/391484662 - add support for |deskId|. return moveBackgroundTaskToDesktop( taskId, wct, Loading @@ -445,8 +487,8 @@ class DesktopTasksController( callback, ) } moveRunningTaskToDesktop(runningTask, wct, transitionSource, remoteTransition, callback) return true logW("moveTaskToDesk taskId=%d not found", taskId) return false } private fun moveBackgroundTaskToDesktop( Loading Loading @@ -500,8 +542,9 @@ class DesktopTasksController( } /** Moves a running task to desktop. */ fun moveRunningTaskToDesktop( private fun moveRunningTaskToDesk( task: RunningTaskInfo, deskId: Int, wct: WindowContainerTransaction = WindowContainerTransaction(), transitionSource: DesktopModeTransitionSource, remoteTransition: RemoteTransition? = null, Loading @@ -511,20 +554,49 @@ class DesktopTasksController( logW("Cannot enter desktop for taskId %d, ineligible top activity found", task.taskId) return } logV("moveRunningTaskToDesktop taskId=%d", task.taskId) val displayId = taskRepository.getDisplayForDesk(deskId) logV( "moveRunningTaskToDesk taskId=%d deskId=%d displayId=%d", task.taskId, deskId, displayId, ) exitSplitIfApplicable(wct, task) val exitResult = desktopImmersiveController.exitImmersiveIfApplicable( wct = wct, displayId = task.displayId, displayId = displayId, excludeTaskId = task.taskId, reason = DesktopImmersiveController.ExitReason.TASK_LAUNCH, ) // Bring other apps to front first val taskIdToMinimize = if (Flags.enableMultipleDesktopsBackend()) { // Activate the desk first. prepareForDeskActivation(displayId, wct) desksOrganizer.activateDesk(wct, deskId) if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_PERSISTENCE.isTrue()) { // TODO: 362720497 - do non-running tasks need to be restarted with // |wct#startTask|? } taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate( doesAnyTaskRequireTaskbarRounding(displayId) ) // TODO: 362720497 - activating a desk with the intention to move a new task to it // means we may need to minimize something in the activating desk. Do so here // similar // to how it's done in #bringDesktopAppsToFrontBeforeShowingNewTask instead of // returning null. null } else { // Bring other apps to front first. bringDesktopAppsToFrontBeforeShowingNewTask(task.displayId, wct, task.taskId) } if (Flags.enableMultipleDesktopsBackend()) { prepareMoveTaskToDesk(wct, task, deskId) } else { addMoveToDesktopChanges(wct, task) } val transition: IBinder if (remoteTransition != null) { Loading @@ -543,6 +615,18 @@ class DesktopTasksController( addPendingMinimizeTransition(transition, it, MinimizeReason.TASK_LIMIT) } exitResult.asExit()?.runOnTransitionStart?.invoke(transition) if (Flags.enableMultipleDesktopsBackend()) { desksTransitionObserver.addPendingTransition( DeskTransition.ActiveDeskWithTask( token = transition, displayId = displayId, deskId = deskId, enterTaskId = task.taskId, ) ) } else { taskRepository.setActiveDesk(displayId = displayId, deskId = deskId) } } private fun invokeCallbackToOverview(transition: IBinder, callback: IMoveToDesktopCallback?) { Loading Loading @@ -2152,6 +2236,7 @@ class DesktopTasksController( * different [displayId] if the task should be moved to a different display. */ @VisibleForTesting @Deprecated("Deprecated with multiple desks", ReplaceWith("prepareMoveTaskToDesk()")) fun addMoveToDesktopChanges( wct: WindowContainerTransaction, taskInfo: RunningTaskInfo, Loading Loading @@ -2179,6 +2264,24 @@ class DesktopTasksController( } } private fun prepareMoveTaskToDesk( wct: WindowContainerTransaction, taskInfo: RunningTaskInfo, deskId: Int, ) { if (!Flags.enableMultipleDesktopsBackend()) return val displayId = taskRepository.getDisplayForDesk(deskId) val displayLayout = displayController.getDisplayLayout(displayId) ?: return val initialBounds = getInitialBounds(displayLayout, taskInfo, displayId) if (canChangeTaskPosition(taskInfo)) { wct.setBounds(taskInfo.token, initialBounds) } desksOrganizer.moveTaskToDesk(wct, deskId = deskId, task = taskInfo) if (useDesktopOverrideDensity()) { wct.setDensityDpi(taskInfo.token, DESKTOP_DENSITY_OVERRIDE) } } /** * Apply changes to move a freeform task from one display to another, which includes handling * density changes between displays. Loading Loading @@ -3173,7 +3276,7 @@ class DesktopTasksController( callback: IMoveToDesktopCallback?, ) { executeRemoteCallWithTaskPermission(controller, "moveTaskToDesktop") { c -> c.moveTaskToDesktop( c.moveTaskToDefaultDeskAndActivate( taskId, transitionSource = transitionSource, remoteTransition = remoteTransition, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DeskTransition.kt +8 −0 Original line number Diff line number Diff line Loading @@ -34,4 +34,12 @@ sealed class DeskTransition { /** A transition to activate a desk in its display. */ data class ActivateDesk(override val token: IBinder, val displayId: Int, val deskId: Int) : DeskTransition() /** A transition to activate a desk by moving an outside task to it. */ data class ActiveDeskWithTask( override val token: IBinder, val displayId: Int, val deskId: Int, val enterTaskId: Int, ) : DeskTransition() }
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/multidesks/DesksTransitionObserver.kt +20 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,26 @@ class DesksTransitionObserver( ) } } is DeskTransition.ActiveDeskWithTask -> { val withTask = info.changes.find { change -> change.taskInfo?.taskId == deskTransition.enterTaskId && change.taskInfo?.isVisibleRequested == true && desksOrganizer.getDeskAtEnd(change) == deskTransition.deskId } withTask?.let { desktopRepository.setActiveDesk( displayId = deskTransition.displayId, deskId = deskTransition.deskId, ) desktopRepository.addTaskToDesk( displayId = deskTransition.displayId, deskId = deskTransition.deskId, taskId = deskTransition.enterTaskId, isVisible = true, ) } } } } }