Merge "Fixing issue where drag view is jumping when you scroll from hovering over an edge.  (Bug 8522679)" into jb-mr2-dev
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index 83bc1fd..a4a9ea9 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -998,6 +998,7 @@
 
     public void syncAppsPageItems(int page, boolean immediate) {
         // ensure that we have the right number of items on the pages
+        final boolean isRtl = isLayoutRtl();
         int numCells = mCellCountX * mCellCountY;
         int startIndex = page * numCells;
         int endIndex = Math.min(startIndex + numCells, mApps.size());
@@ -1019,6 +1020,9 @@
             int index = i - startIndex;
             int x = index % mCellCountX;
             int y = index / mCellCountX;
+            if (isRtl) {
+                x = mCellCountX - x - 1;
+            }
             layout.addViewToCellLayout(icon, -1, i, new PagedViewCellLayout.LayoutParams(x,y, 1,1));
 
             items.add(info);
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 1d6472f..78afe57 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -529,22 +529,26 @@
     private void checkScrollState(int x, int y) {
         final int slop = ViewConfiguration.get(mLauncher).getScaledWindowTouchSlop();
         final int delay = mDistanceSinceScroll < slop ? RESCROLL_DELAY : SCROLL_DELAY;
+        final DragLayer dragLayer = mLauncher.getDragLayer();
+        final boolean isRtl = (dragLayer.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
+        final int forwardDirection = isRtl ? SCROLL_RIGHT : SCROLL_LEFT;
+        final int backwardsDirection = isRtl ? SCROLL_LEFT : SCROLL_RIGHT;
 
         if (x < mScrollZone) {
             if (mScrollState == SCROLL_OUTSIDE_ZONE) {
                 mScrollState = SCROLL_WAITING_IN_ZONE;
-                if (mDragScroller.onEnterScrollArea(x, y, SCROLL_LEFT)) {
-                    mLauncher.getDragLayer().onEnterScrollArea(SCROLL_LEFT);
-                    mScrollRunnable.setDirection(SCROLL_LEFT);
+                if (mDragScroller.onEnterScrollArea(x, y, forwardDirection)) {
+                    dragLayer.onEnterScrollArea(forwardDirection);
+                    mScrollRunnable.setDirection(forwardDirection);
                     mHandler.postDelayed(mScrollRunnable, delay);
                 }
             }
         } else if (x > mScrollView.getWidth() - mScrollZone) {
             if (mScrollState == SCROLL_OUTSIDE_ZONE) {
                 mScrollState = SCROLL_WAITING_IN_ZONE;
-                if (mDragScroller.onEnterScrollArea(x, y, SCROLL_RIGHT)) {
-                    mLauncher.getDragLayer().onEnterScrollArea(SCROLL_RIGHT);
-                    mScrollRunnable.setDirection(SCROLL_RIGHT);
+                if (mDragScroller.onEnterScrollArea(x, y, backwardsDirection)) {
+                    dragLayer.onEnterScrollArea(backwardsDirection);
+                    mScrollRunnable.setDirection(backwardsDirection);
                     mHandler.postDelayed(mScrollRunnable, delay);
                 }
             }
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index e870d0a..a819cb7 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -742,6 +742,13 @@
         invalidate();
     }
 
+    /**
+     * Note: this is a reimplementation of View.isLayoutRtl() since that is currently hidden api.
+     */
+    private boolean isLayoutRtl() {
+        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
+    }
+
     @Override
     protected void dispatchDraw(Canvas canvas) {
         super.dispatchDraw(canvas);
@@ -753,8 +760,9 @@
             getDescendantRectRelativeToSelf(workspace.getChildAt(0), childRect);
 
             int page = workspace.getNextPage();
-            CellLayout leftPage = (CellLayout) workspace.getChildAt(page - 1);
-            CellLayout rightPage = (CellLayout) workspace.getChildAt(page + 1);
+            final boolean isRtl = isLayoutRtl();
+            CellLayout leftPage = (CellLayout) workspace.getChildAt(isRtl ? page + 1 : page - 1);
+            CellLayout rightPage = (CellLayout) workspace.getChildAt(isRtl ? page - 1 : page + 1);
 
             if (leftPage != null && leftPage.getIsDragOverlapping()) {
                 mLeftHoverDrawable.setBounds(0, childRect.top,
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 9e651c6..56a854c 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -1272,15 +1272,22 @@
                 // layers on all the workspace pages, so that transitioning to Launcher from other
                 // apps is nice and speedy.
                 observer.addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
+                    private boolean mStarted = false;
                     public void onDraw() {
+                        if (mStarted) return;
+                        mStarted = true;
                         // We delay the layer building a bit in order to give
                         // other message processing a time to run.  In particular
                         // this avoids a delay in hiding the IME if it was
                         // currently shown, because doing that may involve
                         // some communication back with the app.
                         mWorkspace.postDelayed(mBuildLayersRunnable, 500);
-
-                        observer.removeOnDrawListener(this);
+                        final ViewTreeObserver.OnDrawListener listener = this;
+                        mWorkspace.post(new Runnable() {
+                                public void run() {
+                                    mWorkspace.getViewTreeObserver().removeOnDrawListener(listener);
+                                }
+                            });
                         return;
                     }
                 });
diff --git a/src/com/android/launcher2/LauncherAnimUtils.java b/src/com/android/launcher2/LauncherAnimUtils.java
index 5055d35..a89cb46 100644
--- a/src/com/android/launcher2/LauncherAnimUtils.java
+++ b/src/com/android/launcher2/LauncherAnimUtils.java
@@ -52,15 +52,23 @@
     // Helper method. Assumes a draw is pending, and that if the animation's duration is 0
     // it should be cancelled
     public static void startAnimationAfterNextDraw(final Animator animator, final View view) {
-        final ViewTreeObserver observer = view.getViewTreeObserver();
-        observer.addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
+        view.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
+                private boolean mStarted = false;
                 public void onDraw() {
+                    if (mStarted) return;
+                    mStarted = true;
                     // Use this as a signal that the animation was cancelled
                     if (animator.getDuration() == 0) {
                         return;
                     }
                     animator.start();
-                    view.getViewTreeObserver().removeOnDrawListener(this);
+
+                    final ViewTreeObserver.OnDrawListener listener = this;
+                    view.post(new Runnable() {
+                            public void run() {
+                                view.getViewTreeObserver().removeOnDrawListener(listener);
+                            }
+                        });
                 }
             });
     }