Merge "Fxing issues with the scroll bar"
diff --git a/src/com/android/launcher2/AppWidgetResizeFrame.java b/src/com/android/launcher2/AppWidgetResizeFrame.java
index 22bd6e6..c7dbc0f 100644
--- a/src/com/android/launcher2/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher2/AppWidgetResizeFrame.java
@@ -77,7 +77,7 @@
         mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
 
         final AppWidgetProviderInfo info = widgetView.getAppWidgetInfo();
-        int[] result = mCellLayout.rectToCell(info.minWidth, info.minHeight, null);
+        int[] result = mCellLayout.rectToCell(info.minResizeWidth, info.minResizeHeight, null);
         mMinHSpan = result[0];
         mMinVSpan = result[1];
 
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index 8a4bdc7..c127ecd 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -449,7 +449,8 @@
     }
     private void endDragging(View target, boolean success) {
         mLauncher.getWorkspace().onDragStopped(success);
-        if (!success || target != mLauncher.getWorkspace()) {
+        if (!success || (target != mLauncher.getWorkspace() &&
+                !(target instanceof DeleteDropTarget))) {
             // Exit spring loaded mode if we have not successfully dropped or have not handled the
             // drop in Workspace
             mLauncher.exitSpringLoadedDragMode();
@@ -734,15 +735,11 @@
                 mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
 
         // Note: We force a measure here to get around the fact that when we do layout calculations
-        // immediately after syncing, we don't have a proper width.  That said, we already know the
-        // expected page width, so we can actually optimize by hiding all the TextView-based
-        // children that are expensive to measure, and let that happen naturally later.
-        setVisibilityOnChildren(layout, View.GONE);
+        // immediately after syncing, we don't have a proper width.
         int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
         int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
         layout.setMinimumWidth(getPageContentWidth());
         layout.measure(widthSpec, heightSpec);
-        setVisibilityOnChildren(layout, View.VISIBLE);
     }
     private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h,
             float scaleX, float scaleY) {
@@ -893,7 +890,8 @@
     private void onSyncWidgetPageItems(AsyncTaskPageData data) {
         int page = data.page;
         PagedViewGridLayout layout = (PagedViewGridLayout) getChildAt(page);
-        layout.removeAllViews();
+        // Only set the column count once we have items
+        layout.setColumnCount(layout.getCellCountX());
 
         ArrayList<Object> items = data.items;
         int count = items.size();
@@ -935,8 +933,8 @@
             int ix = i % cellCountX;
             int iy = i / cellCountX;
             GridLayout.LayoutParams lp = new GridLayout.LayoutParams(
-                    new GridLayout.Group(iy, 1, GridLayout.LEFT),
-                    new GridLayout.Group(ix, 1, GridLayout.TOP));
+                    GridLayout.spec(iy, GridLayout.LEFT, GridLayout.CAN_STRETCH),
+                    GridLayout.spec(ix, GridLayout.TOP, GridLayout.CAN_STRETCH));
             lp.width = cellWidth;
             lp.height = cellHeight;
             if (ix > 0) lp.leftMargin = mWidgetWidthGap;
diff --git a/src/com/android/launcher2/ButtonDropTarget.java b/src/com/android/launcher2/ButtonDropTarget.java
index edc5acf..138770a 100644
--- a/src/com/android/launcher2/ButtonDropTarget.java
+++ b/src/com/android/launcher2/ButtonDropTarget.java
@@ -21,6 +21,7 @@
 import android.graphics.Paint;
 import android.util.AttributeSet;
 import android.widget.FrameLayout;
+import android.widget.TextView;
 
 import com.android.launcher.R;
 
@@ -34,6 +35,8 @@
 
     protected Launcher mLauncher;
     private int mBottomDragPadding;
+    protected TextView mText;
+    protected SearchDropTargetBar mSearchDropTargetBar;
 
     /** Whether this drop target is active for the current drag */
     protected boolean mActive;
@@ -61,8 +64,11 @@
         return false;
     }
 
+    public void setSearchDropTargetBar(SearchDropTargetBar searchDropTargetBar) {
+        mSearchDropTargetBar = searchDropTargetBar;
+    }
+
     public void onDrop(DragObject d) {
-        // Do nothing
     }
 
     public void onDragEnter(DragObject d) {
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 22516cc..ae22507 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -64,6 +64,8 @@
     private int mCountX;
     private int mCountY;
 
+    private int mOriginalWidthGap;
+    private int mOriginalHeightGap;
     private int mWidthGap;
     private int mHeightGap;
     private int mMaxGap;
@@ -155,8 +157,8 @@
             mCellWidth = a.getDimensionPixelSize(R.styleable.CellLayout_cellWidth, 10);
         mOriginalCellHeight =
             mCellHeight = a.getDimensionPixelSize(R.styleable.CellLayout_cellHeight, 10);
-        mWidthGap = a.getDimensionPixelSize(R.styleable.CellLayout_widthGap, 0);
-        mHeightGap = a.getDimensionPixelSize(R.styleable.CellLayout_heightGap, 0);
+        mWidthGap = mOriginalWidthGap = a.getDimensionPixelSize(R.styleable.CellLayout_widthGap, 0);
+        mHeightGap = mOriginalHeightGap = a.getDimensionPixelSize(R.styleable.CellLayout_heightGap, 0);
         mMaxGap = a.getDimensionPixelSize(R.styleable.CellLayout_maxGap, 0);
         mCountX = LauncherModel.getCellCountX();
         mCountY = LauncherModel.getCellCountY();
@@ -872,7 +874,7 @@
         int numWidthGaps = mCountX - 1;
         int numHeightGaps = mCountY - 1;
 
-        if (mWidthGap < 0 || mHeightGap < 0) {
+        if (mOriginalWidthGap < 0 || mOriginalHeightGap < 0) {
             int hSpace = widthSpecSize - mPaddingLeft - mPaddingRight;
             int vSpace = heightSpecSize - mPaddingTop - mPaddingBottom;
             int hFreeSpace = hSpace - (mCountX * mOriginalCellWidth);
@@ -885,6 +887,9 @@
             mCellHeight = mOriginalCellHeight + remainingVSpace / mCountY;
 
             mChildren.setCellDimensions(mCellWidth, mCellHeight, mWidthGap, mHeightGap);
+        } else {
+            mWidthGap = mOriginalWidthGap;
+            mHeightGap = mOriginalHeightGap;
         }
 
         // Initial values correspond to widthSpecMode == MeasureSpec.EXACTLY
diff --git a/src/com/android/launcher2/DeleteDropTarget.java b/src/com/android/launcher2/DeleteDropTarget.java
index ffe4533..2c84c78 100644
--- a/src/com/android/launcher2/DeleteDropTarget.java
+++ b/src/com/android/launcher2/DeleteDropTarget.java
@@ -22,16 +22,19 @@
 import android.content.res.Resources;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
+import android.graphics.Rect;
 import android.graphics.drawable.TransitionDrawable;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
 import android.widget.TextView;
 
 import com.android.launcher.R;
 
 public class DeleteDropTarget extends ButtonDropTarget {
 
-    private TextView mText;
+    private static int DELETE_ANIMATION_DURATION = 220;
     private ColorStateList mOriginalTextColor;
     private TransitionDrawable mDrawable;
     private int mHoverColor = 0xFFFF0000;
@@ -147,7 +150,37 @@
         }
     }
 
-    public void onDrop(DragObject d) {
+    private void animateToTrashAndCompleteDrop(final DragObject d) {
+        DragLayer dragLayer = mLauncher.getDragLayer();
+        Rect from = new Rect();
+        Rect to = new Rect();
+        dragLayer.getViewRectRelativeToSelf(d.dragView, from);
+        dragLayer.getViewRectRelativeToSelf(mText, to);
+
+        int width = mDrawable.getIntrinsicWidth();
+        int height = mDrawable.getIntrinsicHeight();
+        to.set(to.left, to.top, to.left + width, to.bottom);
+
+        // Center the destination rect about the trash icon
+        int xOffset = (int) -(d.dragView.getMeasuredWidth() - width) / 2;
+        int yOffset = (int) -(d.dragView.getMeasuredHeight() - height) / 2;
+        to.offset(xOffset, yOffset);
+
+        mSearchDropTargetBar.deferOnDragEnd();
+        Runnable onAnimationEndRunnable = new Runnable() {
+            @Override
+            public void run() {
+                mSearchDropTargetBar.onDragEnd();
+                mLauncher.exitSpringLoadedDragMode();
+                completeDrop(d);
+            }
+        };
+        dragLayer.animateView(d.dragView, from, to, 0f, 0.1f,
+                DELETE_ANIMATION_DURATION, new DecelerateInterpolator(2),
+                new AccelerateInterpolator(2), onAnimationEndRunnable, false);
+    }
+
+    private void completeDrop(DragObject d) {
         ItemInfo item = (ItemInfo) d.dragInfo;
 
         if (isAllAppsApplication(d.dragSource, item)) {
@@ -178,4 +211,8 @@
             }
         }
     }
+
+    public void onDrop(DragObject d) {
+        animateToTrashAndCompleteDrop(d);
+    }
 }
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index ef02de6..7641fe7 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -35,6 +35,7 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.View.MeasureSpec;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
 import android.view.inputmethod.EditorInfo;
@@ -783,6 +784,23 @@
         centerAboutIcon();
     }
 
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
+        // Technically there is no padding at the bottom, but we add space equal to the padding
+        // and have to account for that here.
+        int height = getPaddingTop() + mContent.getDesiredHeight() + mFolderNameHeight;
+
+        int contentWidthSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredWidth(),
+                MeasureSpec.EXACTLY);
+        int contentHeightSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredHeight(),
+                MeasureSpec.EXACTLY);
+        mContent.measure(contentWidthSpec, contentHeightSpec);
+
+        mFolderName.measure(contentWidthSpec,
+                MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY));
+        setMeasuredDimension(width, height);
+    }
+
     private void arrangeChildren(ArrayList<View> list) {
         int[] vacant = new int[2];
         if (list == null) {
diff --git a/src/com/android/launcher2/InfoDropTarget.java b/src/com/android/launcher2/InfoDropTarget.java
index 6ad7630..3507181 100644
--- a/src/com/android/launcher2/InfoDropTarget.java
+++ b/src/com/android/launcher2/InfoDropTarget.java
@@ -32,7 +32,6 @@
 
 public class InfoDropTarget extends ButtonDropTarget {
 
-    private TextView mText;
     private ColorStateList mOriginalTextColor;
     private TransitionDrawable mDrawable;
     private int mHoverColor = 0xFF0000FF;
diff --git a/src/com/android/launcher2/InstallWidgetReceiver.java b/src/com/android/launcher2/InstallWidgetReceiver.java
index 4f6cb8d..b4ce038 100644
--- a/src/com/android/launcher2/InstallWidgetReceiver.java
+++ b/src/com/android/launcher2/InstallWidgetReceiver.java
@@ -188,7 +188,7 @@
 
             final PendingAddWidgetInfo createInfo = new PendingAddWidgetInfo(widgetInfo, mMimeType,
                     mClipData);
-            mLauncher.addAppWidgetFromDrop(createInfo, mTargetLayoutScreen, mTargetLayoutPos);
+            mLauncher.addAppWidgetFromDrop(createInfo, mTargetLayoutScreen, null, mTargetLayoutPos);
         }
     }
 }
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 7341e71..26f41fa 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -151,9 +151,9 @@
     // Type: int
     private static final String RUNTIME_STATE_PENDING_ADD_SCREEN = "launcher.add_screen";
     // Type: int
-    private static final String RUNTIME_STATE_PENDING_ADD_CELL_X = "launcher.add_cellX";
+    private static final String RUNTIME_STATE_PENDING_ADD_CELL_X = "launcher.add_cell_x";
     // Type: int
-    private static final String RUNTIME_STATE_PENDING_ADD_CELL_Y = "launcher.add_cellY";
+    private static final String RUNTIME_STATE_PENDING_ADD_CELL_Y = "launcher.add_cell_y";
     // Type: boolean
     private static final String RUNTIME_STATE_PENDING_FOLDER_RENAME = "launcher.rename_folder";
     // Type: long
@@ -186,8 +186,8 @@
     private LauncherAppWidgetHost mAppWidgetHost;
 
     private int mAddScreen = -1;
-    private int mAddIntersectCellX = -1;
-    private int mAddIntersectCellY = -1;
+    private int mAddCellX = -1;
+    private int mAddCellY = -1;
     private int[] mAddDropPosition;
     private int[] mTmpAddItemCellCoordinates = new int[2];
 
@@ -317,6 +317,7 @@
         // If we have a saved version of these external icons, we load them up immediately
         if (sGlobalSearchIcon == null || sVoiceSearchIcon == null || sAppMarketIcon == null) {
             updateIconsAffectedByPackageManagerChanges();
+            updateGlobalSearchIcon();
         }
         if (sGlobalSearchIcon != null) {
              updateGlobalSearchIcon(sGlobalSearchIcon);
@@ -631,14 +632,13 @@
 
         // For example, the user would PICK_SHORTCUT for "Music playlist", and we
         // launch over to the Music app to actually CREATE_SHORTCUT.
-
         if (resultCode == RESULT_OK && mAddScreen != -1) {
             final PendingAddArguments args = new PendingAddArguments();
             args.requestCode = requestCode;
             args.intent = data;
             args.screen = mAddScreen;
-            args.cellX = mAddIntersectCellX;
-            args.cellY = mAddIntersectCellY;
+            args.cellX = mAddCellX;
+            args.cellY = mAddCellY;
 
             // If the loader is still running, defer the add until it is done.
             if (isWorkspaceLocked()) {
@@ -801,8 +801,8 @@
 
         if (addScreen > -1) {
             mAddScreen = addScreen;
-            mAddIntersectCellX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_X);
-            mAddIntersectCellY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_Y);
+            mAddCellX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_X);
+            mAddCellY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_Y);
             mRestoring = true;
         }
 
@@ -976,12 +976,15 @@
      * @param data The intent describing the application.
      * @param cellInfo The position on screen where to create the shortcut.
      */
-    void completeAddApplication(Intent data, int screen,
-            int intersectCellX, int intersectCellY) {
+    void completeAddApplication(Intent data, int screen, int cellX, int cellY) {
         final int[] cellXY = mTmpAddItemCellCoordinates;
         final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
 
-        if (!layout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectCellX, intersectCellY)) {
+        // First we check if we already know the exact location where we want to add this item.
+        if (cellX >= 0 && cellY >= 0) {
+            cellXY[0] = cellX;
+            cellXY[1] = cellY;
+        } else if (!layout.findCellForSpan(cellXY, 1, 1)) {
             showOutOfSpaceMessage();
             return;
         }
@@ -993,7 +996,7 @@
                     Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
             info.container = ItemInfo.NO_ID;
             mWorkspace.addApplicationShortcut(info, screen, cellXY[0], cellXY[1],
-                    isWorkspaceLocked(), mAddIntersectCellX, mAddIntersectCellY);
+                    isWorkspaceLocked(), cellX, cellY);
         } else {
             Log.e(TAG, "Couldn't find ActivityInfo for selected application: " + data);
         }
@@ -1005,22 +1008,26 @@
      * @param data The intent describing the shortcut.
      * @param cellInfo The position on screen where to create the shortcut.
      */
-    private void completeAddShortcut(Intent data, int screen,
-            int intersectCellX, int intersectCellY) {
+    private void completeAddShortcut(Intent data, int screen, int cellX, int cellY) {
         final int[] cellXY = mTmpAddItemCellCoordinates;
         final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
 
         int[] touchXY = mAddDropPosition;
         boolean foundCellSpan = false;
-        if (touchXY != null) {
+
+        // First we check if we already know the exact location where we want to add this item.
+        if (cellX >= 0 && cellY >= 0) {
+            cellXY[0] = cellX;
+            cellXY[1] = cellY;
+            foundCellSpan = true;
+        } else if (touchXY != null) {
             // when dragging and dropping, just find the closest free spot
             CellLayout screenLayout = (CellLayout) mWorkspace.getChildAt(screen);
             int[] result = screenLayout.findNearestVacantArea(
                     touchXY[0], touchXY[1], 1, 1, cellXY);
             foundCellSpan = (result != null);
         } else {
-            foundCellSpan = layout.findCellForSpanThatIntersects(
-                    cellXY, 1, 1, intersectCellX, intersectCellY);
+            foundCellSpan = layout.findCellForSpan(cellXY, 1, 1);
         }
 
         if (!foundCellSpan) {
@@ -1067,19 +1074,18 @@
 
         int[] touchXY = mAddDropPosition;
         boolean foundCellSpan = false;
-        if (touchXY != null) {
+        if (mAddCellX >= 0 && mAddCellY >= 0) {
+            cellXY[0] = mAddCellX;
+            cellXY[1] = mAddCellY;
+            foundCellSpan = true;
+        } else if (touchXY != null) {
             // when dragging and dropping, just find the closest free spot
             CellLayout screenLayout = (CellLayout) mWorkspace.getChildAt(screen);
             int[] result = screenLayout.findNearestVacantArea(
                     touchXY[0], touchXY[1], spanXY[0], spanXY[1], cellXY);
             foundCellSpan = (result != null);
         } else {
-            // if we long pressed on an empty cell to bring up a menu,
-            // make sure we intersect the empty cell
-            // if mAddIntersectCellX/Y are -1 (e.g. we used menu -> add) then
-            // findCellForSpanThatIntersects will just ignore them
-            foundCellSpan = layout.findCellForSpanThatIntersects(cellXY, spanXY[0], spanXY[1],
-                    mAddIntersectCellX, mAddIntersectCellY);
+            foundCellSpan = layout.findCellForSpan(cellXY, spanXY[0], spanXY[1]);
         }
 
         if (!foundCellSpan) {
@@ -1125,6 +1131,7 @@
             final String action = intent.getAction();
             if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                 mUserPresent = false;
+                mDragLayer.clearAllResizeFrames();
                 updateRunning();
 
                 // Reset AllApps to it's initial state
@@ -1156,6 +1163,7 @@
     public void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         mVisible = false;
+        mDragLayer.clearAllResizeFrames();
 
         if (mAttached) {
             unregisterReceiver(mReceiver);
@@ -1217,7 +1225,7 @@
     };
 
     void addWidgetToAutoAdvanceIfNeeded(View hostView, AppWidgetProviderInfo appWidgetInfo) {
-        if (appWidgetInfo.autoAdvanceViewId == -1) return;
+        if (appWidgetInfo == null || appWidgetInfo.autoAdvanceViewId == -1) return;
         View v = hostView.findViewById(appWidgetInfo.autoAdvanceViewId);
         if (v instanceof Advanceable) {
             mWidgetsToAdvance.put(hostView, appWidgetInfo);
@@ -1325,8 +1333,8 @@
 
         if (mAddScreen > -1 && mWaitingForResult) {
             outState.putInt(RUNTIME_STATE_PENDING_ADD_SCREEN, mAddScreen);
-            outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_X, mAddIntersectCellX);
-            outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_Y, mAddIntersectCellY);
+            outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_X, mAddCellX);
+            outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_Y, mAddCellY);
         }
 
         if (mFolderInfo != null && mWaitingForResult) {
@@ -1495,26 +1503,16 @@
 
     private void addItems() {
         showWorkspace(true);
-        showAddDialog(-1, -1);
+        showAddDialog();
     }
 
     private void resetAddInfo() {
         mAddScreen = -1;
-        mAddIntersectCellX = -1;
-        mAddIntersectCellY = -1;
+        mAddCellX = -1;
+        mAddCellY = -1;
         mAddDropPosition = null;
     }
 
-    void addAppWidgetFromDrop(PendingAddWidgetInfo info, int screen, int[] position) {
-        resetAddInfo();
-        mAddScreen = screen;
-        mAddDropPosition = position;
-
-        int appWidgetId = getAppWidgetHost().allocateAppWidgetId();
-        AppWidgetManager.getInstance(this).bindAppWidgetId(appWidgetId, info.componentName);
-        addAppWidgetImpl(appWidgetId, info);
-    }
-
     private void manageApps() {
         startActivity(new Intent(android.provider.Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS));
     }
@@ -1575,16 +1573,52 @@
         }
     }
 
-    void processShortcutFromDrop(ComponentName componentName, int screen, int[] position) {
+    /**
+     * Process a shortcut drop.
+     *
+     * @param componentName The name of the component
+     * @param screen The screen where it should be added
+     * @param cell The cell it should be added to, optional
+     * @param position The location on the screen where it was dropped, optional
+     */
+    void processShortcutFromDrop(ComponentName componentName, int screen, int[] cell, int[] loc) {
         resetAddInfo();
         mAddScreen = screen;
-        mAddDropPosition = position;
+        mAddDropPosition = loc;
+
+        if (cell != null) {
+            mAddCellX = cell[0];
+            mAddCellY = cell[1];
+        }
 
         Intent createShortcutIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
         createShortcutIntent.setComponent(componentName);
         processShortcut(createShortcutIntent);
     }
 
+    /**
+     * Process a widget drop.
+     *
+     * @param info The PendingAppWidgetInfo of the widget being added.
+     * @param screen The screen where it should be added
+     * @param cell The cell it should be added to, optional
+     * @param position The location on the screen where it was dropped, optional
+     */
+    void addAppWidgetFromDrop(PendingAddWidgetInfo info, int screen, int[] cell, int[] loc) {
+        resetAddInfo();
+        mAddScreen = screen;
+        mAddDropPosition = loc;
+
+        if (cell != null) {
+            mAddCellX = cell[0];
+            mAddCellY = cell[1];
+        }
+
+        int appWidgetId = getAppWidgetHost().allocateAppWidgetId();
+        AppWidgetManager.getInstance(this).bindAppWidgetId(appWidgetId, info.componentName);
+        addAppWidgetImpl(appWidgetId, info);
+    }
+
     void processShortcut(Intent intent) {
         // Handle case where user selected "Applications"
         String applicationName = getResources().getString(R.string.group_applications);
@@ -1607,29 +1641,21 @@
         startActivityForResult(intent, REQUEST_PICK_WALLPAPER);
     }
 
-    FolderIcon addFolder(final int screen, int intersectCellX, int intersectCellY) {
+    FolderIcon addFolder(final int screen, int cellX, int cellY) {
         final FolderInfo folderInfo = new FolderInfo();
         folderInfo.title = getText(R.string.folder_name);
 
-        final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
-        final int[] cellXY = mTmpAddItemCellCoordinates;
-        if (!layout.findCellForSpanThatIntersects(cellXY, 1, 1,
-                intersectCellX, intersectCellY)) {
-            showOutOfSpaceMessage();
-            return null;
-        }
-
         // Update the model
         LauncherModel.addItemToDatabase(Launcher.this, folderInfo,
                 LauncherSettings.Favorites.CONTAINER_DESKTOP,
-                screen, cellXY[0], cellXY[1], false);
+                screen, cellX, cellY, false);
         sFolders.put(folderInfo.id, folderInfo);
 
         // Create the view
         FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
                 (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()),
                 folderInfo, mIconCache);
-        mWorkspace.addInScreen(newFolder, screen, cellXY[0], cellXY[1], 1, 1, isWorkspaceLocked());
+        mWorkspace.addInScreen(newFolder, screen, cellX, cellY, 1, 1, isWorkspaceLocked());
         return newFolder;
     }
 
@@ -2008,8 +2034,6 @@
                     // User long pressed on an item
                     mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                             HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
-                    mAddIntersectCellX = longClickCellInfo.cellX;
-                    mAddIntersectCellY = longClickCellInfo.cellY;
                     mWorkspace.startDrag(longClickCellInfo);
                 }
             }
@@ -2189,10 +2213,8 @@
         showDialog(DIALOG_RENAME_FOLDER);
     }
 
-    private void showAddDialog(int intersectX, int intersectY) {
+    private void showAddDialog() {
         resetAddInfo();
-        mAddIntersectCellX = intersectX;
-        mAddIntersectCellY = intersectY;
         mAddScreen = mWorkspace.getCurrentPage();
         mWaitingForResult = true;
         showDialog(DIALOG_CREATE_SHORTCUT);
@@ -3135,10 +3157,14 @@
      */
     private void updateIconsAffectedByPackageManagerChanges() {
         updateAppMarketIcon();
-        updateGlobalSearchIcon();
         updateVoiceSearchIcon();
     }
 
+    @Override
+    public void bindSearchablesChanged() {
+        updateGlobalSearchIcon();
+    }
+
     /**
      * Add the icons for all apps.
      *
@@ -3149,6 +3175,7 @@
             mAppsCustomizeContent.setApps(apps);
         }
         updateIconsAffectedByPackageManagerChanges();
+        updateGlobalSearchIcon();
     }
 
     /**
diff --git a/src/com/android/launcher2/LauncherApplication.java b/src/com/android/launcher2/LauncherApplication.java
index db3a4cb..94163ac 100644
--- a/src/com/android/launcher2/LauncherApplication.java
+++ b/src/com/android/launcher2/LauncherApplication.java
@@ -17,6 +17,7 @@
 package com.android.launcher2;
 
 import android.app.Application;
+import android.app.SearchManager;
 import android.content.ContentResolver;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -57,6 +58,9 @@
         filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
         filter.addAction(Intent.ACTION_LOCALE_CHANGED);
         registerReceiver(mModel, filter);
+        filter = new IntentFilter();
+        filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
+        registerReceiver(mModel, filter);
 
         // Register for changes to the favorites
         ContentResolver resolver = getContentResolver();
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 331f124..b4e632a 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher2;
 
+import android.app.SearchManager;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.BroadcastReceiver;
@@ -129,6 +130,7 @@
         public void bindAppsRemoved(ArrayList<ApplicationInfo> apps, boolean permanent);
         public void bindPackagesUpdated();
         public boolean isAllAppsVisible();
+        public void bindSearchablesChanged();
     }
 
     LauncherModel(LauncherApplication app, IconCache iconCache) {
@@ -513,6 +515,7 @@
      * Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and
      * ACTION_PACKAGE_CHANGED.
      */
+    @Override
     public void onReceive(Context context, Intent intent) {
         if (DEBUG_LOADERS) Log.d(TAG, "onReceive intent=" + intent);
 
@@ -570,6 +573,9 @@
             mAllAppsLoaded = false;
             mWorkspaceLoaded = false;
             startLoaderFromBackground();
+        } else if (SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED.equals(action)) {
+            Callbacks callbacks = mCallbacks.get();
+            callbacks.bindSearchablesChanged();
         }
     }
 
diff --git a/src/com/android/launcher2/PagedViewCellLayout.java b/src/com/android/launcher2/PagedViewCellLayout.java
index fc1b012..bec00ec 100644
--- a/src/com/android/launcher2/PagedViewCellLayout.java
+++ b/src/com/android/launcher2/PagedViewCellLayout.java
@@ -41,6 +41,8 @@
     private int mOriginalCellHeight;
     private int mCellWidth;
     private int mCellHeight;
+    private int mOriginalWidthGap;
+    private int mOriginalHeightGap;
     private int mWidthGap;
     private int mHeightGap;
     private int mMaxGap;
@@ -72,7 +74,7 @@
         mPeekWidth = resources.getDimensionPixelSize(R.dimen.apps_customize_peek_width);
         mCellCountX = LauncherModel.getCellCountX();
         mCellCountY = LauncherModel.getCellCountY();
-        mWidthGap = mHeightGap = -1;
+        mOriginalHeightGap = mOriginalHeightGap = mWidthGap = mHeightGap = -1;
         mMaxGap = resources.getDimensionPixelSize(R.dimen.apps_customize_max_gap);
 
         mChildren = new PagedViewCellLayoutChildren(context);
@@ -221,12 +223,10 @@
             throw new RuntimeException("CellLayout cannot have UNSPECIFIED dimensions");
         }
 
-
-
         int numWidthGaps = mCellCountX - 1;
         int numHeightGaps = mCellCountY - 1;
 
-        if (mWidthGap < 0 || mHeightGap < 0) {
+        if (mOriginalWidthGap < 0 || mOriginalHeightGap < 0) {
             int hSpace = widthSpecSize - mPaddingLeft - mPaddingRight;
             int vSpace = heightSpecSize - mPaddingTop - mPaddingBottom;
             int hFreeSpace = hSpace - (mCellCountX * mOriginalCellWidth);
@@ -236,6 +236,9 @@
 
             mChildren.setGap(mWidthGap, mHeightGap);
             mHolographicChildren.setGap(mWidthGap, mHeightGap);
+        } else {
+            mWidthGap = mOriginalWidthGap;
+            mHeightGap = mOriginalHeightGap;
         }
 
         // Initial values correspond to widthSpecMode == MeasureSpec.EXACTLY
diff --git a/src/com/android/launcher2/PagedViewGridLayout.java b/src/com/android/launcher2/PagedViewGridLayout.java
index a2ab763..4131d8b 100644
--- a/src/com/android/launcher2/PagedViewGridLayout.java
+++ b/src/com/android/launcher2/PagedViewGridLayout.java
@@ -35,7 +35,6 @@
         super(context, null, 0);
         mCellCountX = cellCountX;
         mCellCountY = cellCountY;
-        setColumnCount(mCellCountX);
     }
 
     int getCellCountX() {
diff --git a/src/com/android/launcher2/SearchDropTargetBar.java b/src/com/android/launcher2/SearchDropTargetBar.java
index 201daab..ee3ab18 100644
--- a/src/com/android/launcher2/SearchDropTargetBar.java
+++ b/src/com/android/launcher2/SearchDropTargetBar.java
@@ -50,6 +50,7 @@
     private ButtonDropTarget mInfoDropTarget;
     private ButtonDropTarget mDeleteDropTarget;
     private int mBarHeight;
+    private boolean mDeferOnDragEnd = false;
 
     public SearchDropTargetBar(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -80,6 +81,9 @@
         mDeleteDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.delete_target);
         mBarHeight = getResources().getDimensionPixelSize(R.dimen.qsb_bar_height);
 
+        mInfoDropTarget.setSearchDropTargetBar(this);
+        mDeleteDropTarget.setSearchDropTargetBar(this);
+
         boolean enableDropDownDropTargets =
             getResources().getBoolean(R.bool.config_useDropTargetDownTransition);
 
@@ -191,14 +195,22 @@
         }
     }
 
+    public void deferOnDragEnd() {
+        mDeferOnDragEnd = true;
+    }
+
     @Override
     public void onDragEnd() {
-        // Restore the QSB search bar, and animate out the drop target bar
-        mDropTargetBarFadeInAnim.cancel();
-        mDropTargetBarFadeOutAnim.start();
-        if (!mIsSearchBarHidden) {
-            mQSBSearchBarFadeOutAnim.cancel();
-            mQSBSearchBarFadeInAnim.start();
+        if (!mDeferOnDragEnd) {
+            // Restore the QSB search bar, and animate out the drop target bar
+            mDropTargetBarFadeInAnim.cancel();
+            mDropTargetBarFadeOutAnim.start();
+            if (!mIsSearchBarHidden) {
+                mQSBSearchBarFadeOutAnim.cancel();
+                mQSBSearchBarFadeInAnim.start();
+            }
+        } else {
+            mDeferOnDragEnd = false;
         }
     }
 }
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index d79158d..4fbf70f 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -2446,7 +2446,7 @@
                         final AppWidgetProviderInfo widgetInfo = widgets.get(0).widgetInfo;
                         final PendingAddWidgetInfo createInfo =
                                 new PendingAddWidgetInfo(widgetInfo, mimeType, data);
-                        mLauncher.addAppWidgetFromDrop(createInfo, mCurrentPage, pos);
+                        mLauncher.addAppWidgetFromDrop(createInfo, mCurrentPage, null, pos);
                     } else {
                         // Show the widget picker dialog if there is more than one widget
                         // that can handle this data type
@@ -2853,6 +2853,8 @@
         if (info instanceof PendingAddItemInfo) {
             final PendingAddItemInfo pendingInfo = (PendingAddItemInfo) dragInfo;
 
+            mTargetCell = findNearestVacantArea(touchXY[0], touchXY[1], spanX, spanY, null,
+                    cellLayout, mTargetCell);
             Runnable onAnimationCompleteRunnable = new Runnable() {
                 @Override
                 public void run() {
@@ -2861,11 +2863,11 @@
                     switch (pendingInfo.itemType) {
                     case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
                         mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) pendingInfo,
-                                screen, touchXY);
+                                screen, mTargetCell, null);
                         break;
                     case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                         mLauncher.processShortcutFromDrop(pendingInfo.componentName,
-                                screen, touchXY);
+                                screen, mTargetCell, null);
                         break;
                     default:
                         throw new IllegalStateException("Unknown item type: " +
@@ -2877,13 +2879,6 @@
 
             // Now we animate the dragView, (ie. the widget or shortcut preview) into its final
             // location and size on the home screen.
-
-            // The target cell is also calculated later in Launcher when the widget is actually
-            // added, however, we do it here as well to find out where to animate to. The re-use
-            // of this computation required to much restructuring.
-            mTargetCell = findNearestVacantArea(touchXY[0], touchXY[1], spanX, spanY, null,
-                    cellLayout, mTargetCell);
-
             int loc[] = new int[2];
             cellLayout.cellToPoint(mTargetCell[0], mTargetCell[1], loc);