Merge "Fix occasional widget flashing" into jb-mr2-dev
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 2eace41..78afe57 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -488,6 +488,23 @@
         DropTarget dropTarget = findDropTarget(x, y, coordinates);
         mDragObject.x = coordinates[0];
         mDragObject.y = coordinates[1];
+        checkTouchMove(dropTarget);
+
+        // Check if we are hovering over the scroll areas
+        mDistanceSinceScroll +=
+            Math.sqrt(Math.pow(mLastTouch[0] - x, 2) + Math.pow(mLastTouch[1] - y, 2));
+        mLastTouch[0] = x;
+        mLastTouch[1] = y;
+        checkScrollState(x, y);
+    }
+
+    public void forceTouchMove() {
+        int[] dummyCoordinates = mCoordinatesTemp;
+        DropTarget dropTarget = findDropTarget(mLastTouch[0], mLastTouch[1], dummyCoordinates);
+        checkTouchMove(dropTarget);
+    }
+
+    private void checkTouchMove(DropTarget dropTarget) {
         if (dropTarget != null) {
             DropTarget delegate = dropTarget.getDropTargetDelegate(mDragObject);
             if (delegate != null) {
@@ -507,14 +524,10 @@
             }
         }
         mLastDropTarget = dropTarget;
+    }
 
-        // After a scroll, the touch point will still be in the scroll region.
-        // Rather than scrolling immediately, require a bit of twiddling to scroll again
+    private void checkScrollState(int x, int y) {
         final int slop = ViewConfiguration.get(mLauncher).getScaledWindowTouchSlop();
-        mDistanceSinceScroll +=
-            Math.sqrt(Math.pow(mLastTouch[0] - x, 2) + Math.pow(mLastTouch[1] - y, 2));
-        mLastTouch[0] = x;
-        mLastTouch[1] = y;
         final int delay = mDistanceSinceScroll < slop ? RESCROLL_DELAY : SCROLL_DELAY;
         final DragLayer dragLayer = mLauncher.getDragLayer();
         final boolean isRtl = (dragLayer.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
@@ -544,12 +557,6 @@
         }
     }
 
-    public void forceMoveEvent() {
-        if (mDragging) {
-            handleMoveEvent(mDragObject.x, mDragObject.y);
-        }
-    }
-
     /**
      * Call this from a drag source view.
      */
@@ -800,8 +807,8 @@
                 mLauncher.getDragLayer().onExitScrollArea();
 
                 if (isDragging()) {
-                    // Force an update so that we can requeue the scroller if necessary
-                    forceMoveEvent();
+                    // Check the scroll again so that we can requeue the scroller if necessary
+                    checkScrollState(mLastTouch[0], mLastTouch[1]);
                 }
             }
         }
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index c3bec84..2c0f6b0 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -1280,15 +1280,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);
+                            }
+                        });
                 }
             });
     }
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 7d7ca86..d4488db 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -773,7 +773,7 @@
             if (isSmall()) {
                 // If we are in springloaded mode, then force an event to check if the current touch
                 // is under a new page (to scroll to)
-                mDragController.forceMoveEvent();
+                mDragController.forceTouchMove();
             }
         } else {
             // If we are not mid-dragging, hide the page outlines if we are on a large screen