From cc973dfdce4dff21f469fbd9cb5d817e0fee7ba3 Mon Sep 17 00:00:00 2001 From: Pat Manning Date: Fri, 14 Mar 2025 16:06:46 +0000 Subject: [PATCH] Prevent multiple competing dismissals. This brings into line with existing UX prior to the feature. Fix: 400727071 Test: Manual. Dismiss as quickly as possible. Flag: com.android.launcher3.enable_expressive_dismiss_task_motion Change-Id: Ie3f6f82c3ed4626829f3a61307e73cbdb8a31ceb --- .../touchcontrollers/TaskViewDismissTouchController.kt | 6 ++++++ .../src/com/android/quickstep/views/RecentsDismissUtils.kt | 7 +++++-- quickstep/src/com/android/quickstep/views/RecentsView.java | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewDismissTouchController.kt b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewDismissTouchController.kt index 454a307300..76eb138ed6 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewDismissTouchController.kt +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewDismissTouchController.kt @@ -63,6 +63,7 @@ CONTAINER : RecentsViewContainer { private var hasDismissThresholdHapticRun = false private var initialDisplacement: Float = 0f private var recentsScaleAnimation: SpringAnimation? = null + private var isBlockedDuringDismissal = false private fun canInterceptTouch(ev: MotionEvent): Boolean = when { @@ -137,6 +138,7 @@ CONTAINER : RecentsViewContainer { } override fun onDragStart(start: Boolean, startDisplacement: Float) { + if (isBlockedDuringDismissal) return val taskBeingDragged = taskBeingDragged ?: return initialDisplacement = @@ -149,6 +151,7 @@ CONTAINER : RecentsViewContainer { } override fun onDrag(displacement: Float): Boolean { + if (isBlockedDuringDismissal) return true val taskBeingDragged = taskBeingDragged ?: return false val currentDisplacement = displacement + initialDisplacement val boundedDisplacement = @@ -204,6 +207,7 @@ CONTAINER : RecentsViewContainer { } override fun onDragEnd(velocity: Float) { + if (isBlockedDuringDismissal) return val taskBeingDragged = taskBeingDragged ?: return val currentDisplacement = @@ -234,6 +238,7 @@ CONTAINER : RecentsViewContainer { if (isDismissing) (dismissLength * verticalFactor).toFloat() else 0f ) } + isBlockedDuringDismissal = true recentsScaleAnimation = recentsView.animateRecentsScale(RECENTS_SCALE_DEFAULT).addEndListener { _, _, _, _ -> recentsScaleAnimation = null @@ -246,6 +251,7 @@ CONTAINER : RecentsViewContainer { taskBeingDragged?.translationZ = 0f taskBeingDragged = null springAnimation = null + isBlockedDuringDismissal = false } private fun getRecentsScale(dismissFraction: Float): Float { diff --git a/quickstep/src/com/android/quickstep/views/RecentsDismissUtils.kt b/quickstep/src/com/android/quickstep/views/RecentsDismissUtils.kt index 4ce18f50a1..dc780612c4 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsDismissUtils.kt +++ b/quickstep/src/com/android/quickstep/views/RecentsDismissUtils.kt @@ -82,6 +82,7 @@ class RecentsDismissUtils(private val recentsView: RecentsView<*, *>) { runTaskGridReflowSpringAnimation( draggedTaskView, getDismissedTaskGapForReflow(draggedTaskView), + onEndRunnable, ) } else { recentsView.dismissTaskView( @@ -89,11 +90,12 @@ class RecentsDismissUtils(private val recentsView: RecentsView<*, *>) { /* animateTaskView = */ false, /* removeTask = */ true, ) + onEndRunnable() } } else { recentsView.onDismissAnimationEnds() + onEndRunnable() } - onEndRunnable() } if (!isDismissing) { addNeighboringSpringAnimationsForDismissCancel( @@ -312,6 +314,7 @@ class RecentsDismissUtils(private val recentsView: RecentsView<*, *>) { private fun runTaskGridReflowSpringAnimation( dismissedTaskView: TaskView, dismissedTaskGap: Float, + onEndRunnable: () -> Unit, ) { // Empty spring animation exists for conditional start, and to drive neighboring springs. val springAnimationDriver = @@ -384,7 +387,7 @@ class RecentsDismissUtils(private val recentsView: RecentsView<*, *>) { // Start animations and remove the dismissed task at the end, dismiss immediately if no // neighboring tasks exist. val runGridEndAnimationAndRelayout = { - recentsView.expressiveDismissTaskView(dismissedTaskView) + recentsView.expressiveDismissTaskView(dismissedTaskView, onEndRunnable) } springAnimationDriver?.apply { addEndListener { _, _, _, _ -> runGridEndAnimationAndRelayout() } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 6067550507..758124aeaa 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -142,7 +142,6 @@ import androidx.annotation.UiThread; import androidx.core.graphics.ColorUtils; import androidx.dynamicanimation.animation.SpringAnimation; -import com.android.app.tracing.TraceUtilsKt; import com.android.internal.jank.Cuj; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BaseActivity.MultiWindowModeChangedListener; @@ -4748,11 +4747,12 @@ public abstract class RecentsView< runDismissAnimation(pa); } - protected void expressiveDismissTaskView(TaskView taskView) { + protected void expressiveDismissTaskView(TaskView taskView, Function0 onEndRunnable) { PendingAnimation pa = new PendingAnimation(DISMISS_TASK_DURATION); createTaskDismissAnimation(pa, taskView, false /* animateTaskView */, true /* removeTask */, DISMISS_TASK_DURATION, false /* dismissingForSplitSelection*/, true /* isExpressiveDismiss */); + pa.addEndListener((success) -> onEndRunnable.invoke()); runDismissAnimation(pa); }