Fix deep shortcuts RTL issues.

- Container was shifted off screen.
- Touch down x coordinate was incorrect, causing the deferred
  drag to start immediately upon moving the original icon.

Bug: 30075428
Change-Id: I148b6f4f7945ecbcf67b52ba26a2af0065d8f538
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
index 9f59e06..ffa9c26 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
@@ -75,7 +75,7 @@
     private final int mStartDragThreshold;
     private BubbleTextView mDeferredDragIcon;
     private int mActivePointerId;
-    private Point mTouchDown = null;
+    private int[] mTouchDown = null;
     private DragView mDragView;
     private float mLastX, mLastY;
     private float mDistanceDragged = 0;
@@ -236,7 +236,7 @@
     /**
      * Orients this container above or below the given icon, aligning with the left or right.
      *
-     * These are the preferred orientations, in order:
+     * These are the preferred orientations, in order (RTL prefers right-aligned over left):
      * - Above and left-aligned
      * - Above and right-aligned
      * - Below and left-aligned
@@ -253,16 +253,25 @@
 
         DragLayer dragLayer = mLauncher.getDragLayer();
         dragLayer.getDescendantRectRelativeToSelf(icon, mTempRect);
-        // Align left and above by default.
-        int x = mTempRect.left + icon.getPaddingLeft();
-        int y = mTempRect.top - height;
         Rect insets = dragLayer.getInsets();
 
-        mIsLeftAligned = x + width < dragLayer.getRight() - insets.right;
-        if (!mIsLeftAligned) {
-            x = mTempRect.right - width - icon.getPaddingRight();
+        // Align left (right in RTL) if there is room.
+        boolean isRtl = Utilities.isRtl(getResources());
+        int leftAlignedX = mTempRect.left + icon.getPaddingLeft();
+        int rightAlignedX = mTempRect.right - width - icon.getPaddingRight();
+        int x = leftAlignedX;
+        boolean canBeLeftAligned = leftAlignedX + width < dragLayer.getRight() - insets.right;
+        boolean canBeRightAligned = rightAlignedX > dragLayer.getLeft() + insets.left;
+        if (!canBeLeftAligned || (isRtl && canBeRightAligned)) {
+            x = rightAlignedX;
+        }
+        mIsLeftAligned = x == leftAlignedX;
+        if (isRtl) {
+            x -= dragLayer.getWidth() - width;
         }
 
+        // Open above icon if there is room.
+        int y = mTempRect.top - height;
         mIsAboveIcon = mTempRect.top - height > dragLayer.getTop() + insets.top;
         if (!mIsAboveIcon) {
             y = mTempRect.bottom;
@@ -304,7 +313,7 @@
         mDragView.show(motionDownX, motionDownY);
     }
 
-    public boolean onForwardedEvent(MotionEvent ev, int activePointerId, Point touchDown) {
+    public boolean onForwardedEvent(MotionEvent ev, int activePointerId, int[] touchDown) {
         mActivePointerId = activePointerId;
         mTouchDown = touchDown;
         return dispatchTouchEvent(ev);
@@ -398,9 +407,9 @@
      */
     private boolean shouldStartDeferredDrag(int x, int y, boolean containerContainsTouch) {
         int closestEdgeY = mIsAboveIcon ? getMeasuredHeight() : 0;
-        double distToEdge = Math.abs(mTouchDown.y - closestEdgeY);
-        double newDistToEdge = Math.hypot(x - mTouchDown.x, y - closestEdgeY);
-        return  !containerContainsTouch && (newDistToEdge - distToEdge > mStartDragThreshold);
+        double distToEdge = Math.abs(mTouchDown[1] - closestEdgeY);
+        double newDistToEdge = Math.hypot(x - mTouchDown[0], y - closestEdgeY);
+        return !containerContainsTouch && (newDistToEdge - distToEdge > mStartDragThreshold);
     }
 
     public void cleanupDeferredDrag() {
diff --git a/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java b/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java
index 63c8363..962fbac 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java
@@ -1,7 +1,6 @@
 package com.android.launcher3.shortcuts;
 
 import android.content.Context;
-import android.graphics.Point;
 import android.os.SystemClock;
 import android.view.HapticFeedbackConstants;
 import android.view.LayoutInflater;
@@ -53,9 +52,9 @@
 
     private Launcher mLauncher;
     private DragLayer mDragLayer;
-    private MotionEvent mTouchDownEvent;
-    /** The coordinates of the touch down, relative do the shortcuts container. */
-    private final Point mTouchDown;
+    /** The coordinates of the touch down, relative to the shortcuts container. */
+    private final int[] mTouchDown;
+    private boolean mHasMappedTouchDownToContainerCoord;
 
     public ShortcutsContainerListener(BubbleTextView icon) {
         mSrcIcon = icon;
@@ -68,7 +67,7 @@
 
         mLauncher = Launcher.getLauncher(mSrcIcon.getContext());
         mDragLayer = mLauncher.getDragLayer();
-        mTouchDown = new Point();
+        mTouchDown = new int[2];
     }
 
     @Override
@@ -79,10 +78,10 @@
         }
 
         if (event.getAction() == MotionEvent.ACTION_DOWN) {
-            if (mTouchDownEvent != null) {
-                mTouchDownEvent.recycle();
-            }
-            mTouchDownEvent = MotionEvent.obtainNoHistory(event);
+            mTouchDown[0] = (int) event.getX();
+            mTouchDown[1] = (int) event.getY();
+            mDragLayer.getDescendantCoordRelativeToSelf(mSrcIcon, mTouchDown);
+            mHasMappedTouchDownToContainerCoord = false;
         }
 
         final boolean wasForwarding = mForwarding;
@@ -140,10 +139,6 @@
             deepShortcutsContainer.populateAndShow(mSrcIcon, ids);
             mSrcIcon.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                     HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
-
-            // Convert touch down event to the container's coordinates.
-            Utilities.translateEventCoordinates(mSrcIcon, deepShortcutsContainer, mTouchDownEvent);
-            mTouchDown.set((int) mTouchDownEvent.getX(), (int) mTouchDownEvent.getY());
             return true;
         }
         return false;
@@ -257,13 +252,21 @@
         if (dst == null) {
             return false;
         }
+        if (!dst.isLaidOut()) {
+            return true;
+        }
 
         // Convert event to destination-local coordinates.
         final MotionEvent dstEvent = MotionEvent.obtainNoHistory(srcEvent);
         Utilities.translateEventCoordinates(src, dst, dstEvent);
 
+        // Convert touch down event to destination-local coordinates.
+        if (!mHasMappedTouchDownToContainerCoord) {
+            mDragLayer.mapCoordInSelfToDescendent(dst, mTouchDown);
+            mHasMappedTouchDownToContainerCoord = true;
+        }
+
         // Forward converted event to destination view, then recycle it.
-        // TODO: don't create objects in onForwardedEvent.
         final boolean handled = dst.onForwardedEvent(dstEvent, mActivePointerId, mTouchDown);
         dstEvent.recycle();