Merge "Update for Allocation API changes."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 247f5b7..6cdf205 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -86,10 +86,10 @@
 
         <activity
             android:name="com.android.launcher2.WallpaperChooser"
+            style="@style/config_orientation"
             android:label="@string/pick_wallpaper"
             android:icon="@drawable/ic_launcher_wallpaper"
             android:theme="@style/Theme.WallpaperPicker"
-            android:screenOrientation="nosensor"
             android:finishOnCloseSystemDialogs="true">
             <intent-filter>
                 <action android:name="android.intent.action.SET_WALLPAPER" />
diff --git a/res/drawable-hdpi/focused_application_background.9.png b/res/drawable-hdpi/focused_application_background.9.png
index ac67b06..01c83c3 100644
--- a/res/drawable-hdpi/focused_application_background.9.png
+++ b/res/drawable-hdpi/focused_application_background.9.png
Binary files differ
diff --git a/res/drawable-hdpi/pressed_application_background.9.png b/res/drawable-hdpi/pressed_application_background.9.png
index fdb064a..c7d0bd4 100644
--- a/res/drawable-hdpi/pressed_application_background.9.png
+++ b/res/drawable-hdpi/pressed_application_background.9.png
Binary files differ
diff --git a/res/drawable-mdpi/focused_application_background.9.png b/res/drawable-mdpi/focused_application_background.9.png
index 259f122..341a80b 100644
--- a/res/drawable-mdpi/focused_application_background.9.png
+++ b/res/drawable-mdpi/focused_application_background.9.png
Binary files differ
diff --git a/res/drawable-mdpi/home_screen_bg.9.png b/res/drawable-mdpi/home_screen_bg.9.png
deleted file mode 100644
index 023e8da..0000000
--- a/res/drawable-mdpi/home_screen_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/home_screen_bg_hover.9.png b/res/drawable-mdpi/home_screen_bg_hover.9.png
deleted file mode 100644
index 3443fd4..0000000
--- a/res/drawable-mdpi/home_screen_bg_hover.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/mini_home_screen_bg.9.png b/res/drawable-mdpi/mini_home_screen_bg.9.png
deleted file mode 100644
index a567457..0000000
--- a/res/drawable-mdpi/mini_home_screen_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/mini_home_screen_bg_accepts_drops.9.png b/res/drawable-mdpi/mini_home_screen_bg_accepts_drops.9.png
deleted file mode 100644
index 53048ec..0000000
--- a/res/drawable-mdpi/mini_home_screen_bg_accepts_drops.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/mini_home_screen_bg_hover.9.png b/res/drawable-mdpi/mini_home_screen_bg_hover.9.png
deleted file mode 100644
index ff8b28d..0000000
--- a/res/drawable-mdpi/mini_home_screen_bg_hover.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/pressed_application_background.9.png b/res/drawable-mdpi/pressed_application_background.9.png
index 754af48..4b00eec 100644
--- a/res/drawable-mdpi/pressed_application_background.9.png
+++ b/res/drawable-mdpi/pressed_application_background.9.png
Binary files differ
diff --git a/res/layout-xlarge-land/launcher.xml b/res/layout-xlarge-land/launcher.xml
index 7b66d7c..e421e07 100644
--- a/res/layout-xlarge-land/launcher.xml
+++ b/res/layout-xlarge-land/launcher.xml
@@ -161,7 +161,7 @@
     </RelativeLayout>
 
     <TabHost
-        android:id="@android:id/tabhost"
+        android:id="@+id/customization_drawer"
         android:layout_width="match_parent"
         android:layout_height="480dp"
         android:layout_gravity="bottom">
diff --git a/res/layout-xlarge-port/launcher.xml b/res/layout-xlarge-port/launcher.xml
index c5691b8..d9839da 100644
--- a/res/layout-xlarge-port/launcher.xml
+++ b/res/layout-xlarge-port/launcher.xml
@@ -174,7 +174,7 @@
     </RelativeLayout>
 
     <TabHost
-        android:id="@android:id/tabhost"
+        android:id="@+id/customization_drawer"
         android:layout_width="match_parent"
         android:layout_height="800dp"
         android:layout_gravity="bottom">
diff --git a/res/layout-xlarge/all_apps_paged_view_application.xml b/res/layout-xlarge/all_apps_paged_view_application.xml
index a080bcec..e5f07bf 100644
--- a/res/layout-xlarge/all_apps_paged_view_application.xml
+++ b/res/layout-xlarge/all_apps_paged_view_application.xml
@@ -20,8 +20,6 @@
 
     launcher:blurColor="#FF6B8CF0"
     launcher:outlineColor="#FF8CD2FF"
-    launcher:checkedBlurColor="#FFBBE83C"
-    launcher:checkedOutlineColor="#FF8CD2FF"
 
     android:id="@+id/application_icon"
     android:layout_width="match_parent"
diff --git a/res/layout-xlarge/customize_paged_view_item.xml b/res/layout-xlarge/customize_paged_view_item.xml
index 35e06c3..b2e5f08 100644
--- a/res/layout-xlarge/customize_paged_view_item.xml
+++ b/res/layout-xlarge/customize_paged_view_item.xml
@@ -20,8 +20,6 @@
 
     launcher:blurColor="#FF6B8CF0"
     launcher:outlineColor="#FF8CD2FF"
-    launcher:checkedBlurColor="#FFBBE83C"
-    launcher:checkedOutlineColor="#FF8CD2FF"
 
     android:id="@+id/customize_icon"
     android:layout_width="match_parent"
diff --git a/res/layout-xlarge/wallpaper_chooser.xml b/res/layout-xlarge/wallpaper_chooser.xml
index 9649e88..76a896d 100644
--- a/res/layout-xlarge/wallpaper_chooser.xml
+++ b/res/layout-xlarge/wallpaper_chooser.xml
@@ -20,8 +20,11 @@
 
 <GridView xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/gallery"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:numColumns="4"
-    android:columnWidth="@dimen/wallpaper_small_width"
-    android:stretchMode="columnWidth" />
\ No newline at end of file
+    android:layout_width="match_parent"
+    android:layout_height="400dp"
+    android:layout_gravity="center"
+    android:numColumns="3"
+    android:stretchMode="spacingWidth"
+    android:columnWidth="@dimen/wallpaper_chooser_grid_width"
+    android:verticalSpacing="15dp"
+    android:drawSelectorOnTop="false" />
diff --git a/res/layout-xlarge/wallpaper_chooser_base.xml b/res/layout-xlarge/wallpaper_chooser_base.xml
new file mode 100644
index 0000000..16888ec
--- /dev/null
+++ b/res/layout-xlarge/wallpaper_chooser_base.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.
+*/
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
diff --git a/res/layout-xlarge/wallpaper_item.xml b/res/layout-xlarge/wallpaper_item.xml
index 4246b9a..e17c046 100644
--- a/res/layout-xlarge/wallpaper_item.xml
+++ b/res/layout-xlarge/wallpaper_item.xml
@@ -15,9 +15,9 @@
 -->
 
 <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="@dimen/wallpaper_small_width"
-    android:layout_height="wrap_content"
-    android:padding="5dp"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/wallpaper_chooser_grid_height"
+    android:padding="6dp"
     android:scaleType="fitXY"
     android:adjustViewBounds="false"
     android:focusable="false" />
diff --git a/res/layout/wallpaper_chooser_base.xml b/res/layout/wallpaper_chooser_base.xml
index 8447027..fa8ea93 100644
--- a/res/layout/wallpaper_chooser_base.xml
+++ b/res/layout/wallpaper_chooser_base.xml
@@ -19,7 +19,10 @@
 -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/wallpaper_chooser_base"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
+    <fragment class="com.android.launcher2.WallpaperChooserDialogFragment"
+        android:id="@+id/wallpaper_chooser_fragment"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
 </FrameLayout>
diff --git a/res/values-ca-xlarge/strings.xml b/res/values-ca-xlarge/strings.xml
index 9db0ce9..67ad78d 100644
--- a/res/values-ca-xlarge/strings.xml
+++ b/res/values-ca-xlarge/strings.xml
@@ -19,6 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="wallpaper_dialog_title" msgid="5764793286524787718">"Seleccionar un empaperat"</string>
+    <string name="wallpaper_dialog_title" msgid="5764793286524787718">"Seleccionar un fons de pantalla"</string>
     <string name="wallpaper_cancel" msgid="6502936522490675611">"Cancel·la"</string>
 </resources>
diff --git a/res/values-xlarge/config.xml b/res/values-xlarge/config.xml
index 55a96f6..62f1671 100644
--- a/res/values-xlarge/config.xml
+++ b/res/values-xlarge/config.xml
@@ -51,4 +51,9 @@
     <!-- The slope, in percent, of the drag movement needed to drag an item out of the customization
          drawer (y / x * 100%)  -->
     <integer name="config_customizationDrawerDragSlopeThreshold">150</integer>
+    <integer name="config_allAppsDrawerDragSlopeThreshold">150</integer>
+
+    <style name="config_orientation">
+        <item name="@android:screenOrientation">unspecified</item>
+    </style>
 </resources>
diff --git a/res/values-xlarge/dimens.xml b/res/values-xlarge/dimens.xml
index a9ba1d5..89722e4 100644
--- a/res/values-xlarge/dimens.xml
+++ b/res/values-xlarge/dimens.xml
@@ -51,5 +51,6 @@
     <dimen name="delete_zone_padding">20dip</dimen>
 
     <!-- dimensions for the wallpaper picker wallpaper thumbnail width -->
-    <dimen name="wallpaper_small_width">170dp</dimen>
+    <dimen name="wallpaper_chooser_grid_width">230dp</dimen>
+    <dimen name="wallpaper_chooser_grid_height">185dp</dimen>
 </resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 3373869..5e6a2ab 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -68,10 +68,6 @@
         <attr name="blurColor" format="color" />
         <!-- The outline color of the holographic outline -->
         <attr name="outlineColor" format="color" />
-        <!-- The checked blur color of the holographic outline -->
-        <attr name="checkedBlurColor" format="color" />
-        <!-- The checked outline color of the holographic outline -->
-        <attr name="checkedOutlineColor" format="color" />
     </declare-styleable>
 
     <!-- PagedViewWidget specific attributes. These attributes are used to
diff --git a/res/values/config.xml b/res/values/config.xml
index 9350ad1..473ed58 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -32,4 +32,8 @@
 
     <!-- The distance at which the animation should take the max duration -->
     <integer name="config_dropAnimMaxDist">800</integer>
+
+    <style name="config_orientation">
+        <item name="@android:screenOrientation">nosensor</item>
+    </style>
 </resources>
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index 1ad7e07..dccc03d 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -20,13 +20,13 @@
 
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.animation.AnimationUtils;
@@ -41,12 +41,10 @@
  * An implementation of PagedView that populates the pages of the workspace
  * with all of the user's applications.
  */
-public class AllAppsPagedView extends PagedView
-        implements AllAppsView, View.OnClickListener, View.OnLongClickListener, DragSource,
-        DropTarget {
+public class AllAppsPagedView extends PagedViewWithDraggableItems implements AllAppsView,
+    View.OnClickListener, DragSource, DropTarget {
 
     private static final String TAG = "AllAppsPagedView";
-    private static final boolean DEBUG = false;
 
     private Launcher mLauncher;
     private DragController mDragController;
@@ -84,6 +82,10 @@
         mInflater = LayoutInflater.from(context);
         a.recycle();
         setSoundEffectsEnabled(false);
+
+        Resources r = context.getResources();
+        setDragSlopeThreshold(
+                r.getInteger(R.integer.config_allAppsDrawerDragSlopeThreshold) / 100.0f);
     }
 
     @Override
@@ -242,10 +244,11 @@
     }
 
     @Override
-    public boolean onLongClick(View v) {
+    protected boolean beginDragging(View v) {
         if (!v.isInTouchMode()) {
             return false;
         }
+        super.beginDragging(v);
 
         // Start drag mode after the item is selected
         setupDragMode();
@@ -475,6 +478,7 @@
                         R.layout.all_apps_paged_view_application, layout, false);
                 text.setOnClickListener(this);
                 text.setOnLongClickListener(this);
+                text.setOnTouchListener(this);
 
                 layout.addViewToCellLayout(text, -1, i,
                     new PagedViewCellLayout.LayoutParams(0, 0, 1, 1));
diff --git a/src/com/android/launcher2/BubbleTextView.java b/src/com/android/launcher2/BubbleTextView.java
index 855f261..995877b 100644
--- a/src/com/android/launcher2/BubbleTextView.java
+++ b/src/com/android/launcher2/BubbleTextView.java
@@ -36,6 +36,11 @@
  */
 public class BubbleTextView extends CacheableTextView {
     static final float CORNER_RADIUS = 4.0f;
+    static final float SHADOW_LARGE_RADIUS = 4.0f;
+    static final float SHADOW_SMALL_RADIUS = 1.75f;
+    static final float SHADOW_Y_OFFSET = 2.0f;
+    static final int SHADOW_LARGE_COLOUR = 0xCC000000;
+    static final int SHADOW_SMALL_COLOUR = 0xBB000000;
     static final float PADDING_H = 8.0f;
     static final float PADDING_V = 3.0f;
 
@@ -83,11 +88,17 @@
         mPaddingV = PADDING_V * scale;
     }
 
-    protected int getVerticalPadding() {
+    protected int getCacheTopPadding() {
         return (int) PADDING_V;
     }
-    protected int getHorizontalPadding() {
-        return (int) PADDING_H;
+    protected int getCacheBottomPadding() {
+        return (int) (PADDING_V + SHADOW_LARGE_RADIUS + SHADOW_Y_OFFSET);
+    }
+    protected int getCacheLeftPadding() {
+        return (int) (PADDING_H + SHADOW_LARGE_RADIUS);
+    }
+    protected int getCacheRightPadding() {
+        return (int) (PADDING_H + SHADOW_LARGE_RADIUS);
     }
 
     public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache) {
@@ -126,41 +137,34 @@
 
     @Override
     public void draw(Canvas canvas) {
-        final Drawable background = mBackground;
-        if (background != null) {
-            final int scrollX = mScrollX;
-            final int scrollY = mScrollY;
+        if (isBuildingCache()) {
+            // We enhance the shadow by drawing the shadow twice
+            this.setShadowLayer(SHADOW_LARGE_RADIUS, 0.0f, SHADOW_Y_OFFSET, SHADOW_LARGE_COLOUR);
+            super.draw(canvas);
+            this.setShadowLayer(SHADOW_SMALL_RADIUS, 0.0f, 0.0f, SHADOW_SMALL_COLOUR);
+            super.draw(canvas);
+        } else {
+            final Drawable background = mBackground;
+            if (background != null) {
+                final int scrollX = mScrollX;
+                final int scrollY = mScrollY;
 
-            if (mBackgroundSizeChanged) {
-                background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
-                mBackgroundSizeChanged = false;
+                if (mBackgroundSizeChanged) {
+                    background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
+                    mBackgroundSizeChanged = false;
+                }
+
+                if ((scrollX | scrollY) == 0) {
+                    background.draw(canvas);
+                } else {
+                    canvas.translate(scrollX, scrollY);
+                    background.draw(canvas);
+                    canvas.translate(-scrollX, -scrollY);
+                }
             }
 
-            if ((scrollX | scrollY) == 0) {
-                background.draw(canvas);
-            } else {
-                canvas.translate(scrollX, scrollY);
-                background.draw(canvas);
-                canvas.translate(-scrollX, -scrollY);
-            }
+            super.draw(canvas);
         }
-
-        // Draw the hotdog bubble
-        final Layout layout = getLayout();
-        if (layout != null) {
-            final int offset = getExtendedPaddingTop();
-            final int paddingLeft = getPaddingLeft();
-            final int paddingRight = getPaddingRight();
-            final float left = layout.getLineLeft(0) + paddingLeft;
-            final float right = Math.min(layout.getLineRight(0) + paddingRight,
-                    left + getWidth() - paddingLeft - paddingRight);
-            mRect.set(left - mPaddingH, offset + (int) layout.getLineTop(0) - mPaddingV,
-                    right + mPaddingH, offset + (int) layout.getLineBottom(0) + mPaddingV);
-
-            canvas.drawRoundRect(mRect, mCornerRadius, mCornerRadius, mPaint);
-        }
-
-        super.draw(canvas);
     }
 
     @Override
diff --git a/src/com/android/launcher2/CacheableTextView.java b/src/com/android/launcher2/CacheableTextView.java
index 873cd4e..da2f302 100644
--- a/src/com/android/launcher2/CacheableTextView.java
+++ b/src/com/android/launcher2/CacheableTextView.java
@@ -20,8 +20,8 @@
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Paint;
-import android.graphics.Rect;
 import android.text.Layout;
 import android.util.AttributeSet;
 import android.widget.TextView;
@@ -60,10 +60,16 @@
         super(context, attrs, defStyle);
     }
 
-    protected int getVerticalPadding() {
+    protected int getCacheTopPadding() {
         return 0;
     }
-    protected int getHorizontalPadding() {
+    protected int getCacheLeftPadding() {
+        return 0;
+    }
+    protected int getCacheRightPadding() {
+        return 0;
+    }
+    protected int getCacheBottomPadding() {
         return 0;
     }
 
@@ -84,21 +90,21 @@
         final int top = getExtendedPaddingTop();
         final float prevAlpha = getAlpha();
 
-        int vPadding = getVerticalPadding();
-        int hPadding = getHorizontalPadding();
-
-        mTextCacheLeft = layout.getLineLeft(0) - hPadding;
-        mTextCacheTop = top + layout.getLineTop(0) - mPaddingV - vPadding;
+        mTextCacheLeft = layout.getLineLeft(0) - getCacheLeftPadding();
+        mTextCacheTop = top + layout.getLineTop(0) - mPaddingV - getCacheTopPadding();
 
         mRectLeft = mScrollX + getLeft();
         mRectTop = 0;
         mTextCacheScrollX = mScrollX;
 
         final float textCacheRight =
-            Math.min(left + layout.getLineRight(0) + mPaddingH, mScrollX + mRight - mLeft) + hPadding;
-        final float textCacheBottom = top + layout.getLineBottom(0) + mPaddingV + vPadding;
+            Math.min(left + layout.getLineRight(0) + mPaddingH, mScrollX + mRight - mLeft) +
+            getCacheRightPadding();
+        final float textCacheBottom = top + layout.getLineBottom(0) + mPaddingV +
+            getCacheBottomPadding();
+        final float xCharWidth = getPaint().measureText("x");
 
-        int width = (int) (textCacheRight - mTextCacheLeft);
+        int width = (int) (textCacheRight - mTextCacheLeft + (2 * xCharWidth));
         int height = (int) (textCacheBottom - mTextCacheTop);
 
         if (width != 0 && height != 0) {
@@ -150,6 +156,10 @@
         super.draw(canvas);
     }
 
+    protected boolean isBuildingCache() {
+        return mIsBuildingCache;
+    }
+
     @Override
     protected boolean onSetAlpha(int alpha) {
         if (mPrevAlpha != alpha) {
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index fd0ef51..daaf4be 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -139,6 +139,7 @@
         // A ViewGroup usually does not draw, but CellLayout needs to draw a rectangle to show
         // the user where a dragged item will land when dropped.
         setWillNotDraw(false);
+        setClipChildren(false);
 
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CellLayout, defStyle, 0);
 
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 694d4d0..cfc15d1 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -16,10 +16,7 @@
 
 package com.android.launcher2;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
+import com.android.launcher.R;
 
 import org.xmlpull.v1.XmlPullParser;
 
@@ -55,7 +52,6 @@
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.MotionEvent;
 import android.view.View;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
@@ -63,12 +59,14 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
-import com.android.launcher.R;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
 
 
-public class CustomizePagedView extends PagedView
-    implements View.OnLongClickListener, View.OnClickListener, View.OnTouchListener,
-                DragSource, ActionMode.Callback {
+public class CustomizePagedView extends PagedViewWithDraggableItems
+    implements View.OnClickListener, DragSource, ActionMode.Callback {
 
     public enum CustomizationType {
         WidgetCustomization,
@@ -78,14 +76,10 @@
     }
 
     private static final String TAG = "CustomizeWorkspace";
-    private static final boolean DEBUG = false;
 
-    private View mLastTouchedItem;
     private Launcher mLauncher;
     private DragController mDragController;
     private PackageManager mPackageManager;
-    private boolean mIsDragging;
-    private float mDragSlopeThreshold;
 
     private CustomizationType mCustomizationType;
 
@@ -158,8 +152,8 @@
         mInflater = LayoutInflater.from(context);
 
         final Resources r = context.getResources();
-        mDragSlopeThreshold =
-            r.getInteger(R.integer.config_customizationDrawerDragSlopeThreshold) / 100.0f;
+        setDragSlopeThreshold(
+                r.getInteger(R.integer.config_customizationDrawerDragSlopeThreshold) / 100.0f);
 
         setVisibility(View.GONE);
         setSoundEffectsEnabled(false);
@@ -324,8 +318,6 @@
 
         // End the current choice mode so that we don't carry selections across tabs
         endChoiceMode();
-        // Reset the touch item (if we are mid-dragging)
-        mLastTouchedItem = null;
     }
 
     @Override
@@ -480,98 +472,6 @@
         }
     }
 
-    @Override
-    public boolean onLongClick(View v) {
-        // Return early if this is not initiated from a touch
-        if (!v.isInTouchMode()) return false;
-        // Return early if we are still animating the pages
-        if (mNextPage != INVALID_PAGE) return false;
-        return beginDragging(v);
-    }
-
-    @Override
-    public boolean onTouch(View v, MotionEvent event) {
-        mLastTouchedItem = v;
-        return false;
-    }
-
-    /*
-     * Determines if we should change the touch state to start scrolling after the
-     * user moves their touch point too far.
-     */
-    protected void determineScrollingStart(MotionEvent ev) {
-        if (!mIsDragging) super.determineScrollingStart(ev);
-    }
-
-    /*
-     * Determines if we should change the touch state to start dragging after the
-     * user moves their touch point far enough.
-     */
-    protected void determineDraggingStart(MotionEvent ev) {
-        /*
-         * Locally do absolute value. mLastMotionX is set to the y value
-         * of the down event.
-         */
-        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
-        final float x = ev.getX(pointerIndex);
-        final float y = ev.getY(pointerIndex);
-        final int xDiff = (int) Math.abs(x - mLastMotionX);
-        final int yDiff = (int) Math.abs(y - mLastMotionY);
-
-        final int touchSlop = mTouchSlop;
-        boolean yMoved = yDiff > touchSlop;
-        boolean isUpwardMotion = (yDiff / (float) xDiff) > mDragSlopeThreshold;
-
-        if (isUpwardMotion && yMoved && mLastTouchedItem != null) {
-            // Drag if the user moved far enough along the Y axis
-            beginDragging(mLastTouchedItem);
-
-            // Cancel any pending longpress
-            if (mAllowLongPress) {
-                mAllowLongPress = false;
-                // Try canceling the long press. It could also have been scheduled
-                // by a distant descendant, so use the mAllowLongPress flag to block
-                // everything
-                final View currentPage = getPageAt(mCurrentPage);
-                if (currentPage != null) {
-                    currentPage.cancelLongPress();
-                }
-            }
-        }
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        final int action = ev.getAction();
-        switch (action & MotionEvent.ACTION_MASK) {
-            case MotionEvent.ACTION_DOWN:
-                mIsDragging = false;
-                break;
-            case MotionEvent.ACTION_MOVE:
-                if (mTouchState != TOUCH_STATE_SCROLLING && !mIsDragging) {
-                    determineDraggingStart(ev);
-                }
-                break;
-        }
-        return super.onInterceptTouchEvent(ev);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        final int action = ev.getAction();
-        switch (action & MotionEvent.ACTION_MASK) {
-            case MotionEvent.ACTION_DOWN:
-                mIsDragging = false;
-                break;
-            case MotionEvent.ACTION_MOVE:
-                if (mTouchState != TOUCH_STATE_SCROLLING && !mIsDragging) {
-                    determineDraggingStart(ev);
-                }
-                break;
-        }
-        return super.onTouchEvent(ev);
-    }
-
     Bitmap drawableToBitmap(Drawable d, View v) {
         Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
         Canvas c = new Canvas(b);
@@ -585,12 +485,12 @@
                 v.findViewById(R.id.widget_preview) : v;
     }
 
-    private boolean beginDragging(View v) {
+    protected boolean beginDragging(View v) {
         // End the current choice mode before we start dragging anything
         if (isChoiceMode(CHOICE_MODE_SINGLE)) {
             endChoiceMode();
         }
-        mIsDragging = true;
+        super.beginDragging(v);
 
         switch (mCustomizationType) {
         case WidgetCustomization: {
diff --git a/src/com/android/launcher2/HolographicOutlineHelper.java b/src/com/android/launcher2/HolographicOutlineHelper.java
index bf4c05a..0311afa 100644
--- a/src/com/android/launcher2/HolographicOutlineHelper.java
+++ b/src/com/android/launcher2/HolographicOutlineHelper.java
@@ -55,7 +55,6 @@
         sMediumInnerBlurMaskFilter = new BlurMaskFilter(scale * 2.0f, BlurMaskFilter.Blur.NORMAL);
     }
 
-    private static final MaskFilter sFineClipTable = TableMaskFilter.CreateClipTable(0, 20);
     private static final MaskFilter sCoarseClipTable = TableMaskFilter.CreateClipTable(0, 200);
 
     private int[] mTempOffset = new int[2];
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 0cb0e13..455b130 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -294,7 +294,7 @@
         checkForLocaleChange();
         setWallpaperDimension();
         setContentView(R.layout.launcher);
-        mHomeCustomizationDrawer = (TabHost) findViewById(com.android.internal.R.id.tabhost);
+        mHomeCustomizationDrawer = (TabHost) findViewById(R.id.customization_drawer);
         if (mHomeCustomizationDrawer != null) {
             mHomeCustomizationDrawer.setup();
 
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 856507d..8483f95 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -595,20 +595,14 @@
             int rightScreen = 0;
             while (x <= mScrollX) {
                 leftScreen++;
-                x += pageWidth + mPageSpacing;
-                // replace above line with this if you don't assume all pages have same width as 0th
-                // page:
-                // x += getScaledMeasuredWidth(getChildAt(leftScreen));
+                x += getScaledMeasuredWidth(getChildAt(leftScreen)) + mPageSpacing;
             }
             rightScreen = leftScreen;
-            while (x < mScrollX + screenWidth) {
+            while (x < mScrollX + screenWidth && rightScreen < pageCount) {
                 rightScreen++;
-                x += pageWidth + mPageSpacing;
-                // replace above line with this if you don't assume all pages have same width as 0th
-                // page:
-                //if (rightScreen < pageCount) {
-                //    x += getScaledMeasuredWidth(getChildAt(rightScreen));
-                //}
+                if (rightScreen < pageCount) {
+                    x += getScaledMeasuredWidth(getChildAt(rightScreen)) + mPageSpacing;
+                }
             }
             rightScreen = Math.min(getChildCount() - 1, rightScreen);
 
diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java
index 884884e..d91daf9 100644
--- a/src/com/android/launcher2/PagedViewIcon.java
+++ b/src/com/android/launcher2/PagedViewIcon.java
@@ -52,7 +52,7 @@
     private Object mIconCacheKey;
     private PagedViewIconCache mIconCache;
 
-    private int mAlpha;
+    private int mAlpha = 255;
     private int mHolographicAlpha;
 
     private boolean mIsChecked;
@@ -64,8 +64,6 @@
     // Highlight colors
     private int mHoloBlurColor;
     private int mHoloOutlineColor;
-    private int mCheckedBlurColor;
-    private int mCheckedOutlineColor;
 
     private static final HandlerThread sWorkerThread = new HandlerThread("pagedviewicon-helper");
     static {
@@ -110,11 +108,8 @@
         super(context, attrs, defStyle);
 
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedViewIcon, defStyle, 0);
-	mAlpha = 255;
         mHoloBlurColor = a.getColor(R.styleable.PagedViewIcon_blurColor, 0);
         mHoloOutlineColor = a.getColor(R.styleable.PagedViewIcon_outlineColor, 0);
-        mCheckedBlurColor = a.getColor(R.styleable.PagedViewIcon_checkedBlurColor, 0);
-        mCheckedOutlineColor = a.getColor(R.styleable.PagedViewIcon_checkedOutlineColor, 0);
         a.recycle();
 
         if (sHolographicOutlineHelper == null) {
@@ -126,14 +121,12 @@
     }
 
     private void queueHolographicOutlineCreation() {
-        /* Temporarily disabling holographic outline creation.
         // Generate the outline in the background
         if (mHolographicOutline == null) {
             Message m = sWorker.obtainMessage(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE);
             m.obj = this;
             sWorker.sendMessage(m);
         }
-        */
     }
 
     public void applyFromApplicationInfo(ApplicationInfo info, PagedViewIconCache cache,
@@ -248,7 +241,7 @@
             if (mCheckedAlphaAnimator != null) {
                 mCheckedAlphaAnimator.cancel();
             }
-            mCheckedAlphaAnimator = ObjectAnimator.ofFloat(this, "alpha", alpha);
+            mCheckedAlphaAnimator = ObjectAnimator.ofFloat(this, "alpha", getAlpha(), alpha);
             mCheckedAlphaAnimator.setDuration(duration);
             mCheckedAlphaAnimator.start();
 
diff --git a/src/com/android/launcher2/PagedViewWidget.java b/src/com/android/launcher2/PagedViewWidget.java
index 89ed0ec..5f5844f 100644
--- a/src/com/android/launcher2/PagedViewWidget.java
+++ b/src/com/android/launcher2/PagedViewWidget.java
@@ -25,6 +25,8 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -78,6 +80,8 @@
             widget.mPreview.setAlpha(255);
             widget.mPreview.draw(widget.mHolographicOutlineCanvas);
             widget.mPreview.setAlpha(prevAlpha);
+            // Temporary workaround to make the default widget outlines visible
+            widget.mHolographicOutlineCanvas.drawColor(Color.argb(156, 0, 0, 0), Mode.SRC_OVER);
             widget.mHolographicOutlineCanvas.restore();
 
             sHolographicOutlineHelper.applyThickExpensiveOutlineWithBlur(outline,
@@ -120,14 +124,12 @@
     }
 
     private void queueHolographicOutlineCreation() {
-        /* Temporarily disabling holographic outline creation.
         // Generate the outline in the background
         if (mHolographicOutline == null) {
             Message m = sWorker.obtainMessage(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE);
             m.obj = this;
             sWorker.sendMessage(m);
         }
-        */
     }
 
     public void applyFromAppWidgetProviderInfo(AppWidgetProviderInfo info,
diff --git a/src/com/android/launcher2/PagedViewWithDraggableItems.java b/src/com/android/launcher2/PagedViewWithDraggableItems.java
new file mode 100644
index 0000000..283cced
--- /dev/null
+++ b/src/com/android/launcher2/PagedViewWithDraggableItems.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2010 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.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+
+/* Class that does most of the work of enabling dragging items out of a PagedView by performing a
+ * vertical drag. Used by both CustomizePagedView and AllAppsPagedView.
+ * Subclasses must do the following:
+ *   * call setDragSlopeThreshold after making an instance of the PagedViewWithDraggableItems
+ *   * call child.setOnLongClickListener(this) and child.setOnTouchListener(this) on all children
+ *       (good place to do it is in syncPageItems)
+ *   * override beginDragging(View) (but be careful to call super.beginDragging(View)
+ *
+ */
+public abstract class PagedViewWithDraggableItems extends PagedView
+    implements View.OnLongClickListener, View.OnTouchListener {
+    private View mLastTouchedItem;
+    private boolean mIsDragging;
+    private float mDragSlopeThreshold;
+
+    public PagedViewWithDraggableItems(Context context) {
+        super(context, null);
+    }
+
+    public PagedViewWithDraggableItems(Context context, AttributeSet attrs) {
+        super(context, attrs, 0);
+    }
+
+    public PagedViewWithDraggableItems(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    protected boolean beginDragging(View v) {
+        mIsDragging = true;
+        return false;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        final int action = ev.getAction();
+        switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN:
+                mIsDragging = false;
+                mLastTouchedItem = null;
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (mTouchState != TOUCH_STATE_SCROLLING && !mIsDragging) {
+                    determineDraggingStart(ev);
+                }
+                break;
+        }
+        return super.onInterceptTouchEvent(ev);
+    }
+
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+        mLastTouchedItem = v;
+        return false;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        final int action = ev.getAction();
+        switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN:
+                mIsDragging = false;
+                mLastTouchedItem = null;
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (mTouchState != TOUCH_STATE_SCROLLING && !mIsDragging) {
+                    determineDraggingStart(ev);
+                }
+                break;
+        }
+        return super.onTouchEvent(ev);
+    }
+
+    @Override
+    public boolean onLongClick(View v) {
+        // Return early if this is not initiated from a touch
+        if (!v.isInTouchMode()) return false;
+        // Return early if we are still animating the pages
+        if (mNextPage != INVALID_PAGE) return false;
+        return beginDragging(v);
+    }
+
+
+    /*
+     * Determines if we should change the touch state to start scrolling after the
+     * user moves their touch point too far.
+     */
+    protected void determineScrollingStart(MotionEvent ev) {
+        if (!mIsDragging) super.determineScrollingStart(ev);
+    }
+
+    /*
+     * Determines if we should change the touch state to start dragging after the
+     * user moves their touch point far enough.
+     */
+    protected void determineDraggingStart(MotionEvent ev) {
+        /*
+         * Locally do absolute value. mLastMotionX is set to the y value
+         * of the down event.
+         */
+        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+        final float x = ev.getX(pointerIndex);
+        final float y = ev.getY(pointerIndex);
+        final int xDiff = (int) Math.abs(x - mLastMotionX);
+        final int yDiff = (int) Math.abs(y - mLastMotionY);
+
+        final int touchSlop = mTouchSlop;
+        boolean yMoved = yDiff > touchSlop;
+        boolean isUpwardMotion = (yDiff / (float) xDiff) > mDragSlopeThreshold;
+
+        if (isUpwardMotion && yMoved && mLastTouchedItem != null) {
+            // Drag if the user moved far enough along the Y axis
+            beginDragging(mLastTouchedItem);
+
+            // Cancel any pending long press
+            if (mAllowLongPress) {
+                mAllowLongPress = false;
+                // Try canceling the long press. It could also have been scheduled
+                // by a distant descendant, so use the mAllowLongPress flag to block
+                // everything
+                final View currentPage = getPageAt(mCurrentPage);
+                if (currentPage != null) {
+                    currentPage.cancelLongPress();
+                }
+            }
+        }
+    }
+
+    public void setDragSlopeThreshold(float dragSlopeThreshold) {
+        mDragSlopeThreshold = dragSlopeThreshold;
+    }
+}
diff --git a/src/com/android/launcher2/WallpaperChooser.java b/src/com/android/launcher2/WallpaperChooser.java
index 0a8d9f4..2311d1e 100644
--- a/src/com/android/launcher2/WallpaperChooser.java
+++ b/src/com/android/launcher2/WallpaperChooser.java
@@ -16,309 +16,29 @@
 
 package com.android.launcher2;
 
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.app.FragmentTransaction;
-import android.app.WallpaperManager;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.res.Resources;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.AsyncTask;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.View.OnClickListener;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.Gallery;
-import android.widget.GridView;
-import android.widget.ImageView;
-import android.widget.ListAdapter;
-import android.widget.SpinnerAdapter;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
 import com.android.launcher.R;
 
+import android.app.Activity;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.os.Bundle;
+
 public class WallpaperChooser extends Activity {
     private static final String TAG = "Launcher.WallpaperChooser";
 
-    private ViewGroup mWallpaperChooserBase;
-    private ImageView mImageView = null;
-    private Bitmap mBitmap = null;
-
-    private ArrayList<Integer> mThumbs;
-    private ArrayList<Integer> mImages;
-    private WallpaperLoader mLoader;
-
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        /* We need some container to attach to in order for the fragment to be
-         * considered embedded, so inflate an empty FrameLayout and use that
-         * as the parent view
-         */
         setContentView(R.layout.wallpaper_chooser_base);
-        mWallpaperChooserBase = (ViewGroup) findViewById(R.id.wallpaper_chooser_base);
 
-        findWallpapers();
-
-        DialogFragment newFragment = new WallpaperDialogFragment(this);
-        if (LauncherApplication.isScreenXLarge()) {
-            // Display a dialog instead of embedding the view in the activity
-            newFragment.show(getFragmentManager(), "dialog");
-        } else {
-            // Embed the fragment in the base view
-            FragmentTransaction ft = getFragmentManager().openTransaction();
-            ft.add(R.id.wallpaper_chooser_base, newFragment);
-            ft.commit();
-        }
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-
-        if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
-            mLoader.cancel(true);
-            mLoader = null;
-        }
-    }
-
-    private void findWallpapers() {
-        mThumbs = new ArrayList<Integer>(24);
-        mImages = new ArrayList<Integer>(24);
-
-        final Resources resources = getResources();
-        // Context.getPackageName() may return the "original" package name,
-        // com.android.launcher2; Resources needs the real package name,
-        // com.android.launcher. So we ask Resources for what it thinks the
-        // package name should be.
-        final String packageName = resources.getResourcePackageName(R.array.wallpapers);
-
-        addWallpapers(resources, packageName, R.array.wallpapers);
-        addWallpapers(resources, packageName, R.array.extra_wallpapers);
-    }
-
-    private void addWallpapers(Resources resources, String packageName, int list) {
-        final String[] extras = resources.getStringArray(list);
-        for (String extra : extras) {
-            int res = resources.getIdentifier(extra, "drawable", packageName);
-            if (res != 0) {
-                final int thumbRes = resources.getIdentifier(extra + "_small",
-                        "drawable", packageName);
-
-                if (thumbRes != 0) {
-                    mThumbs.add(thumbRes);
-                    mImages.add(res);
-                    // Log.d(TAG, "addWallpapers: [" + packageName + "]: " + extra + " (" + res + ")");
-                }
-            }
-        }
-    }
-
-    private void selectWallpaper(int position) {
-        try {
-            WallpaperManager wpm = (WallpaperManager)getSystemService(WALLPAPER_SERVICE);
-            wpm.setResource(mImages.get(position));
-            setResult(RESULT_OK);
-            finish();
-        } catch (IOException e) {
-            Log.e(TAG, "Failed to set wallpaper: " + e);
-        }
-    }
-
-    private class WallpaperDialogFragment extends DialogFragment implements
-            AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
-        private Context mContext;
-
-        public WallpaperDialogFragment(Context context) {
-            super();
-            mContext = context;
-            setCancelable(true);
-        }
-
-        @Override
-        public void onDismiss(DialogInterface dialog) {
-            WallpaperChooser.this.finish();
-        }
-
-        /* This will only be called when in XLarge mode, since this Fragment is invoked like
-         * a dialog in that mode
-         */
-        @Override
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            final View v = getLayoutInflater().inflate(
-                    R.layout.wallpaper_chooser, mWallpaperChooserBase, false);
-
-            GridView gridView = (GridView) v.findViewById(R.id.gallery);
-            gridView.setOnItemClickListener(this);
-            gridView.setAdapter(new ImageAdapter(WallpaperChooser.this));
-
-            final int viewInset =
-                    getResources().getDimensionPixelSize(R.dimen.alert_dialog_content_inset);
-
-            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
-            builder.setCancelable(true);
-            builder.setNegativeButton(R.string.wallpaper_cancel, null);
-            builder.setTitle(R.string.wallpaper_dialog_title);
-            builder.setView(gridView, viewInset, viewInset, viewInset, viewInset);
-            return builder.create();
-        }
-
-        /* This will be called on both XLarge and small screens, but since the dialog
-         * is already created on XLarge, we want to skip this view creation
-         */
-        @Override
-        public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                Bundle savedInstanceState) {
-            /* Only generate a custom view if this fragment is being embedded in a view,
-             * i.e: on a small screen
+        Fragment fragmentView =
+                getFragmentManager().findFragmentById(R.id.wallpaper_chooser_fragment);
+        if (fragmentView == null) {
+            /* When the screen is XLarge, the fragment is not included in the layout, so show it
+             * as a dialog
              */
-            if (!LauncherApplication.isScreenXLarge()) {
-                View view = inflater.inflate(R.layout.wallpaper_chooser, container, false);
-
-                final Gallery gallery = (Gallery) view.findViewById(R.id.gallery);
-                gallery.setCallbackDuringFling(false);
-                gallery.setOnItemSelectedListener(this);
-                gallery.setAdapter(new ImageAdapter(WallpaperChooser.this));
-
-                View setButton = view.findViewById(R.id.set);
-                setButton.setOnClickListener(new OnClickListener() {
-                    @Override
-                    public void onClick(View v) {
-                        selectWallpaper(gallery.getSelectedItemPosition());
-                    }
-                });
-                mImageView = (ImageView) view.findViewById(R.id.wallpaper);
-                return view;
-            }
-            return super.onCreateView(inflater, container, savedInstanceState);
-        }
-
-        // Click handler for the Dialog's GridView
-        @Override
-        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-            selectWallpaper(position);
-        }
-
-        // Selection handler for the embedded Gallery view
-        @Override
-        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-            if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
-                mLoader.cancel();
-            }
-            mLoader = (WallpaperLoader) new WallpaperLoader().execute(position);
-        }
-
-        @Override
-        public void onNothingSelected(AdapterView<?> parent) {
-        }
-    }
-
-    private class ImageAdapter extends BaseAdapter implements ListAdapter, SpinnerAdapter {
-        private LayoutInflater mLayoutInflater;
-
-        ImageAdapter(WallpaperChooser context) {
-            mLayoutInflater = context.getLayoutInflater();
-        }
-
-        public int getCount() {
-            return mThumbs.size();
-        }
-
-        public Object getItem(int position) {
-            return position;
-        }
-
-        public long getItemId(int position) {
-            return position;
-        }
-
-        public View getView(int position, View convertView, ViewGroup parent) {
-            ImageView image;
-
-            if (convertView == null) {
-                image = (ImageView) mLayoutInflater.inflate(R.layout.wallpaper_item, parent, false);
-            } else {
-                image = (ImageView) convertView;
-            }
-
-            int thumbRes = mThumbs.get(position);
-            image.setImageResource(thumbRes);
-            Drawable thumbDrawable = image.getDrawable();
-            if (thumbDrawable != null) {
-                thumbDrawable.setDither(true);
-            } else {
-                Log.e(TAG, "Error decoding thumbnail resId=" + thumbRes + " for wallpaper #"
-                        + position);
-            }
-
-            return image;
-        }
-    }
-
-    class WallpaperLoader extends AsyncTask<Integer, Void, Bitmap> {
-        BitmapFactory.Options mOptions;
-
-        WallpaperLoader() {
-            mOptions = new BitmapFactory.Options();
-            mOptions.inDither = false;
-            mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;            
-        }
-
-        @Override
-        protected Bitmap doInBackground(Integer... params) {
-            if (isCancelled()) return null;
-            try {
-                return BitmapFactory.decodeResource(getResources(),
-                        mImages.get(params[0]), mOptions);
-            } catch (OutOfMemoryError e) {
-                return null;
-            }
-        }
-
-        @Override
-        protected void onPostExecute(Bitmap b) {
-            if (b == null) return;
-
-            if (!isCancelled() && !mOptions.mCancel) {
-                // Help the GC
-                if (mBitmap != null) {
-                    mBitmap.recycle();
-                }
-
-                // This should always be the case, but check anyways
-                final ImageView view = mImageView;
-                if (view != null) {
-                    view.setImageBitmap(b);
-
-                    mBitmap = b;
-
-                    final Drawable drawable = view.getDrawable();
-                    drawable.setFilterBitmap(true);
-                    drawable.setDither(true);
-
-                    view.postInvalidate();
-                }
-
-                mLoader = null;
-            } else {
-               b.recycle(); 
-            }
-        }
-
-        void cancel() {
-            mOptions.requestCancelDecode();
-            super.cancel(true);
+            DialogFragment fragment = WallpaperChooserDialogFragment.newInstance();
+            fragment.show(getFragmentManager(), "dialog");
         }
     }
 }
diff --git a/src/com/android/launcher2/WallpaperChooserDialogFragment.java b/src/com/android/launcher2/WallpaperChooserDialogFragment.java
new file mode 100644
index 0000000..10bfc56
--- /dev/null
+++ b/src/com/android/launcher2/WallpaperChooserDialogFragment.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2010 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 com.android.launcher.R;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Gallery;
+import android.widget.GridView;
+import android.widget.ImageView;
+import android.widget.ListAdapter;
+import android.widget.SpinnerAdapter;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class WallpaperChooserDialogFragment extends DialogFragment implements
+        AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
+
+    private static final String TAG = "Launcher.WallpaperChooserDialogFragment";
+    private static final String EMBEDDED_KEY = "com.android.launcher2."
+            + "WallpaperChooserDialogFragment.EMBEDDED_KEY";
+
+    private boolean mEmbedded;
+    private ImageView mImageView = null;
+    private Bitmap mBitmap = null;
+
+    private ArrayList<Integer> mThumbs;
+    private ArrayList<Integer> mImages;
+    private WallpaperLoader mLoader;
+
+    public static WallpaperChooserDialogFragment newInstance() {
+        WallpaperChooserDialogFragment fragment = new WallpaperChooserDialogFragment();
+        fragment.setCancelable(true);
+        return fragment;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (savedInstanceState != null && savedInstanceState.containsKey(EMBEDDED_KEY)) {
+            mEmbedded = savedInstanceState.getBoolean(EMBEDDED_KEY);
+        } else {
+            mEmbedded = isInLayout();
+        }
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putBoolean(EMBEDDED_KEY, mEmbedded);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+
+        if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
+            mLoader.cancel(true);
+            mLoader = null;
+        }
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        /* On orientation changes, the dialog is effectively "dismissed" so this is called
+         * when the activity is no longer associated with this dying dialog fragment. We
+         * should just safely ignore this case by checking if getActivity() returns null
+         */
+        Activity activity = getActivity();
+        if (activity != null) {
+            activity.finish();
+        }
+    }
+
+    /* This will only be called when in XLarge mode, since this Fragment is invoked like
+     * a dialog in that mode
+     */
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        final View v = getActivity().getLayoutInflater().inflate(
+                R.layout.wallpaper_chooser, null, false);
+
+        GridView gridView = (GridView) v.findViewById(R.id.gallery);
+        gridView.setOnItemClickListener(this);
+        gridView.setAdapter(new ImageAdapter(getActivity()));
+
+        final int viewInset =
+                getResources().getDimensionPixelSize(R.dimen.alert_dialog_content_inset);
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setNegativeButton(R.string.wallpaper_cancel, null);
+        builder.setTitle(R.string.wallpaper_dialog_title);
+        builder.setView(gridView, viewInset, viewInset, viewInset, viewInset);
+        return builder.create();
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        findWallpapers();
+
+        /* If this fragment is embedded in the layout of this activity, then we should
+         * generate a view to display. Otherwise, a dialog will be created in
+         * onCreateDialog()
+         */
+        if (mEmbedded) {
+            View view = inflater.inflate(R.layout.wallpaper_chooser, container, false);
+
+            final Gallery gallery = (Gallery) view.findViewById(R.id.gallery);
+            gallery.setCallbackDuringFling(false);
+            gallery.setOnItemSelectedListener(this);
+            gallery.setAdapter(new ImageAdapter(getActivity()));
+
+            View setButton = view.findViewById(R.id.set);
+            setButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    selectWallpaper(gallery.getSelectedItemPosition());
+                }
+            });
+            mImageView = (ImageView) view.findViewById(R.id.wallpaper);
+            return view;
+        }
+        return null;
+    }
+
+    private void selectWallpaper(int position) {
+        try {
+            WallpaperManager wpm = (WallpaperManager) getActivity().getSystemService(
+                    Context.WALLPAPER_SERVICE);
+            wpm.setResource(mImages.get(position));
+            Activity activity = getActivity();
+            activity.setResult(Activity.RESULT_OK);
+            activity.finish();
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to set wallpaper: " + e);
+        }
+    }
+
+    // Click handler for the Dialog's GridView
+    @Override
+    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        selectWallpaper(position);
+    }
+
+    // Selection handler for the embedded Gallery view
+    @Override
+    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+        if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
+            mLoader.cancel();
+        }
+        mLoader = (WallpaperLoader) new WallpaperLoader().execute(position);
+    }
+
+    @Override
+    public void onNothingSelected(AdapterView<?> parent) {
+    }
+
+    private void findWallpapers() {
+        mThumbs = new ArrayList<Integer>(24);
+        mImages = new ArrayList<Integer>(24);
+
+        final Resources resources = getResources();
+        // Context.getPackageName() may return the "original" package name,
+        // com.android.launcher2; Resources needs the real package name,
+        // com.android.launcher. So we ask Resources for what it thinks the
+        // package name should be.
+        final String packageName = resources.getResourcePackageName(R.array.wallpapers);
+
+        addWallpapers(resources, packageName, R.array.wallpapers);
+        addWallpapers(resources, packageName, R.array.extra_wallpapers);
+    }
+
+    private void addWallpapers(Resources resources, String packageName, int list) {
+        final String[] extras = resources.getStringArray(list);
+        for (String extra : extras) {
+            int res = resources.getIdentifier(extra, "drawable", packageName);
+            if (res != 0) {
+                final int thumbRes = resources.getIdentifier(extra + "_small",
+                        "drawable", packageName);
+
+                if (thumbRes != 0) {
+                    mThumbs.add(thumbRes);
+                    mImages.add(res);
+                    // Log.d(TAG, "add: [" + packageName + "]: " + extra + " (" + res + ")");
+                }
+            }
+        }
+    }
+
+    private class ImageAdapter extends BaseAdapter implements ListAdapter, SpinnerAdapter {
+        private LayoutInflater mLayoutInflater;
+
+        ImageAdapter(Activity activity) {
+            mLayoutInflater = activity.getLayoutInflater();
+        }
+
+        public int getCount() {
+            return mThumbs.size();
+        }
+
+        public Object getItem(int position) {
+            return position;
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            ImageView image;
+
+            if (convertView == null) {
+                image = (ImageView) mLayoutInflater.inflate(R.layout.wallpaper_item, parent, false);
+            } else {
+                image = (ImageView) convertView;
+            }
+
+            int thumbRes = mThumbs.get(position);
+            image.setImageResource(thumbRes);
+            Drawable thumbDrawable = image.getDrawable();
+            if (thumbDrawable != null) {
+                thumbDrawable.setDither(true);
+            } else {
+                Log.e(TAG, "Error decoding thumbnail resId=" + thumbRes + " for wallpaper #"
+                        + position);
+            }
+
+            return image;
+        }
+    }
+
+    class WallpaperLoader extends AsyncTask<Integer, Void, Bitmap> {
+        BitmapFactory.Options mOptions;
+
+        WallpaperLoader() {
+            mOptions = new BitmapFactory.Options();
+            mOptions.inDither = false;
+            mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        }
+
+        @Override
+        protected Bitmap doInBackground(Integer... params) {
+            if (isCancelled()) return null;
+            try {
+                return BitmapFactory.decodeResource(getResources(),
+                        mImages.get(params[0]), mOptions);
+            } catch (OutOfMemoryError e) {
+                return null;
+            }
+        }
+
+        @Override
+        protected void onPostExecute(Bitmap b) {
+            if (b == null) return;
+
+            if (!isCancelled() && !mOptions.mCancel) {
+                // Help the GC
+                if (mBitmap != null) {
+                    mBitmap.recycle();
+                }
+
+                // This should always be the case, but check anyways
+                final ImageView view = mImageView;
+                if (view != null) {
+                    view.setImageBitmap(b);
+
+                    mBitmap = b;
+
+                    final Drawable drawable = view.getDrawable();
+                    drawable.setFilterBitmap(true);
+                    drawable.setDither(true);
+
+                    view.postInvalidate();
+                }
+
+                mLoader = null;
+            } else {
+               b.recycle();
+            }
+        }
+
+        void cancel() {
+            mOptions.requestCancelDecode();
+            super.cancel(true);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 705453d..bbcd0af 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -62,6 +62,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.animation.DecelerateInterpolator;
+import android.widget.TabHost;
 import android.widget.TextView;
 import android.widget.Toast;
 
@@ -117,6 +118,11 @@
     private float mOverScrollMaxBackgroundAlpha = 0.0f;
     private int mOverScrollPageIndex = -1;
 
+    private View mCustomizationDrawer;
+    private View mCustomizationDrawerContent;
+    private int[] mCustomizationDrawerPos = new int[2];
+    private float[] mCustomizationDrawerTransformedPos = new float[2];
+
     private final WallpaperManager mWallpaperManager;
 
     private int mDefaultPage;
@@ -154,7 +160,7 @@
     private float[] mTempDragBottomRightCoordinates = new float[2];
     private Matrix mTempInverseMatrix = new Matrix();
 
-    private SpringLoadedDragController mSpringLoadedDragControllger;
+    private SpringLoadedDragController mSpringLoadedDragController;
 
     private static final int DEFAULT_CELL_COUNT_X = 4;
     private static final int DEFAULT_CELL_COUNT_Y = 4;
@@ -180,8 +186,6 @@
     /** If mInScrollArea is true, the direction of the scroll. */
     private int mPendingScrollDirection = DragController.SCROLL_NONE;
 
-    private boolean mInDragMode = false;
-
     private final HolographicOutlineHelper mOutlineHelper = new HolographicOutlineHelper();
     private Bitmap mDragOutline = null;
     private final Rect mTempRect = new Rect();
@@ -271,7 +275,9 @@
             @Override
             public void onAnimationEndOrCancel(Animator animation) {
                 mIsInUnshrinkAnimation = false;
-                mDrawCustomizeTrayBackground = false;
+                if (mShrinkState != ShrinkState.SPRING_LOADED) {
+                    mDrawCustomizeTrayBackground = false;
+                }
             }
         };
         mSnapVelocity = 600;
@@ -754,6 +760,21 @@
             mBackground.setBounds(mScrollX, 0, mScrollX + getMeasuredWidth(), getMeasuredHeight());
             mBackground.draw(canvas);
             if (mDrawCustomizeTrayBackground) {
+                // Find out where to offset the gradient for the customization tray content
+                mCustomizationDrawer.getLocationOnScreen(mCustomizationDrawerPos);
+                final Matrix m = mCustomizationDrawer.getMatrix();
+                mCustomizationDrawerTransformedPos[0] = 0.0f;
+                mCustomizationDrawerTransformedPos[1] = mCustomizationDrawerContent.getTop();
+                m.mapPoints(mCustomizationDrawerTransformedPos);
+
+                // Draw the bg gradient
+                final int  offset = (int) (mCustomizationDrawerPos[1] +
+                        mCustomizationDrawerTransformedPos[1]);
+                mBackground.setBounds(mScrollX, offset, mScrollX + getMeasuredWidth(),
+                        offset + getMeasuredHeight());
+                mBackground.draw(canvas);
+
+                // Draw the bg glow
                 mCustomizeTrayBackground.setAlpha(alpha);
                 mCustomizeTrayBackground.setBounds(mScrollX, 0, mScrollX + getMeasuredWidth(),
                         getMeasuredHeight());
@@ -1297,7 +1318,9 @@
             }
         }
 
-        hideBackgroundGradient();
+        if (!springLoaded) {
+            hideBackgroundGradient();
+        }
     }
 
     /**
@@ -1998,12 +2021,12 @@
                 if (layout != mDragTargetLayout) {
                     if (mDragTargetLayout != null) {
                         mDragTargetLayout.setHover(false);
-                        mSpringLoadedDragControllger.onDragExit();
+                        mSpringLoadedDragController.onDragExit();
                     }
                     mDragTargetLayout = layout;
                     if (mDragTargetLayout != null && mDragTargetLayout.getAcceptsDrops()) {
                         mDragTargetLayout.setHover(true);
-                        mSpringLoadedDragControllger.onDragEnter(mDragTargetLayout);
+                        mSpringLoadedDragController.onDragEnter(mDragTargetLayout);
                     }
                 }
             } else {
@@ -2215,7 +2238,11 @@
 
     void setLauncher(Launcher launcher) {
         mLauncher = launcher;
-        mSpringLoadedDragControllger = new SpringLoadedDragController(mLauncher);
+        mSpringLoadedDragController = new SpringLoadedDragController(mLauncher);
+
+        mCustomizationDrawer = mLauncher.findViewById(R.id.customization_drawer);
+        mCustomizationDrawerContent =
+            mCustomizationDrawer.findViewById(com.android.internal.R.id.tabcontent);
     }
 
     public void setDragController(DragController dragController) {
@@ -2295,7 +2322,7 @@
         for (int i = 0; i < childCount; i++) {
             ((CellLayout) getChildAt(i)).setHover(false);
         }
-        mSpringLoadedDragControllger.onDragExit();
+        mSpringLoadedDragController.onDragExit();
     }
 
     @Override