Loading libs/WindowManager/Shell/res/values/dimen.xml +6 −0 Original line number Diff line number Diff line Loading @@ -459,6 +459,12 @@ start of this area. --> <dimen name="desktop_mode_customizable_caption_margin_end">152dp</dimen> <!-- The default minimum allowed window width when resizing a window in desktop mode. --> <dimen name="desktop_mode_minimum_window_width">386dp</dimen> <!-- The default minimum allowed window height when resizing a window in desktop mode. --> <dimen name="desktop_mode_minimum_window_height">352dp</dimen> <!-- The width of the maximize menu in desktop mode. --> <dimen name="desktop_mode_maximize_menu_width">228dp</dimen> Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java +44 −12 Original line number Diff line number Diff line Loading @@ -22,12 +22,16 @@ import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP; import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_UNDEFINED; import android.content.Context; import android.graphics.PointF; import android.graphics.Rect; import android.util.DisplayMetrics; import android.view.SurfaceControl; import com.android.window.flags.Flags; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.shared.DesktopModeStatus; /** * Utility class that contains logic common to classes implementing {@link DragPositioningCallback} Loading @@ -35,9 +39,9 @@ import com.android.wm.shell.common.DisplayController; * and applying that change to the task bounds when applicable. */ public class DragPositioningCallbackUtility { /** * Determine the delta between input's current point and the input start point. * * @param inputX current input x coordinate * @param inputY current input y coordinate * @param repositionStartPoint initial input coordinate Loading @@ -52,12 +56,13 @@ public class DragPositioningCallbackUtility { /** * Based on type of resize and delta provided, calculate the new bounds to display for this * task. * * @param ctrlType type of drag being performed * @param repositionTaskBounds the bounds the task is being repositioned to * @param taskBoundsAtDragStart the bounds of the task on the first drag input event * @param stableBounds bounds that represent the resize limit of this task * @param delta difference between start input and current input in x/y coordinates * @param displayController task's display controller * @param delta difference between start input and current input in x/y * coordinates * @param windowDecoration window decoration of the task being dragged * @return whether this method changed repositionTaskBounds */ Loading Loading @@ -142,6 +147,7 @@ public class DragPositioningCallbackUtility { /** * If task bounds are outside of provided drag area, snap the bounds to be just inside the * drag area. * * @param repositionTaskBounds bounds determined by task positioner * @param validDragArea the area that task must be positioned inside * @return whether bounds were modified Loading Loading @@ -170,18 +176,38 @@ public class DragPositioningCallbackUtility { private static float getMinWidth(DisplayController displayController, WindowDecoration windowDecoration) { return windowDecoration.mTaskInfo.minWidth < 0 ? getDefaultMinSize(displayController, return windowDecoration.mTaskInfo.minWidth < 0 ? getDefaultMinWidth(displayController, windowDecoration) : windowDecoration.mTaskInfo.minWidth; } private static float getMinHeight(DisplayController displayController, WindowDecoration windowDecoration) { return windowDecoration.mTaskInfo.minHeight < 0 ? getDefaultMinSize(displayController, return windowDecoration.mTaskInfo.minHeight < 0 ? getDefaultMinHeight(displayController, windowDecoration) : windowDecoration.mTaskInfo.minHeight; } private static float getDefaultMinWidth(DisplayController displayController, WindowDecoration windowDecoration) { if (isSizeConstraintForDesktopModeEnabled(windowDecoration.mDecorWindowContext)) { return WindowDecoration.loadDimensionPixelSize( windowDecoration.mDecorWindowContext.getResources(), R.dimen.desktop_mode_minimum_window_width); } return getDefaultMinSize(displayController, windowDecoration); } private static float getDefaultMinHeight(DisplayController displayController, WindowDecoration windowDecoration) { if (isSizeConstraintForDesktopModeEnabled(windowDecoration.mDecorWindowContext)) { return WindowDecoration.loadDimensionPixelSize( windowDecoration.mDecorWindowContext.getResources(), R.dimen.desktop_mode_minimum_window_height); } return getDefaultMinSize(displayController, windowDecoration); } private static float getDefaultMinSize(DisplayController displayController, WindowDecoration windowDecoration) { float density = displayController.getDisplayLayout(windowDecoration.mTaskInfo.displayId) Loading @@ -189,9 +215,15 @@ public class DragPositioningCallbackUtility { return windowDecoration.mTaskInfo.defaultMinSize * density; } private static boolean isSizeConstraintForDesktopModeEnabled(Context context) { return DesktopModeStatus.canEnterDesktopMode(context) && Flags.enableDesktopWindowingSizeConstraints(); } interface DragStartListener { /** * Inform the implementing class that a drag resize has started * * @param taskId id of this positioner's {@link WindowDecoration} */ void onDragStart(int taskId); Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt +138 −29 Original line number Diff line number Diff line Loading @@ -16,14 +16,20 @@ package com.android.wm.shell.windowdecor import android.app.ActivityManager import android.content.Context import android.content.res.Resources import android.graphics.PointF import android.graphics.Rect import android.os.IBinder import android.platform.test.annotations.EnableFlags import android.testing.AndroidTestingRunner import android.view.Display import android.window.WindowContainerToken import com.android.window.flags.Flags import com.android.wm.shell.R import com.android.wm.shell.common.DisplayController import com.android.wm.shell.common.DisplayLayout import com.android.wm.shell.shared.DesktopModeStatus import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP Loading @@ -33,8 +39,8 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.`when` as whenever import org.mockito.Mockito.any import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations /** Loading @@ -57,6 +63,10 @@ class DragPositioningCallbackUtilityTest { private lateinit var mockDisplayLayout: DisplayLayout @Mock private lateinit var mockDisplay: Display @Mock private lateinit var mockContext: Context @Mock private lateinit var mockResources: Resources @Before fun setup() { Loading @@ -69,16 +79,15 @@ class DragPositioningCallbackUtilityTest { (i.arguments.first() as Rect).set(STABLE_BOUNDS) } mockWindowDecoration.mTaskInfo = ActivityManager.RunningTaskInfo().apply { taskId = TASK_ID token = taskToken minWidth = MIN_WIDTH minHeight = MIN_HEIGHT defaultMinSize = DEFAULT_MIN displayId = DISPLAY_ID configuration.windowConfiguration.setBounds(STARTING_BOUNDS) } initializeTaskInfo() mockWindowDecoration.mDisplay = mockDisplay mockWindowDecoration.mDecorWindowContext = mockContext whenever(mockContext.getResources()).thenReturn(mockResources) whenever(mockWindowDecoration.mDecorWindowContext.resources).thenReturn(mockResources) whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_width)) .thenReturn(DESKTOP_MODE_MIN_WIDTH) whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_height)) .thenReturn(DESKTOP_MODE_MIN_HEIGHT) whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID } } Loading @@ -93,8 +102,8 @@ class DragPositioningCallbackUtilityTest { val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) Loading @@ -113,8 +122,8 @@ class DragPositioningCallbackUtilityTest { val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top + 5) Loading @@ -127,14 +136,14 @@ class DragPositioningCallbackUtilityTest { val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.top.toFloat()) val repositionTaskBounds = Rect(STARTING_BOUNDS) // Resize to width of 95px and width of -5px with minimum of 10px // Resize to width of 95px and height of -5px with minimum of 10px val newX = STARTING_BOUNDS.right.toFloat() - 5 val newY = STARTING_BOUNDS.top.toFloat() + 105 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) Loading @@ -153,8 +162,8 @@ class DragPositioningCallbackUtilityTest { val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top + 80) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 80) Loading @@ -172,8 +181,8 @@ class DragPositioningCallbackUtilityTest { val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right) Loading Loading @@ -203,7 +212,6 @@ class DragPositioningCallbackUtilityTest { @Test fun testChangeBounds_toDisallowedBounds_freezesAtLimit() { var hasMoved = false val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat()) val repositionTaskBounds = Rect(STARTING_BOUNDS) Loading @@ -212,26 +220,127 @@ class DragPositioningCallbackUtilityTest { var newY = STARTING_BOUNDS.bottom.toFloat() + 10 var delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) assertTrue(DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration)) hasMoved = true repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration)) // Resize width to 120px, height to disallowed area which should not result in a change. newX += 10 newY = DISALLOWED_RESIZE_AREA.top.toFloat() delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) assertTrue(DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration)) repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration)) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right + 20) assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom + 10) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS) fun taskMinWidthHeightUndefined_changeBoundsInDesktopModeLessThanMin_shouldNotChangeBounds() { whenever(DesktopModeStatus.canEnterDesktopMode(mockContext)).thenReturn(true) initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1) val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat()) val repositionTaskBounds = Rect(STARTING_BOUNDS) // Shrink height and width to 1px. The default allowed width and height are defined in // R.dimen.desktop_mode_minimum_window_width and R.dimen.desktop_mode_minimum_window_height val newX = STARTING_BOUNDS.right.toFloat() - 99 val newY = STARTING_BOUNDS.bottom.toFloat() - 99 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right) assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS) fun taskMinWidthHeightUndefined_changeBoundsInDesktopModeAllowedSize_shouldChangeBounds() { whenever(DesktopModeStatus.canEnterDesktopMode(mockContext)).thenReturn(true) initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1) val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat()) val repositionTaskBounds = Rect(STARTING_BOUNDS) // Shrink height and width to 20px. The default allowed width and height are defined in // R.dimen.desktop_mode_minimum_window_width and R.dimen.desktop_mode_minimum_window_height val newX = STARTING_BOUNDS.right.toFloat() - 80 val newY = STARTING_BOUNDS.bottom.toFloat() - 80 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 80) assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom - 80) } @Test fun taskMinWidthHeightUndefined_changeBoundsLessThanDefaultMinSize_shouldNotChangeBounds() { initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1) val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat()) val repositionTaskBounds = Rect(STARTING_BOUNDS) // Shrink height and width to 1px. The default allowed width and height are defined in the // defaultMinSize of the TaskInfo. val newX = STARTING_BOUNDS.right.toFloat() - 99 val newY = STARTING_BOUNDS.bottom.toFloat() - 99 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right) assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom) } @Test fun taskMinWidthHeightUndefined_changeBoundsToAnAllowedSize_shouldChangeBounds() { initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1) val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat()) val repositionTaskBounds = Rect(STARTING_BOUNDS) // Shrink height and width to 50px. The default allowed width and height are defined in the // defaultMinSize of the TaskInfo. val newX = STARTING_BOUNDS.right.toFloat() - 50 val newY = STARTING_BOUNDS.bottom.toFloat() - 50 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 50) assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom - 50) } private fun initializeTaskInfo(taskMinWidth: Int = MIN_WIDTH, taskMinHeight: Int = MIN_HEIGHT) { mockWindowDecoration.mTaskInfo = ActivityManager.RunningTaskInfo().apply { taskId = TASK_ID token = taskToken minWidth = taskMinWidth minHeight = taskMinHeight defaultMinSize = DEFAULT_MIN displayId = DISPLAY_ID configuration.windowConfiguration.setBounds(STARTING_BOUNDS) } } companion object { private const val TASK_ID = 5 private const val MIN_WIDTH = 10 private const val MIN_HEIGHT = 10 private const val DESKTOP_MODE_MIN_WIDTH = 20 private const val DESKTOP_MODE_MIN_HEIGHT = 20 private const val DENSITY_DPI = 20 private const val DEFAULT_MIN = 40 private const val DISPLAY_ID = 1 Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt +15 −1 Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ package com.android.wm.shell.windowdecor import android.app.ActivityManager import android.app.WindowConfiguration import android.content.Context import android.content.res.Resources import android.graphics.Point import android.graphics.Rect import android.os.IBinder Loading @@ -17,6 +19,7 @@ import android.window.WindowContainerToken import android.window.WindowContainerTransaction import android.window.WindowContainerTransaction.Change.CHANGE_DRAG_RESIZING import androidx.test.filters.SmallTest import com.android.wm.shell.R import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase import com.android.wm.shell.common.DisplayController Loading Loading @@ -83,7 +86,10 @@ class FluidResizeTaskPositionerTest : ShellTestCase() { private lateinit var mockTransaction: SurfaceControl.Transaction @Mock private lateinit var mockTransitionBinder: IBinder @Mock private lateinit var mockContext: Context @Mock private lateinit var mockResources: Resources private lateinit var taskPositioner: FluidResizeTaskPositioner @Before Loading Loading @@ -119,6 +125,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() { } `when`(mockWindowDecoration.calculateValidDragArea()).thenReturn(VALID_DRAG_AREA) mockWindowDecoration.mDisplay = mockDisplay mockWindowDecoration.mDecorWindowContext = mockContext whenever(mockWindowDecoration.mDecorWindowContext.resources).thenReturn(mockResources) whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_width)) .thenReturn(DESKTOP_MODE_MIN_WIDTH) whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_height)) .thenReturn(DESKTOP_MODE_MIN_HEIGHT) whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID } whenever(mockTransitions.startTransition(anyInt(), any(), any())) .doReturn(mockTransitionBinder) Loading Loading @@ -788,6 +800,8 @@ class FluidResizeTaskPositionerTest : ShellTestCase() { private const val TASK_ID = 5 private const val MIN_WIDTH = 10 private const val MIN_HEIGHT = 10 private const val DESKTOP_MODE_MIN_WIDTH = 20 private const val DESKTOP_MODE_MIN_HEIGHT = 20 private const val DENSITY_DPI = 20 private const val DEFAULT_MIN = 40 private const val DISPLAY_ID = 1 Loading Loading
libs/WindowManager/Shell/res/values/dimen.xml +6 −0 Original line number Diff line number Diff line Loading @@ -459,6 +459,12 @@ start of this area. --> <dimen name="desktop_mode_customizable_caption_margin_end">152dp</dimen> <!-- The default minimum allowed window width when resizing a window in desktop mode. --> <dimen name="desktop_mode_minimum_window_width">386dp</dimen> <!-- The default minimum allowed window height when resizing a window in desktop mode. --> <dimen name="desktop_mode_minimum_window_height">352dp</dimen> <!-- The width of the maximize menu in desktop mode. --> <dimen name="desktop_mode_maximize_menu_width">228dp</dimen> Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java +44 −12 Original line number Diff line number Diff line Loading @@ -22,12 +22,16 @@ import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP; import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_UNDEFINED; import android.content.Context; import android.graphics.PointF; import android.graphics.Rect; import android.util.DisplayMetrics; import android.view.SurfaceControl; import com.android.window.flags.Flags; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.shared.DesktopModeStatus; /** * Utility class that contains logic common to classes implementing {@link DragPositioningCallback} Loading @@ -35,9 +39,9 @@ import com.android.wm.shell.common.DisplayController; * and applying that change to the task bounds when applicable. */ public class DragPositioningCallbackUtility { /** * Determine the delta between input's current point and the input start point. * * @param inputX current input x coordinate * @param inputY current input y coordinate * @param repositionStartPoint initial input coordinate Loading @@ -52,12 +56,13 @@ public class DragPositioningCallbackUtility { /** * Based on type of resize and delta provided, calculate the new bounds to display for this * task. * * @param ctrlType type of drag being performed * @param repositionTaskBounds the bounds the task is being repositioned to * @param taskBoundsAtDragStart the bounds of the task on the first drag input event * @param stableBounds bounds that represent the resize limit of this task * @param delta difference between start input and current input in x/y coordinates * @param displayController task's display controller * @param delta difference between start input and current input in x/y * coordinates * @param windowDecoration window decoration of the task being dragged * @return whether this method changed repositionTaskBounds */ Loading Loading @@ -142,6 +147,7 @@ public class DragPositioningCallbackUtility { /** * If task bounds are outside of provided drag area, snap the bounds to be just inside the * drag area. * * @param repositionTaskBounds bounds determined by task positioner * @param validDragArea the area that task must be positioned inside * @return whether bounds were modified Loading Loading @@ -170,18 +176,38 @@ public class DragPositioningCallbackUtility { private static float getMinWidth(DisplayController displayController, WindowDecoration windowDecoration) { return windowDecoration.mTaskInfo.minWidth < 0 ? getDefaultMinSize(displayController, return windowDecoration.mTaskInfo.minWidth < 0 ? getDefaultMinWidth(displayController, windowDecoration) : windowDecoration.mTaskInfo.minWidth; } private static float getMinHeight(DisplayController displayController, WindowDecoration windowDecoration) { return windowDecoration.mTaskInfo.minHeight < 0 ? getDefaultMinSize(displayController, return windowDecoration.mTaskInfo.minHeight < 0 ? getDefaultMinHeight(displayController, windowDecoration) : windowDecoration.mTaskInfo.minHeight; } private static float getDefaultMinWidth(DisplayController displayController, WindowDecoration windowDecoration) { if (isSizeConstraintForDesktopModeEnabled(windowDecoration.mDecorWindowContext)) { return WindowDecoration.loadDimensionPixelSize( windowDecoration.mDecorWindowContext.getResources(), R.dimen.desktop_mode_minimum_window_width); } return getDefaultMinSize(displayController, windowDecoration); } private static float getDefaultMinHeight(DisplayController displayController, WindowDecoration windowDecoration) { if (isSizeConstraintForDesktopModeEnabled(windowDecoration.mDecorWindowContext)) { return WindowDecoration.loadDimensionPixelSize( windowDecoration.mDecorWindowContext.getResources(), R.dimen.desktop_mode_minimum_window_height); } return getDefaultMinSize(displayController, windowDecoration); } private static float getDefaultMinSize(DisplayController displayController, WindowDecoration windowDecoration) { float density = displayController.getDisplayLayout(windowDecoration.mTaskInfo.displayId) Loading @@ -189,9 +215,15 @@ public class DragPositioningCallbackUtility { return windowDecoration.mTaskInfo.defaultMinSize * density; } private static boolean isSizeConstraintForDesktopModeEnabled(Context context) { return DesktopModeStatus.canEnterDesktopMode(context) && Flags.enableDesktopWindowingSizeConstraints(); } interface DragStartListener { /** * Inform the implementing class that a drag resize has started * * @param taskId id of this positioner's {@link WindowDecoration} */ void onDragStart(int taskId); Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtilityTest.kt +138 −29 Original line number Diff line number Diff line Loading @@ -16,14 +16,20 @@ package com.android.wm.shell.windowdecor import android.app.ActivityManager import android.content.Context import android.content.res.Resources import android.graphics.PointF import android.graphics.Rect import android.os.IBinder import android.platform.test.annotations.EnableFlags import android.testing.AndroidTestingRunner import android.view.Display import android.window.WindowContainerToken import com.android.window.flags.Flags import com.android.wm.shell.R import com.android.wm.shell.common.DisplayController import com.android.wm.shell.common.DisplayLayout import com.android.wm.shell.shared.DesktopModeStatus import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP Loading @@ -33,8 +39,8 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.`when` as whenever import org.mockito.Mockito.any import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations /** Loading @@ -57,6 +63,10 @@ class DragPositioningCallbackUtilityTest { private lateinit var mockDisplayLayout: DisplayLayout @Mock private lateinit var mockDisplay: Display @Mock private lateinit var mockContext: Context @Mock private lateinit var mockResources: Resources @Before fun setup() { Loading @@ -69,16 +79,15 @@ class DragPositioningCallbackUtilityTest { (i.arguments.first() as Rect).set(STABLE_BOUNDS) } mockWindowDecoration.mTaskInfo = ActivityManager.RunningTaskInfo().apply { taskId = TASK_ID token = taskToken minWidth = MIN_WIDTH minHeight = MIN_HEIGHT defaultMinSize = DEFAULT_MIN displayId = DISPLAY_ID configuration.windowConfiguration.setBounds(STARTING_BOUNDS) } initializeTaskInfo() mockWindowDecoration.mDisplay = mockDisplay mockWindowDecoration.mDecorWindowContext = mockContext whenever(mockContext.getResources()).thenReturn(mockResources) whenever(mockWindowDecoration.mDecorWindowContext.resources).thenReturn(mockResources) whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_width)) .thenReturn(DESKTOP_MODE_MIN_WIDTH) whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_height)) .thenReturn(DESKTOP_MODE_MIN_HEIGHT) whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID } } Loading @@ -93,8 +102,8 @@ class DragPositioningCallbackUtilityTest { val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) Loading @@ -113,8 +122,8 @@ class DragPositioningCallbackUtilityTest { val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top + 5) Loading @@ -127,14 +136,14 @@ class DragPositioningCallbackUtilityTest { val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.top.toFloat()) val repositionTaskBounds = Rect(STARTING_BOUNDS) // Resize to width of 95px and width of -5px with minimum of 10px // Resize to width of 95px and height of -5px with minimum of 10px val newX = STARTING_BOUNDS.right.toFloat() - 5 val newY = STARTING_BOUNDS.top.toFloat() + 105 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) Loading @@ -153,8 +162,8 @@ class DragPositioningCallbackUtilityTest { val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top + 80) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 80) Loading @@ -172,8 +181,8 @@ class DragPositioningCallbackUtilityTest { val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_TOP, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right) Loading Loading @@ -203,7 +212,6 @@ class DragPositioningCallbackUtilityTest { @Test fun testChangeBounds_toDisallowedBounds_freezesAtLimit() { var hasMoved = false val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat()) val repositionTaskBounds = Rect(STARTING_BOUNDS) Loading @@ -212,26 +220,127 @@ class DragPositioningCallbackUtilityTest { var newY = STARTING_BOUNDS.bottom.toFloat() + 10 var delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) assertTrue(DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration)) hasMoved = true repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration)) // Resize width to 120px, height to disallowed area which should not result in a change. newX += 10 newY = DISALLOWED_RESIZE_AREA.top.toFloat() delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) assertTrue(DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration)) repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration)) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right + 20) assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom + 10) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS) fun taskMinWidthHeightUndefined_changeBoundsInDesktopModeLessThanMin_shouldNotChangeBounds() { whenever(DesktopModeStatus.canEnterDesktopMode(mockContext)).thenReturn(true) initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1) val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat()) val repositionTaskBounds = Rect(STARTING_BOUNDS) // Shrink height and width to 1px. The default allowed width and height are defined in // R.dimen.desktop_mode_minimum_window_width and R.dimen.desktop_mode_minimum_window_height val newX = STARTING_BOUNDS.right.toFloat() - 99 val newY = STARTING_BOUNDS.bottom.toFloat() - 99 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right) assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom) } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS) fun taskMinWidthHeightUndefined_changeBoundsInDesktopModeAllowedSize_shouldChangeBounds() { whenever(DesktopModeStatus.canEnterDesktopMode(mockContext)).thenReturn(true) initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1) val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat()) val repositionTaskBounds = Rect(STARTING_BOUNDS) // Shrink height and width to 20px. The default allowed width and height are defined in // R.dimen.desktop_mode_minimum_window_width and R.dimen.desktop_mode_minimum_window_height val newX = STARTING_BOUNDS.right.toFloat() - 80 val newY = STARTING_BOUNDS.bottom.toFloat() - 80 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 80) assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom - 80) } @Test fun taskMinWidthHeightUndefined_changeBoundsLessThanDefaultMinSize_shouldNotChangeBounds() { initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1) val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat()) val repositionTaskBounds = Rect(STARTING_BOUNDS) // Shrink height and width to 1px. The default allowed width and height are defined in the // defaultMinSize of the TaskInfo. val newX = STARTING_BOUNDS.right.toFloat() - 99 val newY = STARTING_BOUNDS.bottom.toFloat() - 99 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right) assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom) } @Test fun taskMinWidthHeightUndefined_changeBoundsToAnAllowedSize_shouldChangeBounds() { initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1) val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat()) val repositionTaskBounds = Rect(STARTING_BOUNDS) // Shrink height and width to 50px. The default allowed width and height are defined in the // defaultMinSize of the TaskInfo. val newX = STARTING_BOUNDS.right.toFloat() - 50 val newY = STARTING_BOUNDS.bottom.toFloat() - 50 val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint) DragPositioningCallbackUtility.changeBounds(CTRL_TYPE_RIGHT or CTRL_TYPE_BOTTOM, repositionTaskBounds, STARTING_BOUNDS, STABLE_BOUNDS, delta, mockDisplayController, mockWindowDecoration) assertThat(repositionTaskBounds.left).isEqualTo(STARTING_BOUNDS.left) assertThat(repositionTaskBounds.top).isEqualTo(STARTING_BOUNDS.top) assertThat(repositionTaskBounds.right).isEqualTo(STARTING_BOUNDS.right - 50) assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom - 50) } private fun initializeTaskInfo(taskMinWidth: Int = MIN_WIDTH, taskMinHeight: Int = MIN_HEIGHT) { mockWindowDecoration.mTaskInfo = ActivityManager.RunningTaskInfo().apply { taskId = TASK_ID token = taskToken minWidth = taskMinWidth minHeight = taskMinHeight defaultMinSize = DEFAULT_MIN displayId = DISPLAY_ID configuration.windowConfiguration.setBounds(STARTING_BOUNDS) } } companion object { private const val TASK_ID = 5 private const val MIN_WIDTH = 10 private const val MIN_HEIGHT = 10 private const val DESKTOP_MODE_MIN_WIDTH = 20 private const val DESKTOP_MODE_MIN_HEIGHT = 20 private const val DENSITY_DPI = 20 private const val DEFAULT_MIN = 40 private const val DISPLAY_ID = 1 Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt +15 −1 Original line number Diff line number Diff line Loading @@ -2,6 +2,8 @@ package com.android.wm.shell.windowdecor import android.app.ActivityManager import android.app.WindowConfiguration import android.content.Context import android.content.res.Resources import android.graphics.Point import android.graphics.Rect import android.os.IBinder Loading @@ -17,6 +19,7 @@ import android.window.WindowContainerToken import android.window.WindowContainerTransaction import android.window.WindowContainerTransaction.Change.CHANGE_DRAG_RESIZING import androidx.test.filters.SmallTest import com.android.wm.shell.R import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase import com.android.wm.shell.common.DisplayController Loading Loading @@ -83,7 +86,10 @@ class FluidResizeTaskPositionerTest : ShellTestCase() { private lateinit var mockTransaction: SurfaceControl.Transaction @Mock private lateinit var mockTransitionBinder: IBinder @Mock private lateinit var mockContext: Context @Mock private lateinit var mockResources: Resources private lateinit var taskPositioner: FluidResizeTaskPositioner @Before Loading Loading @@ -119,6 +125,12 @@ class FluidResizeTaskPositionerTest : ShellTestCase() { } `when`(mockWindowDecoration.calculateValidDragArea()).thenReturn(VALID_DRAG_AREA) mockWindowDecoration.mDisplay = mockDisplay mockWindowDecoration.mDecorWindowContext = mockContext whenever(mockWindowDecoration.mDecorWindowContext.resources).thenReturn(mockResources) whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_width)) .thenReturn(DESKTOP_MODE_MIN_WIDTH) whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_height)) .thenReturn(DESKTOP_MODE_MIN_HEIGHT) whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID } whenever(mockTransitions.startTransition(anyInt(), any(), any())) .doReturn(mockTransitionBinder) Loading Loading @@ -788,6 +800,8 @@ class FluidResizeTaskPositionerTest : ShellTestCase() { private const val TASK_ID = 5 private const val MIN_WIDTH = 10 private const val MIN_HEIGHT = 10 private const val DESKTOP_MODE_MIN_WIDTH = 20 private const val DESKTOP_MODE_MIN_HEIGHT = 20 private const val DENSITY_DPI = 20 private const val DEFAULT_MIN = 40 private const val DISPLAY_ID = 1 Loading