Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +3 −2 Original line number Diff line number Diff line Loading @@ -1263,7 +1263,8 @@ public abstract class WMShellModule { FocusTransitionObserver focusTransitionObserver, @ShellMainThread ShellExecutor mainExecutor, DisplayController displayController, DesktopState desktopState) { DesktopState desktopState, Optional<SplitScreenController> splitScreenController) { if (desktopState.canEnterDesktopMode() && (DesktopExperienceFlags.ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT.isTrue() || DesktopModeFlags.ENABLE_TASK_RESIZING_KEYBOARD_SHORTCUTS.isTrue())) { Loading @@ -1271,7 +1272,7 @@ public abstract class WMShellModule { desktopModeWindowDecorViewModel, desktopTasksController, desktopUserRepositories, inputManager, shellTaskOrganizer, focusTransitionObserver, mainExecutor, displayController, desktopState)); mainExecutor, displayController, desktopState, splitScreenController)); } return Optional.empty(); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandler.kt +17 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW import android.content.Context import android.hardware.input.InputManager import android.hardware.input.InputManager.KeyGestureEventHandler Loading @@ -37,6 +38,7 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.shared.desktopmode.DesktopState import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.transition.FocusTransitionObserver import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel import java.util.Optional Loading @@ -53,6 +55,7 @@ class DesktopModeKeyGestureHandler( @ShellMainThread private val mainExecutor: ShellExecutor, private val displayController: DisplayController, private val desktopState: DesktopState, private val splitScreenController: Optional<SplitScreenController>, ) : KeyGestureEventHandler { init { Loading Loading @@ -340,8 +343,21 @@ class DesktopModeKeyGestureHandler( null } } 2 -> { val task = DesktopTasksController.getSplitFocusedTask(tasks[0], tasks[1]) if (task.windowingMode == WINDOWING_MODE_MULTI_WINDOW) { logV("getGloballyFocusedTaskToClose: Found split screen task: %d", task.taskId) task } else { logW( "getGloballyFocusedTaskToClose: Ignored focused pair non-split-screen " + "tasks." ) null } } else -> { logW("getGloballyFocusedTaskToClose: Ignored focused 2+ tasks.") logW("getGloballyFocusedTaskToClose: Ignored focused 3+ tasks.") null } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +4 −4 Original line number Diff line number Diff line Loading @@ -526,10 +526,6 @@ class DesktopTasksController( } } /** Returns child task from two focused tasks in split screen mode. */ 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, Loading Loading @@ -6609,6 +6605,10 @@ class DesktopTasksController( UnminimizeReason.TASKBAR_MANAGE_WINDOW } /** Returns child task from two focused tasks in split screen mode. */ fun getSplitFocusedTask(task1: RunningTaskInfo, task2: RunningTaskInfo) = if (task1.taskId == task2.parentTaskId) task2 else task1 @JvmField /** * A placeholder for a synthetic transition that isn't backed by a true system transition. Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandlerTest.kt +39 −0 Original line number Diff line number Diff line Loading @@ -52,11 +52,13 @@ import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterRe import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.MinimizeReason import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.createSplitScreenTask import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction import com.android.wm.shell.desktopmode.data.DesktopRepository import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.shared.desktopmode.FakeDesktopConfig import com.android.wm.shell.shared.desktopmode.FakeDesktopState import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.sysui.ShellController import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.FocusTransitionObserver Loading Loading @@ -104,6 +106,7 @@ class DesktopModeKeyGestureHandlerTest : ShellTestCase() { private val desktopTasksController = mock<DesktopTasksController>() private val desktopState = FakeDesktopState() private val shellController = mock<ShellController>() private val splitScreenController = mock<SplitScreenController>() private lateinit var desktopModeKeyGestureHandler: DesktopModeKeyGestureHandler private lateinit var keyGestureEventHandler: KeyGestureEventHandler Loading Loading @@ -174,6 +177,7 @@ class DesktopModeKeyGestureHandlerTest : ShellTestCase() { testExecutor, displayController, desktopState, Optional.of(splitScreenController), ) } Loading Loading @@ -413,6 +417,34 @@ class DesktopModeKeyGestureHandlerTest : ShellTestCase() { verify(desktopModeWindowDecorViewModel).closeTask(task) } @Test @EnableFlags(FLAG_CLOSE_FULLSCREEN_AND_SPLITSCREEN_KEYBOARD_SHORTCUT) fun keyGestureQuitFocusedDesktopTask_shouldQuitSplitScreenTask() { // Setup a focused split screen task val task = setUpSplitScreenTask() val splitRoot = setUpFullscreenTask() task.parentTaskId = splitRoot.taskId whenever(focusTransitionObserver.globallyFocusedDisplayId).thenReturn(task.displayId) whenever( desktopTasksController.getFocusedNonDesktopTasks(task.displayId, repository.userId) ) .thenReturn(listOf(splitRoot, task)) whenever(splitScreenController.isTaskInSplitScreen(task.taskId)).thenReturn(true) // Create and handle the key gesture event val event = KeyGestureEvent.Builder() .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_QUIT_FOCUSED_DESKTOP_TASK) .setKeycodes(intArrayOf(KeyEvent.KEYCODE_Q)) .setModifierState(KeyEvent.META_META_ON) .build() keyGestureEventHandler.handleKeyGestureEvent(event, null) testExecutor.flushAll() // Verify closeTask is called verify(desktopModeWindowDecorViewModel).closeTask(task) } @Test fun keyGestureSwitchToPreviousDesk_activatesDesk() { val displayId = 2 Loading Loading @@ -492,6 +524,13 @@ class DesktopModeKeyGestureHandlerTest : ShellTestCase() { return task } private fun setUpSplitScreenTask(): RunningTaskInfo { val task = createSplitScreenTask() whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task) runningTasks.add(task) return task } private companion object { private const val DEFAULT_USER_ID = 0 const val SECOND_DISPLAY = 2 Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt +26 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,8 @@ import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.util.StubTransaction import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel.DefaultWindowDecorationActions Loading Loading @@ -375,6 +377,30 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest assertThat(hierarchyOp.container).isEqualTo(decor.taskInfo.token.asBinder()) } @Test fun testCloseTask_splitScreen_movesOtherToFullscreen() { desktopModeWindowDecorViewModel.setFreeformTaskTransitionStarter( mockFreeformTaskTransitionStarter ) val decor = createOpenTaskDecoration(windowingMode = WINDOWING_MODE_MULTI_WINDOW) val otherTask = createTask(windowingMode = WINDOWING_MODE_MULTI_WINDOW) whenever(mockSplitScreenController.isTaskInSplitScreen(decor.taskInfo.taskId)) .thenReturn(true) whenever(mockSplitScreenController.getSplitPosition(decor.taskInfo.taskId)) .thenReturn(SPLIT_POSITION_TOP_OR_LEFT) whenever(mockSplitScreenController.getTaskInfo(SPLIT_POSITION_BOTTOM_OR_RIGHT)) .thenReturn(otherTask) desktopModeWindowDecorViewModel.closeTask(decor.taskInfo) verify(mockSplitScreenController) .moveTaskToFullscreen( eq(otherTask.taskId), eq(SplitScreenController.EXIT_REASON_DESKTOP_MODE), ) } @Test @EnableFlags(Flags.FLAG_ENABLE_MINIMIZE_BUTTON) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_APP_HEADER_STATE_CHANGE_ANNOUNCEMENTS) Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +3 −2 Original line number Diff line number Diff line Loading @@ -1263,7 +1263,8 @@ public abstract class WMShellModule { FocusTransitionObserver focusTransitionObserver, @ShellMainThread ShellExecutor mainExecutor, DisplayController displayController, DesktopState desktopState) { DesktopState desktopState, Optional<SplitScreenController> splitScreenController) { if (desktopState.canEnterDesktopMode() && (DesktopExperienceFlags.ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT.isTrue() || DesktopModeFlags.ENABLE_TASK_RESIZING_KEYBOARD_SHORTCUTS.isTrue())) { Loading @@ -1271,7 +1272,7 @@ public abstract class WMShellModule { desktopModeWindowDecorViewModel, desktopTasksController, desktopUserRepositories, inputManager, shellTaskOrganizer, focusTransitionObserver, mainExecutor, displayController, desktopState)); mainExecutor, displayController, desktopState, splitScreenController)); } return Optional.empty(); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandler.kt +17 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW import android.content.Context import android.hardware.input.InputManager import android.hardware.input.InputManager.KeyGestureEventHandler Loading @@ -37,6 +38,7 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellMainThread import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.shared.desktopmode.DesktopState import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.transition.FocusTransitionObserver import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel import java.util.Optional Loading @@ -53,6 +55,7 @@ class DesktopModeKeyGestureHandler( @ShellMainThread private val mainExecutor: ShellExecutor, private val displayController: DisplayController, private val desktopState: DesktopState, private val splitScreenController: Optional<SplitScreenController>, ) : KeyGestureEventHandler { init { Loading Loading @@ -340,8 +343,21 @@ class DesktopModeKeyGestureHandler( null } } 2 -> { val task = DesktopTasksController.getSplitFocusedTask(tasks[0], tasks[1]) if (task.windowingMode == WINDOWING_MODE_MULTI_WINDOW) { logV("getGloballyFocusedTaskToClose: Found split screen task: %d", task.taskId) task } else { logW( "getGloballyFocusedTaskToClose: Ignored focused pair non-split-screen " + "tasks." ) null } } else -> { logW("getGloballyFocusedTaskToClose: Ignored focused 2+ tasks.") logW("getGloballyFocusedTaskToClose: Ignored focused 3+ tasks.") null } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +4 −4 Original line number Diff line number Diff line Loading @@ -526,10 +526,6 @@ class DesktopTasksController( } } /** Returns child task from two focused tasks in split screen mode. */ 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, Loading Loading @@ -6609,6 +6605,10 @@ class DesktopTasksController( UnminimizeReason.TASKBAR_MANAGE_WINDOW } /** Returns child task from two focused tasks in split screen mode. */ fun getSplitFocusedTask(task1: RunningTaskInfo, task2: RunningTaskInfo) = if (task1.taskId == task2.parentTaskId) task2 else task1 @JvmField /** * A placeholder for a synthetic transition that isn't backed by a true system transition. Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandlerTest.kt +39 −0 Original line number Diff line number Diff line Loading @@ -52,11 +52,13 @@ import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterRe import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.MinimizeReason import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFreeformTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.createFullscreenTask import com.android.wm.shell.desktopmode.DesktopTestHelpers.createSplitScreenTask import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction import com.android.wm.shell.desktopmode.data.DesktopRepository import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.shared.desktopmode.FakeDesktopConfig import com.android.wm.shell.shared.desktopmode.FakeDesktopState import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.sysui.ShellController import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.FocusTransitionObserver Loading Loading @@ -104,6 +106,7 @@ class DesktopModeKeyGestureHandlerTest : ShellTestCase() { private val desktopTasksController = mock<DesktopTasksController>() private val desktopState = FakeDesktopState() private val shellController = mock<ShellController>() private val splitScreenController = mock<SplitScreenController>() private lateinit var desktopModeKeyGestureHandler: DesktopModeKeyGestureHandler private lateinit var keyGestureEventHandler: KeyGestureEventHandler Loading Loading @@ -174,6 +177,7 @@ class DesktopModeKeyGestureHandlerTest : ShellTestCase() { testExecutor, displayController, desktopState, Optional.of(splitScreenController), ) } Loading Loading @@ -413,6 +417,34 @@ class DesktopModeKeyGestureHandlerTest : ShellTestCase() { verify(desktopModeWindowDecorViewModel).closeTask(task) } @Test @EnableFlags(FLAG_CLOSE_FULLSCREEN_AND_SPLITSCREEN_KEYBOARD_SHORTCUT) fun keyGestureQuitFocusedDesktopTask_shouldQuitSplitScreenTask() { // Setup a focused split screen task val task = setUpSplitScreenTask() val splitRoot = setUpFullscreenTask() task.parentTaskId = splitRoot.taskId whenever(focusTransitionObserver.globallyFocusedDisplayId).thenReturn(task.displayId) whenever( desktopTasksController.getFocusedNonDesktopTasks(task.displayId, repository.userId) ) .thenReturn(listOf(splitRoot, task)) whenever(splitScreenController.isTaskInSplitScreen(task.taskId)).thenReturn(true) // Create and handle the key gesture event val event = KeyGestureEvent.Builder() .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_QUIT_FOCUSED_DESKTOP_TASK) .setKeycodes(intArrayOf(KeyEvent.KEYCODE_Q)) .setModifierState(KeyEvent.META_META_ON) .build() keyGestureEventHandler.handleKeyGestureEvent(event, null) testExecutor.flushAll() // Verify closeTask is called verify(desktopModeWindowDecorViewModel).closeTask(task) } @Test fun keyGestureSwitchToPreviousDesk_activatesDesk() { val displayId = 2 Loading Loading @@ -492,6 +524,13 @@ class DesktopModeKeyGestureHandlerTest : ShellTestCase() { return task } private fun setUpSplitScreenTask(): RunningTaskInfo { val task = createSplitScreenTask() whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task) runningTasks.add(task) return task } private companion object { private const val DEFAULT_USER_ID = 0 const val SECOND_DISPLAY = 2 Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt +26 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,8 @@ import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.util.StubTransaction import com.android.wm.shell.windowdecor.DesktopModeWindowDecorViewModel.DefaultWindowDecorationActions Loading Loading @@ -375,6 +377,30 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest assertThat(hierarchyOp.container).isEqualTo(decor.taskInfo.token.asBinder()) } @Test fun testCloseTask_splitScreen_movesOtherToFullscreen() { desktopModeWindowDecorViewModel.setFreeformTaskTransitionStarter( mockFreeformTaskTransitionStarter ) val decor = createOpenTaskDecoration(windowingMode = WINDOWING_MODE_MULTI_WINDOW) val otherTask = createTask(windowingMode = WINDOWING_MODE_MULTI_WINDOW) whenever(mockSplitScreenController.isTaskInSplitScreen(decor.taskInfo.taskId)) .thenReturn(true) whenever(mockSplitScreenController.getSplitPosition(decor.taskInfo.taskId)) .thenReturn(SPLIT_POSITION_TOP_OR_LEFT) whenever(mockSplitScreenController.getTaskInfo(SPLIT_POSITION_BOTTOM_OR_RIGHT)) .thenReturn(otherTask) desktopModeWindowDecorViewModel.closeTask(decor.taskInfo) verify(mockSplitScreenController) .moveTaskToFullscreen( eq(otherTask.taskId), eq(SplitScreenController.EXIT_REASON_DESKTOP_MODE), ) } @Test @EnableFlags(Flags.FLAG_ENABLE_MINIMIZE_BUTTON) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_APP_HEADER_STATE_CHANGE_ANNOUNCEMENTS) Loading