Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8cc0a3c authored by Eghosa Ewansiha-Vlachavas's avatar Eghosa Ewansiha-Vlachavas
Browse files

Maintain aspect ratio in DragPositioningCallbackUtility.changeBounds()

Adjusting one side of an unresizeable app without also adjusted a
adjacent edge in proportion will cause the aspect ratio of the bounds to
change. To prevent the aspect ratio of unresizeable apps being modified,
opt to reset all coordinates to their previous valid state if at least
one of the coordinates needs adjusting due to constraints.

Flag: com.android.window.flags.enable_windowing_scaled_resizing
Fix: 366424454
Test: atest WMShellUnitTests:DragPositioningCallbackUtilityTest
Test: atest WMShellUnitTests:VeiledResizeTaskPositionerTest
Test: atest WMShellUnitTests:FluidResizeTaskPositionerTest
Change-Id: I4959f3a9a725e619bb620f00cc383e939a173e79
parent bad2c984
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -84,22 +84,47 @@ public class DragPositioningCallbackUtility {

        repositionTaskBounds.set(taskBoundsAtDragStart);

        boolean isAspectRatioMaintained = true;
        // Make sure the new resizing destination in any direction falls within the stable bounds.
        if ((ctrlType & CTRL_TYPE_LEFT) != 0) {
            repositionTaskBounds.left = Math.max(repositionTaskBounds.left + (int) delta.x,
                    stableBounds.left);
            if (repositionTaskBounds.left == stableBounds.left
                    && repositionTaskBounds.left + (int) delta.x != stableBounds.left) {
                // If the task edge have been set to the stable bounds and not due to the users
                // drag, the aspect ratio of the task will not be maintained.
                isAspectRatioMaintained = false;
            }
        }
        if ((ctrlType & CTRL_TYPE_RIGHT) != 0) {
            repositionTaskBounds.right = Math.min(repositionTaskBounds.right + (int) delta.x,
                    stableBounds.right);
            if (repositionTaskBounds.right == stableBounds.right
                    && repositionTaskBounds.right + (int) delta.x != stableBounds.right) {
                // If the task edge have been set to the stable bounds and not due to the users
                // drag, the aspect ratio of the task will not be maintained.
                isAspectRatioMaintained = false;
            }
        }
        if ((ctrlType & CTRL_TYPE_TOP) != 0) {
            repositionTaskBounds.top = Math.max(repositionTaskBounds.top + (int) delta.y,
                    stableBounds.top);
            if (repositionTaskBounds.top == stableBounds.top
                    && repositionTaskBounds.top + (int) delta.y != stableBounds.top) {
                // If the task edge have been set to the stable bounds and not due to the users
                // drag, the aspect ratio of the task will not be maintained.
                isAspectRatioMaintained = false;
            }
        }
        if ((ctrlType & CTRL_TYPE_BOTTOM) != 0) {
            repositionTaskBounds.bottom = Math.min(repositionTaskBounds.bottom + (int) delta.y,
                    stableBounds.bottom);
            if (repositionTaskBounds.bottom == stableBounds.bottom
                    && repositionTaskBounds.bottom + (int) delta.y != stableBounds.bottom) {
                // If the task edge have been set to the stable bounds and not due to the users
                // drag, the aspect ratio of the task will not be maintained.
                isAspectRatioMaintained = false;
            }
        }

        // If width or height are negative or exceeding the width or height constraints, revert the
@@ -108,11 +133,24 @@ public class DragPositioningCallbackUtility {
                windowDecoration)) {
            repositionTaskBounds.right = oldRight;
            repositionTaskBounds.left = oldLeft;
            isAspectRatioMaintained = false;
        }
        if (isExceedingHeightConstraint(repositionTaskBounds, stableBounds, displayController,
                windowDecoration)) {
            repositionTaskBounds.top = oldTop;
            repositionTaskBounds.bottom = oldBottom;
            isAspectRatioMaintained = false;
        }

        // If the application is unresizeable and any bounds have been set back to their old
        // location or to a stable bound edge, reset all the bounds to maintain the applications
        // aspect ratio.
        if (DesktopModeFlags.SCALED_RESIZING.isEnabled(windowDecoration.mDecorWindowContext)
                && !isAspectRatioMaintained && !windowDecoration.mTaskInfo.isResizeable) {
            repositionTaskBounds.top = oldTop;
            repositionTaskBounds.bottom = oldBottom;
            repositionTaskBounds.right = oldRight;
            repositionTaskBounds.left = oldLeft;
        }

        // If there are no changes to the bounds after checking new bounds against minimum and
+84 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ 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
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import org.junit.After
import org.junit.Before
@@ -105,6 +106,7 @@ class DragPositioningCallbackUtilityTest {
        initializeTaskInfo()
        mockWindowDecoration.mDisplay = mockDisplay
        mockWindowDecoration.mDecorWindowContext = mockContext
        mockWindowDecoration.mTaskInfo.isResizeable = true
        whenever(mockContext.getResources()).thenReturn(mockResources)
        whenever(mockWindowDecoration.mDecorWindowContext.resources).thenReturn(mockResources)
        whenever(mockResources.getDimensionPixelSize(R.dimen.desktop_mode_minimum_window_width))
@@ -163,6 +165,60 @@ class DragPositioningCallbackUtilityTest {
        assertThat(repositionTaskBounds.bottom).isEqualTo(STARTING_BOUNDS.bottom)
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_SCALED_RESIZING)
    fun testChangeBounds_unresizeableApp_heightLessThanMin_resetToStartingBounds() {
        mockWindowDecoration.mTaskInfo.isResizeable = false
        val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.top.toFloat())
        val repositionTaskBounds = Rect(STARTING_BOUNDS)

        // Resize to width of 95px and height of 5px with min width of 10px
        val newX = STARTING_BOUNDS.right.toFloat() - 5
        val newY = STARTING_BOUNDS.top.toFloat() + 95
        val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)

        assertFalse(
            DragPositioningCallbackUtility.changeBounds(
                CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
                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_WINDOWING_SCALED_RESIZING)
    fun testChangeBounds_unresizeableApp_widthLessThanMin_resetToStartingBounds() {
        mockWindowDecoration.mTaskInfo.isResizeable = false
        val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.top.toFloat())
        val repositionTaskBounds = Rect(STARTING_BOUNDS)

        // Resize to height of 95px and width of 5px with min width of 10px
        val newX = STARTING_BOUNDS.right.toFloat() - 95
        val newY = STARTING_BOUNDS.top.toFloat() + 5
        val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)

        assertFalse(
            DragPositioningCallbackUtility.changeBounds(
                CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
                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 testChangeBoundsDoesNotChangeHeightWhenNegative() {
        val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.top.toFloat())
@@ -316,6 +372,34 @@ class DragPositioningCallbackUtilityTest {
        assertThat(repositionTaskBounds.bottom).isEqualTo(STABLE_BOUNDS.bottom)
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_SCALED_RESIZING)
    fun testChangeBounds_unresizeableApp_beyondStableBounds_resetToStartingBounds() {
        mockWindowDecoration.mTaskInfo.isResizeable = false
        val startingPoint = PointF(
            STARTING_BOUNDS.right.toFloat(),
            STARTING_BOUNDS.bottom.toFloat()
        )
        val repositionTaskBounds = Rect(STARTING_BOUNDS)

        // Resize to beyond stable bounds.
        val newX = STARTING_BOUNDS.right.toFloat() + STABLE_BOUNDS.width()
        val newY = STARTING_BOUNDS.bottom.toFloat() + STABLE_BOUNDS.height()

        val delta = DragPositioningCallbackUtility.calculateDelta(newX, newY, startingPoint)
        assertFalse(
            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_changeBoundsInDesktopModeLessThanMin_shouldNotChangeBounds() {
+1 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ class FluidResizeTaskPositionerTest : ShellTestCase() {
            displayId = DISPLAY_ID
            configuration.windowConfiguration.setBounds(STARTING_BOUNDS)
            configuration.windowConfiguration.displayRotation = ROTATION_90
            isResizeable = true
        }
        `when`(mockWindowDecoration.calculateValidDragArea()).thenReturn(VALID_DRAG_AREA)
        mockWindowDecoration.mDisplay = mockDisplay
+1 −0
Original line number Diff line number Diff line
@@ -141,6 +141,7 @@ class VeiledResizeTaskPositionerTest : ShellTestCase() {
            displayId = DISPLAY_ID
            configuration.windowConfiguration.setBounds(STARTING_BOUNDS)
            configuration.windowConfiguration.displayRotation = ROTATION_90
            isResizeable = true
        }
        `when`(mockDesktopWindowDecoration.calculateValidDragArea()).thenReturn(VALID_DRAG_AREA)
        mockDesktopWindowDecoration.mDisplay = mockDisplay