Merge "Can now swipe away to dismiss second task" into ub-launcher3-master
diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
index 84a60bd..4c9fd5a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
@@ -22,7 +22,6 @@
 import android.animation.ValueAnimator;
 import android.util.Log;
 import android.view.MotionEvent;
-import android.view.View;
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BaseDraggingActivity;
@@ -106,7 +105,7 @@
 
             // Now figure out which direction scroll events the controller will start
             // calling the callbacks.
-            final int directionsToDetectScroll;
+            int directionsToDetectScroll = 0;
             boolean ignoreSlopWhenSettling = false;
             if (mCurrentAnimation != null) {
                 directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH;
@@ -114,12 +113,19 @@
             } else {
                 mTaskBeingDragged = null;
 
-                View view = mRecentsView.getChildAt(mRecentsView.getCurrentPage());
-                if (view instanceof TaskView && mActivity.getDragLayer().isEventOverView(view, ev)) {
-                    // The tile can be dragged down to open the task.
-                    mTaskBeingDragged = (TaskView) view;
-                    directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH;
-                } else {
+                for (int i = 0; i < mRecentsView.getChildCount(); i++) {
+                    TaskView view = mRecentsView.getPageAt(i);
+                    if (mRecentsView.isTaskViewVisible(view) && mActivity.getDragLayer()
+                            .isEventOverView(view, ev)) {
+                        // The task can be dragged up to dismiss it,
+                        // and down to open if it's the current page.
+                        mTaskBeingDragged = view;
+                        directionsToDetectScroll = i == mRecentsView.getCurrentPage()
+                                ? SwipeDetector.DIRECTION_BOTH : SwipeDetector.DIRECTION_POSITIVE;
+                        break;
+                    }
+                }
+                if (mTaskBeingDragged == null) {
                     mNoIntercept = true;
                     return false;
                 }
@@ -142,10 +148,16 @@
         return mDetector.onTouchEvent(ev);
     }
 
-    private void reInitAnimationController(boolean goingUp) {
+    private boolean reInitAnimationController(boolean goingUp) {
         if (mCurrentAnimation != null && mCurrentAnimationIsGoingUp == goingUp) {
             // No need to init
-            return;
+            return false;
+        }
+        int scrollDirections = mDetector.getScrollDirections();
+        if (goingUp && ((scrollDirections & SwipeDetector.DIRECTION_POSITIVE) == 0)
+                || !goingUp && ((scrollDirections & SwipeDetector.DIRECTION_NEGATIVE) == 0)) {
+            // Trying to re-init in an unsupported direction.
+            return false;
         }
         if (mCurrentAnimation != null) {
             mCurrentAnimation.setPlayFraction(0);
@@ -179,6 +191,7 @@
         mCurrentAnimation.getTarget().addListener(this);
         mCurrentAnimation.dispatchOnStart();
         mProgressMultiplier = 1 / mEndDisplacement;
+        return true;
     }
 
     @Override
@@ -219,8 +232,7 @@
                     // Not allowed
                     goingToEnd = false;
                 } else {
-                    reInitAnimationController(goingUp);
-                    goingToEnd = true;
+                    goingToEnd = reInitAnimationController(goingUp);
                 }
             } else {
                 goingToEnd = true;
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 7e81ba9..faaa40d 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -659,14 +659,14 @@
         int[] newScroll = new int[count];
         getPageScrolls(newScroll, false, (v) -> v.getVisibility() != GONE && v != taskView);
 
-        int maxScrollDiff = 0;
-        int lastPage = mIsRtl ? 0 : count - 1;
-        if (getChildAt(lastPage) == taskView) {
-            if (count > 1) {
-                int secondLastPage = mIsRtl ? 1 : count - 2;
-                maxScrollDiff = oldScroll[lastPage] - newScroll[secondLastPage];
-            }
+        int scrollDiffPerPage = 0;
+        int leftmostPage = mIsRtl ? count -1 : 0;
+        int rightmostPage = mIsRtl ? 0 : count - 1;
+        if (count > 1) {
+            int secondRightmostPage = mIsRtl ? 1 : count - 2;
+            scrollDiffPerPage = oldScroll[rightmostPage] - oldScroll[secondRightmostPage];
         }
+        int draggedIndex = indexOfChild(taskView);
 
         boolean needsCurveUpdates = false;
         for (int i = 0; i < count; i++) {
@@ -678,7 +678,26 @@
                             duration, LINEAR, anim);
                 }
             } else {
-                int scrollDiff = newScroll[i] - oldScroll[i] + maxScrollDiff;
+                // If we just take newScroll - oldScroll, everything to the right of dragged task
+                // translates to the left. We need to offset this in some cases:
+                // - In RTL, add page offset to all pages, since we want pages to move to the right
+                // Additionally, add a page offset if:
+                // - Current page is rightmost page (leftmost for RTL)
+                // - Dragging an adjacent page on the left side (right side for RTL)
+                int offset = mIsRtl ? scrollDiffPerPage : 0;
+                if (mCurrentPage == draggedIndex) {
+                    int lastPage = mIsRtl ? leftmostPage : rightmostPage;
+                    if (mCurrentPage == lastPage) {
+                        offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
+                    }
+                } else {
+                    // Dragging an adjacent page.
+                    int negativeAdjacent = mCurrentPage - 1; // (Right in RTL, left in LTR)
+                    if (draggedIndex == negativeAdjacent) {
+                        offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
+                    }
+                }
+                int scrollDiff = newScroll[i] - oldScroll[i] + offset;
                 if (scrollDiff != 0) {
                     addAnim(ObjectAnimator.ofFloat(child, TRANSLATION_X, scrollDiff),
                             duration, ACCEL, anim);
@@ -710,9 +729,15 @@
                                TaskUtils.getComponentKeyForTask(task.key));
                    }
                }
+               int pageToSnapTo = mCurrentPage;
+               if (draggedIndex < pageToSnapTo) {
+                   pageToSnapTo -= 1;
+               }
                removeView(taskView);
                if (getChildCount() == 0) {
                    onAllTasksRemoved();
+               } else {
+                   snapToPageImmediately(pageToSnapTo);
                }
            }
            resetTaskVisuals();
diff --git a/src/com/android/launcher3/touch/SwipeDetector.java b/src/com/android/launcher3/touch/SwipeDetector.java
index 4b36ad9..703e4fd 100644
--- a/src/com/android/launcher3/touch/SwipeDetector.java
+++ b/src/com/android/launcher3/touch/SwipeDetector.java
@@ -194,6 +194,10 @@
         mIgnoreSlopWhenSettling = ignoreSlop;
     }
 
+    public int getScrollDirections() {
+        return mScrollConditions;
+    }
+
     private boolean shouldScrollStart(MotionEvent ev, int pointerIndex) {
         // reject cases where the angle or slop condition is not met.
         if (Math.max(mDir.getActiveTouchSlop(ev, pointerIndex, mDownPos), mTouchSlop)