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

Commit 51f8ed2a authored by Maryam Dehaini's avatar Maryam Dehaini
Browse files

Do not throw IllegalStateException when second drag to desktop

transition is started

Currently, we throw multiple errors if a second drag to desktop
transition is started (in start, cancel, and finalize drag to desktop
transition). If a swipes from the top while a drag to desktop transition
is currently happening, an error message is thrown since the windowing
mode would not have been set to freeform yet and so the view model
allows another drag to desktop transition to begin.

To fix this issue, this CL makes
DragToDesktopTransitionHandler#startDragToDesktop to return early if a
drag to desktop transition is currently in progress. Finish and cancel
will also return early is a transition is not in progress rather than
returning error to make sure we do not attempt to cancel/finalize a
transition that was never started.

Bug: 315518276
Test: Open task in fullscreen. Swipe down twice quickly and check to see
task animation successfully finishes and no crashes occur.

Change-Id: Ie1730a60393a4c7ef67f064d716d21c4b38bb0cf
parent 9f9c885e
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -99,7 +99,11 @@ class DragToDesktopTransitionHandler(
            windowDecoration: DesktopModeWindowDecoration
    ) {
        if (inProgress) {
            error("A drag to desktop is already in progress")
            KtProtoLog.v(
                    ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
                    "DragToDesktop: Drag to desktop transition already in progress."
            )
            return
        }

        val options = ActivityOptions.makeBasic().apply {
@@ -144,6 +148,12 @@ class DragToDesktopTransitionHandler(
     * inside the desktop drop zone.
     */
    fun finishDragToDesktopTransition(wct: WindowContainerTransaction) {
        if (!inProgress) {
            // Don't attempt to finish a drag to desktop transition since there is no transition in
            // progress which means that the drag to desktop transition was never successfully
            // started.
            return
        }
        if (requireTransitionState().startAborted) {
            // Don't attempt to complete the drag-to-desktop since the start transition didn't
            // succeed as expected. Just reset the state as if nothing happened.
@@ -161,6 +171,12 @@ class DragToDesktopTransitionHandler(
     * means the user wants to remain in their current windowing mode.
     */
    fun cancelDragToDesktopTransition() {
        if (!inProgress) {
            // Don't attempt to cancel a drag to desktop transition since there is no transition in
            // progress which means that the drag to desktop transition was never successfully
            // started.
            return
        }
        val state = requireTransitionState()
        if (state.startAborted) {
            // Don't attempt to cancel the drag-to-desktop since the start transition didn't
+44 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyZeroInteractions
import org.mockito.kotlin.whenever
@@ -149,6 +150,23 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
        assertFalse(handler.inProgress)
    }

    @Test
    fun startDragToDesktop_anotherTransitionInProgress_startDropped() {
        val task = createTask()
        val dragAnimator = mock<MoveToDesktopAnimator>()

        // Simulate attempt to start two drag to desktop transitions.
        startDragToDesktopTransition(task, dragAnimator)
        startDragToDesktopTransition(task, dragAnimator)

        // Verify transition only started once.
        verify(transitions, times(1)).startTransition(
                eq(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP),
                any(),
                eq(handler)
        )
    }

    @Test
    fun cancelDragToDesktop_startWasReady_cancel() {
        val task = createTask()
@@ -189,6 +207,32 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
        verifyZeroInteractions(dragAnimator)
    }

    @Test
    fun cancelDragToDesktop_transitionNotInProgress_dropCancel() {
        // Then cancel is called before the transition was started.
        handler.cancelDragToDesktopTransition()

        // Verify cancel is dropped.
        verify(transitions, never()).startTransition(
                eq(TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP),
                any(),
                eq(handler)
        )
    }

    @Test
    fun finishDragToDesktop_transitionNotInProgress_dropFinish() {
        // Then finish is called before the transition was started.
        handler.finishDragToDesktopTransition(WindowContainerTransaction())

        // Verify finish is dropped.
        verify(transitions, never()).startTransition(
                eq(TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP),
                any(),
                eq(handler)
        )
    }

    private fun startDragToDesktopTransition(
        task: RunningTaskInfo,
        dragAnimator: MoveToDesktopAnimator