Fixing up some Folder bugs

-> Rendering properly while in spring-loaded mode
-> Fixed bug where sometimes the folder's background would vanish
-> Fixed bug where the folder background was "stuck" in a fixed
   location, not following the folder
-> Can now add to folders and create folders from spring-loaded mode

Change-Id: Ie1c5583a6230a192e6d07763d001b50053daca43
diff --git a/src/com/android/launcher2/AllApps2D.java b/src/com/android/launcher2/AllApps2D.java
index 44af7b7..4547f54 100644
--- a/src/com/android/launcher2/AllApps2D.java
+++ b/src/com/android/launcher2/AllApps2D.java
@@ -16,8 +16,6 @@
 
 package com.android.launcher2;
 
-import com.android.launcher.R;
-
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Resources;
@@ -37,6 +35,9 @@
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
+
 import java.util.ArrayList;
 import java.util.Collections;
 
@@ -208,7 +209,7 @@
     }
 
     @Override
-    public void onDropCompleted(View target, Object dragInfo, boolean success) {
+    public void onDropCompleted(View target, DragObject d, boolean success) {
     }
 
     /**
diff --git a/src/com/android/launcher2/AllApps3D.java b/src/com/android/launcher2/AllApps3D.java
index 0e512c6..837ddbb 100644
--- a/src/com/android/launcher2/AllApps3D.java
+++ b/src/com/android/launcher2/AllApps3D.java
@@ -16,12 +16,6 @@
 
 package com.android.launcher2;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-
-import com.android.launcher.R;
-
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Resources;
@@ -29,9 +23,20 @@
 import android.graphics.Canvas;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
-import android.renderscript.*;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.Mesh;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramFragmentFixedFunction;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.renderscript.ProgramVertexFixedFunction;
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+import android.renderscript.Sampler;
 import android.util.AttributeSet;
-import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -42,6 +47,13 @@
 import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityEvent;
 
+import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
 public class AllApps3D extends RSSurfaceView
         implements AllAppsView, View.OnClickListener, View.OnLongClickListener, DragSource {
     private static final String TAG = "Launcher.AllApps3D";
@@ -744,7 +756,7 @@
     }
 
     @Override
-    public void onDropCompleted(View target, Object dragInfo, boolean success) {
+    public void onDropCompleted(View target, DragObject d, boolean success) {
         mLauncher.getWorkspace().onDragStopped(success);
         mLauncher.unlockScreenOrientation();
     }
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index 0f364f8..ae8b970 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -16,9 +16,6 @@
 
 package com.android.launcher2;
 
-import com.android.launcher.R;
-import com.android.launcher2.DropTarget.DragObject;
-
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Resources;
@@ -34,6 +31,8 @@
 import android.widget.Checkable;
 import android.widget.TextView;
 
+import com.android.launcher.R;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
@@ -412,7 +411,7 @@
     }
 
     @Override
-    public void onDropCompleted(View target, Object dragInfo, boolean success) {
+    public void onDropCompleted(View target, DragObject d, boolean success) {
         // close the choice action mode if we have a proper drop
         if (target != this) {
             endChoiceMode();
diff --git a/src/com/android/launcher2/ApplicationInfoDropTarget.java b/src/com/android/launcher2/ApplicationInfoDropTarget.java
index 311ac7e..fa4663a 100644
--- a/src/com/android/launcher2/ApplicationInfoDropTarget.java
+++ b/src/com/android/launcher2/ApplicationInfoDropTarget.java
@@ -16,9 +16,6 @@
 
 package com.android.launcher2;
 
-import com.android.launcher.R;
-import com.android.launcher2.DropTarget.DragObject;
-
 import android.animation.Animator;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
@@ -30,6 +27,8 @@
 import android.util.AttributeSet;
 import android.view.View;
 
+import com.android.launcher.R;
+
 /**
  * Implements a DropTarget which allows applications to be dropped on it,
  * in order to launch the application info for that app.
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index 7c6742f..62a8936 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -16,11 +16,6 @@
 
 package com.android.launcher2;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -38,9 +33,9 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
 import android.graphics.Canvas;
 import android.graphics.Rect;
+import android.graphics.Bitmap.Config;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -56,6 +51,12 @@
 import android.widget.Toast;
 
 import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
 
 public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
         AllAppsView, View.OnClickListener, DragSource {
@@ -448,7 +449,7 @@
     @Override
     public void onDragViewVisible() {}
     @Override
-    public void onDropCompleted(View target, Object dragInfo, boolean success) {
+    public void onDropCompleted(View target, DragObject d, boolean success) {
         endDragging(success);
 
         // Display an error message if the drag failed due to there not being enough space on the
@@ -459,7 +460,7 @@
                 int currentScreen = mLauncher.getCurrentWorkspaceScreen();
                 Workspace workspace = (Workspace) target;
                 CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen);
-                ItemInfo itemInfo = (ItemInfo) dragInfo;
+                ItemInfo itemInfo = (ItemInfo) d.dragInfo;
                 if (layout != null) {
                     layout.calculateSpans(itemInfo);
                     showOutOfSpaceMessage =
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index eb92d20..12b0158 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -16,8 +16,6 @@
 
 package com.android.launcher2;
 
-import java.util.Arrays;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -49,6 +47,8 @@
 
 import com.android.launcher.R;
 
+import java.util.Arrays;
+
 public class CellLayout extends ViewGroup {
     static final String TAG = "CellLayout";
 
@@ -1150,12 +1150,12 @@
         // re-mark space taken by ignoreView as occupied
         markCellsAsOccupiedForView(ignoreView);
 
-        // Return null if no suitable location found
-        if (bestDistance < Double.MAX_VALUE) {
-            return bestXY;
-        } else {
-            return null;
+        // Return -1, -1 if no suitable location found
+        if (bestDistance == Double.MAX_VALUE) {
+            bestXY[0] = -1;
+            bestXY[1] = -1;
         }
+        return bestXY;
     }
 
     /**
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 932af89..b2a7603 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -16,10 +16,6 @@
 
 package com.android.launcher2;
 
-import com.android.launcher.R;
-
-import org.xmlpull.v1.XmlPullParser;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
@@ -54,7 +50,6 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.View.MeasureSpec;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.LinearInterpolator;
 import android.widget.Checkable;
@@ -62,6 +57,11 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
+
+import org.xmlpull.v1.XmlPullParser;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -402,7 +402,7 @@
         }
     }
 
-    public void onDropCompleted(View target, Object dragInfo, boolean success) {
+    public void onDropCompleted(View target, DragObject d, boolean success) {
         final DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
 
         // Create a view, identical to the drag view, that is only used for animating the
@@ -413,7 +413,7 @@
 
         if (success) {
             resetCheckedItem(true);
-            animateDropOntoScreen(animView, (ItemInfo) dragInfo, DROP_ANIM_DURATION, 0);
+            animateDropOntoScreen(animView, (ItemInfo) d.dragInfo, DROP_ANIM_DURATION, 0);
         } else {
             // Animate the icon/widget back to its original position
             animateIntoPosition(animView, mDragViewOrigin[0], mDragViewOrigin[1], new Runnable() {
diff --git a/src/com/android/launcher2/DeleteZone.java b/src/com/android/launcher2/DeleteZone.java
index c349e5d..025b292 100644
--- a/src/com/android/launcher2/DeleteZone.java
+++ b/src/com/android/launcher2/DeleteZone.java
@@ -33,7 +33,6 @@
 import android.view.animation.AccelerateInterpolator;
 
 import com.android.launcher.R;
-import com.android.launcher2.DropTarget.DragObject;
 
 public class DeleteZone extends IconDropTarget {
     private static final int ORIENTATION_HORIZONTAL = 1;
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 1690cac..8ad5c7c 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -16,8 +16,6 @@
 
 package com.android.launcher2;
 
-import java.util.ArrayList;
-
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Rect;
@@ -35,7 +33,8 @@
 import android.view.inputmethod.InputMethodManager;
 
 import com.android.launcher.R;
-import com.android.launcher2.DropTarget.DragObject;
+
+import java.util.ArrayList;
 
 /**
  * Class for initiating a drag within a view or across multiple views.
@@ -374,7 +373,7 @@
     public void cancelDrag() {
         if (mDragging) {
             // Should we also be calling onDragExit() here?
-            mDragObject.dragSource.onDropCompleted(null, mDragObject.dragInfo, false);
+            mDragObject.dragSource.onDropCompleted(null, mDragObject, false);
         }
         endDrag();
     }
@@ -572,8 +571,7 @@
                 accepted = true;
             }
         }
-        mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject.dragInfo, accepted);
-
+        mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject, accepted);
     }
 
     private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {
diff --git a/src/com/android/launcher2/DragSource.java b/src/com/android/launcher2/DragSource.java
index 649120d..2a8f263 100644
--- a/src/com/android/launcher2/DragSource.java
+++ b/src/com/android/launcher2/DragSource.java
@@ -18,6 +18,8 @@
 
 import android.view.View;
 
+import com.android.launcher2.DropTarget.DragObject;
+
 /**
  * Interface defining an object that can originate a drag.
  *
@@ -29,5 +31,5 @@
      */
     void onDragViewVisible();
 
-    void onDropCompleted(View target, Object dragInfo, boolean success);
+    void onDropCompleted(View target, DragObject d, boolean success);
 }
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 0b35acb..08907c9 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -16,8 +16,6 @@
 
 package com.android.launcher2;
 
-import java.util.ArrayList;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
@@ -43,6 +41,8 @@
 import com.android.launcher.R;
 import com.android.launcher2.FolderInfo.FolderListener;
 
+import java.util.ArrayList;
+
 /**
  * Represents a set of icons chosen by the user or generated by the system.
  */
@@ -448,7 +448,7 @@
         return r;
     }
 
-    public void onDropCompleted(View target, Object dragInfo, boolean success) {
+    public void onDropCompleted(View target, DragObject d, boolean success) {
     }
 
     public boolean isDropEnabled() {
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index 952d704..449068c 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -16,8 +16,6 @@
 
 package com.android.launcher2;
 
-import java.util.ArrayList;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
@@ -36,12 +34,15 @@
 import android.widget.TextView;
 
 import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
 import com.android.launcher2.FolderInfo.FolderListener;
 
+import java.util.ArrayList;
+
 /**
  * An icon that can appear on in the workspace representing an {@link UserFolder}.
  */
-public class FolderIcon extends FrameLayout implements DropTarget, FolderListener {
+public class FolderIcon extends FrameLayout implements FolderListener {
     private Launcher mLauncher;
     Folder mFolder;
     FolderInfo mInfo;
@@ -63,7 +64,7 @@
     private static final float OUTER_RING_GROWTH_FACTOR = 0.3f;
 
     // The amount of vertical spread between items in the stack [0...1]
-    private static final float PERSPECTIVE_SHIFT_FACTOR = 0.18f;
+    private static final float PERSPECTIVE_SHIFT_FACTOR = 0.3f;
 
     // The degree to which the item in the back of the stack is scaled [0...1]
     // (0 means it's not scaled at all, 1 means it's scaled to nothing)
@@ -72,9 +73,6 @@
     // The percentage of the FolderIcons view that will be dedicated to the items preview
     private static final float SPACE_PERCENTAGE_FOR_ICONS = 0.8f;
 
-    public static Drawable sFolderOuterRingDrawable = null;
-    public static Drawable sFolderInnerRingDrawable = null;
-
     private int mOriginalWidth = -1;
     private int mOriginalHeight = -1;
 
@@ -127,29 +125,43 @@
         public float mInnerRingScale;
         public FolderIcon mFolderIcon = null;
         private Launcher mLauncher;
+        public Drawable mOuterRingDrawable = null;
+        public Drawable mInnerRingDrawable = null;
+        public static Drawable sSharedOuterRingDrawable = null;
+        public static Drawable sSharedInnerRingDrawable = null;
+        private ValueAnimator mAcceptAnimator;
+        private ValueAnimator mNeutralAnimator;
 
         public FolderRingAnimator(Launcher launcher, FolderIcon folderIcon) {
             mLauncher = launcher;
             mFolderIcon = folderIcon;
-            if (sFolderOuterRingDrawable == null) {
-                sFolderOuterRingDrawable =
+            mOuterRingDrawable =
+                    launcher.getResources().getDrawable(R.drawable.portal_ring_outer_holo);
+            mInnerRingDrawable =
+                    launcher.getResources().getDrawable(R.drawable.portal_ring_inner_holo);
+            if (sSharedOuterRingDrawable == null) {
+                sSharedOuterRingDrawable =
                         launcher.getResources().getDrawable(R.drawable.portal_ring_outer_holo);
             }
-            if (sFolderInnerRingDrawable == null) {
-                sFolderInnerRingDrawable =
+            if (sSharedInnerRingDrawable == null) {
+                sSharedInnerRingDrawable =
                         launcher.getResources().getDrawable(R.drawable.portal_ring_inner_holo);
             }
         }
 
+        // Location is expressed in window coordinates
         public void setLocation(int x, int y) {
             mFolderLocX = x;
             mFolderLocY = y;
         }
 
         public void animateToAcceptState() {
-            ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
-            va.setDuration(CONSUMPTION_ANIMATION_DURATION);
-            va.addUpdateListener(new AnimatorUpdateListener() {
+            if (mNeutralAnimator != null) {
+                mNeutralAnimator.cancel();
+            }
+            mAcceptAnimator = ValueAnimator.ofFloat(0f, 1f);
+            mAcceptAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
+            mAcceptAnimator.addUpdateListener(new AnimatorUpdateListener() {
                 public void onAnimationUpdate(ValueAnimator animation) {
                     final float percent = (Float) animation.getAnimatedValue();
                     mOuterRingScale = OUTER_RING_BASELINE_SCALE + percent * OUTER_RING_GROWTH_FACTOR;
@@ -160,25 +172,24 @@
                     }
                 }
             });
-            va.addListener(new AnimatorListenerAdapter() {
+            mAcceptAnimator.addListener(new AnimatorListenerAdapter() {
                 @Override
-                public void onAnimationEnd(Animator animation) {
-                    // Instead of setting the background drawable to null, we set the color to
-                    // transparent. Setting the background drawable to null results in onDraw
-                    // not getting called.
+                public void onAnimationStart(Animator animation) {
                     if (mFolderIcon != null) {
-                        mFolderIcon.setBackgroundColor(Color.TRANSPARENT);
-                        mFolderIcon.requestLayout();
+                        mFolderIcon.setBackgroundDrawable(null);
                     }
                 }
             });
-            va.start();
+            mAcceptAnimator.start();
         }
 
         public void animateToNaturalState() {
-            ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
-            va.setDuration(CONSUMPTION_ANIMATION_DURATION);
-            va.addUpdateListener(new AnimatorUpdateListener() {
+            if (mAcceptAnimator != null) {
+                mAcceptAnimator.cancel();
+            }
+            mNeutralAnimator = ValueAnimator.ofFloat(0f, 1f);
+            mNeutralAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
+            mNeutralAnimator.addUpdateListener(new AnimatorUpdateListener() {
                 public void onAnimationUpdate(ValueAnimator animation) {
                     final float percent = (Float) animation.getAnimatedValue();
                     mOuterRingScale = OUTER_RING_BASELINE_SCALE + OUTER_RING_GROWTH_FACTOR
@@ -191,18 +202,19 @@
                     }
                 }
             });
-            va.addListener(new AnimatorListenerAdapter() {
+            mNeutralAnimator.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
                     if (mFolderIcon != null) {
-                        mFolderIcon.setBackgroundDrawable(sFolderInnerRingDrawable);
+                        mFolderIcon.setBackgroundDrawable(mInnerRingDrawable);
                     }
                     mLauncher.getWorkspace().hideFolderAccept(FolderRingAnimator.this);
                 }
             });
-            va.start();
+            mNeutralAnimator.start();
         }
 
+        // Location is expressed in window coordinates
         public void getLocation(int[] loc) {
             loc[0] = mFolderLocX;
             loc[1] = mFolderLocY;
@@ -224,8 +236,8 @@
                 !mFolder.isFull() && item != mInfo);
     }
 
-    public boolean acceptDrop(DragObject d) {
-        final ItemInfo item = (ItemInfo) d.dragInfo;
+    public boolean acceptDrop(Object dragInfo) {
+        final ItemInfo item = (ItemInfo) dragInfo;
         return willAcceptItem(item);
     }
 
@@ -234,19 +246,6 @@
         LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
     }
 
-    public void onDrop(DragObject d) {
-        ShortcutInfo item;
-        if (d.dragInfo instanceof ApplicationInfo) {
-            // Came from all apps -- make a copy
-            item = ((ApplicationInfo) d.dragInfo).makeShortcut();
-        } else {
-            item = (ShortcutInfo) d.dragInfo;
-        }
-        item.cellX = -1;
-        item.cellY = -1;
-        addItem(item);
-    }
-
     void saveState(CellLayout.LayoutParams lp) {
         mOriginalWidth = lp.width;
         mOriginalHeight = lp.height;
@@ -255,35 +254,48 @@
     private void determineFolderLocationInWorkspace() {
         int tvLocation[] = new int[2];
         int wsLocation[] = new int[2];
-        getLocationOnScreen(tvLocation);
-        mLauncher.getWorkspace().getLocationOnScreen(wsLocation);
+        getLocationInWindow(tvLocation);
+        mLauncher.getWorkspace().getLocationInWindow(wsLocation);
 
         int x = tvLocation[0] - wsLocation[0] + getMeasuredWidth() / 2;
         int y = tvLocation[1] - wsLocation[1] + getMeasuredHeight() / 2;
         mFolderRingAnimator.setLocation(x, y);
     }
 
-    public void onDragEnter(DragObject d) {
-        if (!willAcceptItem((ItemInfo) d.dragInfo)) return;
+    public void onDragEnter(Object dragInfo) {
+        if (!willAcceptItem((ItemInfo) dragInfo)) return;
         determineFolderLocationInWorkspace();
         mLauncher.getWorkspace().showFolderAccept(mFolderRingAnimator);
         mFolderRingAnimator.animateToAcceptState();
     }
 
-    public void onDragOver(DragObject d) {
+    public void onDragOver(Object dragInfo) {
     }
 
-    public void onDragExit(DragObject d) {
-        if (!willAcceptItem((ItemInfo) d.dragInfo)) return;
+    public void onDragExit(Object dragInfo) {
+        if (!willAcceptItem((ItemInfo) dragInfo)) return;
         mFolderRingAnimator.animateToNaturalState();
     }
 
+    public void onDrop(Object dragInfo) {
+        ShortcutInfo item;
+        if (dragInfo instanceof ApplicationInfo) {
+            // Came from all apps -- make a copy
+            item = ((ApplicationInfo) dragInfo).makeShortcut();
+        } else {
+            item = (ShortcutInfo) dragInfo;
+        }
+        item.cellX = -1;
+        item.cellY = -1;
+        addItem(item);
+    }
+
     public DropTarget getDropTargetDelegate(DragObject d) {
         return null;
     }
 
     @Override
-    protected void onDraw(Canvas canvas) {
+    protected void dispatchDraw(Canvas canvas) {
         if (mFolder == null) return;
         if (mFolder.getItemCount() == 0) return;
 
@@ -337,7 +349,6 @@
             }
             canvas.restore();
         }
-
         canvas.restore();
     }
 
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index eb533fe..22ce003 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -17,14 +17,6 @@
 
 package com.android.launcher2;
 
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -107,6 +99,14 @@
 import com.android.launcher.R;
 import com.android.launcher2.Workspace.ShrinkState;
 
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
 /**
  * Default launcher application.
  */
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index e0472fc..812763f 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -16,10 +16,6 @@
 
 package com.android.launcher2;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -69,6 +65,10 @@
 import com.android.launcher2.FolderIcon.FolderRingAnimator;
 import com.android.launcher2.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
 
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
 /**
  * The workspace is a wide area with a wallpaper and a finite number of pages.
  * Each page contains a number of icons, folders or widgets the user can
@@ -136,7 +136,7 @@
     /**
      * Target drop area calculated during last acceptDrop call.
      */
-    private int[] mTargetCell = null;
+    private int[] mTargetCell = new int[2];
 
     /**
      * The CellLayout that is currently being dragged over
@@ -156,6 +156,7 @@
     private float[] mTempTouchCoordinates = new float[2];
     private float[] mTempCellLayoutCenterCoordinates = new float[2];
     private float[] mTempDragBottomRightCoordinates = new float[2];
+    private float[] mTempFloatTuple = new float[2];
     private Matrix mTempInverseMatrix = new Matrix();
     private int[] mTempLocation = new int[2];
 
@@ -222,7 +223,7 @@
     private ArrayList<FolderRingAnimator> mFolderOuterRings = new ArrayList<FolderRingAnimator>();
 
     // Variables relating to the creation of user folders by hovering shortcuts over shortcuts
-    private static final int FOLDER_CREATION_TIMEOUT = 400;
+    private static final int FOLDER_CREATION_TIMEOUT = 250;
     private final Alarm mFolderCreationAlarm = new Alarm();
     private FolderRingAnimator mDragFolderRingAnimator = null;
     private View mLastDragOverView = null;
@@ -1232,29 +1233,63 @@
 
         // The folder outer / inner ring image(s)
         for (int i = 0; i < mFolderOuterRings.size(); i++) {
+            View currentPage = getChildAt(getCurrentPage());
+            Matrix m = currentPage.getMatrix();
 
             // Draw outer ring
             FolderRingAnimator fra = mFolderOuterRings.get(i);
-            Drawable d = FolderIcon.sFolderOuterRingDrawable;
+            Drawable d = FolderRingAnimator.sSharedOuterRingDrawable;
             int width = (int) (d.getIntrinsicWidth() * fra.getOuterRingScale());
             int height = (int) (d.getIntrinsicHeight() * fra.getOuterRingScale());
             fra.getLocation(mTempLocation);
-            int x = mTempLocation[0] + mScrollX - width / 2;
-            int y = mTempLocation[1] + mScrollY - height / 2;
-            d.setBounds(x, y, x + width, y + height);
+
+            // First we map the folder's location from window coordinates to its containing
+            // CellLayout's coordinates. Then we transform the coordinates according to the
+            // CellLayout's transform. Finally, we map this back into the coordinates of the
+            // the window (ie. Workspace).
+            int x = mTempLocation[0] + mScrollX - width / 2 - currentPage.getLeft();
+            int y = mTempLocation[1] + mScrollY - height / 2 - currentPage.getTop();
+            mTempFloatTuple[0] = x;
+            mTempFloatTuple[1] = y;
+            m.mapPoints(mTempFloatTuple);
+            x = (int) (mTempFloatTuple[0]) + currentPage.getLeft();
+            y = (int) (mTempFloatTuple[1]) + currentPage.getTop();
+
+            canvas.save();
+            canvas.translate(x, y);
+            d.setBounds(0, 0, (int) (width * currentPage.getScaleX()),
+                    (int) (height * currentPage.getScaleY()));
             d.draw(canvas);
+            canvas.restore();
 
             // Draw inner ring
             if (fra.mFolderIcon != null) {
-                int folderWidth = fra.mFolderIcon != null ? fra.mFolderIcon.getMeasuredWidth() : mCellWidth;
-                int folderHeight = fra.mFolderIcon != null ? fra.mFolderIcon.getMeasuredWidth() : mCellHeight;
-                d = FolderIcon.sFolderInnerRingDrawable;
+                int folderWidth = fra.mFolderIcon != null ?
+                        fra.mFolderIcon.getMeasuredWidth() : mCellWidth;
+                int folderHeight = fra.mFolderIcon != null ?
+                        fra.mFolderIcon.getMeasuredWidth() : mCellHeight;
+                d = FolderRingAnimator.sSharedInnerRingDrawable;
                 width = (int) (folderWidth * fra.getInnerRingScale());
                 height = (int) (folderHeight * fra.getInnerRingScale());
-                x = mTempLocation[0] + mScrollX - width / 2;
-                y = mTempLocation[1] + mScrollY - height / 2;
-                d.setBounds(x, y, x + width, y + height);
+
+                // First we map the folder's location from window coordinates to its containing
+                // CellLayout's coordinates. Then we transform the coordinates according to the
+                // CellLayout's transform. Finally, we map this back into the coordinates of the
+                // the window (ie. Workspace).
+                x = mTempLocation[0] + mScrollX - width / 2 - currentPage.getLeft();
+                y = mTempLocation[1] + mScrollY - height / 2 - currentPage.getTop();
+                mTempFloatTuple[0] = x;
+                mTempFloatTuple[1] = y;
+                m.mapPoints(mTempFloatTuple);
+                x = (int) (mTempFloatTuple[0]) + currentPage.getLeft();
+                y = (int) (mTempFloatTuple[1]) + currentPage.getTop();
+
+                canvas.save();
+                canvas.translate(x, y);
+                d.setBounds(0, 0, (int) (width * currentPage.getScaleX()),
+                        (int) (height * currentPage.getScaleY()));
                 d.draw(canvas);
+                canvas.restore();
             }
         }
         super.onDraw(canvas);
@@ -1867,7 +1902,7 @@
         mLastDragView = null;
         // In the success case, DragController has already called onDragExit()
         if (!success) {
-            doDragExit();
+            doDragExit(null);
         }
         mIsDragInProcess = false;
         updateWhichPagesAcceptDrops(mShrinkState);
@@ -2407,42 +2442,29 @@
         return true;
     }
 
-    boolean willCreateUserFolder(ItemInfo info, CellLayout target, int originX, int originY) {
-        mTargetCell = findNearestArea(originX, originY, 1, 1, target, mTargetCell);
-
-        View v = target.getChildAt(mTargetCell[0], mTargetCell[1]);
-        boolean hasntMoved = mDragInfo != null && (mDragInfo.cellX == mTargetCell[0] &&
-                mDragInfo.cellY == mTargetCell[1]);
+    boolean willCreateUserFolder(ItemInfo info, View v, int[] targetCell) {
+        boolean hasntMoved = mDragInfo != null
+                && (mDragInfo.cellX == targetCell[0] && mDragInfo.cellY == targetCell[1]);
 
         if (v == null || hasntMoved) return false;
 
         boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo);
         boolean willBecomeShortcut =
-            (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
-            info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT);
+                (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
+                info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT);
 
         return (aboveShortcut && willBecomeShortcut);
     }
 
-    boolean createUserFolderIfNecessary(View newView, CellLayout target, int originX,
-            int originY, boolean external) {
-        int spanX = mDragInfo != null ? mDragInfo.spanX : 1;
-        int spanY = mDragInfo != null ? mDragInfo.spanY : 1;
-
-        // First we find the cell nearest to point at which the item is dropped, without
-        // any consideration to whether there is an item there.
-        mTargetCell = findNearestArea(originX, originY,
-                spanX, spanY, target,
-                mTargetCell);
-
-        View v = target.getChildAt(mTargetCell[0], mTargetCell[1]);
-        boolean hasntMoved = mDragInfo != null && (mDragInfo.cellX == mTargetCell[0] &&
-                mDragInfo.cellY == mTargetCell[1]);
+    boolean createUserFolderIfNecessary(View newView, CellLayout target,
+            int[] targetCell, boolean external) {
+        View v = target.getChildAt(targetCell[0], targetCell[1]);
+        boolean hasntMoved = mDragInfo != null
+                && (mDragInfo.cellX == targetCell[0] && mDragInfo.cellY == targetCell[1]);
 
         if (v == null || hasntMoved || !mCreateUserFolderOnDrop) return false;
         mCreateUserFolderOnDrop = false;
-        final int screen = (mTargetCell == null) ?
-                mDragInfo.screen : indexOfChild(target);
+        final int screen = (targetCell == null) ? mDragInfo.screen : indexOfChild(target);
 
         boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo);
         boolean willBecomeShortcut = (newView.getTag() instanceof ShortcutInfo);
@@ -2458,7 +2480,7 @@
             }
 
             target.removeView(v);
-            FolderIcon fi = mLauncher.addFolder(screen, mTargetCell[0], mTargetCell[1]);
+            FolderIcon fi = mLauncher.addFolder(screen, targetCell[0], targetCell[1]);
             destInfo.cellX = -1;
             destInfo.cellY = -1;
             sourceInfo.cellX = -1;
@@ -2470,6 +2492,26 @@
         return false;
     }
 
+    boolean addToExistingFolderIfNecessary(View newView, CellLayout target, int[] tagetCell,
+            Object dragInfo, boolean external) {
+        View dropOverView = target.getChildAt(tagetCell[0], tagetCell[1]);
+        if (dropOverView instanceof FolderIcon) {
+            FolderIcon fi = (FolderIcon) dropOverView;
+            if (fi.acceptDrop(dragInfo)) {
+                fi.onDrop(dragInfo);
+
+                // if the drag started here, we need to remove it from the workspace
+                if (!external) {
+                    int fromScreen = mDragInfo.screen;
+                    CellLayout sourceLayout = (CellLayout) getChildAt(fromScreen);
+                    sourceLayout.removeView(newView);
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
     public void onDrop(DragObject d) {
 
         mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView,
@@ -2518,13 +2560,25 @@
 
             if (dropTargetLayout != null) {
                 // Move internally
-                final int screen = (mTargetCell == null) ?
+                final int screen = (mTargetCell[0] < 0) ?
                         mDragInfo.screen : indexOfChild(dropTargetLayout);
 
-                // If the item being dropped is a shortcut and the nearest drop cell also contains
+                int spanX = mDragInfo != null ? mDragInfo.spanX : 1;
+                int spanY = mDragInfo != null ? mDragInfo.spanY : 1;
+                // First we find the cell nearest to point at which the item is
+                // dropped, without any consideration to whether there is an item there.
+                mTargetCell = findNearestArea((int) mDragViewVisualCenter[0], (int)
+                        mDragViewVisualCenter[1], spanX, spanY, dropTargetLayout, mTargetCell);
+                // If the item being dropped is a shortcut and the nearest drop
+                // cell also contains
                 // a shortcut, then create a folder with the two shortcuts.
                 if (!dropInscrollArea && createUserFolderIfNecessary(cell, dropTargetLayout,
-                        (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], false)) {
+                        mTargetCell, false)) {
+                    return;
+                }
+
+                if (addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,
+                        d.dragInfo, false)) {
                     return;
                 }
 
@@ -2538,12 +2592,12 @@
                     snapToPage(screen);
                 }
 
-                if (mTargetCell != null) {
+                if (mTargetCell[0] >= 0 && mTargetCell[1] >= 0) {
                     if (screen != mDragInfo.screen) {
                         // Reparent the view
                         ((CellLayout) getChildAt(mDragInfo.screen)).removeView(cell);
-                        addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
-                                mDragInfo.spanX, mDragInfo.spanY);
+                        addInScreen(cell, screen, mTargetCell[0], mTargetCell[1], mDragInfo.spanX,
+                                mDragInfo.spanY);
                     }
 
                     // update the item's position after drop
@@ -2565,10 +2619,9 @@
                         if (pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
                             final Runnable resizeRunnable = new Runnable() {
                                 public void run() {
-                                    DragLayer dragLayer = (DragLayer)
-                                            mLauncher.findViewById(R.id.drag_layer);
-                                    dragLayer.addResizeFrame(info, hostView,
-                                            cellLayout);
+                                    DragLayer dragLayer =
+                                            (DragLayer) mLauncher.findViewById(R.id.drag_layer);
+                                    dragLayer.addResizeFrame(info, hostView, cellLayout);
                                 }
                             };
                             post(new Runnable() {
@@ -2617,7 +2670,7 @@
 
     public void onDragEnter(DragObject d) {
         mDragTargetLayout = null; // Reset the drag state
-
+        mLastDragOverView = null;
         if (!mIsSmall) {
             mDragTargetLayout = getCurrentDropLayout();
             mDragTargetLayout.onDragEnter();
@@ -3036,8 +3089,8 @@
 
                     if (widgetInfo.spanX == -1) {
                         // Calculate the grid spans needed to fit this widget
-                        int[] spans = layout.rectToCell(
-                                widgetInfo.minWidth, widgetInfo.minHeight, null);
+                        int[] spans = layout.rectToCell(widgetInfo.minWidth,
+                                widgetInfo.minHeight, null);
                         item.spanX = spans[0];
                         item.spanY = spans[1];
                     }
@@ -3049,37 +3102,40 @@
                     mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
                     ItemInfo info = (ItemInfo) d.dragInfo;
 
-                    boolean willCreateUserFolder = willCreateUserFolder(info, mDragTargetLayout,
-                            (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1]);
+                    mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
+                            (int) mDragViewVisualCenter[1], 1, 1, mDragTargetLayout, mTargetCell);
+                    final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0],
+                            mTargetCell[1]);
 
-                    View newDropOver = null;
-                    if (willCreateUserFolder) {
-                        newDropOver = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]);
-                    }
+                    boolean userFolderPending = willCreateUserFolder(info, dragOverView,
+                            mTargetCell);
+                    boolean isOverFolder = dragOverView instanceof FolderIcon;
+                    if (dragOverView != mLastDragOverView) {
+                        cancelFolderCreation();
+                        if (mLastDragOverView != null && mLastDragOverView instanceof FolderIcon) {
 
-                    if (newDropOver != mLastDragOverView || !willCreateUserFolder) {
-                        if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) {
-                            mDragFolderRingAnimator.animateToNaturalState();
+                            ((FolderIcon) mLastDragOverView).onDragExit(d.dragInfo);
                         }
-                        mCreateUserFolderOnDrop = false;
-                        mFolderCreationAlarm.cancelAlarm();
-                        mIsDraggingOverIcon = false;
                     }
 
-                    if (willCreateUserFolder && !mIsDraggingOverIcon) {
-                        mIsDraggingOverIcon = true;
-
-                        mLastDragOverView = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]);
-                        mFolderCreationAlarm.setOnAlarmListener(new FolderCreationAlarmListener(mLastDragOverView));
+                    if (userFolderPending && dragOverView != mLastDragOverView) {
+                        mFolderCreationAlarm.setOnAlarmListener(new
+                                FolderCreationAlarmListener(dragOverView));
                         mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT);
-
-                        mDragTargetLayout.clearDragOutlines();
                     }
 
-                    if (!mCreateUserFolderOnDrop) {
+                    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],
+                                (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1],
                                 item.spanX, item.spanY);
                     }
                 }
@@ -3087,6 +3143,14 @@
         }
     }
 
+    private void cancelFolderCreation() {
+        if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) {
+            mDragFolderRingAnimator.animateToNaturalState();
+        }
+        mCreateUserFolderOnDrop = false;
+        mFolderCreationAlarm.cancelAlarm();
+    }
+
     class FolderCreationAlarmListener implements OnAlarmListener {
         View v;
 
@@ -3097,15 +3161,15 @@
         public void onAlarm(Alarm alarm) {
             int tvLocation[] = new int[2];
             int wsLocation[] = new int[2];
-            v.getLocationOnScreen(tvLocation);
-            getLocationOnScreen(wsLocation);
+            v.getLocationInWindow(tvLocation);
+            getLocationInWindow(wsLocation);
 
-            if (mCellWidth < 0 || mCellHeight < 0) {
+            if (mCellWidth < 0 || mCellHeight < 0 && mDragTargetLayout != null) {
                 mCellWidth = mDragTargetLayout.getCellWidth();
                 mCellHeight = mDragTargetLayout.getCellHeight();
             }
-            int x = tvLocation[0] - wsLocation[0] + mCellWidth / 2;
-            int y = tvLocation[1] - wsLocation[1] + mCellHeight / 2;
+            int x = tvLocation[0] - wsLocation[0] + v.getMeasuredWidth() / 2;
+            int y = tvLocation[1] - wsLocation[1] + v.getMeasuredHeight() / 2;
 
             if (mDragFolderRingAnimator == null) {
                 mDragFolderRingAnimator = new FolderRingAnimator(mLauncher, null);
@@ -3114,16 +3178,22 @@
             mDragFolderRingAnimator.animateToAcceptState();
             showFolderAccept(mDragFolderRingAnimator);
             mCreateUserFolderOnDrop = true;
-            mDragTargetLayout.clearDragOutlines();
+            if (mDragTargetLayout != null) {
+                mDragTargetLayout.clearDragOutlines();
+            }
         }
     }
 
-    private void doDragExit() {
+    private void doDragExit(DragObject d) {
         mWasSpringLoadedOnDragExit = mShrinkState == ShrinkState.SPRING_LOADED;
-
         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) {
@@ -3139,7 +3209,7 @@
     }
 
     public void onDragExit(DragObject d) {
-        doDragExit();
+        doDragExit(d);
     }
 
     @Override
@@ -3210,25 +3280,32 @@
                         (ShortcutInfo) info);
                 break;
             case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
-                view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
-                        cellLayout, (FolderInfo) info, mIconCache);
+                view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, cellLayout,
+                        (FolderInfo) info, mIconCache);
                 break;
             default:
                 throw new IllegalStateException("Unknown item type: " + info.itemType);
             }
 
-            // If the item being dropped is a shortcut and the nearest drop cell also contains
-            // a shortcut, then create a folder with the two shortcuts.
-            if (touchXY != null && createUserFolderIfNecessary(view, cellLayout, touchXY[0],
-                  touchXY[1], true)) {
-                return;
+            int spanX = mDragInfo != null ? mDragInfo.spanX : 1;
+            int spanY = mDragInfo != null ? mDragInfo.spanY : 1;
+            // First we find the cell nearest to point at which the item is
+            // dropped, without any consideration to whether there is an item there.
+            if (touchXY != null) {
+                mTargetCell = findNearestArea((int) touchXY[0], (int) touchXY[1], spanX, spanY,
+                        cellLayout, mTargetCell);
+                if (createUserFolderIfNecessary(view, cellLayout, mTargetCell, true)) {
+                    return;
+                }
+                if (addToExistingFolderIfNecessary(view, cellLayout, mTargetCell, dragInfo, true)) {
+                    return;
+                }
             }
 
-            mTargetCell = new int[2];
             if (touchXY != null) {
                 // when dragging and dropping, just find the closest free spot
-                mTargetCell = findNearestVacantArea(touchXY[0], touchXY[1], 1, 1, null, cellLayout,
-                        mTargetCell);
+                mTargetCell = findNearestVacantArea(touchXY[0], touchXY[1], 1, 1, null,
+                        cellLayout, mTargetCell);
             } else {
                 cellLayout.findCellForSpan(mTargetCell, 1, 1);
             }
@@ -3309,13 +3386,13 @@
     /**
      * Called at the end of a drag which originated on the workspace.
      */
-    public void onDropCompleted(View target, Object dragInfo, boolean success) {
+    public void onDropCompleted(View target, DragObject d, boolean success) {
         if (success) {
             if (target != this && mDragInfo != null) {
                 final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
                 cellLayout.removeView(mDragInfo.cell);
                 if (mDragInfo.cell instanceof DropTarget) {
-                    mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
+                    mDragController.removeDropTarget((DropTarget) mDragInfo.cell);
                 }
                 // final Object tag = mDragInfo.cell.getTag();
             }
@@ -3323,7 +3400,7 @@
             // NOTE: When 'success' is true, onDragExit is called by the DragController before
             // calling onDropCompleted(). We call it ourselves here, but maybe this should be
             // moved into DragController.cancelDrag().
-            doDragExit();
+            doDragExit(null);
             ((CellLayout) getChildAt(mDragInfo.screen)).onDropChild(mDragInfo.cell, false);
         }
         mLauncher.unlockScreenOrientation();
@@ -3368,6 +3445,7 @@
 
             final int page = mCurrentPage + (direction == DragController.SCROLL_LEFT ? -1 : 1);
             final CellLayout layout = (CellLayout) getChildAt(page);
+            cancelFolderCreation();
 
             if (layout != null) {
                 layout.setIsDragOverlapping(true);