merge in ics-release history after reset to master
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5206896..7cbc2eb 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -102,9 +102,7 @@
 
         <activity android:name="com.android.launcher2.RocketLauncher"
             android:label="@string/dream_name"
-            android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
-            android:hardwareAccelerated="true"
-            >
+            android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.DEFAULT" />
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index c8a82e6..7073661 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -87,20 +87,6 @@
         android:focusable="true"
         android:clickable="true" />
 
-    <com.android.launcher2.DeleteZone
-        android:id="@+id/delete_zone"
-        android:layout_width="@dimen/delete_zone_size"
-        android:layout_height="@dimen/delete_zone_size"
-        android:paddingLeft="@dimen/delete_zone_padding"
-        android:layout_marginBottom="@dimen/half_status_bar_height"
-        android:layout_gravity="right|center_vertical"
-
-        android:scaleType="center"
-        android:drawableLeft="@drawable/delete_zone_selector"
-        android:visibility="invisible"
-        launcher:direction="vertical"
-        />
-
     <RelativeLayout
         android:id="@+id/all_apps_button_cluster"
         android:layout_height="fill_parent"
diff --git a/res/layout-large/button_bar.xml b/res/layout-large/button_bar.xml
index 62115f7..a060761 100644
--- a/res/layout-large/button_bar.xml
+++ b/res/layout-large/button_bar.xml
@@ -71,6 +71,7 @@
     <!-- AllApps icon -->
     <com.android.launcher2.StrokedTextView
         android:id="@+id/all_apps_button"
+        android:onClick="onClickAllAppsButton"
         android:text="@string/all_apps_button_label"
         android:drawablePadding="@dimen/all_apps_button_drawable_padding"
         android:drawableLeft="@drawable/ic_home_all_apps_holo_dark"
@@ -103,6 +104,7 @@
     <ImageView
         android:id="@+id/all_apps_divider"
         android:src="@drawable/divider_launcher_holo"
+        android:onClick="onClickAllAppsButton"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_toLeftOf="@+id/configure_button"
@@ -116,6 +118,7 @@
     <ImageView
         android:id="@+id/configure_button"
         android:src="@drawable/ic_home_add_holo_dark"
+        android:onClick="onClickConfigureButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
@@ -141,7 +144,7 @@
         android:paddingRight="@dimen/toolbar_button_horizontal_padding"
         android:paddingTop="@dimen/toolbar_button_vertical_padding"
         android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-       android:background="@drawable/button_bg"
+        android:background="@drawable/button_bg"
 
         android:gravity="center_horizontal|center_vertical"
         android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index f05f9b6..2d5a34f 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -80,19 +80,6 @@
         android:focusable="true"
         android:clickable="true" />
 
-    <com.android.launcher2.DeleteZone
-        android:id="@+id/delete_zone"
-        android:layout_width="@dimen/delete_zone_size"
-        android:layout_height="@dimen/delete_zone_size"
-        android:paddingTop="@dimen/delete_zone_padding"
-        android:layout_gravity="bottom|center_horizontal"
-
-        android:scaleType="center"
-        android:drawableLeft="@drawable/delete_zone_selector"
-        android:visibility="invisible"
-        launcher:direction="horizontal"
-        />
-
     <RelativeLayout
         android:id="@+id/all_apps_button_cluster"
         android:layout_width="fill_parent"
diff --git a/res/layout/apps_customize_pane.xml b/res/layout/apps_customize_pane.xml
index e22ba12..7083bf8 100644
--- a/res/layout/apps_customize_pane.xml
+++ b/res/layout/apps_customize_pane.xml
@@ -94,9 +94,7 @@
                 launcher:widgetCellWidthGap="@dimen/apps_customize_widget_cell_width_gap"
                 launcher:widgetCellHeightGap="@dimen/apps_customize_widget_cell_height_gap"
                 launcher:widgetCountX="@integer/apps_customize_widget_cell_count_x"
-                launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y"
-                launcher:wallpaperCountX="@integer/apps_customize_wallpaper_cell_count_x"
-                launcher:wallpaperCountY="@integer/apps_customize_wallpaper_cell_count_y" />
+                launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y" />
          </FrameLayout>
       </LinearLayout>
 </com.android.launcher2.AppsCustomizeTabHost>
diff --git a/res/layout/qsb_bar.xml b/res/layout/qsb_bar.xml
index 5469224..820fae6 100644
--- a/res/layout/qsb_bar.xml
+++ b/res/layout/qsb_bar.xml
@@ -13,17 +13,17 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<FrameLayout
+<com.android.launcher2.SearchDropTargetBar
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
     android:focusable="false">
 
     <!-- Search buttons container -->
     <LinearLayout
+        style="@style/SearchDropTargetBar"
         android:id="@+id/qsb_search_bar"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        style="@style/SearchBar">
+        android:layout_height="match_parent">
        <!-- Global search icon -->
        <ImageView
             style="@style/SearchButton"
@@ -61,10 +61,32 @@
 
     <!-- Drag specific targets container -->
     <LinearLayout
+        style="@style/SearchDropTargetBar"
         android:id="@+id/drag_target_bar"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="#FF00FF00"
-        android:visibility="gone">
+        android:alpha="0">
+
+        <FrameLayout
+            style="@style/DropTargetButtonContainer"
+            android:layout_weight="1">
+            <!-- Delete target -->
+            <com.android.launcher2.DeleteDropTarget
+                style="@style/DropTargetButton"
+                android:id="@+id/delete_target"
+                android:text="@string/delete_zone_label_workspace"
+                android:drawableLeft="@drawable/delete_zone_selector" />
+        </FrameLayout>
+
+        <FrameLayout
+            style="@style/DropTargetButtonContainer"
+            android:layout_weight="1">
+            <!-- Info target -->
+            <com.android.launcher2.InfoDropTarget
+                style="@style/DropTargetButton"
+                android:id="@+id/info_target"
+                android:text="@string/info_target_label"
+                android:drawableLeft="@drawable/ic_home_info_holo_dark" />
+        </FrameLayout>
     </LinearLayout>
-</FrameLayout>
+</com.android.launcher2.SearchDropTargetBar>
diff --git a/res/values-land/strings.xml b/res/values-land/strings.xml
new file mode 100644
index 0000000..bbe8ff2
--- /dev/null
+++ b/res/values-land/strings.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Manifest configuration. -->
+    <skip />
+
+    <!-- Label for delete drop target. [CHAR_LIMIT=30] -->
+    <string name="delete_target_label"></string>
+    <!-- Label for uninstall drop target. [CHAR_LIMIT=30]-->
+    <string name="delete_target_uninstall_label"></string>
+    <!-- Label for the info icon. [CHAR_LIMIT=30] -->
+    <string name="info_target_label"></string>
+</resources>
diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml
index 50aba09..4daaecc 100644
--- a/res/values-land/styles.xml
+++ b/res/values-land/styles.xml
@@ -19,7 +19,7 @@
 
 <resources>
 <!-- Search Bar -->
-    <style name="SearchBar">
+    <style name="SearchDropTargetBar">
         <item name="android:orientation">vertical</item>
     </style>
     <style name="SearchButton">
@@ -34,6 +34,20 @@
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_gravity">center_horizontal</item>
     </style>
+    <style name="DropTargetButtonContainer">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">0dp</item>
+    </style>
+    <style name="DropTargetButton">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_gravity">center_vertical</item>
+        <item name="android:gravity">center_horizontal</item>
+        <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
+        <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
+        <item name="android:paddingLeft">@dimen/toolbar_button_horizontal_padding</item>
+        <item name="android:paddingRight">@dimen/toolbar_button_horizontal_padding</item>
+    </style>
 
     <style name="HotseatButton">
         <item name="android:paddingTop">12dip</item>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 75b93bf..ae1b7f7 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -120,10 +120,6 @@
         <attr name="widgetCountX" format="integer" />
         <!-- Number of widgets vertically -->
         <attr name="widgetCountY" format="integer" />
-        <!-- Number of wallpaper pickers horizontally -->
-        <attr name="wallpaperCountX" format="integer" />
-        <!-- Number of wallpaper pickers vertically -->
-        <attr name="wallpaperCountY" format="integer" />
     </declare-styleable>
 
     <!-- CustomizePagedView specific attributes. These attributes are used to customize
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 6c372e3..e14fbfe 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -18,10 +18,14 @@
 */
 -->
 <resources>
+    <!-- The color tints to apply to the text and drag view when hovering
+         over the delete target or the info target -->
+    <color name="delete_target_hover_tint">#A5FF0000</color>
+    <color name="info_target_hover_tint">#A50000FE</color>
+
     <color name="window_background">#FF191919</color>
     <color name="grid_dark_background">#EB191919</color>     
     <color name="bubble_dark_background">#20000000</color>
-    <color name="delete_color_filter">#A5FF0000</color>
 
     <color name="appwidget_error_color">#FCCC</color>
     <color name="snag_callout_color">#F444</color>
@@ -29,7 +33,6 @@
     <color name="gesture_color">#ff0563c1</color>
     <color name="uncertain_gesture_color">#ff848484</color>
 
-    <color name="app_info_filter">#A50000FE</color>
     <color name="dimmed_view_color">#FF7F7F7F</color>
 
     <color name="drag_outline_color">#6595f9</color>
diff --git a/res/values/config.xml b/res/values/config.xml
index de05a4b..44ba589 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -1,7 +1,4 @@
 <resources>
-<!-- System -->
-    <bool name="config_hardwareAccelerated">false</bool>
-
 <!-- AllApps/Customize/AppsCustomize -->
     <!-- Fade in/out duration of icons being dragged from the trays -->
     <integer name="config_dragAppsCustomizeIconFadeInDuration">150</integer>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 32e649d..5ecfdd6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -21,16 +21,16 @@
     <!-- Manifest configuration. -->
     <skip />
     <!-- Do not translate. android:sharedUserId of this application. -->
-    <string name="sharedUserId" translate="false"><xliff:g id="x"></xliff:g></string>
+    <string name="sharedUserId" translatable="false"><xliff:g id="x"></xliff:g></string>
     <!-- Do not translate. android:process of this application. -->
-    <string name="process" translate="false"><xliff:g id="x"></xliff:g></string>
+    <string name="process" translatable="false"><xliff:g id="x"></xliff:g></string>
     
     <!-- Do not translate. We wish to prioritize the Wallpaper and Live Wallpaper pickers,
          but because they are in a different package, we need to reference the component in
          a non language-dependent way.  If the Live Wallpaper picker component name changes
          this will have to be updated as well. -->
-    <string name="live_wallpaper_picker_package_name" translate="false">com.android.wallpaper.livepicker</string>
-    <string name="live_wallpaper_picker_class_name" translate="false">com.android.wallpaper.livepicker.LiveWallpaperActivity</string>
+    <string name="live_wallpaper_picker_package_name" translatable="false">com.android.wallpaper.livepicker</string>
+    <string name="live_wallpaper_picker_class_name" translatable="false">com.android.wallpaper.livepicker.LiveWallpaperActivity</string>
 
     <!-- General -->
     <skip />
@@ -162,6 +162,13 @@
          device. [CHAR_LIMIT=30]-->
     <string name="delete_zone_label_all_apps">Uninstall</string>
 
+    <!-- Label for delete drop target. [CHAR_LIMIT=30] -->
+    <string name="delete_target_label">Remove</string>
+    <!-- Label for uninstall drop target. [CHAR_LIMIT=30]-->
+    <string name="delete_target_uninstall_label">Uninstall</string>
+    <!-- Label for the info icon. [CHAR_LIMIT=30] -->
+    <string name="info_target_label">Manage</string>
+
     <!-- Accessibility: Search button -->
     <string name="accessibility_search_button">Search</string>
     <!-- Accessibility: Voice Search button -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index c3e6ce9..f2c07f7 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -68,7 +68,7 @@
         <item name="android:layout_marginRight">10dip</item>
     </style>
 
-    <style name="SearchBar">
+    <style name="SearchDropTargetBar">
         <item name="android:orientation">horizontal</item>
     </style>
     <style name="SearchButton">
@@ -83,7 +83,19 @@
         <item name="android:layout_height">match_parent</item>
         <item name="android:layout_gravity">center_vertical</item>
     </style>
-
+    <style name="DropTargetButtonContainer">
+        <item name="android:layout_width">0dp</item>
+        <item name="android:layout_height">match_parent</item>
+    </style>
+    <style name="DropTargetButton">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">match_parent</item>
+        <item name="android:layout_gravity">center_horizontal</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:drawablePadding">7.5dp</item>
+        <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
+        <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
+    </style>
 
     <style name="TabIndicator">
         <item name="android:layout_width">wrap_content</item>
@@ -103,8 +115,8 @@
     </style>
 
     <style name="MarketButton">
-        <item name="android:paddingRight">20dp</item>
-        <item name="android:text">@string/market</item>
+        <item name="android:paddingLeft">5dp</item>
+        <item name="android:paddingRight">5dp</item>
         <item name="android:textColor">@color/workspace_all_apps_and_delete_zone_text_color</item>
         <item name="android:textSize">18sp</item>
         <item name="android:shadowColor">@color/workspace_all_apps_and_delete_zone_text_shadow_color</item>
diff --git a/src/com/android/launcher2/ApplicationInfoDropTarget.java b/src/com/android/launcher2/ApplicationInfoDropTarget.java
index e02878a..311ac7e 100644
--- a/src/com/android/launcher2/ApplicationInfoDropTarget.java
+++ b/src/com/android/launcher2/ApplicationInfoDropTarget.java
@@ -48,7 +48,7 @@
         super(context, attrs, defStyle);
 
         // Set the hover paint colour
-        int colour = getContext().getResources().getColor(R.color.app_info_filter);
+        int colour = getContext().getResources().getColor(R.color.info_target_hover_tint);
         mHoverPaint.setColorFilter(new PorterDuffColorFilter(colour, PorterDuff.Mode.SRC_ATOP));
 
         if (LauncherApplication.isScreenLarge()) {
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index bd70463..401e8ad 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -28,8 +28,6 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
-import android.animation.ValueAnimator;
-import android.app.WallpaperManager;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
@@ -73,8 +71,7 @@
      */
     public enum ContentType {
         Applications,
-        Widgets,
-        Wallpapers
+        Widgets
     }
 
     // Refs
@@ -87,7 +84,6 @@
     private ContentType mContentType;
     private ArrayList<ApplicationInfo> mApps;
     private List<Object> mWidgets;
-    private List<ResolveInfo> mWallpapers;
 
     // Caching
     private Drawable mDefaultWidgetBackground;
@@ -100,7 +96,6 @@
     private int mMaxWidgetSpan, mMinWidgetSpan;
     private int mCellWidthGap, mCellHeightGap;
     private int mWidgetCountX, mWidgetCountY;
-    private int mWallpaperCountX, mWallpaperCountY;
     private final int mWidgetPreviewIconPaddedDimension;
     private final float sWidgetPreviewIconPaddingPercentage = 0.25f;
     private PagedViewCellLayout mWidgetSpacingLayout;
@@ -117,7 +112,6 @@
         mContentType = ContentType.Applications;
         mApps = new ArrayList<ApplicationInfo>();
         mWidgets = new ArrayList<Object>();
-        mWallpapers = new ArrayList<ResolveInfo>();
         mIconCache = ((LauncherApplication) context.getApplicationContext()).getIconCache();
         mWidgetPreviewCache = new LruCache<Object, Bitmap>(sWidgetPreviewCacheSize) {
             protected int sizeOf(Object key, Bitmap value) {
@@ -140,8 +134,6 @@
             a.getDimensionPixelSize(R.styleable.AppsCustomizePagedView_widgetCellHeightGap, 10);
         mWidgetCountX = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountX, 2);
         mWidgetCountY = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountY, 2);
-        mWallpaperCountX = a.getInt(R.styleable.AppsCustomizePagedView_wallpaperCountX, 2);
-        mWallpaperCountY = a.getInt(R.styleable.AppsCustomizePagedView_wallpaperCountY, 2);
         a.recycle();
 
         // Create a dummy page that we can use to approximate the cell dimensions of widgets and
@@ -196,27 +188,6 @@
         mWidgets.addAll(mPackageManager.queryIntentActivities(shortcutsIntent, 0));
         Collections.sort(mWidgets,
                 new LauncherModel.WidgetAndShortcutNameComparator(mPackageManager));
-
-        // Get the list of wallpapers
-        Intent wallpapersIntent = new Intent(Intent.ACTION_SET_WALLPAPER);
-        mWallpapers = mPackageManager.queryIntentActivities(wallpapersIntent,
-                PackageManager.GET_META_DATA);
-        Collections.sort(mWallpapers,
-                new LauncherModel.ShortcutNameComparator(mPackageManager));
-        // Move Live Wallpapers to the front of the list
-        Context c = getContext();
-        ResolveInfo liveWallpapers = removeResolveInfoWithComponentName(mWallpapers,
-            new ComponentName(c.getString(R.string.live_wallpaper_picker_package_name),
-                c.getString(R.string.live_wallpaper_picker_class_name)));
-        if (liveWallpapers != null) {
-            mWallpapers.add(0, liveWallpapers);
-        }
-        // Move Wallpapers to the front of the list
-        ResolveInfo wallpapers = removeResolveInfoWithComponentName(mWallpapers,
-            new ComponentName(c.getPackageName(), WallpaperChooser.class.getName()));
-        if (wallpapers != null) {
-            mWallpapers.add(0, wallpapers);
-        }
     }
 
     /**
@@ -328,39 +299,31 @@
                 }
             });
         } else if (v instanceof PagedViewWidget) {
-            if (v.getTag() instanceof ResolveInfo) {
-                final ResolveInfo info = (ResolveInfo) v.getTag();
-                if (mWallpapers.contains(info)) {
-                    // Start the wallpaper picker
-                    animateClickFeedback(v, new Runnable() {
-                        @Override
-                        public void run() {
-                            // add the shortcut
-                            Intent createWallpapersIntent = new Intent(Intent.ACTION_SET_WALLPAPER);
-                            ComponentName name = new ComponentName(info.activityInfo.packageName,
-                                    info.activityInfo.name);
-                            createWallpapersIntent.setComponent(name);
-                            mLauncher.processWallpaper(createWallpapersIntent);
+            // Add the widget to the current workspace screen
+            Workspace w = mLauncher.getWorkspace();
+            int currentWorkspaceScreen = mLauncher.getCurrentWorkspaceScreen();
+            final CellLayout cl = (CellLayout) w.getChildAt(currentWorkspaceScreen);
+            final View dragView = v.findViewById(R.id.widget_preview);
+            final ItemInfo itemInfo = (ItemInfo) v.getTag();
+            animateClickFeedback(v, new Runnable() {
+                @Override
+                public void run() {
+                    cl.calculateSpans(itemInfo);
+                    if (cl.findCellForSpan(null, itemInfo.spanX, itemInfo.spanY)) {
+                        if (LauncherApplication.isScreenLarge()) {
+                            animateItemOntoScreen(dragView, cl, itemInfo);
+                        } else {
+                            mLauncher.addExternalItemToScreen(itemInfo, cl);
+                            itemInfo.dropPos = null;
                         }
-                    });
-                }
-            } else {
-                // Let the user know that they have to long press to add a widget
-                Toast.makeText(getContext(), R.string.long_press_widget_to_add,
-                        Toast.LENGTH_SHORT).show();
 
-                // Create a little animation to show that the widget can move
-                float offsetY = getResources().getDimensionPixelSize(R.dimen.dragViewOffsetY);
-                final ImageView p = (ImageView) v.findViewById(R.id.widget_preview);
-                AnimatorSet bounce = new AnimatorSet();
-                ValueAnimator tyuAnim = ObjectAnimator.ofFloat(p, "translationY", offsetY);
-                tyuAnim.setDuration(125);
-                ValueAnimator tydAnim = ObjectAnimator.ofFloat(p, "translationY", 0f);
-                tydAnim.setDuration(100);
-                bounce.play(tyuAnim).before(tydAnim);
-                bounce.setInterpolator(new AccelerateInterpolator());
-                bounce.start();
-            }
+                        // Hide the pane so we can see the workspace we dropped on
+                        mLauncher.showWorkspace(true);
+                    } else {
+                        mLauncher.showOutOfSpaceMessage();
+                    }
+                }
+            });
         }
     }
 
@@ -797,160 +760,6 @@
         }
     }
 
-    /*
-     * This method fetches an xml file specified in the manifest identified by
-     * WallpaperManager.WALLPAPER_PREVIEW_META_DATA). The xml file specifies
-     * an image which will be used as the wallpaper preview for an activity
-     * which responds to ACTION_SET_WALLPAPER. This image is returned and used
-     * in the customize drawer.
-     */
-    private Drawable parseWallpaperPreviewXml(ResolveInfo ri) {
-        ActivityInfo activityInfo = ri.activityInfo;
-        XmlResourceParser parser = null;
-        ComponentName component = new ComponentName(ri.activityInfo.packageName,
-                ri.activityInfo.name);
-        try {
-            parser = activityInfo.loadXmlMetaData(mPackageManager,
-                    WallpaperManager.WALLPAPER_PREVIEW_META_DATA);
-            if (parser == null) {
-                Slog.w(LOG_TAG, "No " + WallpaperManager.WALLPAPER_PREVIEW_META_DATA
-                        + " meta-data for " + "wallpaper provider '" + component + '\'');
-                return null;
-            }
-
-            AttributeSet attrs = Xml.asAttributeSet(parser);
-
-            int type;
-            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
-                    && type != XmlPullParser.START_TAG) {
-                // drain whitespace, comments, etc.
-            }
-
-            String nodeName = parser.getName();
-            if (!"wallpaper-preview".equals(nodeName)) {
-                Slog.w(LOG_TAG, "Meta-data does not start with wallpaper-preview tag for "
-                        + "wallpaper provider '" + component + '\'');
-                return null;
-            }
-
-            // If metaData was null, we would have returned earlier when getting
-            // the parser No need to do the check here
-            Resources res = mPackageManager.getResourcesForApplication(
-                    activityInfo.applicationInfo);
-
-            TypedArray sa = res.obtainAttributes(attrs,
-                    com.android.internal.R.styleable.WallpaperPreviewInfo);
-
-            TypedValue value = sa.peekValue(
-                    com.android.internal.R.styleable.WallpaperPreviewInfo_staticWallpaperPreview);
-            if (value == null) return null;
-
-            return res.getDrawable(value.resourceId);
-        } catch (Exception e) {
-            Slog.w(LOG_TAG, "XML parsing failed for wallpaper provider '" + component + '\'', e);
-            return null;
-        } finally {
-            if (parser != null) parser.close();
-        }
-    }
-    private FastBitmapDrawable getWallpaperPreview(ResolveInfo info, int cellWidth, int cellHeight){
-        // Return the cached version if necessary
-        Bitmap cachedBitmap = mWidgetPreviewCache.get(info);
-        if (cachedBitmap != null) {
-            return new FastBitmapDrawable(cachedBitmap);
-        }
-
-        // Get the preview
-        Resources resources = getContext().getResources();
-        Drawable wallpaperPreview = parseWallpaperPreviewXml(info);
-        Drawable wallpaperIcon = null;
-        int expectedWidth;
-        int expectedHeight;
-        if (wallpaperPreview != null) {
-            expectedWidth = wallpaperPreview.getIntrinsicWidth();
-            expectedHeight = wallpaperPreview.getIntrinsicHeight();
-        } else {
-            wallpaperPreview = mDefaultWidgetBackground;
-            expectedWidth = expectedHeight = Math.min(cellWidth, cellHeight);
-
-            // Draw the icon in the top left corner
-            String packageName = info.activityInfo.packageName;
-            try {
-                if (info.icon > 0) {
-                    wallpaperIcon = mPackageManager.getDrawable(packageName, info.icon, null);
-                }
-                if (wallpaperIcon == null) {
-                    wallpaperIcon = resources.getDrawable(R.drawable.ic_launcher_application);
-                }
-            } catch (Resources.NotFoundException e) {}
-        }
-
-        // Create the bitmap
-        Bitmap preview = Bitmap.createBitmap(expectedWidth, expectedHeight, Config.ARGB_8888);
-        renderDrawableToBitmap(wallpaperPreview, preview, 0, 0, expectedWidth, expectedHeight,
-                1f, 1f);
-        if (wallpaperIcon != null) {
-            int iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size);
-            int offset = (int) (iconSize * sWidgetPreviewIconPaddingPercentage);
-            renderDrawableToBitmap(wallpaperIcon, preview, offset, offset, iconSize, iconSize,
-                    1f, 1f);
-        }
-
-        FastBitmapDrawable previewDrawable = new FastBitmapDrawable(preview);
-        previewDrawable.setBounds(0, 0, expectedWidth, expectedHeight);
-        mWidgetPreviewCache.put(info, preview);
-        return previewDrawable;
-    }
-    /*
-     * Wallpapers PagedView implementation
-     */
-    public void syncWallpaperPages() {
-        // Ensure that we have the right number of pages
-        Context context = getContext();
-        int numWidgetsPerPage = mWallpaperCountX * mWallpaperCountY;
-        int numPages = (int) Math.ceil(mWallpapers.size() / (float) numWidgetsPerPage);
-        for (int i = 0; i < numPages; ++i) {
-            PagedViewGridLayout layout = new PagedViewGridLayout(context, mWallpaperCountX,
-                    mWallpaperCountY);
-            setupPage(layout);
-            addView(layout);
-        }
-    }
-    public void syncWallpaperPageItems(int page) {
-        PagedViewGridLayout layout = (PagedViewGridLayout) getChildAt(page);
-        layout.removeAllViews();
-
-        // Calculate the dimensions of each cell we are giving to each widget
-        int numWidgetsPerPage = mWallpaperCountX * mWallpaperCountY;
-        int offset = page * numWidgetsPerPage;
-        int cellWidth = ((mWidgetSpacingLayout.getContentWidth() - mPageLayoutWidthGap
-                - ((mWallpaperCountX - 1) * mCellWidthGap)) / mWallpaperCountX);
-        int cellHeight = ((mWidgetSpacingLayout.getContentHeight() - mPageLayoutHeightGap
-                - ((mWallpaperCountY - 1) * mCellHeightGap)) / mWallpaperCountY);
-        for (int i = 0; i < Math.min(numWidgetsPerPage, mWallpapers.size() - offset); ++i) {
-            ResolveInfo info = mWallpapers.get(offset + i);
-            PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate(
-                    R.layout.apps_customize_wallpaper, layout, false);
-
-            // Fill in the shortcuts information
-            FastBitmapDrawable preview = getWallpaperPreview(info, cellWidth, cellHeight);
-            widget.applyFromResolveInfo(mPackageManager, info, preview, null, false);
-            widget.setTag(info);
-            widget.setOnClickListener(this);
-            widget.setOnLongClickListener(this);
-            widget.setOnTouchListener(this);
-
-            // Layout each widget
-            int ix = i % mWallpaperCountX;
-            int iy = i / mWallpaperCountX;
-            PagedViewGridLayout.LayoutParams lp = new PagedViewGridLayout.LayoutParams(cellWidth,
-                    cellHeight);
-            lp.leftMargin = (ix * cellWidth) + (ix * mCellWidthGap);
-            lp.topMargin = (iy * cellHeight) + (iy * mCellHeightGap);
-            layout.addView(widget, lp);
-        }
-    }
-
     @Override
     public void syncPages() {
         removeAllViews();
@@ -961,9 +770,6 @@
         case Widgets:
             syncWidgetPages();
             break;
-        case Wallpapers:
-            syncWallpaperPages();
-            break;
         }
     }
     @Override
@@ -975,9 +781,6 @@
         case Widgets:
             syncWidgetPageItems(page);
             break;
-        case Wallpapers:
-            syncWallpaperPageItems(page);
-            break;
         }
     }
 
diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java
index cd8e7ef..e40524d 100644
--- a/src/com/android/launcher2/AppsCustomizeTabHost.java
+++ b/src/com/android/launcher2/AppsCustomizeTabHost.java
@@ -20,6 +20,7 @@
 import android.content.res.Resources;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TabHost;
@@ -33,9 +34,9 @@
 
     private static final String APPS_TAB_TAG = "APPS";
     private static final String WIDGETS_TAB_TAG = "WIDGETS";
-    private static final String WALLPAPERS_TAB_TAG = "WALLPAPERS";
 
     private final LayoutInflater mLayoutInflater;
+    private AppsCustomizePagedView mAppsCustomizePane;
 
     public AppsCustomizeTabHost(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -58,15 +59,16 @@
         setup();
 
         final ViewGroup tabs = (ViewGroup) findViewById(com.android.internal.R.id.tabs);
-        final AppsCustomizePagedView content = (AppsCustomizePagedView)
+        final AppsCustomizePagedView appsCustomizePane = (AppsCustomizePagedView)
                 findViewById(R.id.apps_customize_pane_content);
-        if (tabs == null || content == null) throw new Resources.NotFoundException();
+        mAppsCustomizePane = appsCustomizePane;
+        if (tabs == null || mAppsCustomizePane == null) throw new Resources.NotFoundException();
 
         // Configure the tabs content factory to return the same paged view (that we change the
         // content filter on)
         TabContentFactory contentFactory = new TabContentFactory() {
             public View createTabContent(String tag) {
-                return content;
+                return appsCustomizePane;
             }
         };
 
@@ -78,20 +80,25 @@
         tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
         tabView.setText(mContext.getString(R.string.widgets_tab_label));
         addTab(newTabSpec(WIDGETS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
-        tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
-        tabView.setText(mContext.getString(R.string.wallpapers_tab_label));
-        addTab(newTabSpec(WALLPAPERS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
         setOnTabChangedListener(this);
 
         // Set the width of the tab bar to match the content (for now)
-        tabs.getLayoutParams().width = content.getPageContentWidth();
+        tabs.getLayoutParams().width = mAppsCustomizePane.getPageContentWidth();
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        // Intercept all touch events up to the bottom of the AppsCustomizePane so they do not fall
+        // through to the workspace and trigger showWorkspace()
+        if (event.getY() < mAppsCustomizePane.getBottom()) {
+            return true;
+        }
+        return super.onTouchEvent(event);
     }
 
     @Override
     public void onTabChanged(String tabId) {
-        final AppsCustomizePagedView content = (AppsCustomizePagedView)
-                findViewById(R.id.apps_customize_pane_content);
-        content.setContentType(getContentTypeForTabTag(tabId));
+        mAppsCustomizePane.setContentType(getContentTypeForTabTag(tabId));
     }
 
     /**
@@ -102,8 +109,6 @@
             return AppsCustomizePagedView.ContentType.Applications;
         } else if (tag.equals(WIDGETS_TAB_TAG)) {
             return AppsCustomizePagedView.ContentType.Widgets;
-        } else if (tag.equals(WALLPAPERS_TAB_TAG)) {
-            return AppsCustomizePagedView.ContentType.Wallpapers;
         }
         return AppsCustomizePagedView.ContentType.Applications;
     }
@@ -116,8 +121,6 @@
             return APPS_TAB_TAG;
         } else if (type == AppsCustomizePagedView.ContentType.Widgets) {
             return WIDGETS_TAB_TAG;
-        } else if (type == AppsCustomizePagedView.ContentType.Wallpapers) {
-            return WALLPAPERS_TAB_TAG;
         }
         return APPS_TAB_TAG;
     }
diff --git a/src/com/android/launcher2/DeleteDropTarget.java b/src/com/android/launcher2/DeleteDropTarget.java
new file mode 100644
index 0000000..5c67793
--- /dev/null
+++ b/src/com/android/launcher2/DeleteDropTarget.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.TransitionDrawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.launcher.R;
+
+public class DeleteDropTarget extends IconDropTarget {
+
+    private static final int sTransitionDuration = 0;
+
+    private TransitionDrawable mIcon;
+    private int mDefaultTextColor;
+    private int mHoverColor = 0xFFFF0000;
+
+    public DeleteDropTarget(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public DeleteDropTarget(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        // Get the drawable
+        mIcon = (TransitionDrawable) getCompoundDrawables()[0];
+
+        // Get the hover color
+        Resources r = getResources();
+        mDefaultTextColor = getTextColors().getDefaultColor();
+        mHoverColor = r.getColor(R.color.delete_target_hover_tint);
+        mHoverPaint.setColorFilter(new PorterDuffColorFilter(
+                mHoverColor, PorterDuff.Mode.SRC_ATOP));
+    }
+
+    private boolean isAllAppsApplication(DragSource source, Object info) {
+        return (source instanceof AppsCustomizePagedView) && (info instanceof ApplicationInfo);
+    }
+    private boolean isAllAppsWidget(DragSource source, Object info) {
+        return (source instanceof AppsCustomizePagedView) && (info instanceof PendingAddWidgetInfo);
+    }
+    private boolean isWorkspaceApplication(DragObject d) {
+        return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof ShortcutInfo);
+    }
+    private boolean isWorkspaceWidget(DragObject d) {
+        return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof LauncherAppWidgetInfo);
+    }
+    private boolean isWorkspaceFolder(DragObject d) {
+        return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof FolderInfo);
+    }
+
+    @Override
+    public boolean acceptDrop(DragObject d) {
+        // We can remove everything including App shortcuts, folders, widgets, etc.
+        return true;
+    }
+
+    @Override
+    public void onDragStart(DragSource source, Object info, int dragAction) {
+        ItemInfo item = (ItemInfo) info;
+        boolean isVisible = true;
+        boolean isUninstall = false;
+
+        // If we are dragging a widget from AppsCustomize , hide the delete target
+        if (isAllAppsWidget(source, info)) {
+            isVisible = false;
+        }
+
+        // If we are dragging an application from AppsCustomize, only show the control if we can
+        // delete the app (it was downloaded), and rename the string to "uninstall" in such a case
+        if (isAllAppsApplication(source, info)) {
+            ApplicationInfo appInfo = (ApplicationInfo) info;
+            if ((appInfo.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) {
+                isUninstall = true;
+            } else {
+                isVisible = false;
+            }
+        }
+
+        mActive = isVisible;
+        ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE);
+        if (getText().length() > 0) {
+            setText(isUninstall ? R.string.delete_target_uninstall_label
+                : R.string.delete_target_label);
+        }
+    }
+
+    @Override
+    public void onDragEnd() {
+        super.onDragEnd();
+        mActive = false;
+    }
+
+    public void onDragEnter(DragObject d) {
+        super.onDragEnter(d);
+
+        mIcon.startTransition(sTransitionDuration);
+        setTextColor(mHoverColor);
+    }
+
+    public void onDragExit(DragObject d) {
+        super.onDragExit(d);
+
+        mIcon.reverseTransition(sTransitionDuration);
+        setTextColor(mDefaultTextColor);
+    }
+
+    public void onDrop(DragObject d) {
+        ItemInfo item = (ItemInfo) d.dragInfo;
+
+        if (isAllAppsApplication(d.dragSource, item)) {
+            // Uninstall the application if it is being dragged from AppsCustomize
+            mLauncher.startApplicationUninstallActivity((ApplicationInfo) item);
+        } else if (isWorkspaceApplication(d)) {
+            LauncherModel.deleteItemFromDatabase(mLauncher, item);
+        } else if (isWorkspaceFolder(d)) {
+            // Remove the folder from the workspace and delete the contents from launcher model
+            FolderInfo folderInfo = (FolderInfo) item;
+            mLauncher.removeFolder(folderInfo);
+            LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo);
+        } else if (isWorkspaceWidget(d)) {
+            // Remove the widget from the workspace
+            mLauncher.removeAppWidget((LauncherAppWidgetInfo) item);
+            LauncherModel.deleteItemFromDatabase(mLauncher, item);
+
+            final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
+            final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
+            if (appWidgetHost != null) {
+                // Deleting an app widget ID is a void call but writes to disk before returning
+                // to the caller...
+                new Thread("deleteAppWidgetId") {
+                    public void run() {
+                        appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId);
+                    }
+                }.start();
+            }
+        }
+    }
+}
diff --git a/src/com/android/launcher2/DeleteZone.java b/src/com/android/launcher2/DeleteZone.java
index 21b1cf1..c349e5d 100644
--- a/src/com/android/launcher2/DeleteZone.java
+++ b/src/com/android/launcher2/DeleteZone.java
@@ -62,7 +62,7 @@
     public DeleteZone(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        final int srcColor = context.getResources().getColor(R.color.delete_color_filter);
+        final int srcColor = context.getResources().getColor(R.color.delete_target_hover_tint);
         mHoverPaint.setColorFilter(new PorterDuffColorFilter(srcColor, PorterDuff.Mode.SRC_ATOP));
 
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DeleteZone, defStyle, 0);
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index 7503dda..af47bea 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -58,7 +58,8 @@
         setMotionEventSplittingEnabled(false);
     }
 
-    public void setDragController(DragController controller) {
+    public void setup(Launcher launcher, DragController controller) {
+        mLauncher = launcher;
         mDragController = controller;
     }
     
@@ -252,10 +253,6 @@
         resizeFrame.snapToWidget(false);
     }
 
-    public void setLauncher(Launcher l) {
-        mLauncher = l;
-    }
-
     public void setCurrentFolder(Folder f) {
         mCurrentFolder = f;
     }
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index e97676d..952d704 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -78,10 +78,7 @@
     private int mOriginalWidth = -1;
     private int mOriginalHeight = -1;
 
-    private int mFolderLocX;
-    private int mFolderLocY;
-    private float mOuterRingScale;
-    private float mInnerRingScale;
+    FolderRingAnimator mFolderRingAnimator = null;
 
     public FolderIcon(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -117,18 +114,107 @@
         folder.setFolderIcon(icon);
         folder.bind(folderInfo);
         icon.mFolder = folder;
-
+        icon.mFolderRingAnimator = new FolderRingAnimator(launcher, icon);
         folderInfo.addListener(icon);
-        if (sFolderOuterRingDrawable == null) {
-            sFolderOuterRingDrawable =
-                    launcher.getResources().getDrawable(R.drawable.portal_ring_outer_holo);
+
+        return icon;
+    }
+
+    public static class FolderRingAnimator {
+        public int mFolderLocX;
+        public int mFolderLocY;
+        public float mOuterRingScale;
+        public float mInnerRingScale;
+        public FolderIcon mFolderIcon = null;
+        private Launcher mLauncher;
+
+        public FolderRingAnimator(Launcher launcher, FolderIcon folderIcon) {
+            mLauncher = launcher;
+            mFolderIcon = folderIcon;
+            if (sFolderOuterRingDrawable == null) {
+                sFolderOuterRingDrawable =
+                        launcher.getResources().getDrawable(R.drawable.portal_ring_outer_holo);
+            }
+            if (sFolderInnerRingDrawable == null) {
+                sFolderInnerRingDrawable =
+                        launcher.getResources().getDrawable(R.drawable.portal_ring_inner_holo);
+            }
         }
 
-        if (sFolderInnerRingDrawable == null) {
-            sFolderInnerRingDrawable =
-                    launcher.getResources().getDrawable(R.drawable.portal_ring_inner_holo);
+        public void setLocation(int x, int y) {
+            mFolderLocX = x;
+            mFolderLocY = y;
         }
-        return icon;
+
+        public void animateToAcceptState() {
+            ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
+            va.setDuration(CONSUMPTION_ANIMATION_DURATION);
+            va.addUpdateListener(new AnimatorUpdateListener() {
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    final float percent = (Float) animation.getAnimatedValue();
+                    mOuterRingScale = OUTER_RING_BASELINE_SCALE + percent * OUTER_RING_GROWTH_FACTOR;
+                    mInnerRingScale = INNER_RING_BASELINE_SCALE + percent * INNER_RING_GROWTH_FACTOR;
+                    mLauncher.getWorkspace().invalidate();
+                    if (mFolderIcon != null) {
+                        mFolderIcon.invalidate();
+                    }
+                }
+            });
+            va.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.
+                    if (mFolderIcon != null) {
+                        mFolderIcon.setBackgroundColor(Color.TRANSPARENT);
+                        mFolderIcon.requestLayout();
+                    }
+                }
+            });
+            va.start();
+        }
+
+        public void animateToNaturalState() {
+            ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
+            va.setDuration(CONSUMPTION_ANIMATION_DURATION);
+            va.addUpdateListener(new AnimatorUpdateListener() {
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    final float percent = (Float) animation.getAnimatedValue();
+                    mOuterRingScale = OUTER_RING_BASELINE_SCALE + OUTER_RING_GROWTH_FACTOR
+                            - percent * OUTER_RING_GROWTH_FACTOR;
+                    mInnerRingScale = INNER_RING_BASELINE_SCALE + INNER_RING_GROWTH_FACTOR
+                            - percent * INNER_RING_GROWTH_FACTOR;
+                    mLauncher.getWorkspace().invalidate();
+                    if (mFolderIcon != null) {
+                        mFolderIcon.invalidate();
+                    }
+                }
+            });
+            va.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    if (mFolderIcon != null) {
+                        mFolderIcon.setBackgroundDrawable(sFolderInnerRingDrawable);
+                    }
+                    mLauncher.getWorkspace().hideFolderAccept(FolderRingAnimator.this);
+                }
+            });
+            va.start();
+        }
+
+        public void getLocation(int[] loc) {
+            loc[0] = mFolderLocX;
+            loc[1] = mFolderLocY;
+        }
+
+        public float getOuterRingScale() {
+            return mOuterRingScale;
+        }
+
+        public float getInnerRingScale() {
+            return mInnerRingScale;
+        }
     }
 
     private boolean willAcceptItem(ItemInfo item) {
@@ -166,69 +252,22 @@
         mOriginalHeight = lp.height;
     }
 
-    private void animateToAcceptState() {
-        ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
-        va.setDuration(CONSUMPTION_ANIMATION_DURATION);
-        va.addUpdateListener(new AnimatorUpdateListener() {
-            public void onAnimationUpdate(ValueAnimator animation) {
-                final float percent = (Float) animation.getAnimatedValue();
-                mOuterRingScale = OUTER_RING_BASELINE_SCALE + percent * OUTER_RING_GROWTH_FACTOR;
-                mInnerRingScale = INNER_RING_BASELINE_SCALE + percent * INNER_RING_GROWTH_FACTOR;
-                mLauncher.getWorkspace().invalidate();
-                invalidate();
-            }
-        });
-        va.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.
-                setBackgroundColor(Color.TRANSPARENT);
-                requestLayout();
-            }
-        });
-        va.start();
-    }
-
-    private void animateToNaturalState() {
-        ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
-        va.setDuration(CONSUMPTION_ANIMATION_DURATION);
-        va.addUpdateListener(new AnimatorUpdateListener() {
-            public void onAnimationUpdate(ValueAnimator animation) {
-                final float percent = (Float) animation.getAnimatedValue();
-                mOuterRingScale = OUTER_RING_BASELINE_SCALE + OUTER_RING_GROWTH_FACTOR
-                        - percent * OUTER_RING_GROWTH_FACTOR;
-                mInnerRingScale = INNER_RING_BASELINE_SCALE + INNER_RING_GROWTH_FACTOR
-                        - percent * INNER_RING_GROWTH_FACTOR;
-                mLauncher.getWorkspace().invalidate();
-                invalidate();
-            }
-        });
-        va.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                setBackgroundDrawable(sFolderInnerRingDrawable);
-                mLauncher.getWorkspace().hideFolderAccept(FolderIcon.this);
-            }
-        });
-        va.start();
-    }
-
     private void determineFolderLocationInWorkspace() {
         int tvLocation[] = new int[2];
         int wsLocation[] = new int[2];
         getLocationOnScreen(tvLocation);
         mLauncher.getWorkspace().getLocationOnScreen(wsLocation);
-        mFolderLocX = tvLocation[0] - wsLocation[0] + getMeasuredWidth() / 2;
-        mFolderLocY = tvLocation[1] - wsLocation[1] + getMeasuredHeight() / 2;
+
+        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;
         determineFolderLocationInWorkspace();
-        mLauncher.getWorkspace().showFolderAccept(this);
-        animateToAcceptState();
+        mLauncher.getWorkspace().showFolderAccept(mFolderRingAnimator);
+        mFolderRingAnimator.animateToAcceptState();
     }
 
     public void onDragOver(DragObject d) {
@@ -236,26 +275,13 @@
 
     public void onDragExit(DragObject d) {
         if (!willAcceptItem((ItemInfo) d.dragInfo)) return;
-        animateToNaturalState();
+        mFolderRingAnimator.animateToNaturalState();
     }
 
     public DropTarget getDropTargetDelegate(DragObject d) {
         return null;
     }
 
-    public void getFolderLocation(int[] loc) {
-        loc[0] = mFolderLocX;
-        loc[1] = mFolderLocY;
-    }
-
-    public float getOuterRingScale() {
-        return mOuterRingScale;
-    }
-
-    public float getInnerRingScale() {
-        return mInnerRingScale;
-    }
-
     @Override
     protected void onDraw(Canvas canvas) {
         if (mFolder == null) return;
diff --git a/src/com/android/launcher2/InfoDropTarget.java b/src/com/android/launcher2/InfoDropTarget.java
new file mode 100644
index 0000000..bbde2b8
--- /dev/null
+++ b/src/com/android/launcher2/InfoDropTarget.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.launcher.R;
+
+public class InfoDropTarget extends IconDropTarget {
+
+    private int mDefaultTextColor;
+    private int mHoverColor = 0xFF0000FF;
+
+    public InfoDropTarget(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public InfoDropTarget(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        // Get the hover color
+        Resources r = getResources();
+        mDefaultTextColor = getTextColors().getDefaultColor();
+        mHoverColor = r.getColor(R.color.info_target_hover_tint);
+        mHoverPaint.setColorFilter(new PorterDuffColorFilter(
+                mHoverColor, PorterDuff.Mode.SRC_ATOP));
+    }
+
+    private boolean isApplication(Object info) {
+        if (info instanceof ApplicationInfo) return true;
+        return (((ItemInfo) info).itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION);
+    }
+
+    @Override
+    public boolean acceptDrop(DragObject d) {
+        // acceptDrop is called just before onDrop. We do the work here, rather than
+        // in onDrop, because it allows us to reject the drop (by returning false)
+        // so that the object being dragged isn't removed from the drag source.
+        ComponentName componentName = null;
+        if (d.dragInfo instanceof ApplicationInfo) {
+            componentName = ((ApplicationInfo) d.dragInfo).componentName;
+        } else if (d.dragInfo instanceof ShortcutInfo) {
+            componentName = ((ShortcutInfo) d.dragInfo).intent.getComponent();
+        }
+        if (componentName != null) {
+            mLauncher.startApplicationDetailsActivity(componentName);
+        }
+        return false;
+    }
+
+    @Override
+    public void onDragStart(DragSource source, Object info, int dragAction) {
+        ItemInfo item = (ItemInfo) info;
+        boolean isVisible = true;
+
+        // If we are dragging a widget or shortcut, hide the info target
+        if (!isApplication(info)) {
+            isVisible = false;
+        }
+
+        mActive = isVisible;
+        ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public void onDragEnd() {
+        super.onDragEnd();
+        mActive = false;
+    }
+
+    public void onDragEnter(DragObject d) {
+        super.onDragEnter(d);
+
+        setTextColor(mHoverColor);
+    }
+
+    public void onDragExit(DragObject d) {
+        super.onDragExit(d);
+
+        setTextColor(mDefaultTextColor);
+    }
+}
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 5cf8e9c..48869d3 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -199,6 +199,7 @@
 
     private DeleteZone mDeleteZone;
     private HandleView mHandleView;
+    private SearchDropTargetBar mSearchDeleteBar;
     private AllAppsView mAllAppsGrid;
     private AppsCustomizeTabHost mAppsCustomizeTabHost;
     private AppsCustomizePagedView mAppsCustomizeContent;
@@ -896,128 +897,110 @@
     private void setupViews() {
         final DragController dragController = mDragController;
 
-        DragLayer dragLayer = (DragLayer) findViewById(R.id.drag_layer);
-        dragLayer.setDragController(dragController);
-        dragLayer.setLauncher(this);
-        mDragLayer = dragLayer;
+        mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
+        mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
 
+        // Setup the drag layer
+        mDragLayer.setup(this, dragController);
+
+        // Setup the workspace
+        mWorkspace.setHapticFeedbackEnabled(false);
+        mWorkspace.setOnLongClickListener(this);
+        mWorkspace.setup(this, dragController);
+        mWorkspace.setWallpaperDimension();
+
+        // Setup the different configurations
+        DeleteZone allAppsDeleteZone = null;
+        ApplicationInfoDropTarget allAppsInfoTarget = null;
         if (LauncherApplication.isScreenLarge()) {
-            mAllAppsGrid = (AllAppsView) dragLayer.findViewById(R.id.all_apps_view);
+            // Setup AllApps
+            mAllAppsGrid = (AllAppsView) mDragLayer.findViewById(R.id.all_apps_view);
             mAllAppsGrid.setup(this, dragController);
             // We don't want a hole punched in our window.
             ((View) mAllAppsGrid).setWillNotDraw(false);
-        } else {
-            mAppsCustomizeTabHost = (AppsCustomizeTabHost)
-                    findViewById(R.id.apps_customize_pane);
-            mAppsCustomizeContent = (AppsCustomizePagedView)
-                    mAppsCustomizeTabHost.findViewById(R.id.apps_customize_pane_content);
-            mAppsCustomizeContent.setup(this, dragController);
-        }
 
-        mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
-
-        final Workspace workspace = mWorkspace;
-        workspace.setHapticFeedbackEnabled(false);
-
-        DeleteZone deleteZone = (DeleteZone) dragLayer.findViewById(R.id.delete_zone);
-        mDeleteZone = deleteZone;
-
-        View handleView = findViewById(R.id.all_apps_button);
-        if (handleView != null && handleView instanceof HandleView) {
-            // we don't use handle view in xlarge mode
-            mHandleView = (HandleView)handleView;
-            mHandleView.setLauncher(this);
-            mHandleView.setOnLongClickListener(this);
-        }
-
-        if (mCustomizePagedView != null) {
+            // Setup Customize
             mCustomizePagedView.setLauncher(this);
             mCustomizePagedView.setDragController(dragController);
             mCustomizePagedView.setAllAppsPagedView(mAllAppsPagedView);
-        } else {
-             ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left);
-             hotseatLeft.setContentDescription(mHotseatLabels[0]);
-             hotseatLeft.setImageDrawable(mHotseatIcons[0]);
-             ImageView hotseatRight = (ImageView) findViewById(R.id.hotseat_right);
-             hotseatRight.setContentDescription(mHotseatLabels[1]);
-             hotseatRight.setImageDrawable(mHotseatIcons[1]);
 
-             View.OnKeyListener listener = new IndicatorKeyEventListener();
-             mPreviousView = (ImageView) dragLayer.findViewById(R.id.previous_screen);
-             mPreviousView.setOnKeyListener(listener);
-             mNextView = (ImageView) dragLayer.findViewById(R.id.next_screen);
-             mNextView.setOnKeyListener(listener);
+            // Setup DeleteZone
+            mDeleteZone = (DeleteZone) mDragLayer.findViewById(R.id.delete_zone);
+            mDeleteZone.setLauncher(this);
+            mDeleteZone.setDragController(dragController);
 
-             Drawable previous = mPreviousView.getDrawable();
-             Drawable next = mNextView.getDrawable();
-             mWorkspace.setIndicators(previous, next);
+            // Setup the top-right Apps/Customize buttons
+            mAllAppsButton = findViewById(R.id.all_apps_button);
+            mDivider = findViewById(R.id.all_apps_divider);
+            mConfigureButton = findViewById(R.id.configure_button);
+            mDeleteZone.setOverlappingViews(new View[] { mAllAppsButton, mDivider,
+                    mConfigureButton });
 
-             mPreviousView.setHapticFeedbackEnabled(false);
-             mPreviousView.setOnLongClickListener(this);
-             mNextView.setHapticFeedbackEnabled(false);
-             mNextView.setOnLongClickListener(this);
-        }
-
-        workspace.setOnLongClickListener(this);
-        workspace.setDragController(dragController);
-        workspace.setLauncher(this);
-        workspace.setWallpaperDimension();
-
-        deleteZone.setLauncher(this);
-        deleteZone.setDragController(dragController);
-
-        final View allAppsButton = findViewById(R.id.all_apps_button);
-        final View divider = findViewById(R.id.all_apps_divider);
-        final View configureButton = findViewById(R.id.configure_button);
-
-        if (LauncherApplication.isScreenLarge()) {
-            deleteZone.setOverlappingViews(new View[] { allAppsButton, divider, configureButton });
-        } else {
-            deleteZone.setOverlappingView(findViewById(R.id.all_apps_button_cluster));
-        }
-        dragController.addDragListener(deleteZone);
-
-        DeleteZone allAppsDeleteZone = (DeleteZone) findViewById(R.id.all_apps_delete_zone);
-        if (allAppsDeleteZone != null) {
+            // Setup the AllApps Delete toolbar button
+            allAppsDeleteZone = (DeleteZone) findViewById(R.id.all_apps_delete_zone);
             allAppsDeleteZone.setLauncher(this);
             allAppsDeleteZone.setDragController(dragController);
             allAppsDeleteZone.setDragAndDropEnabled(false);
-            dragController.addDragListener(allAppsDeleteZone);
-            dragController.addDropTarget(allAppsDeleteZone);
-        }
 
-        ApplicationInfoDropTarget allAppsInfoTarget = (ApplicationInfoDropTarget)
-                findViewById(R.id.all_apps_info_target);
-        if (allAppsInfoTarget != null) {
+            // Setup the AllApps Info toolbar button
+            allAppsInfoTarget = (ApplicationInfoDropTarget) findViewById(R.id.all_apps_info_target);
             allAppsInfoTarget.setLauncher(this);
-            dragController.addDragListener(allAppsInfoTarget);
             allAppsInfoTarget.setDragAndDropEnabled(false);
-        }
-        View marketButton = findViewById(R.id.market_button);
-        if (marketButton != null) {
-            if (allAppsInfoTarget != null) {
-                allAppsInfoTarget.setOverlappingView(marketButton);
-            }
+
+            // Setup the AllApps Market toolbar button
+            View marketButton = findViewById(R.id.market_button);
+            allAppsInfoTarget.setOverlappingView(marketButton);
             marketButton.setOnClickListener(new OnClickListener() {
                 public void onClick(View v) {
                     onClickAppMarketButton(v);
                 }
             });
+        } else {
+            // Get the search/delete bar
+            mSearchDeleteBar = (SearchDropTargetBar) mDragLayer.findViewById(R.id.qsb_bar);
+
+            // Setup AppsCustomize
+            mAppsCustomizeTabHost = (AppsCustomizeTabHost)
+                    findViewById(R.id.apps_customize_pane);
+            mAppsCustomizeContent = (AppsCustomizePagedView)
+                    mAppsCustomizeTabHost.findViewById(R.id.apps_customize_pane_content);
+            mAppsCustomizeContent.setup(this, dragController);
+
+            // Setup AppsCustomize button
+            mHandleView = (HandleView) mDragLayer.findViewById(R.id.all_apps_button);
+            mHandleView.setLauncher(this);
+            mHandleView.setOnLongClickListener(this);
+            mHandleView.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    onClickAllAppsButton(v);
+                }
+            });
+
+            // Setup Hotseat
+            ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left);
+            hotseatLeft.setContentDescription(mHotseatLabels[0]);
+            hotseatLeft.setImageDrawable(mHotseatIcons[0]);
+            ImageView hotseatRight = (ImageView) findViewById(R.id.hotseat_right);
+            hotseatRight.setContentDescription(mHotseatLabels[1]);
+            hotseatRight.setImageDrawable(mHotseatIcons[1]);
+
+            View.OnKeyListener listener = new IndicatorKeyEventListener();
+            mPreviousView = (ImageView) mDragLayer.findViewById(R.id.previous_screen);
+            mPreviousView.setOnKeyListener(listener);
+            mNextView = (ImageView) mDragLayer.findViewById(R.id.next_screen);
+            mNextView.setOnKeyListener(listener);
+
+            Drawable previous = mPreviousView.getDrawable();
+            Drawable next = mNextView.getDrawable();
+            mWorkspace.setIndicators(previous, next);
+
+            mPreviousView.setHapticFeedbackEnabled(false);
+            mPreviousView.setOnLongClickListener(this);
+            mNextView.setHapticFeedbackEnabled(false);
+            mNextView.setOnLongClickListener(this);
         }
 
-        dragController.setDragScoller(workspace);
-        dragController.setScrollView(dragLayer);
-        dragController.setMoveTarget(workspace);
-
-        // The order here is bottom to top.
-        dragController.addDropTarget(workspace);
-        dragController.addDropTarget(deleteZone);
-        if (allAppsInfoTarget != null) {
-            dragController.addDropTarget(allAppsInfoTarget);
-        }
-        if (allAppsDeleteZone != null) {
-            dragController.addDropTarget(allAppsDeleteZone);
-        }
+        // Setup keylistener for button cluster
         mButtonCluster = (ViewGroup) findViewById(R.id.all_apps_button_cluster);
         View.OnKeyListener listener = null;
         if (LauncherApplication.isScreenLarge()) {
@@ -1032,33 +1015,25 @@
             mButtonCluster.getChildAt(i).setOnKeyListener(listener);
         }
 
-        mAllAppsButton = findViewById(R.id.all_apps_button);
-        mDivider = findViewById(R.id.all_apps_divider);
-        mConfigureButton = findViewById(R.id.configure_button);
-
-        // We had previously set these click handlers in XML, but the first time we launched
-        // Configure or All Apps we had an extra 50ms of delay while the java reflection methods
-        // found the right handler. Setting the handlers directly here eliminates that cost.
-        if (mConfigureButton != null) {
-            mConfigureButton.setOnClickListener(new OnClickListener() {
-                public void onClick(View v) {
-                    onClickConfigureButton(v);
-                }
-            });
+        // Setup the drag controller (the drop targets have to be added in reverse order)
+        dragController.setDragScoller(mWorkspace);
+        dragController.setScrollView(mDragLayer);
+        dragController.setMoveTarget(mWorkspace);
+        dragController.addDropTarget(mWorkspace);
+        if (mDeleteZone != null) {
+            dragController.addDragListener(mDeleteZone);
+            dragController.addDropTarget(mDeleteZone);
         }
-        if (mDivider != null) {
-            mDivider.setOnClickListener(new OnClickListener() {
-                public void onClick(View v) {
-                    onClickAllAppsButton(v);
-                }
-            });
+        if (mSearchDeleteBar != null) {
+            mSearchDeleteBar.setup(this, dragController);
         }
-        if (mAllAppsButton != null) {
-            mAllAppsButton.setOnClickListener(new OnClickListener() {
-                public void onClick(View v) {
-                    onClickAllAppsButton(v);
-                }
-            });
+        if (allAppsDeleteZone != null) {
+            dragController.addDragListener(allAppsDeleteZone);
+            dragController.addDropTarget(allAppsDeleteZone);
+        }
+        if (allAppsInfoTarget != null) {
+            dragController.addDragListener(allAppsInfoTarget);
+            dragController.addDropTarget(allAppsInfoTarget);
         }
     }
 
@@ -2613,22 +2588,30 @@
         switch (newState) {
         case WORKSPACE:
             hideOrShowToolbarButton(true, mButtonCluster, showSeq);
-            mDeleteZone.setDragAndDropEnabled(true);
-            if (LauncherApplication.isScreenLarge()) {
-                mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_workspace));
+            if (mDeleteZone != null) {
+                mDeleteZone.setDragAndDropEnabled(true);
+                if (LauncherApplication.isScreenLarge()) {
+                    mDeleteZone.setText(
+                            getResources().getString(R.string.delete_zone_label_workspace));
+                }
             }
             break;
         case ALL_APPS:
         case APPS_CUSTOMIZE:
             hideOrShowToolbarButton(false, mButtonCluster, hideSeq);
-            mDeleteZone.setDragAndDropEnabled(false);
-            if (LauncherApplication.isScreenLarge()) {
-                mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_all_apps));
+            if (mDeleteZone != null) {
+                mDeleteZone.setDragAndDropEnabled(false);
+                if (LauncherApplication.isScreenLarge()) {
+                    mDeleteZone.setText(
+                            getResources().getString(R.string.delete_zone_label_all_apps));
+                }
             }
             break;
         case CUSTOMIZE:
             hideOrShowToolbarButton(false, mButtonCluster, hideSeq);
-            mDeleteZone.setDragAndDropEnabled(false);
+            if (mDeleteZone != null) {
+                mDeleteZone.setDragAndDropEnabled(false);
+            }
             break;
         }
     }
@@ -2960,8 +2943,9 @@
             cameraZoomOut(State.ALL_APPS, animated, false);
             ((View) mAllAppsGrid).requestFocus();
 
-            // TODO: fade these two too
-            mDeleteZone.setVisibility(View.GONE);
+            if (mDeleteZone != null) {
+                mDeleteZone.setVisibility(View.GONE);
+            }
 
             // Change the state *after* we've called all the transition code
             mState = State.ALL_APPS;
@@ -3217,7 +3201,7 @@
         // Find the app market activity by resolving an intent.
         // (If multiple app markets are installed, it will return the ResolverActivity.)
         ComponentName activityName = intent.resolveActivity(getPackageManager());
-        if (activityName != null && LauncherApplication.isScreenLarge()) {
+        if (activityName != null) {
             mAppMarketIntent = intent;
             sAppMarketIcon = updateTextButtonWithIconFromExternalActivity(
                     R.id.market_button, activityName, R.drawable.app_market_generic);
diff --git a/src/com/android/launcher2/LauncherAppWidgetHostView.java b/src/com/android/launcher2/LauncherAppWidgetHostView.java
index 099a676..670c8b6 100644
--- a/src/com/android/launcher2/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher2/LauncherAppWidgetHostView.java
@@ -60,7 +60,7 @@
             mHasPerformedLongPress = false;
             return true;
         }
-            
+
         // Watch for longpress events at this level to make sure
         // users can always pick up this widget
         switch (ev.getAction()) {
@@ -68,7 +68,7 @@
                 postCheckForLongClick();
                 break;
             }
-            
+
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
                 mHasPerformedLongPress = false;
@@ -77,7 +77,7 @@
                 }
                 break;
         }
-        
+
         // Otherwise continue letting touch events fall through to children
         return false;
     }
diff --git a/src/com/android/launcher2/SearchDropTargetBar.java b/src/com/android/launcher2/SearchDropTargetBar.java
new file mode 100644
index 0000000..7a208b7
--- /dev/null
+++ b/src/com/android/launcher2/SearchDropTargetBar.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.launcher.R;
+
+/*
+ * Ths bar will manage the transition between the QSB search bar and the delete drop
+ * targets so that each of the individual IconDropTargets don't have to.
+ */
+public class SearchDropTargetBar extends FrameLayout implements DragController.DragListener {
+
+    private static final int sTransitionInDuration = 275;
+    private static final int sTransitionOutDuration = 200;
+
+    private View mQSBSearchBar;
+    private View mDropTargetBar;
+    private IconDropTarget mInfoDropTarget;
+    private IconDropTarget mDeleteDropTarget;
+
+    public SearchDropTargetBar(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public SearchDropTargetBar(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public void setup(Launcher launcher, DragController dragController) {
+        dragController.addDragListener(this);
+        dragController.addDragListener(mInfoDropTarget);
+        dragController.addDragListener(mDeleteDropTarget);
+        dragController.addDropTarget(mInfoDropTarget);
+        dragController.addDropTarget(mDeleteDropTarget);
+        mInfoDropTarget.setLauncher(launcher);
+        mDeleteDropTarget.setLauncher(launcher);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        // Get the individual components
+        mQSBSearchBar = findViewById(R.id.qsb_search_bar);
+        mDropTargetBar = findViewById(R.id.drag_target_bar);
+        mInfoDropTarget = (IconDropTarget) mDropTargetBar.findViewById(R.id.info_target);
+        mDeleteDropTarget = (IconDropTarget) mDropTargetBar.findViewById(R.id.delete_target);
+    }
+
+    /*
+     * DragController.DragListener implementation
+     */
+    @Override
+    public void onDragStart(DragSource source, Object info, int dragAction) {
+        // Animate out the QSB search bar, and animate in the drop target bar
+        mQSBSearchBar.animate().alpha(0f).setDuration(sTransitionOutDuration);
+        mDropTargetBar.animate().alpha(1f).setDuration(sTransitionInDuration);
+    }
+
+    @Override
+    public void onDragEnd() {
+        // Restore the QSB search bar, and animate out the drop target bar
+        mDropTargetBar.animate().alpha(0f).setDuration(sTransitionOutDuration);
+        mQSBSearchBar.animate().alpha(1f).setDuration(sTransitionInDuration);
+    }
+}
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 7d2626d..7d1ee19 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -67,6 +67,7 @@
 import android.widget.Toast;
 
 import com.android.launcher.R;
+import com.android.launcher2.FolderIcon.FolderRingAnimator;
 import com.android.launcher2.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
 
 /**
@@ -219,7 +220,16 @@
     private int mLastDragXOffset;
     private int mLastDragYOffset;
 
-    private ArrayList<FolderIcon> mFolderOuterRings = new ArrayList<FolderIcon>();
+    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 final Alarm mFolderCreationAlarm = new Alarm();
+    private FolderRingAnimator mDragFolderRingAnimator = null;
+    private View mLastDragOverView = null;
+    private boolean mCreateUserFolderOnDrop = false;
+    private int mCellWidth = -1;
+    private int mCellHeight = -1;
 
     // Variables relating to touch disambiguation (scrolling workspace vs. scrolling a widget)
     private float mXDown;
@@ -613,10 +623,15 @@
             if (mLauncher.isAllAppsVisible() && mShrinkState == ShrinkState.BOTTOM_HIDDEN) {
                 // Intercept this event so we can show the workspace in full view
                 // when it is clicked on and it is small
-                AllAppsPagedView allApps = (AllAppsPagedView)
-                        mLauncher.findViewById(R.id.all_apps_paged_view);
-                if (allApps != null) {
-                    allApps.onInterceptTouchEvent(ev);
+                PagedView appsPane = null;
+                if (LauncherApplication.isScreenLarge()) {
+                    appsPane = (PagedView) mLauncher.findViewById(R.id.all_apps_paged_view);
+                } else {
+                    appsPane = (PagedView) mLauncher.findViewById(R.id.apps_customize_pane_content);
+                }
+
+                if (appsPane != null) {
+                    appsPane.onInterceptTouchEvent(ev);
                 }
                 return true;
             }
@@ -896,7 +911,6 @@
             }
             float fractionToCatchUpIn1MsVertical = mVerticalCatchupConstant;
 
-
             fractionToCatchUpIn1MsHorizontal /= 33f;
             fractionToCatchUpIn1MsVertical /= 33f;
 
@@ -1184,14 +1198,15 @@
         }
     }
 
-    public void showFolderAccept(FolderIcon fi) {
-        mFolderOuterRings.add(fi);
+    public void showFolderAccept(FolderRingAnimator fra) {
+        mFolderOuterRings.add(fra);
     }
 
-    public void hideFolderAccept(FolderIcon fi) {
-        if (mFolderOuterRings.contains(fi)) {
-            mFolderOuterRings.remove(fi);
+    public void hideFolderAccept(FolderRingAnimator fra) {
+        if (mFolderOuterRings.contains(fra)) {
+            mFolderOuterRings.remove(fra);
         }
+        invalidate();
     }
 
     @Override
@@ -1234,24 +1249,28 @@
         for (int i = 0; i < mFolderOuterRings.size(); i++) {
 
             // Draw outer ring
-            FolderIcon fi = mFolderOuterRings.get(i);
+            FolderRingAnimator fra = mFolderOuterRings.get(i);
             Drawable d = FolderIcon.sFolderOuterRingDrawable;
-            int width = (int) (d.getIntrinsicWidth() * fi.getOuterRingScale());
-            int height = (int) (d.getIntrinsicHeight() * fi.getOuterRingScale());
-            fi.getFolderLocation(mTempLocation);
+            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);
             d.draw(canvas);
 
             // Draw inner ring
-            d = FolderIcon.sFolderInnerRingDrawable;
-            width = (int) (fi.getMeasuredWidth() * fi.getInnerRingScale());
-            height = (int) (fi.getMeasuredHeight() * fi.getInnerRingScale());
-            x = mTempLocation[0] + mScrollX - width / 2;
-            y = mTempLocation[1] + mScrollY - height / 2;
-            d.setBounds(x, y, x + width, y + height);
-            d.draw(canvas);
+            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;
+                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);
+                d.draw(canvas);
+            }
         }
         super.onDraw(canvas);
     }
@@ -2404,9 +2423,7 @@
     }
 
     boolean willCreateUserFolder(ItemInfo info, CellLayout target, int originX, int originY) {
-        mTargetCell = findNearestArea(originX, originY,
-                1, 1, target,
-                mTargetCell);
+        mTargetCell = findNearestArea(originX, originY, 1, 1, target, mTargetCell);
 
         View v = target.getChildAt(mTargetCell[0], mTargetCell[1]);
         boolean hasntMoved = mDragInfo != null && (mDragInfo.cellX == mTargetCell[0] &&
@@ -2437,8 +2454,8 @@
         boolean hasntMoved = mDragInfo != null && (mDragInfo.cellX == mTargetCell[0] &&
                 mDragInfo.cellY == mTargetCell[1]);
 
-        if (v == null || hasntMoved) return false;
-
+        if (v == null || hasntMoved || !mCreateUserFolderOnDrop) return false;
+        mCreateUserFolderOnDrop = false;
         final int screen = (mTargetCell == null) ?
                 mDragInfo.screen : indexOfChild(target);
 
@@ -3047,24 +3064,83 @@
                     mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
                     ItemInfo info = (ItemInfo) d.dragInfo;
 
-                    if (!willCreateUserFolder(info, mDragTargetLayout,
-                            (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1])) {
+                    boolean willCreateUserFolder = willCreateUserFolder(info, mDragTargetLayout,
+                            (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1]);
+
+                    View newDropOver = null;
+                    if (willCreateUserFolder) {
+                        newDropOver = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]);
+                    }
+
+                    if (newDropOver != mLastDragOverView || !willCreateUserFolder) {
+                        if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) {
+                            mDragFolderRingAnimator.animateToNaturalState();
+                        }
+                        mCreateUserFolderOnDrop = false;
+                        mFolderCreationAlarm.cancelAlarm();
                         mIsDraggingOverIcon = false;
+                    }
+
+                    if (willCreateUserFolder && !mIsDraggingOverIcon) {
+                        mIsDraggingOverIcon = true;
+
+                        mLastDragOverView = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]);
+                        mFolderCreationAlarm.setOnAlarmListener(new FolderCreationAlarmListener(mLastDragOverView));
+                        mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT);
+
+                        mDragTargetLayout.clearDragOutlines();
+                    }
+
+                    if (!mCreateUserFolderOnDrop) {
                         mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
                                 (int) mDragViewVisualCenter[0],
                                 (int) mDragViewVisualCenter[1],
                                 item.spanX, item.spanY);
-                    } else if (!mIsDraggingOverIcon) {
-                        mIsDraggingOverIcon = true;
-                        mDragTargetLayout.clearDragOutlines();
                     }
                 }
             }
         }
     }
 
+    class FolderCreationAlarmListener implements OnAlarmListener {
+        View v;
+
+        public FolderCreationAlarmListener(View v) {
+            this.v = v;
+        }
+
+        public void onAlarm(Alarm alarm) {
+            int tvLocation[] = new int[2];
+            int wsLocation[] = new int[2];
+            v.getLocationOnScreen(tvLocation);
+            getLocationOnScreen(wsLocation);
+
+            if (mCellWidth < 0 || mCellHeight < 0) {
+                mCellWidth = mDragTargetLayout.getCellWidth();
+                mCellHeight = mDragTargetLayout.getCellHeight();
+            }
+            int x = tvLocation[0] - wsLocation[0] + mCellWidth / 2;
+            int y = tvLocation[1] - wsLocation[1] + mCellHeight / 2;
+
+            if (mDragFolderRingAnimator == null) {
+                mDragFolderRingAnimator = new FolderRingAnimator(mLauncher, null);
+            }
+            mDragFolderRingAnimator.setLocation(x, y);
+            mDragFolderRingAnimator.animateToAcceptState();
+            showFolderAccept(mDragFolderRingAnimator);
+            mCreateUserFolderOnDrop = true;
+            mDragTargetLayout.clearDragOutlines();
+        }
+    }
+
     private void doDragExit() {
         mWasSpringLoadedOnDragExit = mShrinkState == ShrinkState.SPRING_LOADED;
+
+        if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) {
+            mDragFolderRingAnimator.animateToNaturalState();
+        }
+        mFolderCreationAlarm.cancelAlarm();
+
         if (mDragTargetLayout != null) {
             mDragTargetLayout.onDragExit();
         }
@@ -3233,7 +3309,7 @@
                 pixelX, pixelY, spanX, spanY, recycle);
     }
 
-    void setLauncher(Launcher launcher) {
+    void setup(Launcher launcher, DragController dragController) {
         mLauncher = launcher;
         mSpringLoadedDragController = new SpringLoadedDragController(mLauncher);
 
@@ -3242,9 +3318,6 @@
             mCustomizationDrawerContent =
                 mCustomizationDrawer.findViewById(com.android.internal.R.id.tabcontent);
         }
-    }
-
-    public void setDragController(DragController dragController) {
         mDragController = dragController;
     }