Loading core/java/android/hardware/input/KeyGestureEvent.java +8 −0 Original line number Diff line number Diff line Loading @@ -129,6 +129,8 @@ public final class KeyGestureEvent { public static final int KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW = 74; public static final int KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB = 75; public static final int KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS = 76; public static final int KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK = 77; public static final int KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK = 78; public static final int FLAG_CANCELLED = 1; Loading Loading @@ -219,6 +221,8 @@ public final class KeyGestureEvent { KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW, KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB, KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS, KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK, KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK, }) @Retention(RetentionPolicy.SOURCE) public @interface KeyGestureType { Loading Loading @@ -807,6 +811,10 @@ public final class KeyGestureEvent { return "KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB"; case KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS: return "KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS"; case KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK: return "KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK"; case KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK: return "KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK"; default: return Integer.toHexString(value); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandler.kt +18 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,8 @@ class DesktopModeKeyGestureHandler( KeyGestureEvent.KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW, KeyGestureEvent.KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW, KeyGestureEvent.KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK, KeyGestureEvent.KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK, ) inputManager.registerKeyGestureEventHandler(supportedGestures, this) } Loading @@ -71,6 +73,22 @@ class DesktopModeKeyGestureHandler( } } } KeyGestureEvent.KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK -> { logV("Key gesture SWITCH_TO_PREVIOUS_DESK is handled") mainExecutor.execute { desktopTasksController .get() .activatePreviousDesk(focusTransitionObserver.globallyFocusedDisplayId) } } KeyGestureEvent.KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK -> { logV("Key gesture SWITCH_TO_NEXT_DESK is handled") mainExecutor.execute { desktopTasksController .get() .activateNextDesk(focusTransitionObserver.globallyFocusedDisplayId) } } KeyGestureEvent.KEY_GESTURE_TYPE_SNAP_LEFT_FREEFORM_WINDOW -> { logV("Key gesture SNAP_LEFT_FREEFORM_WINDOW is handled") getGloballyFocusedFreeformTask()?.let { Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt +33 −6 Original line number Diff line number Diff line Loading @@ -47,12 +47,11 @@ class DesktopRepository( val userId: Int, ) { /** A display that supports desktops. */ private data class DesktopDisplay( val displayId: Int, val orderedDesks: MutableSet<Desk> = mutableSetOf(), // TODO: b/389960283 - update on desk activation / deactivation. var activeDeskId: Int? = null, ) private class DesktopDisplay(val displayId: Int) { // The set implementation must preserve order. val orderedDesks: MutableSet<Desk> = mutableSetOf() var activeDeskId: Int? = null } /** * Task data tracked per desk. Loading Loading @@ -236,6 +235,25 @@ class DesktopRepository( /** Returns the default desk in the given display. */ private fun getDefaultDesk(displayId: Int): Desk? = desktopData.getDefaultDesk(displayId) /** Returns the id of the desk ordered previous to the given one, or null if there isn't one. */ fun getPreviousDeskId(deskId: Int): Int? { val desks = desktopData.getOrderedDesks(getDisplayForDesk(deskId)) val index = desks.indexOfFirst { it.deskId == deskId } if (index <= 0) return null return desks[index - 1].deskId } /** Returns the id of the desk ordered next to the given one, or null if there isn't one. */ fun getNextDeskId(deskId: Int): Int? { val desks = desktopData.getOrderedDesks(getDisplayForDesk(deskId)) val index = desks.indexOfFirst { it.deskId == deskId } return if (index >= 0 && index < desks.size - 1) { desks[index + 1].deskId } else { null } } /** Returns whether the given desk is active in its display. */ fun isDeskActive(deskId: Int): Boolean = desktopData.getAllActiveDesks().any { desk -> desk.deskId == deskId } Loading Loading @@ -1181,6 +1199,9 @@ class DesktopRepository( /** Returns the number of desks in the given display. */ fun getNumberOfDesks(displayId: Int): Int /** Returns a list of ordered desks in a given display. */ fun getOrderedDesks(displayId: Int): List<Desk> /** Applies a function to all desks. */ fun forAllDesks(consumer: (Desk) -> Unit) Loading Loading @@ -1256,6 +1277,9 @@ class DesktopRepository( override fun getNumberOfDesks(displayId: Int): Int = 1 override fun getOrderedDesks(displayId: Int): List<Desk> = listOf(getDesk(deskId = displayId)) override fun forAllDesks(consumer: (Desk) -> Unit) { deskByDisplayId.forEach { _, desk -> consumer(desk) } } Loading Loading @@ -1332,6 +1356,9 @@ class DesktopRepository( ?: display.orderedDesks.firstOrNull() } override fun getOrderedDesks(displayId: Int): List<Desk> = desktopDisplays[displayId].orderedDesks.toList() override fun getAllActiveDesks(): Set<Desk> { return desktopDisplays .valueIterator() Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +76 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import android.os.UserManager import android.util.Slog import android.view.Display import android.view.Display.DEFAULT_DISPLAY import android.view.Display.INVALID_DISPLAY import android.view.DragEvent import android.view.MotionEvent import android.view.SurfaceControl Loading Loading @@ -2992,8 +2993,83 @@ class DesktopTasksController( } } /** Activates the desk at the given index if it exists. */ fun activatePreviousDesk(displayId: Int) { if ( !DesktopExperienceFlags.ENABLE_KEYBOARD_SHORTCUTS_TO_SWITCH_DESKS.isTrue || !DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue ) { return } val validDisplay = when { displayId != INVALID_DISPLAY -> displayId focusTransitionObserver.globallyFocusedDisplayId != INVALID_DISPLAY -> focusTransitionObserver.globallyFocusedDisplayId else -> { logW("activatePreviousDesk no valid display found") return } } val activeDeskId = taskRepository.getActiveDeskId(validDisplay) if (activeDeskId == null) { logV("activatePreviousDesk no active desk in display=%d", validDisplay) return } val destinationDeskId = taskRepository.getPreviousDeskId(activeDeskId) if (destinationDeskId == null) { logV( "activatePreviousDesk no previous desk before deskId=%d in display=%d", activeDeskId, validDisplay, ) // TODO: b/389957556 - add animation. return } logV("activatePreviousDesk from deskId=%d to deskId=%d", activeDeskId, destinationDeskId) activateDesk(destinationDeskId) } /** Activates the desk at the given index if it exists. */ fun activateNextDesk(displayId: Int) { if ( !DesktopExperienceFlags.ENABLE_KEYBOARD_SHORTCUTS_TO_SWITCH_DESKS.isTrue || !DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue ) { return } val validDisplay = when { displayId != INVALID_DISPLAY -> displayId focusTransitionObserver.globallyFocusedDisplayId != INVALID_DISPLAY -> focusTransitionObserver.globallyFocusedDisplayId else -> { logW("activateNextDesk no valid display found") return } } val activeDeskId = taskRepository.getActiveDeskId(validDisplay) if (activeDeskId == null) { logV("activateNextDesk no active desk in display=%d", validDisplay) return } val destinationDeskId = taskRepository.getNextDeskId(activeDeskId) if (destinationDeskId == null) { logV( "activateNextDesk no next desk before deskId=%d in display=%d", activeDeskId, validDisplay, ) // TODO: b/389957556 - add animation. return } logV("activateNextDesk from deskId=%d to deskId=%d", activeDeskId, destinationDeskId) activateDesk(destinationDeskId) } /** Activates the given desk. */ fun activateDesk(deskId: Int, remoteTransition: RemoteTransition? = null) { logV("activateDesk deskId=%d", deskId) val wct = WindowContainerTransaction() val runOnTransitStart = addDeskActivationChanges(deskId, wct) Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/FocusTransitionObserver.java +8 −0 Original line number Diff line number Diff line Loading @@ -218,6 +218,14 @@ public class FocusTransitionObserver { return focusedTaskOnDisplay != null && focusedTaskOnDisplay.taskId == task.taskId; } /** Returns the globally focused display id. */ public int getGloballyFocusedDisplayId() { if (!enableDisplayFocusInShellTransitions() || mFocusedDisplayId == INVALID_DISPLAY) { return INVALID_DISPLAY; } return mFocusedDisplayId; } /** * Gets the globally focused task ID. */ Loading Loading
core/java/android/hardware/input/KeyGestureEvent.java +8 −0 Original line number Diff line number Diff line Loading @@ -129,6 +129,8 @@ public final class KeyGestureEvent { public static final int KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW = 74; public static final int KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB = 75; public static final int KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS = 76; public static final int KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK = 77; public static final int KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK = 78; public static final int FLAG_CANCELLED = 1; Loading Loading @@ -219,6 +221,8 @@ public final class KeyGestureEvent { KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW, KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB, KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS, KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK, KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK, }) @Retention(RetentionPolicy.SOURCE) public @interface KeyGestureType { Loading Loading @@ -807,6 +811,10 @@ public final class KeyGestureEvent { return "KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB"; case KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS: return "KEY_GESTURE_TYPE_TOGGLE_VOICE_ACCESS"; case KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK: return "KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK"; case KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK: return "KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK"; default: return Integer.toHexString(value); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandler.kt +18 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,8 @@ class DesktopModeKeyGestureHandler( KeyGestureEvent.KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW, KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW, KeyGestureEvent.KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW, KeyGestureEvent.KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK, KeyGestureEvent.KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK, ) inputManager.registerKeyGestureEventHandler(supportedGestures, this) } Loading @@ -71,6 +73,22 @@ class DesktopModeKeyGestureHandler( } } } KeyGestureEvent.KEY_GESTURE_TYPE_SWITCH_TO_PREVIOUS_DESK -> { logV("Key gesture SWITCH_TO_PREVIOUS_DESK is handled") mainExecutor.execute { desktopTasksController .get() .activatePreviousDesk(focusTransitionObserver.globallyFocusedDisplayId) } } KeyGestureEvent.KEY_GESTURE_TYPE_SWITCH_TO_NEXT_DESK -> { logV("Key gesture SWITCH_TO_NEXT_DESK is handled") mainExecutor.execute { desktopTasksController .get() .activateNextDesk(focusTransitionObserver.globallyFocusedDisplayId) } } KeyGestureEvent.KEY_GESTURE_TYPE_SNAP_LEFT_FREEFORM_WINDOW -> { logV("Key gesture SNAP_LEFT_FREEFORM_WINDOW is handled") getGloballyFocusedFreeformTask()?.let { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt +33 −6 Original line number Diff line number Diff line Loading @@ -47,12 +47,11 @@ class DesktopRepository( val userId: Int, ) { /** A display that supports desktops. */ private data class DesktopDisplay( val displayId: Int, val orderedDesks: MutableSet<Desk> = mutableSetOf(), // TODO: b/389960283 - update on desk activation / deactivation. var activeDeskId: Int? = null, ) private class DesktopDisplay(val displayId: Int) { // The set implementation must preserve order. val orderedDesks: MutableSet<Desk> = mutableSetOf() var activeDeskId: Int? = null } /** * Task data tracked per desk. Loading Loading @@ -236,6 +235,25 @@ class DesktopRepository( /** Returns the default desk in the given display. */ private fun getDefaultDesk(displayId: Int): Desk? = desktopData.getDefaultDesk(displayId) /** Returns the id of the desk ordered previous to the given one, or null if there isn't one. */ fun getPreviousDeskId(deskId: Int): Int? { val desks = desktopData.getOrderedDesks(getDisplayForDesk(deskId)) val index = desks.indexOfFirst { it.deskId == deskId } if (index <= 0) return null return desks[index - 1].deskId } /** Returns the id of the desk ordered next to the given one, or null if there isn't one. */ fun getNextDeskId(deskId: Int): Int? { val desks = desktopData.getOrderedDesks(getDisplayForDesk(deskId)) val index = desks.indexOfFirst { it.deskId == deskId } return if (index >= 0 && index < desks.size - 1) { desks[index + 1].deskId } else { null } } /** Returns whether the given desk is active in its display. */ fun isDeskActive(deskId: Int): Boolean = desktopData.getAllActiveDesks().any { desk -> desk.deskId == deskId } Loading Loading @@ -1181,6 +1199,9 @@ class DesktopRepository( /** Returns the number of desks in the given display. */ fun getNumberOfDesks(displayId: Int): Int /** Returns a list of ordered desks in a given display. */ fun getOrderedDesks(displayId: Int): List<Desk> /** Applies a function to all desks. */ fun forAllDesks(consumer: (Desk) -> Unit) Loading Loading @@ -1256,6 +1277,9 @@ class DesktopRepository( override fun getNumberOfDesks(displayId: Int): Int = 1 override fun getOrderedDesks(displayId: Int): List<Desk> = listOf(getDesk(deskId = displayId)) override fun forAllDesks(consumer: (Desk) -> Unit) { deskByDisplayId.forEach { _, desk -> consumer(desk) } } Loading Loading @@ -1332,6 +1356,9 @@ class DesktopRepository( ?: display.orderedDesks.firstOrNull() } override fun getOrderedDesks(displayId: Int): List<Desk> = desktopDisplays[displayId].orderedDesks.toList() override fun getAllActiveDesks(): Set<Desk> { return desktopDisplays .valueIterator() Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +76 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import android.os.UserManager import android.util.Slog import android.view.Display import android.view.Display.DEFAULT_DISPLAY import android.view.Display.INVALID_DISPLAY import android.view.DragEvent import android.view.MotionEvent import android.view.SurfaceControl Loading Loading @@ -2992,8 +2993,83 @@ class DesktopTasksController( } } /** Activates the desk at the given index if it exists. */ fun activatePreviousDesk(displayId: Int) { if ( !DesktopExperienceFlags.ENABLE_KEYBOARD_SHORTCUTS_TO_SWITCH_DESKS.isTrue || !DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue ) { return } val validDisplay = when { displayId != INVALID_DISPLAY -> displayId focusTransitionObserver.globallyFocusedDisplayId != INVALID_DISPLAY -> focusTransitionObserver.globallyFocusedDisplayId else -> { logW("activatePreviousDesk no valid display found") return } } val activeDeskId = taskRepository.getActiveDeskId(validDisplay) if (activeDeskId == null) { logV("activatePreviousDesk no active desk in display=%d", validDisplay) return } val destinationDeskId = taskRepository.getPreviousDeskId(activeDeskId) if (destinationDeskId == null) { logV( "activatePreviousDesk no previous desk before deskId=%d in display=%d", activeDeskId, validDisplay, ) // TODO: b/389957556 - add animation. return } logV("activatePreviousDesk from deskId=%d to deskId=%d", activeDeskId, destinationDeskId) activateDesk(destinationDeskId) } /** Activates the desk at the given index if it exists. */ fun activateNextDesk(displayId: Int) { if ( !DesktopExperienceFlags.ENABLE_KEYBOARD_SHORTCUTS_TO_SWITCH_DESKS.isTrue || !DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue ) { return } val validDisplay = when { displayId != INVALID_DISPLAY -> displayId focusTransitionObserver.globallyFocusedDisplayId != INVALID_DISPLAY -> focusTransitionObserver.globallyFocusedDisplayId else -> { logW("activateNextDesk no valid display found") return } } val activeDeskId = taskRepository.getActiveDeskId(validDisplay) if (activeDeskId == null) { logV("activateNextDesk no active desk in display=%d", validDisplay) return } val destinationDeskId = taskRepository.getNextDeskId(activeDeskId) if (destinationDeskId == null) { logV( "activateNextDesk no next desk before deskId=%d in display=%d", activeDeskId, validDisplay, ) // TODO: b/389957556 - add animation. return } logV("activateNextDesk from deskId=%d to deskId=%d", activeDeskId, destinationDeskId) activateDesk(destinationDeskId) } /** Activates the given desk. */ fun activateDesk(deskId: Int, remoteTransition: RemoteTransition? = null) { logV("activateDesk deskId=%d", deskId) val wct = WindowContainerTransaction() val runOnTransitStart = addDeskActivationChanges(deskId, wct) Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/FocusTransitionObserver.java +8 −0 Original line number Diff line number Diff line Loading @@ -218,6 +218,14 @@ public class FocusTransitionObserver { return focusedTaskOnDisplay != null && focusedTaskOnDisplay.taskId == task.taskId; } /** Returns the globally focused display id. */ public int getGloballyFocusedDisplayId() { if (!enableDisplayFocusInShellTransitions() || mFocusedDisplayId == INVALID_DISPLAY) { return INVALID_DISPLAY; } return mFocusedDisplayId; } /** * Gets the globally focused task ID. */ Loading