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

Commit ed5b55a4 authored by mpodolian's avatar mpodolian
Browse files

Added method to perform actions on all drop targets removed.

We need to delay taskbar window shrinking after drop is done to allow
DropTargetManager to animate out drop target views. Added corresponding
method to the DropTargetManager.

Bug: 411506181
Flag: com.android.wm.shell.enable_create_any_bubble
Test: DropTargetManagerTest
Change-Id: I47bd67615a87c23a13d1889a9a1dacc4a21a64ea
parent f3f47b74
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ class DropTargetManager(
    private var morphRect: RectF = RectF(0f, 0f, 0f, 0f)
    private val isLayoutRtl = container.isLayoutRtl
    private val viewAnimatorsMap = mutableMapOf<View, ValueAnimator>()
    private var onDropTargetsRemovedAction: Runnable? = null

    private companion object {
        const val MORPH_ANIM_DURATION = 250L
@@ -111,15 +112,29 @@ class DropTargetManager(
    /** Called when the drag ended. */
    fun onDragEnded() {
        val dropState = state ?: return
        startFadeAnimation(dropTargetView, to = 0f) { container.removeView(dropTargetView) }
        startFadeAnimation(dropTargetView, to = 0f) {
            container.removeView(dropTargetView)
            onDropTargetRemoved()
        }
        startFadeAnimation(secondDropTargetView, to = 0f) {
            container.removeView(secondDropTargetView)
            secondDropTargetView = null
            onDropTargetRemoved()
        }
        dragZoneChangedListener.onDragEnded(dropState.currentDragZone)
        state = null
    }

    /**
     * Runs the provided action once all drop target views are removed from the container.
     * If there are no drop target views currently present or being animated, the action will be
     * executed immediately.
     */
    fun onDropTargetRemoved(action: Runnable) {
        onDropTargetsRemovedAction = action
        onDropTargetRemoved()
    }

    private fun updateDropTarget() {
        val dropState = state ?: return
        val currentDragZone = dropState.currentDragZone
@@ -191,6 +206,15 @@ class DropTargetManager(
        animator.start()
    }

    private fun onDropTargetRemoved() {
        val action = onDropTargetsRemovedAction ?: return
        if ((0 until container.childCount).any { container.getChildAt(it) is DropTargetView }) {
            return
        }
        onDropTargetsRemovedAction = null
        action.run()
    }

    /** Stores the current drag state. */
    private inner class DragState(
        private val dragZones: List<DragZone>,
+46 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.wm.shell.shared.bubbles

import android.content.Context
import android.graphics.Rect
import android.view.View
import android.widget.FrameLayout
import androidx.core.animation.AnimatorTestRule
import androidx.test.core.app.ApplicationProvider.getApplicationContext
@@ -469,6 +470,51 @@ class DropTargetManagerTest {
        )
    }

    @Test
    fun runOnDropTargetsRemoved_dropTargetViewsAdded_notExecutedUntilAllViewsRemoved() {
        var runnableExecuted = false
        val action = Runnable { runnableExecuted = true }
        dropTargetManager.onDragStarted(
            DraggedObject.LauncherIcon(bubbleBarHasBubbles = false) {},
            listOf(bubbleLeftDragZoneWithSecondDropTarget, bubbleRightDragZoneWithSecondDropTarget)
        )
        assertThat(container.childCount).isEqualTo(DROP_VIEWS_COUNT_FOR_LAUNCHER_ICON)
        dropTargetManager.onDropTargetRemoved(action)
        assertThat(runnableExecuted).isFalse()

        InstrumentationRegistry.getInstrumentation().runOnMainSync {
            dropTargetManager.onDragEnded()
        }
        assertThat(container.childCount).isEqualTo(DROP_VIEWS_COUNT_FOR_LAUNCHER_ICON)
        assertThat(runnableExecuted).isFalse()

        InstrumentationRegistry.getInstrumentation().runOnMainSync {
            animatorTestRule.advanceTimeBy(200)
        }

        assertThat(container.childCount).isEqualTo(0)
        assertThat(runnableExecuted).isTrue()
    }

    @Test
    fun onDropTargetsRemoved_dropTargetViewsAbsent_actionExecuted() {
        var runnableExecuted = false
        val action = Runnable { runnableExecuted = true }
        assertThat(container.childCount).isEqualTo(0)
        dropTargetManager.onDropTargetRemoved(action)
        assertThat(runnableExecuted).isTrue()
    }

    @Test
    fun onDropTargetsRemoved_NonDropTargetViewPresent_actionExecuted() {
        var runnableExecuted = false
        val action = Runnable { runnableExecuted = true }
        container.addView(View(context))
        assertThat(container.childCount).isEqualTo(1)
        dropTargetManager.onDropTargetRemoved(action)
        assertThat(runnableExecuted).isTrue()
    }

    private fun verifyDropTargetPosition(rect: Rect) {
        verifyDropTargetPosition(dropTargetView, rect)
    }