Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +4 −2 Original line number Diff line number Diff line Loading @@ -857,14 +857,16 @@ public abstract class WMShellModule { InputManager inputManager, ShellTaskOrganizer shellTaskOrganizer, FocusTransitionObserver focusTransitionObserver, @ShellMainThread ShellExecutor mainExecutor) { @ShellMainThread ShellExecutor mainExecutor, DisplayController displayController) { if (DesktopModeStatus.canEnterDesktopMode(context) && useKeyGestureEventHandler() && manageKeyGestures() && (Flags.enableMoveToNextDisplayShortcut() || Flags.enableTaskResizingKeyboardShortcuts())) { return Optional.of(new DesktopModeKeyGestureHandler(context, desktopModeWindowDecorViewModel, desktopTasksController, inputManager, shellTaskOrganizer, focusTransitionObserver, mainExecutor)); inputManager, shellTaskOrganizer, focusTransitionObserver, mainExecutor, displayController)); } return Optional.empty(); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandler.kt +11 −6 Original line number Diff line number Diff line Loading @@ -31,7 +31,8 @@ import android.content.Context import com.android.hardware.input.Flags.manageKeyGestures import com.android.window.flags.Flags.enableTaskResizingKeyboardShortcuts import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger import com.android.wm.shell.common.DisplayController import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction import com.android.wm.shell.transition.FocusTransitionObserver import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellMainThread Loading @@ -48,6 +49,7 @@ class DesktopModeKeyGestureHandler( private val shellTaskOrganizer: ShellTaskOrganizer, private val focusTransitionObserver: FocusTransitionObserver, @ShellMainThread private val mainExecutor: ShellExecutor, private val displayController: DisplayController, ) : KeyGestureEventHandler { init { Loading Loading @@ -99,12 +101,15 @@ class DesktopModeKeyGestureHandler( } KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW -> { logV("Key gesture TOGGLE_MAXIMIZE_FREEFORM_WINDOW is handled") getGloballyFocusedFreeformTask()?.let { getGloballyFocusedFreeformTask()?.let { taskInfo -> mainExecutor.execute { desktopTasksController.get().toggleDesktopTaskSize( it, ResizeTrigger.MAXIMIZE_MENU, DesktopModeEventLogger.Companion.InputMethod.KEYBOARD, taskInfo, ToggleTaskSizeInteraction( isMaximized = isTaskMaximized(taskInfo, displayController), source = ToggleTaskSizeInteraction.Source.KEYBOARD_SHORTCUT, inputMethod = DesktopModeEventLogger.Companion.InputMethod.KEYBOARD ) ) } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt +9 −1 Original line number Diff line number Diff line Loading @@ -103,8 +103,12 @@ class DesktopModeUiEventLogger( DESKTOP_WINDOW_CORNER_DRAG_RESIZE(1722), @UiEvent(doc = "Tap on the window header maximize button in desktop windowing mode") DESKTOP_WINDOW_MAXIMIZE_BUTTON_TAP(1723), @UiEvent(doc = "Tap on the window header restore button in desktop windowing mode") DESKTOP_WINDOW_RESTORE_BUTTON_TAP(2017), @UiEvent(doc = "Double tap on window header to maximize it in desktop windowing mode") DESKTOP_WINDOW_HEADER_DOUBLE_TAP_TO_MAXIMIZE(1724), @UiEvent(doc = "Double tap on window header to restore from maximize in desktop windowing") DESKTOP_WINDOW_HEADER_DOUBLE_TAP_TO_RESTORE(2018), @UiEvent(doc = "Tap on the window Handle to open the Handle Menu") DESKTOP_WINDOW_APP_HANDLE_TAP(1998), @UiEvent(doc = "Tap on the desktop mode option under app handle menu") Loading Loading @@ -136,7 +140,11 @@ class DesktopModeUiEventLogger( @UiEvent(doc = "Tap on the tile to left option in the maximize button menu") DESKTOP_WINDOW_MAXIMIZE_BUTTON_MENU_TAP_TO_TILE_TO_LEFT(2012), @UiEvent(doc = "Tap on the tile to right option in the maximize button menu") DESKTOP_WINDOW_MAXIMIZE_BUTTON_MENU_TAP_TO_TILE_TO_RIGHT(2013); DESKTOP_WINDOW_MAXIMIZE_BUTTON_MENU_TAP_TO_TILE_TO_RIGHT(2013), @UiEvent(doc = "Moving the desktop window by dragging the header") DESKTOP_WINDOW_MOVE_BY_HEADER_DRAG(2021), @UiEvent(doc = "Double tap on the window header to refocus a desktop window") DESKTOP_WINDOW_HEADER_TAP_TO_REFOCUS(2022); override fun getId(): Int = mId } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt +26 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.content.res.Configuration.ORIENTATION_PORTRAIT import android.graphics.Rect import android.os.SystemProperties import android.util.Size import com.android.wm.shell.common.DisplayController import com.android.wm.shell.common.DisplayLayout val DESKTOP_MODE_INITIAL_BOUNDS_SCALE: Float = Loading Loading @@ -211,6 +212,31 @@ fun calculateAspectRatio(taskInfo: RunningTaskInfo): Float { minOf(appBounds.height(), appBounds.width()).toFloat() } /** Returns whether the task is maximized. */ fun isTaskMaximized( taskInfo: RunningTaskInfo, displayController: DisplayController ): Boolean { val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: error("Could not get display layout for display=${taskInfo.displayId}") val stableBounds = Rect() displayLayout.getStableBounds(stableBounds) return isTaskMaximized(taskInfo, stableBounds) } /** Returns whether the task is maximized. */ fun isTaskMaximized( taskInfo: RunningTaskInfo, stableBounds: Rect ): Boolean { val currentTaskBounds = taskInfo.configuration.windowConfiguration.bounds return if (taskInfo.isResizeable) { isTaskBoundsEqual(currentTaskBounds, stableBounds) } else { isTaskWidthOrHeightEqual(currentTaskBounds, stableBounds) } } /** Returns true if task's width or height is maximized else returns false. */ fun isTaskWidthOrHeightEqual(taskBounds: Rect, stableBounds: Rect): Boolean { return taskBounds.width() == stableBounds.width() || Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +21 −36 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SingleInstanceRemoteListener import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.DragStartState import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType import com.android.wm.shell.desktopmode.DesktopRepository.VisibleTasksListener Loading Loading @@ -795,32 +796,24 @@ class DesktopTasksController( */ fun toggleDesktopTaskSize( taskInfo: RunningTaskInfo, resizeTrigger: ResizeTrigger, inputMethod: InputMethod, maximizeCujRecorder: (() -> Unit)? = null, unmaximizeCujRecorder: (() -> Unit)? = null, interaction: ToggleTaskSizeInteraction ) { val currentTaskBounds = taskInfo.configuration.windowConfiguration.bounds desktopModeEventLogger.logTaskResizingStarted( resizeTrigger, inputMethod, interaction.resizeTrigger, interaction.inputMethod, taskInfo, currentTaskBounds.width(), currentTaskBounds.height(), displayController ) val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return val stableBounds = Rect().apply { displayLayout.getStableBounds(this) } val destinationBounds = Rect() val isMaximized = isTaskMaximized(taskInfo, stableBounds) val isMaximized = interaction.direction == ToggleTaskSizeInteraction.Direction.RESTORE // If the task is currently maximized, we will toggle it not to be and vice versa. This is // helpful to eliminate the current task from logic to calculate taskbar corner rounding. val willMaximize = !isMaximized val willMaximize = interaction.direction == ToggleTaskSizeInteraction.Direction.MAXIMIZE if (isMaximized) { unmaximizeCujRecorder?.invoke() // The desktop task is at the maximized width and/or height of the stable bounds. // If the task's pre-maximize stable bounds were saved, toggle the task to those bounds. // Otherwise, toggle to the default bounds. Loading @@ -836,7 +829,6 @@ class DesktopTasksController( } } } else { maximizeCujRecorder?.invoke() // Save current bounds so that task can be restored back to original bounds if necessary // and toggle to the stable bounds. desktopTilingDecorViewModel.removeTaskIfTiled(taskInfo.displayId, taskInfo.taskId) Loading @@ -857,10 +849,16 @@ class DesktopTasksController( taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(doesAnyTaskRequireTaskbarRounding) val wct = WindowContainerTransaction().setBounds(taskInfo.token, destinationBounds) interaction.uiEvent?.let { uiEvent -> desktopModeUiEventLogger.log(taskInfo, uiEvent) } desktopModeEventLogger.logTaskResizingEnded( resizeTrigger, inputMethod, taskInfo, destinationBounds.width(), destinationBounds.height(), displayController interaction.resizeTrigger, interaction.inputMethod, taskInfo, destinationBounds.width(), destinationBounds.height(), displayController, ) toggleResizeDesktopTaskTransitionHandler.startTransition(wct) } Loading @@ -871,10 +869,7 @@ class DesktopTasksController( currentDragBounds: Rect, motionEvent: MotionEvent ) { val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return val stableBounds = Rect() displayLayout.getStableBounds(stableBounds) if (isTaskMaximized(taskInfo, stableBounds)) { if (isTaskMaximized(taskInfo, displayController)) { // Handle the case where we attempt to drag-to-maximize when already maximized: the task // position won't need to change but we want to animate the surface going back to the // maximized position. Loading @@ -892,8 +887,11 @@ class DesktopTasksController( toggleDesktopTaskSize( taskInfo, ResizeTrigger.DRAG_TO_TOP_RESIZE_TRIGGER, DesktopModeEventLogger.getInputMethodFromMotionEvent(motionEvent), ToggleTaskSizeInteraction( direction = ToggleTaskSizeInteraction.Direction.MAXIMIZE, source = ToggleTaskSizeInteraction.Source.HEADER_DRAG_TO_TOP, inputMethod = DesktopModeEventLogger.getInputMethodFromMotionEvent(motionEvent), ) ) } Loading @@ -911,19 +909,6 @@ class DesktopTasksController( } } private fun isTaskMaximized( taskInfo: RunningTaskInfo, stableBounds: Rect ): Boolean { val currentTaskBounds = taskInfo.configuration.windowConfiguration.bounds return if (taskInfo.isResizeable) { isTaskBoundsEqual(currentTaskBounds, stableBounds) } else { isTaskWidthOrHeightEqual(currentTaskBounds, stableBounds) } } private fun isMaximizedToStableBoundsEdges( taskInfo: RunningTaskInfo, stableBounds: Rect Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +4 −2 Original line number Diff line number Diff line Loading @@ -857,14 +857,16 @@ public abstract class WMShellModule { InputManager inputManager, ShellTaskOrganizer shellTaskOrganizer, FocusTransitionObserver focusTransitionObserver, @ShellMainThread ShellExecutor mainExecutor) { @ShellMainThread ShellExecutor mainExecutor, DisplayController displayController) { if (DesktopModeStatus.canEnterDesktopMode(context) && useKeyGestureEventHandler() && manageKeyGestures() && (Flags.enableMoveToNextDisplayShortcut() || Flags.enableTaskResizingKeyboardShortcuts())) { return Optional.of(new DesktopModeKeyGestureHandler(context, desktopModeWindowDecorViewModel, desktopTasksController, inputManager, shellTaskOrganizer, focusTransitionObserver, mainExecutor)); inputManager, shellTaskOrganizer, focusTransitionObserver, mainExecutor, displayController)); } return Optional.empty(); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeKeyGestureHandler.kt +11 −6 Original line number Diff line number Diff line Loading @@ -31,7 +31,8 @@ import android.content.Context import com.android.hardware.input.Flags.manageKeyGestures import com.android.window.flags.Flags.enableTaskResizingKeyboardShortcuts import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger import com.android.wm.shell.common.DisplayController import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction import com.android.wm.shell.transition.FocusTransitionObserver import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.annotations.ShellMainThread Loading @@ -48,6 +49,7 @@ class DesktopModeKeyGestureHandler( private val shellTaskOrganizer: ShellTaskOrganizer, private val focusTransitionObserver: FocusTransitionObserver, @ShellMainThread private val mainExecutor: ShellExecutor, private val displayController: DisplayController, ) : KeyGestureEventHandler { init { Loading Loading @@ -99,12 +101,15 @@ class DesktopModeKeyGestureHandler( } KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW -> { logV("Key gesture TOGGLE_MAXIMIZE_FREEFORM_WINDOW is handled") getGloballyFocusedFreeformTask()?.let { getGloballyFocusedFreeformTask()?.let { taskInfo -> mainExecutor.execute { desktopTasksController.get().toggleDesktopTaskSize( it, ResizeTrigger.MAXIMIZE_MENU, DesktopModeEventLogger.Companion.InputMethod.KEYBOARD, taskInfo, ToggleTaskSizeInteraction( isMaximized = isTaskMaximized(taskInfo, displayController), source = ToggleTaskSizeInteraction.Source.KEYBOARD_SHORTCUT, inputMethod = DesktopModeEventLogger.Companion.InputMethod.KEYBOARD ) ) } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt +9 −1 Original line number Diff line number Diff line Loading @@ -103,8 +103,12 @@ class DesktopModeUiEventLogger( DESKTOP_WINDOW_CORNER_DRAG_RESIZE(1722), @UiEvent(doc = "Tap on the window header maximize button in desktop windowing mode") DESKTOP_WINDOW_MAXIMIZE_BUTTON_TAP(1723), @UiEvent(doc = "Tap on the window header restore button in desktop windowing mode") DESKTOP_WINDOW_RESTORE_BUTTON_TAP(2017), @UiEvent(doc = "Double tap on window header to maximize it in desktop windowing mode") DESKTOP_WINDOW_HEADER_DOUBLE_TAP_TO_MAXIMIZE(1724), @UiEvent(doc = "Double tap on window header to restore from maximize in desktop windowing") DESKTOP_WINDOW_HEADER_DOUBLE_TAP_TO_RESTORE(2018), @UiEvent(doc = "Tap on the window Handle to open the Handle Menu") DESKTOP_WINDOW_APP_HANDLE_TAP(1998), @UiEvent(doc = "Tap on the desktop mode option under app handle menu") Loading Loading @@ -136,7 +140,11 @@ class DesktopModeUiEventLogger( @UiEvent(doc = "Tap on the tile to left option in the maximize button menu") DESKTOP_WINDOW_MAXIMIZE_BUTTON_MENU_TAP_TO_TILE_TO_LEFT(2012), @UiEvent(doc = "Tap on the tile to right option in the maximize button menu") DESKTOP_WINDOW_MAXIMIZE_BUTTON_MENU_TAP_TO_TILE_TO_RIGHT(2013); DESKTOP_WINDOW_MAXIMIZE_BUTTON_MENU_TAP_TO_TILE_TO_RIGHT(2013), @UiEvent(doc = "Moving the desktop window by dragging the header") DESKTOP_WINDOW_MOVE_BY_HEADER_DRAG(2021), @UiEvent(doc = "Double tap on the window header to refocus a desktop window") DESKTOP_WINDOW_HEADER_TAP_TO_REFOCUS(2022); override fun getId(): Int = mId } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt +26 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.content.res.Configuration.ORIENTATION_PORTRAIT import android.graphics.Rect import android.os.SystemProperties import android.util.Size import com.android.wm.shell.common.DisplayController import com.android.wm.shell.common.DisplayLayout val DESKTOP_MODE_INITIAL_BOUNDS_SCALE: Float = Loading Loading @@ -211,6 +212,31 @@ fun calculateAspectRatio(taskInfo: RunningTaskInfo): Float { minOf(appBounds.height(), appBounds.width()).toFloat() } /** Returns whether the task is maximized. */ fun isTaskMaximized( taskInfo: RunningTaskInfo, displayController: DisplayController ): Boolean { val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: error("Could not get display layout for display=${taskInfo.displayId}") val stableBounds = Rect() displayLayout.getStableBounds(stableBounds) return isTaskMaximized(taskInfo, stableBounds) } /** Returns whether the task is maximized. */ fun isTaskMaximized( taskInfo: RunningTaskInfo, stableBounds: Rect ): Boolean { val currentTaskBounds = taskInfo.configuration.windowConfiguration.bounds return if (taskInfo.isResizeable) { isTaskBoundsEqual(currentTaskBounds, stableBounds) } else { isTaskWidthOrHeightEqual(currentTaskBounds, stableBounds) } } /** Returns true if task's width or height is maximized else returns false. */ fun isTaskWidthOrHeightEqual(taskBounds: Rect, stableBounds: Rect): Boolean { return taskBounds.width() == stableBounds.width() || Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +21 −36 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SingleInstanceRemoteListener import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.DragStartState import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType import com.android.wm.shell.desktopmode.DesktopRepository.VisibleTasksListener Loading Loading @@ -795,32 +796,24 @@ class DesktopTasksController( */ fun toggleDesktopTaskSize( taskInfo: RunningTaskInfo, resizeTrigger: ResizeTrigger, inputMethod: InputMethod, maximizeCujRecorder: (() -> Unit)? = null, unmaximizeCujRecorder: (() -> Unit)? = null, interaction: ToggleTaskSizeInteraction ) { val currentTaskBounds = taskInfo.configuration.windowConfiguration.bounds desktopModeEventLogger.logTaskResizingStarted( resizeTrigger, inputMethod, interaction.resizeTrigger, interaction.inputMethod, taskInfo, currentTaskBounds.width(), currentTaskBounds.height(), displayController ) val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return val stableBounds = Rect().apply { displayLayout.getStableBounds(this) } val destinationBounds = Rect() val isMaximized = isTaskMaximized(taskInfo, stableBounds) val isMaximized = interaction.direction == ToggleTaskSizeInteraction.Direction.RESTORE // If the task is currently maximized, we will toggle it not to be and vice versa. This is // helpful to eliminate the current task from logic to calculate taskbar corner rounding. val willMaximize = !isMaximized val willMaximize = interaction.direction == ToggleTaskSizeInteraction.Direction.MAXIMIZE if (isMaximized) { unmaximizeCujRecorder?.invoke() // The desktop task is at the maximized width and/or height of the stable bounds. // If the task's pre-maximize stable bounds were saved, toggle the task to those bounds. // Otherwise, toggle to the default bounds. Loading @@ -836,7 +829,6 @@ class DesktopTasksController( } } } else { maximizeCujRecorder?.invoke() // Save current bounds so that task can be restored back to original bounds if necessary // and toggle to the stable bounds. desktopTilingDecorViewModel.removeTaskIfTiled(taskInfo.displayId, taskInfo.taskId) Loading @@ -857,10 +849,16 @@ class DesktopTasksController( taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(doesAnyTaskRequireTaskbarRounding) val wct = WindowContainerTransaction().setBounds(taskInfo.token, destinationBounds) interaction.uiEvent?.let { uiEvent -> desktopModeUiEventLogger.log(taskInfo, uiEvent) } desktopModeEventLogger.logTaskResizingEnded( resizeTrigger, inputMethod, taskInfo, destinationBounds.width(), destinationBounds.height(), displayController interaction.resizeTrigger, interaction.inputMethod, taskInfo, destinationBounds.width(), destinationBounds.height(), displayController, ) toggleResizeDesktopTaskTransitionHandler.startTransition(wct) } Loading @@ -871,10 +869,7 @@ class DesktopTasksController( currentDragBounds: Rect, motionEvent: MotionEvent ) { val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return val stableBounds = Rect() displayLayout.getStableBounds(stableBounds) if (isTaskMaximized(taskInfo, stableBounds)) { if (isTaskMaximized(taskInfo, displayController)) { // Handle the case where we attempt to drag-to-maximize when already maximized: the task // position won't need to change but we want to animate the surface going back to the // maximized position. Loading @@ -892,8 +887,11 @@ class DesktopTasksController( toggleDesktopTaskSize( taskInfo, ResizeTrigger.DRAG_TO_TOP_RESIZE_TRIGGER, DesktopModeEventLogger.getInputMethodFromMotionEvent(motionEvent), ToggleTaskSizeInteraction( direction = ToggleTaskSizeInteraction.Direction.MAXIMIZE, source = ToggleTaskSizeInteraction.Source.HEADER_DRAG_TO_TOP, inputMethod = DesktopModeEventLogger.getInputMethodFromMotionEvent(motionEvent), ) ) } Loading @@ -911,19 +909,6 @@ class DesktopTasksController( } } private fun isTaskMaximized( taskInfo: RunningTaskInfo, stableBounds: Rect ): Boolean { val currentTaskBounds = taskInfo.configuration.windowConfiguration.bounds return if (taskInfo.isResizeable) { isTaskBoundsEqual(currentTaskBounds, stableBounds) } else { isTaskWidthOrHeightEqual(currentTaskBounds, stableBounds) } } private fun isMaximizedToStableBoundsEdges( taskInfo: RunningTaskInfo, stableBounds: Rect Loading