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

Commit bf7c62bc authored by Daniel Akinola's avatar Daniel Akinola Committed by Android (Google) Code Review
Browse files

Merge "Animate task surface when attempting to snap resize from currently snap...

Merge "Animate task surface when attempting to snap resize from currently snap resized bounds" into main
parents e43ecab3 69aee985
Loading
Loading
Loading
Loading
+20 −3
Original line number Diff line number Diff line
@@ -734,17 +734,33 @@ class DesktopTasksController(
     * Quick-resize to the right or left half of the stable bounds.
     *
     * @param taskInfo current task that is being snap-resized via dragging or maximize menu button
     * @param taskSurface the leash of the task being dragged
     * @param currentDragBounds current position of the task leash being dragged (or current task
     *                          bounds if being snapped resize via maximize menu button)
     * @param position the portion of the screen (RIGHT or LEFT) we want to snap the task to.
     */
    fun snapToHalfScreen(
        taskInfo: RunningTaskInfo,
        taskSurface: SurfaceControl,
        currentDragBounds: Rect,
        position: SnapPosition
    ) {
        val destinationBounds = getSnapBounds(taskInfo, position)
        if (destinationBounds == taskInfo.configuration.windowConfiguration.bounds) return
        if (destinationBounds == taskInfo.configuration.windowConfiguration.bounds) {
            // Handle the case where we attempt to snap resize when already snap resized: the task
            // position won't need to change but we want to animate the surface going back to the
            // snapped position from the "dragged-to-the-edge" position.
            if (destinationBounds != currentDragBounds) {
                returnToDragStartAnimator.start(
                    taskInfo.taskId,
                    taskSurface,
                    startBounds = currentDragBounds,
                    endBounds = destinationBounds,
                    isResizable = taskInfo.isResizeable
                )
            }
            return
        }

        taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(true)
        val wct = WindowContainerTransaction().setBounds(taskInfo.token, destinationBounds)
@@ -774,13 +790,14 @@ class DesktopTasksController(
                taskInfo.taskId,
                taskSurface,
                startBounds = currentDragBounds,
                endBounds = dragStartBounds
                endBounds = dragStartBounds,
                isResizable = taskInfo.isResizeable,
            )
        } else {
            interactionJankMonitor.begin(
                taskSurface, context, CUJ_DESKTOP_MODE_SNAP_RESIZE, "drag_resizable"
            )
            snapToHalfScreen(taskInfo, currentDragBounds, position)
            snapToHalfScreen(taskInfo, taskSurface, currentDragBounds, position)
        }
    }

+14 −6
Original line number Diff line number Diff line
@@ -48,7 +48,13 @@ class ReturnToDragStartAnimator(
    }

    /** Builds new animator and starts animation of task leash reposition. */
    fun start(taskId: Int, taskSurface: SurfaceControl, startBounds: Rect, endBounds: Rect) {
    fun start(
        taskId: Int,
        taskSurface: SurfaceControl,
        startBounds: Rect,
        endBounds: Rect,
        isResizable: Boolean
    ) {
        val tx = transactionSupplier.get()

        boundsAnimator?.cancel()
@@ -81,11 +87,13 @@ class ReturnToDragStartAnimator(
                                .apply()
                            taskRepositionAnimationListener.onAnimationEnd(taskId)
                            boundsAnimator = null
                            if (!isResizable) {
                                Toast.makeText(
                                    context,
                                    R.string.desktop_mode_non_resizable_snap_text,
                                    Toast.LENGTH_SHORT
                                ).show()
                            }
                            interactionJankMonitor.end(Cuj.CUJ_DESKTOP_MODE_SNAP_RESIZE)
                        }
                    )
+3 −1
Original line number Diff line number Diff line
@@ -491,7 +491,9 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
        } else {
            mInteractionJankMonitor.begin(decoration.mTaskSurface, mContext,
                    Cuj.CUJ_DESKTOP_MODE_SNAP_RESIZE, "maximize_menu_resizable");
            mDesktopTasksController.snapToHalfScreen(decoration.mTaskInfo,
            mDesktopTasksController.snapToHalfScreen(
                    decoration.mTaskInfo,
                    decoration.mTaskSurface,
                    decoration.mTaskInfo.configuration.windowConfiguration.getBounds(),
                    left ? SnapPosition.LEFT : SnapPosition.RIGHT);
        }
+37 −4
Original line number Diff line number Diff line
@@ -123,12 +123,12 @@ import org.mockito.ArgumentMatchers.isA
import org.mockito.ArgumentMatchers.isNull
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.any
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.mock
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.kotlin.any
import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.atLeastOnce
import org.mockito.kotlin.eq
@@ -2859,7 +2859,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
  }

  @Test
  fun getSnapBounds_calculatesBoundsForResizable() {
  fun snapToHalfScreen_getSnapBounds_calculatesBoundsForResizable() {
    val bounds = Rect(100, 100, 300, 300)
    val task = setUpFreeformTask(DEFAULT_DISPLAY, bounds).apply {
      topActivityInfo = ActivityInfo().apply {
@@ -2874,12 +2874,44 @@ class DesktopTasksControllerTest : ShellTestCase() {
      STABLE_BOUNDS.left, STABLE_BOUNDS.top, STABLE_BOUNDS.right / 2, STABLE_BOUNDS.bottom
    )

    controller.snapToHalfScreen(task, currentDragBounds, SnapPosition.LEFT)
    controller.snapToHalfScreen(task, mockSurface, currentDragBounds, SnapPosition.LEFT)
    // Assert bounds set to stable bounds
    val wct = getLatestToggleResizeDesktopTaskWct(currentDragBounds)
    assertThat(findBoundsChange(wct, task)).isEqualTo(expectedBounds)
  }

  @Test
  fun snapToHalfScreen_snapBoundsWhenAlreadySnapped_animatesSurfaceWithoutWCT() {
    assumeTrue(ENABLE_SHELL_TRANSITIONS)
    // Set up task to already be in snapped-left bounds
    val bounds = Rect(
      STABLE_BOUNDS.left, STABLE_BOUNDS.top, STABLE_BOUNDS.right / 2, STABLE_BOUNDS.bottom
    )
    val task = setUpFreeformTask(DEFAULT_DISPLAY, bounds).apply {
      topActivityInfo = ActivityInfo().apply {
        screenOrientation = SCREEN_ORIENTATION_LANDSCAPE
        configuration.windowConfiguration.appBounds = bounds
      }
      isResizeable = true
    }

    // Attempt to snap left again
    val currentDragBounds = Rect(bounds).apply { offset(-100, 0) }
    controller.snapToHalfScreen(task, mockSurface, currentDragBounds, SnapPosition.LEFT)

    // Assert that task is NOT updated via WCT
    verify(toggleResizeDesktopTaskTransitionHandler, never()).startTransition(any(), any())

    // Assert that task leash is updated via Surface Animations
    verify(mReturnToDragStartAnimator).start(
      eq(task.taskId),
      eq(mockSurface),
      eq(currentDragBounds),
      eq(bounds),
      eq(true)
    )
  }

  @Test
  @DisableFlags(Flags.FLAG_DISABLE_NON_RESIZABLE_APP_SNAP_RESIZING)
  fun handleSnapResizingTask_nonResizable_snapsToHalfScreen() {
@@ -2911,7 +2943,8 @@ class DesktopTasksControllerTest : ShellTestCase() {
      eq(task.taskId),
      eq(mockSurface),
      eq(currentDragBounds),
      eq(preDragBounds)
      eq(preDragBounds),
      eq(false)
    )
  }

+37 −12
Original line number Diff line number Diff line
@@ -113,7 +113,7 @@ import org.mockito.Mockito.anyInt
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.kotlin.verify
import org.mockito.kotlin.any
import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.argThat
@@ -600,6 +600,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {

    @Test
    fun testOnDecorSnappedLeft_snapResizes() {
        val taskSurfaceCaptor = argumentCaptor<SurfaceControl>()
        val onLeftSnapClickListenerCaptor = forClass(Function0::class.java)
                as ArgumentCaptor<Function0<Unit>>
        val decor = createOpenTaskDecoration(
@@ -610,8 +611,13 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
        val currentBounds = decor.mTaskInfo.configuration.windowConfiguration.bounds
        onLeftSnapClickListenerCaptor.value.invoke()

        verify(mockDesktopTasksController)
            .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.LEFT)
        verify(mockDesktopTasksController).snapToHalfScreen(
            eq(decor.mTaskInfo),
            taskSurfaceCaptor.capture(),
            eq(currentBounds),
            eq(SnapPosition.LEFT)
        )
        assertEquals(taskSurfaceCaptor.firstValue, decor.mTaskSurface)
    }

    @Test
@@ -632,6 +638,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
    @Test
    @DisableFlags(Flags.FLAG_DISABLE_NON_RESIZABLE_APP_SNAP_RESIZING)
    fun testOnSnapResizeLeft_nonResizable_decorSnappedLeft() {
        val taskSurfaceCaptor = argumentCaptor<SurfaceControl>()
        val onLeftSnapClickListenerCaptor = forClass(Function0::class.java)
                as ArgumentCaptor<Function0<Unit>>
        val decor = createOpenTaskDecoration(
@@ -642,8 +649,13 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
        val currentBounds = decor.mTaskInfo.configuration.windowConfiguration.bounds
        onLeftSnapClickListenerCaptor.value.invoke()

        verify(mockDesktopTasksController)
            .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.LEFT)
        verify(mockDesktopTasksController).snapToHalfScreen(
            eq(decor.mTaskInfo),
            taskSurfaceCaptor.capture(),
            eq(currentBounds),
            eq(SnapPosition.LEFT)
        )
        assertEquals(decor.mTaskSurface, taskSurfaceCaptor.firstValue)
    }

    @Test
@@ -660,12 +672,13 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
        onLeftSnapClickListenerCaptor.value.invoke()

        verify(mockDesktopTasksController, never())
            .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.LEFT)
            .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.LEFT))
        verify(mockToast).show()
    }

    @Test
    fun testOnDecorSnappedRight_snapResizes() {
        val taskSurfaceCaptor = argumentCaptor<SurfaceControl>()
        val onRightSnapClickListenerCaptor = forClass(Function0::class.java)
                as ArgumentCaptor<Function0<Unit>>
        val decor = createOpenTaskDecoration(
@@ -676,8 +689,13 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
        val currentBounds = decor.mTaskInfo.configuration.windowConfiguration.bounds
        onRightSnapClickListenerCaptor.value.invoke()

        verify(mockDesktopTasksController)
            .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.RIGHT)
        verify(mockDesktopTasksController).snapToHalfScreen(
            eq(decor.mTaskInfo),
            taskSurfaceCaptor.capture(),
            eq(currentBounds),
            eq(SnapPosition.RIGHT)
        )
        assertEquals(decor.mTaskSurface, taskSurfaceCaptor.firstValue)
    }

    @Test
@@ -698,6 +716,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
    @Test
    @DisableFlags(Flags.FLAG_DISABLE_NON_RESIZABLE_APP_SNAP_RESIZING)
    fun testOnSnapResizeRight_nonResizable_decorSnappedRight() {
        val taskSurfaceCaptor = argumentCaptor<SurfaceControl>()
        val onRightSnapClickListenerCaptor = forClass(Function0::class.java)
                as ArgumentCaptor<Function0<Unit>>
        val decor = createOpenTaskDecoration(
@@ -708,8 +727,13 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
        val currentBounds = decor.mTaskInfo.configuration.windowConfiguration.bounds
        onRightSnapClickListenerCaptor.value.invoke()

        verify(mockDesktopTasksController)
            .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.RIGHT)
        verify(mockDesktopTasksController).snapToHalfScreen(
            eq(decor.mTaskInfo),
            taskSurfaceCaptor.capture(),
            eq(currentBounds),
            eq(SnapPosition.RIGHT)
        )
        assertEquals(decor.mTaskSurface, taskSurfaceCaptor.firstValue)
    }

    @Test
@@ -726,7 +750,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
        onRightSnapClickListenerCaptor.value.invoke()

        verify(mockDesktopTasksController, never())
            .snapToHalfScreen(decor.mTaskInfo, currentBounds, SnapPosition.RIGHT)
            .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.RIGHT))
        verify(mockToast).show()
    }

@@ -1033,6 +1057,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {

    private fun createOpenTaskDecoration(
        @WindowingMode windowingMode: Int,
        taskSurface: SurfaceControl = SurfaceControl(),
        onMaxOrRestoreListenerCaptor: ArgumentCaptor<Function0<Unit>> =
            forClass(Function0::class.java) as ArgumentCaptor<Function0<Unit>>,
        onLeftSnapClickListenerCaptor: ArgumentCaptor<Function0<Unit>> =
@@ -1051,7 +1076,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
            forClass(View.OnClickListener::class.java) as ArgumentCaptor<View.OnClickListener>
    ): DesktopModeWindowDecoration {
        val decor = setUpMockDecorationForTask(createTask(windowingMode = windowingMode))
        onTaskOpening(decor.mTaskInfo)
        onTaskOpening(decor.mTaskInfo, taskSurface)
        verify(decor).setOnMaximizeOrRestoreClickListener(onMaxOrRestoreListenerCaptor.capture())
        verify(decor).setOnLeftSnapClickListener(onLeftSnapClickListenerCaptor.capture())
        verify(decor).setOnRightSnapClickListener(onRightSnapClickListenerCaptor.capture())