Cleaning up some spring-loaded related dragging code.  Allow cancel spring loaded mode.

Change-Id: Ie1f0468c563bed7abc1aa6416e222cdb0853c03a
diff --git a/res/layout/apps_customize_pane.xml b/res/layout/apps_customize_pane.xml
index ecb10ec..a94b6e6 100644
--- a/res/layout/apps_customize_pane.xml
+++ b/res/layout/apps_customize_pane.xml
@@ -80,6 +80,8 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_gravity="bottom"
+                android:visibility="gone"
+                android:alpha="0"
                 android:scaleType="fitXY"
                 android:src="@drawable/hotseat_track_holo" />
             <ImageView
diff --git a/res/values/config.xml b/res/values/config.xml
index d4c5ca4..a5d7b91 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -45,7 +45,7 @@
 
 <!-- Workspace -->
     <!-- The transition duration for the background of the drop targets -->
-    <integer name="config_dropTargetBgTransitionDuration">100</integer>
+    <integer name="config_dropTargetBgTransitionDuration">200</integer>
 
     <integer name="config_crosshairsFadeInTime">600</integer>
 
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index 2a4af44..e55a55c 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -460,22 +460,21 @@
     protected boolean beginDragging(View v) {
         if (!super.beginDragging(v)) return false;
 
+        // Go into spring loaded mode (must happen before we startDrag())
+        int currentPageIndex = mLauncher.getWorkspace().getCurrentPage();
+        CellLayout currentPage = (CellLayout) mLauncher.getWorkspace().getChildAt(currentPageIndex);
+        mLauncher.enterSpringLoadedDragMode(currentPage);
 
         if (v instanceof PagedViewIcon) {
             beginDraggingApplication(v);
         } else if (v instanceof PagedViewWidget) {
             beginDraggingWidget(v);
         }
-
-        // Go into spring loaded mode
-        int currentPageIndex = mLauncher.getWorkspace().getCurrentPage();
-        CellLayout currentPage = (CellLayout) mLauncher.getWorkspace().getChildAt(currentPageIndex);
-        mLauncher.enterSpringLoadedDragMode(currentPage);
         return true;
     }
     private void endDragging(boolean success) {
-        mLauncher.exitSpringLoadedDragMode();
         mLauncher.getWorkspace().onDragStopped(success);
+        mLauncher.exitSpringLoadedDragMode();
         mLauncher.unlockScreenOrientation();
 
     }
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index dae73e1..f890808 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -1403,6 +1403,21 @@
     }
 
     /**
+     * A drag event has begun over this layout.
+     * It may have begun over this layout (in which case onDragChild is called first),
+     * or it may have begun on another layout.
+     */
+    void onDragEnter() {
+        if (!mDragging) {
+            // Fade in the drag indicators
+            if (mCrosshairsAnimator != null) {
+                mCrosshairsAnimator.animateIn();
+            }
+        }
+        mDragging = true;
+    }
+
+    /**
      * Called when drag has left this CellLayout or has been completed (successfully or not)
      */
     void onDragExit() {
@@ -1454,21 +1469,6 @@
     }
 
     /**
-     * A drag event has begun over this layout.
-     * It may have begun over this layout (in which case onDragChild is called first),
-     * or it may have begun on another layout.
-     */
-    void onDragEnter() {
-        if (!mDragging) {
-            // Fade in the drag indicators
-            if (mCrosshairsAnimator != null) {
-                mCrosshairsAnimator.animateIn();
-            }
-        }
-        mDragging = true;
-    }
-
-    /**
      * Computes a bounding rectangle for a range of cells
      *
      * @param cellX X coordinate of upper left corner expressed as a cell position
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index ca72ce9..9a6335b 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -366,7 +366,9 @@
      */
     public void cancelDrag() {
         if (mDragging) {
-            // Should we also be calling onDragExit() here?
+            if (mLastDropTarget != null) {
+                mLastDropTarget.onDragExit(mDragObject);
+            }
             mDragObject.dragComplete = true;
             mDragObject.dragSource.onDropCompleted(null, mDragObject, false);
         }
diff --git a/src/com/android/launcher2/ItemInfo.java b/src/com/android/launcher2/ItemInfo.java
index 3bb3b07..3a1c29a 100644
--- a/src/com/android/launcher2/ItemInfo.java
+++ b/src/com/android/launcher2/ItemInfo.java
@@ -150,6 +150,8 @@
 
     @Override
     public String toString() {
-        return "Item(id=" + this.id + " type=" + this.itemType + ")";
+        return "Item(id=" + this.id + " type=" + this.itemType + " container=" + this.container
+            + " screen=" + screen + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX
+            + " spanY=" + spanY + " isGesture=" + isGesture + " dropPos=" + dropPos + ")";
     }
 }
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 894e395..0c052a7 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -2322,7 +2322,7 @@
      * of the screen.
      * @param toState The state to zoom out to. Must be APPS_CUSTOMIZE.
      */
-    private void cameraZoomOut(State toState, boolean animated, boolean springLoaded) {
+    private void cameraZoomOut(State toState, boolean animated, final boolean springLoaded) {
         final Resources res = getResources();
 
         final int duration = res.getInteger(R.integer.config_appsCustomizeZoomInTime);
@@ -2381,9 +2381,11 @@
                     toView.setVisibility(View.VISIBLE);
                     toView.bringToFront();
 
-                    // Hide the workspace scrollbar
-                    mWorkspace.hideScrollingIndicator(true);
-                    mWorkspace.hideScrollIndicatorTrack();
+                    if (!springLoaded && !LauncherApplication.isScreenLarge()) {
+                        // Hide the workspace scrollbar
+                        mWorkspace.hideScrollingIndicator(true);
+                        mWorkspace.hideScrollIndicatorTrack();
+                    }
                 }
                 @Override
                 public void onAnimationEnd(Animator animation) {
@@ -2416,9 +2418,11 @@
                 ((LauncherTransitionable) toView).onLauncherTransitionStart(null);
                 ((LauncherTransitionable) toView).onLauncherTransitionEnd(null);
 
-                // Hide the workspace scrollbar
-                mWorkspace.hideScrollingIndicator(true);
-                mWorkspace.hideScrollIndicatorTrack();
+                if (!springLoaded && !LauncherApplication.isScreenLarge()) {
+                    // Hide the workspace scrollbar
+                    mWorkspace.hideScrollingIndicator(true);
+                    mWorkspace.hideScrollIndicatorTrack();
+                }
             }
         }
     }
@@ -2429,7 +2433,7 @@
      * @param fromState The current state (must be APPS_CUSTOMIZE).
      * @param animated If true, the transition will be animated.
      */
-    private void cameraZoomIn(State fromState, boolean animated, boolean springLoaded) {
+    private void cameraZoomIn(State fromState, boolean animated, final boolean springLoaded) {
         Resources res = getResources();
 
         final int duration = res.getInteger(R.integer.config_appsCustomizeZoomOutTime);
@@ -2477,9 +2481,11 @@
                     if (fromView instanceof LauncherTransitionable) {
                         ((LauncherTransitionable) fromView).onLauncherTransitionEnd(alphaAnim);
 
-                        // Show the workspace scrollbar
-                        mWorkspace.showScrollIndicatorTrack();
-                        mWorkspace.flashScrollingIndicator();
+                        if (!springLoaded && !LauncherApplication.isScreenLarge()) {
+                            // Show the workspace scrollbar
+                            mWorkspace.showScrollIndicatorTrack();
+                            mWorkspace.flashScrollingIndicator();
+                        }
                     }
                 }
             });
@@ -2492,9 +2498,11 @@
                 ((LauncherTransitionable) fromView).onLauncherTransitionStart(null);
                 ((LauncherTransitionable) fromView).onLauncherTransitionEnd(null);
 
-                // Show the workspace scrollbar
-                mWorkspace.showScrollIndicatorTrack();
-                mWorkspace.flashScrollingIndicator();
+                if (!springLoaded && !LauncherApplication.isScreenLarge()) {
+                    // Show the workspace scrollbar
+                    mWorkspace.showScrollIndicatorTrack();
+                    mWorkspace.flashScrollingIndicator();
+                }
             }
         }
     }
@@ -2527,12 +2535,10 @@
     }
 
     void enterSpringLoadedDragMode(CellLayout layout) {
-        // Enter spring loaded mode on a new layout
-        mWorkspace.enterSpringLoadedDragMode(layout);
-
         if (mState == State.APPS_CUSTOMIZE) {
-            mState = State.APPS_CUSTOMIZE_SPRING_LOADED;
+            mWorkspace.enterSpringLoadedDragMode(layout);
             cameraZoomIn(State.APPS_CUSTOMIZE, true, true);
+            mState = State.APPS_CUSTOMIZE_SPRING_LOADED;
         }
         // Otherwise, we are not in spring loaded mode, so don't do anything.
     }
diff --git a/src/com/android/launcher2/SpringLoadedDragController.java b/src/com/android/launcher2/SpringLoadedDragController.java
index 37a94d4..0d4785d 100644
--- a/src/com/android/launcher2/SpringLoadedDragController.java
+++ b/src/com/android/launcher2/SpringLoadedDragController.java
@@ -40,6 +40,7 @@
     // Set a new alarm to expire for the screen that we are hovering over now
     public void setAlarm(CellLayout cl) {
         if (mScreen != cl) {
+            mAlarm.cancelAlarm();
             mAlarm.setAlarm(ENTER_SPRING_LOAD_HOVER_TIME);
         }
         mScreen = cl;
@@ -52,6 +53,8 @@
             Workspace w = mLauncher.getWorkspace();
             int page = w.indexOfChild(mScreen);
             w.snapToPage(page);
+        } else {
+            mLauncher.getDragController().cancelDrag();
         }
     }
 }
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 88405c7..caf62b4 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -198,10 +198,6 @@
 
     // info about the last drag
     private DragView mLastDragView;
-    private int mLastDragOriginX;
-    private int mLastDragOriginY;
-    private int mLastDragXOffset;
-    private int mLastDragYOffset;
 
     // Variables relating to the creation of user folders by hovering shortcuts over shortcuts
     private static final int FOLDER_CREATION_TIMEOUT = 250;
@@ -330,13 +326,6 @@
             public void onAnimationEnd(Animator animation) {
                 mIsInUnshrinkAnimation = false;
                 mSyncWallpaperOffsetWithScroll = true;
-                if (mShrinkState == ShrinkState.SPRING_LOADED) {
-                    View layout = null;
-                    if (mLastDragView != null) {
-                        layout = findMatchingPageForDragOver(mLastDragView, mLastDragOriginX,
-                                mLastDragOriginY, mLastDragXOffset, mLastDragYOffset);
-                    }
-                }
                 mWallpaperOffset.setOverrideHorizontalCatchupConstant(false);
                 mAnimator = null;
                 enableChildrenLayers(false);
@@ -1157,11 +1146,9 @@
         } else {
             super.dispatchDraw(canvas);
 
-            final int width = getWidth();
-            final int height = getHeight();
-
-            // In portrait orientation, draw the glowing edge when dragging to adjacent screens
-            if (mInScrollArea && (height > width)) {
+            if (mInScrollArea && !LauncherApplication.isScreenLarge()) {
+                final int width = getWidth();
+                final int height = getHeight();
                 final int pageHeight = getChildAt(0).getHeight();
 
                 // This determines the height of the glowing edge: 90% of the page height
@@ -1629,7 +1616,6 @@
     // we call this method whenever a drag and drop in Launcher finishes, even if Workspace was
     // never dragged over
     public void onDragStopped(boolean success) {
-        mLastDragView = null;
         // In the success case, DragController has already called onDragExit()
         if (!success) {
             doDragExit(null);
@@ -1657,18 +1643,10 @@
     public void enterSpringLoadedDragMode(CellLayout clThatWasClicked) {
         mShrinkState = ShrinkState.SPRING_LOADED;
         unshrink(clThatWasClicked, true);
-        mDragTargetLayout = getCurrentDropLayout();
-        mDragTargetLayout.onDragEnter();
-        mDragTargetLayout.setIsDragOverlapping(true);
-        showOutlines();
     }
 
     public void exitSpringLoadedDragMode(ShrinkState shrinkState) {
         shrink(shrinkState);
-        if (mDragTargetLayout != null) {
-            mDragTargetLayout.onDragExit();
-            mDragTargetLayout = null;
-        }
     }
 
     public void exitWidgetResizeMode() {
@@ -2323,24 +2301,45 @@
     }
 
     public void onDragEnter(DragObject d) {
-        mLastDragOverView = null;
         if (mDragTargetLayout != null) {
+            mDragTargetLayout.setIsDragOverlapping(false);
             mDragTargetLayout.onDragExit();
-            mDragTargetLayout = null; // Reset the drag state
         }
+        mDragTargetLayout = getCurrentDropLayout();
+        mDragTargetLayout.setIsDragOverlapping(true);
+        mDragTargetLayout.onDragEnter();
+        mLastDragView = d.dragView;
 
-        if (!mIsSmall) {
-            mDragTargetLayout = getCurrentDropLayout();
-            mDragTargetLayout.onDragEnter();
-
-            // Because we don't have space in the Phone UI (the CellLayouts run to the edge) we
-            // don't need to show the outlines
-            if (!LauncherApplication.isScreenLarge()) {
-                showOutlines();
-            }
+        // Because we don't have space in the Phone UI (the CellLayouts run to the edge) we
+        // don't need to show the outlines
+        if (LauncherApplication.isScreenLarge()) {
+            showOutlines();
         }
     }
 
+    private void doDragExit(DragObject d) {
+        // Clean up folders
+        cleanupFolderCreation(d);
+
+        // Reset the scroll area and previous drag target
+        onResetScrollArea();
+
+        if (mDragTargetLayout != null) {
+            mDragTargetLayout.setIsDragOverlapping(false);
+            mDragTargetLayout.onDragExit();
+        }
+        mLastDragView = null;
+        mLastDragOverView = null;
+
+        if (!mIsPageMoving) {
+            hideOutlines();
+        }
+    }
+
+    public void onDragExit(DragObject d) {
+        doDragExit(d);
+    }
+
     public DropTarget getDropTargetDelegate(DragObject d) {
         return null;
     }
@@ -2577,6 +2576,10 @@
      */
     private CellLayout findMatchingPageForDragOver(
             DragView dragView, int originX, int originY, int offsetX, int offsetY) {
+        return findMatchingPageForDragOver(dragView, originX, originY, offsetX, offsetY, false);
+    }
+    private CellLayout findMatchingPageForDragOver(
+            DragView dragView, int originX, int originY, int offsetX, int offsetY, boolean exact) {
         // We loop through all the screens (ie CellLayouts) and see which ones overlap
         // with the item being dragged and then choose the one that's closest to the touch point
         final int screenCount = getChildCount();
@@ -2600,7 +2603,7 @@
                 return cl;
             }
 
-            if (overlaps(cl, dragView, originX, originY, mTempInverseMatrix)) {
+            if (!exact && overlaps(cl, dragView, originX, originY, mTempInverseMatrix)) {
                 // Get the center of the cell layout in screen coordinates
                 final float[] cellLayoutCenter = mTempCellLayoutCenterCoordinates;
                 cellLayoutCenter[0] = cl.getWidth()/2;
@@ -2656,114 +2659,115 @@
     }
 
     public void onDragOver(DragObject d) {
-        // When touch is inside the scroll area, skip dragOver actions for the current screen
-        if (!mInScrollArea) {
-            CellLayout layout;
+        // Skip drag over events while we are dragging over side pages
+        if (mInScrollArea) return;
+        if (mIsInUnshrinkAnimation) return;
+
+        CellLayout layout;
+        ItemInfo item = (ItemInfo) d.dragInfo;
+
+        // Ensure that we have proper spans for the item that we are dropping
+        if (item.spanX < 0 || item.spanY < 0) throw new RuntimeException("Improper spans found");
+
+        // Identify whether we have dragged over a side page
+        if (mIsSmall) {
             int left = d.x - d.xOffset;
             int top = d.y - d.yOffset;
+            layout = findMatchingPageForDragOver(d.dragView, left, top, d.xOffset, d.yOffset, true);
+            if (layout != mDragTargetLayout) {
+                // Cancel all intermediate folder states
+                cleanupFolderCreation(d);
+
+                if (mDragTargetLayout != null) {
+                    mDragTargetLayout.setIsDragOverlapping(false);
+                    mDragTargetLayout.onDragExit();
+                }
+                mDragTargetLayout = layout;
+                if (mDragTargetLayout != null) {
+                    mDragTargetLayout.setIsDragOverlapping(true);
+                    mDragTargetLayout.onDragEnter();
+                } else {
+                    mLastDragOverView = null;
+                }
+
+                boolean isInSpringLoadedMode = (mShrinkState == ShrinkState.SPRING_LOADED);
+                if (isInSpringLoadedMode) {
+                    mSpringLoadedDragController.setAlarm(mDragTargetLayout);
+                }
+            }
+        } else {
+            layout = getCurrentDropLayout();
+            if (layout != mDragTargetLayout) {
+                if (mDragTargetLayout != null) {
+                    mDragTargetLayout.setIsDragOverlapping(false);
+                    mDragTargetLayout.onDragExit();
+                }
+                mDragTargetLayout = layout;
+                mDragTargetLayout.setIsDragOverlapping(true);
+                mDragTargetLayout.onDragEnter();
+            }
+        }
+
+        // Handle the drag over
+        if (mDragTargetLayout != null) {
+            final View child = (mDragInfo == null) ? null : mDragInfo.cell;
 
             mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset,
                     d.dragView, mDragViewVisualCenter);
 
-            boolean shrunken = mIsSmall || mIsInUnshrinkAnimation;
-            if (shrunken) {
-                mLastDragView = d.dragView;
-                mLastDragOriginX = left;
-                mLastDragOriginY = top;
-                mLastDragXOffset = d.xOffset;
-                mLastDragYOffset = d.yOffset;
-                layout = findMatchingPageForDragOver(d.dragView, left, top, d.xOffset, d.yOffset);
+            // We want the point to be mapped to the dragTarget.
+            mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
+            ItemInfo info = (ItemInfo) d.dragInfo;
 
-                if (layout != null && layout != mDragTargetLayout) {
-                    if (mDragTargetLayout != null) {
-                        mDragTargetLayout.setIsDragOverlapping(false);
-                        mDragTargetLayout.clearDragOutlines();
-                    }
-                    mDragTargetLayout = layout;
+            mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
+                    (int) mDragViewVisualCenter[1], 1, 1, mDragTargetLayout, mTargetCell);
+            final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0],
+                    mTargetCell[1]);
 
-                    // In spring-loaded mode, we still want the user to be able to hover over a
-                    // full screen (which is traditionally set to not accept drops) if they want
-                    // to get to pages beyond the screen that is full.
-                    boolean isInSpringLoadedMode = (mShrinkState == ShrinkState.SPRING_LOADED);
-                    boolean allowDragOver = (mDragTargetLayout != null);
-                    if (allowDragOver) {
-                        if (isInSpringLoadedMode) {
-                            mSpringLoadedDragController.setAlarm(mDragTargetLayout);
-                        }
-                        mDragTargetLayout.setIsDragOverlapping(true);
-                    }
-                }
-            } else {
-                layout = getCurrentDropLayout();
-                if (layout != mDragTargetLayout) {
-                    if (mDragTargetLayout != null) {
-                        mDragTargetLayout.onDragExit();
-                    }
-                    layout.onDragEnter();
-                    mDragTargetLayout = layout;
+            boolean userFolderPending = willCreateUserFolder(info, mDragTargetLayout,
+                    mTargetCell, false);
+            boolean isOverFolder = dragOverView instanceof FolderIcon;
+            if (dragOverView != mLastDragOverView) {
+                cancelFolderCreation();
+                if (mLastDragOverView != null && mLastDragOverView instanceof FolderIcon) {
+                    ((FolderIcon) mLastDragOverView).onDragExit(d.dragInfo);
                 }
             }
-            if (!shrunken || mShrinkState == ShrinkState.SPRING_LOADED) {
-                layout = getCurrentDropLayout();
 
-                final ItemInfo item = (ItemInfo) d.dragInfo;
-                if (d.dragInfo instanceof LauncherAppWidgetInfo) {
-                    LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) d.dragInfo;
+            if (userFolderPending && dragOverView != mLastDragOverView) {
+                mFolderCreationAlarm.setOnAlarmListener(new
+                        FolderCreationAlarmListener(mDragTargetLayout, mTargetCell[0], mTargetCell[1]));
+                mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT);
+            }
 
-                    if (widgetInfo.spanX == -1) {
-                        // Calculate the grid spans needed to fit this widget
-                        int[] spans = layout.rectToCell(widgetInfo.minWidth,
-                                widgetInfo.minHeight, null);
-                        item.spanX = spans[0];
-                        item.spanY = spans[1];
-                    }
-                }
-
+            if (dragOverView != mLastDragOverView && isOverFolder) {
+                ((FolderIcon) dragOverView).onDragEnter(d.dragInfo);
                 if (mDragTargetLayout != null) {
-                    final View child = (mDragInfo == null) ? null : mDragInfo.cell;
-                    // We want the point to be mapped to the dragTarget.
-                    mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
-                    ItemInfo info = (ItemInfo) d.dragInfo;
-
-                    mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
-                            (int) mDragViewVisualCenter[1], 1, 1, mDragTargetLayout, mTargetCell);
-                    final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0],
-                            mTargetCell[1]);
-
-                    boolean userFolderPending = willCreateUserFolder(info, mDragTargetLayout,
-                            mTargetCell, false);
-                    boolean isOverFolder = dragOverView instanceof FolderIcon;
-                    if (dragOverView != mLastDragOverView) {
-                        cancelFolderCreation();
-                        if (mLastDragOverView != null && mLastDragOverView instanceof FolderIcon) {
-                            ((FolderIcon) mLastDragOverView).onDragExit(d.dragInfo);
-                        }
-                    }
-
-                    if (userFolderPending && dragOverView != mLastDragOverView) {
-                        mFolderCreationAlarm.setOnAlarmListener(new
-                                FolderCreationAlarmListener(mDragTargetLayout, mTargetCell[0], mTargetCell[1]));
-                        mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT);
-                    }
-
-                    if (dragOverView != mLastDragOverView && isOverFolder) {
-                        ((FolderIcon) dragOverView).onDragEnter(d.dragInfo);
-                        if (mDragTargetLayout != null) {
-                            mDragTargetLayout.clearDragOutlines();
-                        }
-                    }
-                    mLastDragOverView = dragOverView;
-
-                    if (!mCreateUserFolderOnDrop && !isOverFolder) {
-                        mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
-                                (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1],
-                                item.spanX, item.spanY);
-                    }
+                    mDragTargetLayout.clearDragOutlines();
                 }
             }
+            mLastDragOverView = dragOverView;
+
+            if (!mCreateUserFolderOnDrop && !isOverFolder) {
+                mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
+                        (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1],
+                        item.spanX, item.spanY);
+            }
         }
     }
 
+    private void cleanupFolderCreation(DragObject d) {
+        if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) {
+            mDragFolderRingAnimator.animateToNaturalState();
+        }
+        if (mLastDragOverView != null && mLastDragOverView instanceof FolderIcon) {
+            if (d != null) {
+                ((FolderIcon) mLastDragOverView).onDragExit(d.dragInfo);
+            }
+        }
+        mFolderCreationAlarm.cancelAlarm();
+    }
+
     private void cancelFolderCreation() {
         if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) {
             mDragFolderRingAnimator.animateToNaturalState();
@@ -2796,30 +2800,6 @@
         }
     }
 
-    private void doDragExit(DragObject d) {
-        if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) {
-            mDragFolderRingAnimator.animateToNaturalState();
-        }
-        if (mLastDragOverView != null && mLastDragOverView instanceof FolderIcon) {
-            if (d != null) {
-                ((FolderIcon) mLastDragOverView).onDragExit(d.dragInfo);
-            }
-        }
-        mFolderCreationAlarm.cancelAlarm();
-
-        if (mDragTargetLayout != null) {
-            mDragTargetLayout.onDragExit();
-        }
-        if (!mIsPageMoving) {
-            hideOutlines();
-        }
-        clearAllHovers();
-    }
-
-    public void onDragExit(DragObject d) {
-        doDragExit(d);
-    }
-
     @Override
     public void getHitRect(Rect outRect) {
         // We want the workspace to have the whole area of the display (it will find the correct
@@ -3056,42 +3036,52 @@
             cancelFolderCreation();
 
             if (layout != null) {
-                layout.setIsDragOverlapping(true);
-
+                // Exit the current layout and mark the overlapping layout
                 if (mDragTargetLayout != null) {
+                    mDragTargetLayout.setIsDragOverlapping(false);
                     mDragTargetLayout.onDragExit();
-                    mDragTargetLayout = layout;
                 }
-                // In portrait, need to redraw the edge glow when entering the scroll area
-                if (getHeight() > getWidth()) {
-                    invalidate();
-                }
+                mDragTargetLayout = layout;
+                mDragTargetLayout.setIsDragOverlapping(true);
+
+                // Workspace is responsible for drawing the edge glow on adjacent pages,
+                // so we need to redraw the workspace when this may have changed.
+                invalidate();
             }
         }
     }
 
-    private void clearAllHovers() {
-        final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            ((CellLayout) getChildAt(i)).setIsDragOverlapping(false);
-        }
-
-        // In portrait, workspace is responsible for drawing the edge glow on adjacent pages,
-        // so we need to redraw the workspace when this may have changed.
-        if (getHeight() > getWidth()) {
-            invalidate();
-        }
-    }
-
     @Override
     public void onExitScrollArea() {
         if (mInScrollArea) {
-            mInScrollArea = false;
+            if (mDragTargetLayout != null) {
+                // Unmark the overlapping layout and re-enter the current layout
+                mDragTargetLayout.setIsDragOverlapping(false);
+                mDragTargetLayout = getCurrentDropLayout();
+                mDragTargetLayout.onDragEnter();
+
+                // Workspace is responsible for drawing the edge glow on adjacent pages,
+                // so we need to redraw the workspace when this may have changed.
+                invalidate();
+            }
             mPendingScrollDirection = DragController.SCROLL_NONE;
-            clearAllHovers();
+            mInScrollArea = false;
         }
     }
 
+    private void onResetScrollArea() {
+        if (mDragTargetLayout != null) {
+            // Unmark the overlapping layout
+            mDragTargetLayout.setIsDragOverlapping(false);
+
+            // Workspace is responsible for drawing the edge glow on adjacent pages,
+            // so we need to redraw the workspace when this may have changed.
+            invalidate();
+        }
+        mPendingScrollDirection = DragController.SCROLL_NONE;
+        mInScrollArea = false;
+    }
+
     public Folder getFolderForTag(Object tag) {
         final int screenCount = getChildCount();
         for (int screen = 0; screen < screenCount; screen++) {