Merge "Adding stress test for launcher2 rotation."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5d0f323..01e2b77 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -67,7 +67,7 @@
         android:process="@string/process"
         android:label="@string/application_name"
         android:icon="@drawable/ic_launcher_home"
-        android:hardwareAccelerated="@bool/config_hardwareAccelerated"
+        android:hardwareAccelerated="true"
         android:largeHeap="true">
 
         <activity
diff --git a/res/drawable-hdpi/app_market_generic.png b/res/drawable-hdpi/app_market_generic.png
new file mode 100644
index 0000000..117453c
--- /dev/null
+++ b/res/drawable-hdpi/app_market_generic.png
Binary files differ
diff --git a/res/drawable-large-hdpi/app_market_generic.png b/res/drawable-large-hdpi/app_market_generic.png
deleted file mode 100644
index 2a2381f..0000000
--- a/res/drawable-large-hdpi/app_market_generic.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-large-mdpi/app_market_generic.png b/res/drawable-mdpi/app_market_generic.png
similarity index 100%
rename from res/drawable-large-mdpi/app_market_generic.png
rename to res/drawable-mdpi/app_market_generic.png
Binary files differ
diff --git a/res/layout-land/workspace_screen.xml b/res/layout-land/workspace_screen.xml
index 9323f58..f2bac59 100644
--- a/res/layout-land/workspace_screen.xml
+++ b/res/layout-land/workspace_screen.xml
@@ -24,7 +24,7 @@
 
     launcher:cellWidth="@dimen/workspace_cell_width"
     launcher:cellHeight="@dimen/workspace_cell_height"
-    launcher:xAxisStartPadding="65dip"
-    launcher:xAxisEndPadding="65dip"
+    launcher:xAxisStartPadding="48dip"
+    launcher:xAxisEndPadding="0dip"
     launcher:yAxisStartPadding="0dip"
     launcher:yAxisEndPadding="0dip"/>
diff --git a/res/layout-large/all_apps_tabbed.xml b/res/layout-large/all_apps_tabbed.xml
index b00b3c3..1a20440 100644
--- a/res/layout-large/all_apps_tabbed.xml
+++ b/res/layout-large/all_apps_tabbed.xml
@@ -101,8 +101,6 @@
                 android:id="@+id/all_apps_paged_view"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                launcher:cellCountX="@integer/all_apps_view_cellCountX"
-                launcher:cellCountY="@integer/all_apps_view_cellCountY"
                 launcher:pageLayoutWidthGap="@dimen/all_apps_view_pageLayoutWidthGap"
                 launcher:pageLayoutHeightGap="@dimen/all_apps_view_pageLayoutHeightGap"
                 launcher:pageLayoutPaddingTop="@dimen/all_apps_view_pageLayoutPaddingTop"
diff --git a/res/layout-large/customization_drawer.xml b/res/layout-large/customization_drawer.xml
index d8db066..0c59a3f 100644
--- a/res/layout-large/customization_drawer.xml
+++ b/res/layout-large/customization_drawer.xml
@@ -40,15 +40,12 @@
                 launcher:wallpaperCellSpanX="@integer/customization_drawer_contents_wallpaperCellSpanX"
                 launcher:wallpaperCellCountX="@integer/customization_drawer_contents_wallpaperCellCountX"
                 launcher:widgetCellCountX="@integer/customization_drawer_contents_widgetCellCountX"
-                launcher:cellCountX="@integer/customization_drawer_contents_cellCountX"
-                launcher:cellCountY="@integer/customization_drawer_contents_cellCountY"
                 launcher:pageLayoutWidthGap="@dimen/customization_drawer_contents_pageLayoutWidthGap"
-                launcher:pageLayoutHeightGap="12dp"
-                launcher:pageLayoutPaddingTop="40dp"
-                launcher:pageLayoutPaddingBottom="25dp"
-                launcher:pageLayoutPaddingLeft="20dp"
-                launcher:pageLayoutPaddingRight="20dp"
-                launcher:pageLayoutMaxHeight="@dimen/customization_drawer_content_height" />
+                launcher:pageLayoutHeightGap="@dimen/customization_drawer_contents_pageLayoutHeightGap"
+                launcher:pageLayoutPaddingTop="@dimen/customization_drawer_contents_pageLayoutPaddingTop"
+                launcher:pageLayoutPaddingBottom="@dimen/customization_drawer_contents_pageLayoutPaddingBottom"
+                launcher:pageLayoutPaddingLeft="@dimen/customization_drawer_contents_pageLayoutPaddingLeft"
+                launcher:pageLayoutPaddingRight="@dimen/customization_drawer_contents_pageLayoutPaddingRight" />
          </FrameLayout>
       </LinearLayout>
 </com.android.launcher2.CustomizeTrayTabHost>
\ No newline at end of file
diff --git a/res/layout-large/customize_tab_widget_indicator.xml b/res/layout-large/customize_tab_widget_indicator.xml
new file mode 100644
index 0000000..186a342
--- /dev/null
+++ b/res/layout-large/customize_tab_widget_indicator.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<com.android.launcher2.AccessibleTabView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/CustomizeTabIndicator.Wide" />
diff --git a/res/layout-large/launcher.xml b/res/layout-large/launcher.xml
index 6a16eb5..2d14137 100644
--- a/res/layout-large/launcher.xml
+++ b/res/layout-large/launcher.xml
@@ -44,7 +44,7 @@
     <include layout="@layout/customization_drawer"
         android:id="@+id/customization_drawer"
         android:layout_width="match_parent"
-        android:layout_height="@dimen/customization_drawer_height"
+        android:layout_height="wrap_content"
         android:layout_gravity="bottom"
         android:visibility="invisible" />
 </com.android.launcher2.DragLayer>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index e1b0214..b3d0b2e 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -15,7 +15,7 @@
 -->
 
 <resources>
-    <dimen name="workspace_cell_width">106dip</dimen>
+    <dimen name="workspace_cell_width">96dip</dimen>
     <dimen name="workspace_cell_height">74dip</dimen>
     <dimen name="folder_cell_width">100dip</dimen>
     <dimen name="folder_cell_height">74dip</dimen>
diff --git a/res/values-large-land/dimens.xml b/res/values-large-land/dimens.xml
index 196cdb0..eeb16f4 100644
--- a/res/values-large-land/dimens.xml
+++ b/res/values-large-land/dimens.xml
@@ -19,11 +19,6 @@
          or right while you're dragging. -->
     <dimen name="scroll_zone">100dip</dimen>
 
-    <dimen name="customization_drawer_height">480dp</dimen>
-    <dimen name="customization_drawer_content_height">420dp</dimen>
-
-    <integer name="all_apps_view_cellCountX">7</integer>
-    <integer name="all_apps_view_cellCountY">5</integer>
     <dimen name="all_apps_view_pageLayoutWidthGap">36dp</dimen>
     <dimen name="all_apps_view_pageLayoutHeightGap">6dp</dimen>
     <dimen name="all_apps_view_pageLayoutPaddingTop">20dp</dimen>
@@ -31,10 +26,15 @@
     <dimen name="all_apps_view_pageLayoutPaddingLeft">40dp</dimen>
     <dimen name="all_apps_view_pageLayoutPaddingRight">40dp</dimen>
 
+    <!-- Dimensions for customize should generally be the same as all apps, or very similar. -->
+    <dimen name="customization_drawer_contents_pageLayoutWidthGap">32dp</dimen>
+    <dimen name="customization_drawer_contents_pageLayoutHeightGap">12dp</dimen>
+    <dimen name="customization_drawer_contents_pageLayoutPaddingTop">20dp</dimen>
+    <dimen name="customization_drawer_contents_pageLayoutPaddingBottom">20dp</dimen>
+    <dimen name="customization_drawer_contents_pageLayoutPaddingLeft">40dp</dimen>
+    <dimen name="customization_drawer_contents_pageLayoutPaddingRight">40dp</dimen>
+
     <integer name="customization_drawer_contents_wallpaperCellSpanX">3</integer>
     <integer name="customization_drawer_contents_wallpaperCellCountX">12</integer>
     <integer name="customization_drawer_contents_widgetCellCountX">14</integer>
-    <integer name="customization_drawer_contents_cellCountX">8</integer>
-    <integer name="customization_drawer_contents_cellCountY">3</integer>
-    <dimen name="customization_drawer_contents_pageLayoutWidthGap">32dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/res/values-large-port/dimens.xml b/res/values-large-port/dimens.xml
index 47cac78..89f8605 100644
--- a/res/values-large-port/dimens.xml
+++ b/res/values-large-port/dimens.xml
@@ -19,11 +19,6 @@
          or right while you're dragging. -->
     <dimen name="scroll_zone">40dp</dimen>
 
-    <dimen name="customization_drawer_height">800dp</dimen>
-    <dimen name="customization_drawer_content_height">420dp</dimen>
-
-    <integer name="all_apps_view_cellCountX">5</integer>
-    <integer name="all_apps_view_cellCountY">7</integer>
     <dimen name="all_apps_view_pageLayoutWidthGap">36dp</dimen>
     <dimen name="all_apps_view_pageLayoutHeightGap">36dp</dimen>
     <dimen name="all_apps_view_pageLayoutPaddingTop">25dp</dimen>
@@ -34,7 +29,12 @@
     <integer name="customization_drawer_contents_wallpaperCellSpanX">3</integer>
     <integer name="customization_drawer_contents_wallpaperCellCountX">9</integer>
     <integer name="customization_drawer_contents_widgetCellCountX">9</integer>
-    <integer name="customization_drawer_contents_cellCountX">5</integer>
-    <integer name="customization_drawer_contents_cellCountY">3</integer>
+
+    <!-- Dimensions for customize should generally be the same as all apps, or very similar. -->
     <dimen name="customization_drawer_contents_pageLayoutWidthGap">36dp</dimen>
+    <dimen name="customization_drawer_contents_pageLayoutHeightGap">12dp</dimen>
+    <dimen name="customization_drawer_contents_pageLayoutPaddingTop">25dp</dimen>
+    <dimen name="customization_drawer_contents_pageLayoutPaddingBottom">25dp</dimen>
+    <dimen name="customization_drawer_contents_pageLayoutPaddingLeft">20dp</dimen>
+    <dimen name="customization_drawer_contents_pageLayoutPaddingRight">20dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/res/values-large-port/styles.xml b/res/values-large-port/styles.xml
new file mode 100644
index 0000000..ba23a89
--- /dev/null
+++ b/res/values-large-port/styles.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2008 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>
+    <style name="CustomizeTabIndicator.Wide" parent="TabIndicator.Wide">
+        <item name="android:paddingLeft">20dp</item>
+        <item name="android:paddingRight">20dp</item>
+        <item name="android:paddingTop">12dp</item>
+        <item name="android:paddingBottom">16dp</item>
+        <item name="android:textSize">16sp</item>
+    </style>
+</resources>
diff --git a/res/values-large/config.xml b/res/values-large/config.xml
index 99ee1ec..8b77696 100644
--- a/res/values-large/config.xml
+++ b/res/values-large/config.xml
@@ -21,6 +21,9 @@
          Should be an even number, for pixel alignment. -->
     <integer name="config_dragViewExtraPixels">0</integer>
 
+    <!-- When shrinking the workspace, this is the percentage of its original size. -->
+    <integer name="config_workspaceShrinkPercent">17</integer>
+
     <!-- When items are dropped on the mini screens in customize mode, we have a bounce animation
          of the bright green hover outline, and then fade out the outline at the end. These are
          the values used in that animation -->
diff --git a/res/values-large/dimens.xml b/res/values-large/dimens.xml
index 2416109..10836b9 100644
--- a/res/values-large/dimens.xml
+++ b/res/values-large/dimens.xml
@@ -88,4 +88,14 @@
      the drag view should be offset from the position of the original view. -->
     <dimen name="dragViewOffsetX">0dp</dimen>
     <dimen name="dragViewOffsetY">-12dp</dimen>
+
+    <!-- The actual number of rows/columns will be determined dynamically based on the screen
+         size, but in portrait we want to cap the rows at 3, otherwise it looks weird. -->
+    <integer name="customization_drawer_contents_maxCellCountY">3</integer>
+
+    <!-- The percentage of vertical space that the customize tray should try to fill. -->
+    <integer name="customization_drawer_verticalFillPercentage">65</integer>
+
+    <!-- Max number of rows in all apps, because too many looks weird. -->
+    <integer name="all_apps_view_maxCellCountY">6</integer>
 </resources>
diff --git a/res/values-large/styles.xml b/res/values-large/styles.xml
index bcbe038..ebb26f5 100644
--- a/res/values-large/styles.xml
+++ b/res/values-large/styles.xml
@@ -50,6 +50,9 @@
         <item name="android:textSize">20sp</item>
     </style>
 
+    <style name="CustomizeTabIndicator.Wide" parent="TabIndicator.Wide">
+    </style>
+
     <style name="config_orientation">
         <item name="@android:screenOrientation">unspecified</item>
     </style>
diff --git a/res/values-xlarge/styles.xml b/res/values-xlarge/styles.xml
new file mode 100644
index 0000000..fdf2f19
--- /dev/null
+++ b/res/values-xlarge/styles.xml
@@ -0,0 +1,23 @@
+<?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>
+    <style name="CustomizeTabIndicator.Wide" parent="TabIndicator.Wide">
+    </style>
+</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 1cc019b..de05a4b 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -66,4 +66,7 @@
          than the view itself (workspaceScreenBitmapCacheScale)  -->
     <integer name="config_workspaceScreenBitmapCacheScale">20</integer>
     <integer name="config_maxScaleForUsingWorkspaceScreenBitmapCache">50</integer>
+
+    <!-- When shrinking the workspace, this is the percentage of its original size. -->
+    <integer name="config_workspaceShrinkPercent">17</integer>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9ad3e24..7e8bec0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -25,6 +25,13 @@
     <!-- Do not translate. android:process of this application. -->
     <string name="process" translate="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>
+
     <!-- General -->
     <skip />
     <!-- Application name -->
diff --git a/src/com/android/launcher2/AllAppsBackground.java b/src/com/android/launcher2/AllAppsBackground.java
index 5292d0a..51e1ee4 100644
--- a/src/com/android/launcher2/AllAppsBackground.java
+++ b/src/com/android/launcher2/AllAppsBackground.java
@@ -25,8 +25,8 @@
 import android.view.View;
 
 /**
- * An implementation of PagedView that populates the pages of the workspace
- * with all of the user's applications.
+ * The background for AllApps which moves independently of the AllApps tray (for example, when we
+ * transition between AllApps and the Workspace while in spring-loaded mode).
  */
 public class AllAppsBackground extends View {
     private Drawable mBackground;
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index 59ba57b..64e6f98 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -17,6 +17,7 @@
 package com.android.launcher2;
 
 import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
 
 import android.content.ComponentName;
 import android.content.Context;
@@ -66,11 +67,14 @@
     private final LayoutInflater mInflater;
     private boolean mAllowHardwareLayerCreation;
 
-    private boolean mFirstMeasure = true;
-
     private int mPageContentWidth;
     private boolean mHasMadeSuccessfulDrop;
 
+    private int mLastMeasureWidth = -1;
+    private int mLastMeasureHeight = -1;
+
+    private int mMaxCellCountY;
+
     public AllAppsPagedView(Context context) {
         this(context, null);
     }
@@ -82,17 +86,16 @@
     public AllAppsPagedView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, defStyle, 0);
-        mCellCountX = a.getInt(R.styleable.PagedView_cellCountX, 6);
-        mCellCountY = a.getInt(R.styleable.PagedView_cellCountY, 4);
         mInflater = LayoutInflater.from(context);
         mApps = new ArrayList<ApplicationInfo>();
         mFilteredApps = new ArrayList<ApplicationInfo>();
         a.recycle();
         setSoundEffectsEnabled(false);
 
-        Resources r = context.getResources();
+        final Resources r = context.getResources();
         setDragSlopeThreshold(
                 r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold) / 100.0f);
+        mMaxCellCountY = r.getInteger(R.integer.all_apps_view_maxCellCountY);
     }
 
     @Override
@@ -103,27 +106,88 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        final int width = MeasureSpec.getSize(widthMeasureSpec);
+        final int height = MeasureSpec.getSize(heightMeasureSpec);
 
-        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
-        if (mFirstMeasure) {
-            mFirstMeasure = false;
-
-            // TODO: actually calculate mCellCountX/mCellCountY as some function of
-            // widthSize and heightSize
-            //mCellCountX = ?;
-            //mCellCountY = ?;
-
-            // Since mCellCountX/mCellCountY changed, we need to update the pages
-            invalidatePageData();
-
+        if (mLastMeasureWidth != width || mLastMeasureHeight != height) {
             // Create a dummy page and set it up to find out the content width (used by our parent)
             PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
             setupPage(layout);
             mPageContentWidth = layout.getContentWidth();
+
+            mCellCountX = determineCellCountX(width, layout);
+            mCellCountY = determineCellCountY(height, layout);
+            mLastMeasureWidth = width;
+            mLastMeasureHeight = height;
         }
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (mFirstLayout) {
+            invalidatePageData();
+
+            // invalidatePageData() is what causes the child pages to be created. We need the
+            // children to be measured before layout, so force a new measure here.
+            measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
+        }
+        super.onLayout(changed, left, top, right, bottom);
+    }
+
+    private int determineCellCountX(int availableWidth, PagedViewCellLayout layout) {
+        int cellCountX = 0;
+        final int cellWidth = layout.getCellWidth();
+
+        // Subtract padding for current page and adjacent pages
+        availableWidth -= mPageLayoutPaddingLeft * 2 + mPageLayoutPaddingRight * 2;
+
+        availableWidth -= cellWidth; // Assume at least one column
+        cellCountX = 1 + availableWidth / (cellWidth + mPageLayoutWidthGap);
+        availableWidth = availableWidth % (cellWidth + mPageLayoutWidthGap);
+
+        // Ensures that we show at least 30% of the holo icons on each side
+        final int minLeftoverWidth = (int) (cellWidth * 0.6f);
+
+        // Reserve room for the holo outlines
+        if (cellCountX <= 4) {
+            // When we're really tight on space, just pack the icons a bit closer together
+            final int missingWidth = minLeftoverWidth - availableWidth;
+            if (missingWidth > 0) {
+                mPageLayoutWidthGap -= Math.ceil(missingWidth * 1.0f / (cellCountX - 1));
+            }
+        } else {
+            if (cellCountX >= 8) {
+                // Carve out a few extra columns for very large widths
+                cellCountX = (int) (cellCountX * 0.9f);
+            } else if (availableWidth < minLeftoverWidth) {
+                cellCountX -= 1;
+            }
+        }
+        return cellCountX;
+    }
+
+    private int determineCellCountY(int availableHeight, PagedViewCellLayout layout) {
+        final int cellHeight = layout.getCellHeight();
+        final int screenHeight = mLauncher.getResources().getDisplayMetrics().heightPixels;
+
+        availableHeight -= mPageLayoutPaddingTop + mPageLayoutPaddingBottom;
+        availableHeight -= cellHeight; // Assume at least one row
+        availableHeight -= screenHeight * 0.16f;
+        if (availableHeight > 0) {
+            return Math.min(mMaxCellCountY,
+                    1 + availableHeight / (cellHeight + mPageLayoutHeightGap));
+        }
+        return 0;
+    }
+
+    int getCellCountX() {
+        return mCellCountX;
+    }
+
+    int getCellCountY() {
+        return mCellCountY;
     }
 
     void allowHardwareLayerCreation() {
@@ -504,7 +568,7 @@
 
     @Override
     public void syncPages() {
-        if (mFirstMeasure) {
+        if (mCellCountX <= 0 || mCellCountY <= 0) {
             // We don't know our size yet, which means we haven't calculated cell count x/y;
             // onMeasure will call us once we figure out our size
             return;
@@ -623,28 +687,16 @@
      * We don't actually use AllAppsPagedView as a drop target... it's only used to intercept a drop
      * to the workspace.
      */
-    @Override
-    public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public boolean acceptDrop(DragObject d) {
         return false;
     }
-    @Override
-    public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset,
-            int yOffset, DragView dragView, Object dragInfo) {
+    public DropTarget getDropTargetDelegate(DragObject d) {
         return null;
     }
-    @Override
-    public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {}
-    @Override
-    public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {}
-    @Override
-    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {}
-    @Override
-    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {}
+    public void onDragEnter(DragObject d) {}
+    public void onDragExit(DragObject d) {}
+    public void onDragOver(DragObject d) {}
+    public void onDrop(DragObject d) {}
 
     public boolean isDropEnabled() {
         return true;
diff --git a/src/com/android/launcher2/ApplicationInfoDropTarget.java b/src/com/android/launcher2/ApplicationInfoDropTarget.java
index f42aaf5..e02878a 100644
--- a/src/com/android/launcher2/ApplicationInfoDropTarget.java
+++ b/src/com/android/launcher2/ApplicationInfoDropTarget.java
@@ -17,6 +17,7 @@
 package com.android.launcher2;
 
 import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
@@ -61,33 +62,30 @@
         }
     }
 
-    public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    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 home screen.
         if (getVisibility() != VISIBLE) return false;
 
         ComponentName componentName = null;
-        if (dragInfo instanceof ApplicationInfo) {
-            componentName = ((ApplicationInfo)dragInfo).componentName;
-        } else if (dragInfo instanceof ShortcutInfo) {
-            componentName = ((ShortcutInfo)dragInfo).intent.getComponent();
+        if (d.dragInfo instanceof ApplicationInfo) {
+            componentName = ((ApplicationInfo) d.dragInfo).componentName;
+        } else if (d.dragInfo instanceof ShortcutInfo) {
+            componentName = ((ShortcutInfo) d.dragInfo).intent.getComponent();
         }
         mLauncher.startApplicationDetailsActivity(componentName);
         return false;
     }
 
-    public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDragEnter(DragObject d) {
         if (!mDragAndDropEnabled) return;
-        dragView.setPaint(mHoverPaint);
+        d.dragView.setPaint(mHoverPaint);
     }
 
-    public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDragExit(DragObject d) {
         if (!mDragAndDropEnabled) return;
-        dragView.setPaint(null);
+        d.dragView.setPaint(null);
     }
 
     public void onDragStart(DragSource source, Object info, int dragAction) {
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index 87be63e..4500744 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -18,6 +18,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -167,6 +168,22 @@
         setDragSlopeThreshold(r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold)/100f);
     }
 
+    /** Removes and returns the ResolveInfo with the specified ComponentName */
+    private ResolveInfo removeResolveInfoWithComponentName(List<ResolveInfo> list,
+            ComponentName cn) {
+        Iterator<ResolveInfo> iter = list.iterator();
+        while (iter.hasNext()) {
+            ResolveInfo rinfo = iter.next();
+            ActivityInfo info = rinfo.activityInfo;
+            ComponentName c = new ComponentName(info.packageName, info.name);
+            if (c.equals(cn)) {
+                iter.remove();
+                return rinfo;
+            }
+        }
+        return null;
+    }
+
     public void onPackagesUpdated() {
         // Get the list of widgets and shortcuts
         mWidgets.clear();
@@ -182,6 +199,20 @@
                 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);
+        }
     }
 
     /**
@@ -293,20 +324,22 @@
                 }
             });
         } else if (v instanceof PagedViewWidget) {
-            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);
-                    }
-                });
+            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);
+                        }
+                    });
+                }
             } else {
                 // Add the widget to the current workspace screen
                 Workspace w = mLauncher.getWorkspace();
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 5f848a8..f189cd5 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -71,7 +71,7 @@
 
     // These are temporary variables to prevent having to allocate a new object just to
     // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
-    private final int[] mTmpCellXY = new int[2];
+    private final int[] mTmpXY = new int[2];
     private final int[] mTmpPoint = new int[2];
     private final PointF mTmpPointF = new PointF();
 
@@ -694,6 +694,14 @@
             if ((child.getVisibility() == VISIBLE || child.getAnimation() != null) &&
                     lp.isLockedToGrid) {
                 child.getHitRect(frame);
+
+                // The child hit rect is relative to the CellLayoutChildren parent, so we need to
+                // offset that by this CellLayout's padding to test an (x,y) point that is relative
+                // to this view.
+                final int tmpXY[] = mTmpXY;
+                child.getLocationOnScreen(tmpXY);
+                frame.offset(mLeftPadding, mTopPadding);
+
                 if (frame.contains(x, y)) {
                     cellInfo.cell = child;
                     cellInfo.cellX = lp.cellX;
@@ -708,7 +716,7 @@
         }
 
         if (!found) {
-            final int cellXY[] = mTmpCellXY;
+            final int cellXY[] = mTmpXY;
             pointToCellExact(x, y, cellXY);
 
             cellInfo.cell = null;
@@ -1161,7 +1169,7 @@
                         }
                     }
                 }
-                final int[] cellXY = mTmpCellXY;
+                final int[] cellXY = mTmpXY;
                 cellToCenterPoint(x, y, cellXY);
 
                 double distance = Math.sqrt(Math.pow(cellXY[0] - pixelX, 2)
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 68ec535..5ac261f 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -108,6 +108,9 @@
     // The max number of wallpaper cells to take a "page" of wallpaper items
     private int mMaxWallpaperCellHSpan;
 
+    // The maximum number of rows in a paged view.
+    private int mMaxCellCountY;
+
     // The raw sources of data for each of the different tabs of the customization page
     private List<AppWidgetProviderInfo> mWidgetList;
     private List<ResolveInfo> mShortcutList;
@@ -143,7 +146,10 @@
 
     private int[] mDragViewOrigin = new int[2];
 
-    private int mPageContentWidth;
+    private int mPageContentWidth = -1;
+    private int mPageContentHeight = -1;
+
+    private AllAppsPagedView mAllAppsPagedView;
 
     public CustomizePagedView(Context context) {
         this(context, null, 0);
@@ -162,10 +168,6 @@
         mMaxWallpaperCellHSpan = a.getInt(R.styleable.CustomizePagedView_wallpaperCellCountX, 8);
         mMaxWidgetsCellHSpan = a.getInt(R.styleable.CustomizePagedView_widgetCellCountX, 8);
         a.recycle();
-        a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, defStyle, 0);
-        mCellCountX = a.getInt(R.styleable.PagedView_cellCountX, 7);
-        mCellCountY = a.getInt(R.styleable.PagedView_cellCountY, 4);
-        a.recycle();
 
         mCustomizationType = CustomizationType.WidgetCustomization;
         mWidgetPages = new ArrayList<ArrayList<AppWidgetProviderInfo>>();
@@ -176,6 +178,8 @@
         setDragSlopeThreshold(
                 r.getInteger(R.integer.config_customizationDrawerDragSlopeThreshold) / 100.0f);
 
+        mMaxCellCountY = r.getInteger(R.integer.customization_drawer_contents_maxCellCountY);
+
         setVisibility(View.GONE);
         setSoundEffectsEnabled(false);
         setupWorkspaceLayout();
@@ -188,29 +192,44 @@
     }
 
     @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    protected void onMeasure(int widthSpec, int heightSpec) {
+        // Base the size of this control on the size of the All Apps view.
+        final int cellCountX = mAllAppsPagedView.getCellCountX();
+        final int cellCountY = Math.min(mAllAppsPagedView.getCellCountY(), mMaxCellCountY);
 
-        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+        if (cellCountX != mCellCountX || cellCountY != mCellCountY) {
+            mCellCountX = cellCountX;
+            mCellCountY = cellCountY;
 
-        if (mFirstMeasure) {
-            mFirstMeasure = false;
-
-            // TODO: actually calculate mCellCountX/mCellCountY as some function of
-            // widthSize and heightSize
-            //mCellCountX = ?
-            //mCellCountY = ?
-
-            // Since mCellCountX/mCellCountY changed, we need to update the pages
-            invalidatePageData();
-
-            // Create a dummy page and set it up to find out the content width (used by our parent)
+            // Create a dummy page and set it up to determine our size.
+            // The size is based on the app shortcuts tab having the same dimensions as All Apps.
             PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
             setupPage(layout);
             mPageContentWidth = layout.getContentWidth();
+            mPageContentHeight = layout.getContentHeight();
             mMinPageWidth = layout.getWidthBeforeFirstLayout();
         }
+        if (mPageContentHeight > 0) {
+            // Lock our height to the size of the page content
+            final int h = mPageContentHeight + mPageLayoutPaddingTop + mPageLayoutPaddingBottom;
+            heightSpec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
+        }
+        super.onMeasure(widthSpec, heightSpec);
+        mFirstMeasure = false;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (mFirstLayout) {
+            invalidatePageData();
+
+            // invalidatePageData() is what causes the child pages to be created. We need the
+            // children to be measured before layout, so force a new measure here.
+            measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
+        }
+        super.onLayout(changed, left, top, right, bottom);
+        mFirstLayout = false;
     }
 
     public void setLauncher(Launcher launcher) {
@@ -219,6 +238,10 @@
         mPackageManager = context.getPackageManager();
     }
 
+    public void setAllAppsPagedView(AllAppsPagedView view) {
+        mAllAppsPagedView = view;
+    }
+
     /**
      * Sets the list of applications that launcher has loaded.
      */
diff --git a/src/com/android/launcher2/CustomizeTrayTabHost.java b/src/com/android/launcher2/CustomizeTrayTabHost.java
index ab50cf1..c6a39b3 100644
--- a/src/com/android/launcher2/CustomizeTrayTabHost.java
+++ b/src/com/android/launcher2/CustomizeTrayTabHost.java
@@ -44,9 +44,14 @@
 
     private boolean mFirstLayout = true;
 
+    // How much of the vertical space this control should attempt to fill
+    private float mVerticalFillPercentage;
+
     private final LayoutInflater mInflater;
     private Context mContext;
 
+    private CustomizePagedView mCustomizePagedView;
+
     public CustomizeTrayTabHost(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContext = context;
@@ -55,58 +60,66 @@
 
     @Override
     protected void onFinishInflate() {
+        final Resources res = getResources();
+
         setup();
 
-        final CustomizePagedView customizePagedView =
+        mCustomizePagedView =
             (CustomizePagedView) findViewById(R.id.customization_drawer_tab_contents);
 
         // Configure tabs
         TabContentFactory contentFactory = new TabContentFactory() {
             public View createTabContent(String tag) {
-                return customizePagedView;
+                return mCustomizePagedView;
             }
         };
 
         TextView tabView;
         TabWidget tabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
 
-        tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
+        tabView = (TextView) mInflater.inflate(
+                R.layout.customize_tab_widget_indicator, tabWidget, false);
         tabView.setText(mContext.getString(R.string.widgets_tab_label));
         addTab(newTabSpec(WIDGETS_TAG)
                 .setIndicator(tabView).setContent(contentFactory));
-        tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
+        tabView = (TextView) mInflater.inflate(
+                R.layout.customize_tab_widget_indicator, tabWidget, false);
         tabView.setText(mContext.getString(R.string.applications_tab_label));
         addTab(newTabSpec(APPLICATIONS_TAG)
                 .setIndicator(tabView).setContent(contentFactory));
-        tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
+        tabView = (TextView) mInflater.inflate(
+                R.layout.customize_tab_widget_indicator, tabWidget, false);
         tabView.setText(mContext.getString(R.string.wallpapers_tab_label));
         addTab(newTabSpec(WALLPAPERS_TAG)
                 .setIndicator(tabView).setContent(contentFactory));
-        tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
+        tabView = (TextView) mInflater.inflate(
+                R.layout.customize_tab_widget_indicator, tabWidget, false);
         tabView.setText(mContext.getString(R.string.shortcuts_tab_label));
         addTab(newTabSpec(SHORTCUTS_TAG)
                 .setIndicator(tabView).setContent(contentFactory));
 
+        mVerticalFillPercentage =
+                res.getInteger(R.integer.customization_drawer_verticalFillPercentage) / 100f;
+
         setOnTabChangedListener(new OnTabChangeListener() {
             public void onTabChanged(String tabId) {
                 final CustomizePagedView.CustomizationType newType =
                     getCustomizeFilterForTabTag(tabId);
-                if (newType != customizePagedView.getCustomizationFilter()) {
+                if (newType != mCustomizePagedView.getCustomizationFilter()) {
                     // animate the changing of the tab content by fading pages in and out
-                    final Resources res = getResources();
                     final int duration = res.getInteger(R.integer.config_tabTransitionDuration);
-                    final float alpha = customizePagedView.getAlpha();
-                    ValueAnimator alphaAnim = ObjectAnimator.ofFloat(customizePagedView,
+                    final float alpha = mCustomizePagedView.getAlpha();
+                    ValueAnimator alphaAnim = ObjectAnimator.ofFloat(mCustomizePagedView,
                             "alpha", alpha, 0.0f);
                     alphaAnim.setDuration(duration);
                     alphaAnim.addListener(new AnimatorListenerAdapter() {
                         @Override
                         public void onAnimationEnd(Animator animation) {
-                            customizePagedView.setCustomizationFilter(newType);
+                            mCustomizePagedView.setCustomizationFilter(newType);
 
-                            final float alpha = customizePagedView.getAlpha();
+                            final float alpha = mCustomizePagedView.getAlpha();
                             ValueAnimator alphaAnim = ObjectAnimator.ofFloat(
-                                    customizePagedView, "alpha", alpha, 1.0f);
+                                    mCustomizePagedView, "alpha", alpha, 1.0f);
                             alphaAnim.setDuration(duration);
                             alphaAnim.start();
                         }
@@ -138,6 +151,22 @@
     }
 
     @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        // If there's extra room, try to grow to fill it
+        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
+            final int availableHeight = MeasureSpec.getSize(heightMeasureSpec);
+            final int finalHeight = Math.max(getMeasuredHeight(),
+                        (int) (availableHeight * mVerticalFillPercentage));
+
+            // Measure a second time with EXACTLY so that we get sized correctly
+            heightMeasureSpec = MeasureSpec.makeMeasureSpec(finalHeight, MeasureSpec.EXACTLY);
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        }
+    }
+
+    @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         if (mFirstLayout) {
             mFirstLayout = false;
diff --git a/src/com/android/launcher2/DeleteZone.java b/src/com/android/launcher2/DeleteZone.java
index 5d9b5db..21b1cf1 100644
--- a/src/com/android/launcher2/DeleteZone.java
+++ b/src/com/android/launcher2/DeleteZone.java
@@ -33,6 +33,7 @@
 import android.view.animation.AccelerateInterpolator;
 
 import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
 
 public class DeleteZone extends IconDropTarget {
     private static final int ORIENTATION_HORIZONTAL = 1;
@@ -90,16 +91,14 @@
         mDragTextColor = r.getColor(R.color.workspace_delete_zone_drag_text_color);
     }
 
-    public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public boolean acceptDrop(DragObject d) {
         return true;
     }
 
-    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDrop(DragObject d) {
         if (!mDragAndDropEnabled) return;
 
-        final ItemInfo item = (ItemInfo) dragInfo;
+        final ItemInfo item = (ItemInfo) d.dragInfo;
 
         // On x-large screens, you can uninstall an app by dragging from all apps
         if (item instanceof ApplicationInfo && LauncherApplication.isScreenLarge()) {
@@ -135,21 +134,19 @@
         LauncherModel.deleteItemFromDatabase(mLauncher, item);
     }
 
-    public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDragEnter(DragObject d) {
         if (mDragAndDropEnabled) {
             mTransition.reverseTransition(getTransitionAnimationDuration());
             setTextColor(mDragTextColor);
-            super.onDragEnter(source, x, y, xOffset, yOffset, dragView, dragInfo);
+            super.onDragEnter(d);
         }
     }
 
-    public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDragExit(DragObject d) {
         if (mDragAndDropEnabled) {
             mTransition.reverseTransition(getTransitionAnimationDuration());
             setTextColor(mTextColor);
-            super.onDragExit(source, x, y, xOffset, yOffset, dragView, dragInfo);
+            super.onDragExit(d);
         }
     }
 
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 5ca1e1c..1690cac 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -35,6 +35,7 @@
 import android.view.inputmethod.InputMethodManager;
 
 import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
 
 /**
  * Class for initiating a drag within a view or across multiple views.
@@ -84,25 +85,12 @@
     /** Original view that is being dragged.  */
     private View mOriginator;
 
-    /** X offset from the upper-left corner of the cell to where we touched.  */
-    private int mTouchOffsetX;
-
-    /** Y offset from the upper-left corner of the cell to where we touched.  */
-    private int mTouchOffsetY;
-
     /** the area at the edge of the screen that makes the workspace go left
      *   or right while you're dragging.
      */
     private int mScrollZone;
 
-    /** Where the drag originated */
-    private DragSource mDragSource;
-
-    /** The data associated with the object being dragged */
-    private Object mDragInfo;
-
-    /** The view that moves around while you drag.  */
-    private DragView mDragView;
+    private DropTarget.DragObject mDragObject = new DropTarget.DragObject();
 
     /** Who can receive drop events */
     private ArrayList<DropTarget> mDropTargets = new ArrayList<DropTarget>();
@@ -295,17 +283,17 @@
         final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
         final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
 
-        mTouchOffsetX = mMotionDownX - (screenX + dragRegionLeft);
-        mTouchOffsetY = mMotionDownY - (screenY + dragRegionTop);
-
         mDragging = true;
-        mDragSource = source;
-        mDragInfo = dragInfo;
+
+        mDragObject.xOffset = mMotionDownX - (screenX + dragRegionLeft);
+        mDragObject.yOffset = mMotionDownY - (screenY + dragRegionTop);
+        mDragObject.dragSource = source;
+        mDragObject.dragInfo = dragInfo;
 
         mVibrator.vibrate(VIBRATE_DURATION);
 
-        DragView dragView = mDragView = new DragView(mContext, b, registrationX, registrationY,
-                0, 0, b.getWidth(), b.getHeight());
+        final DragView dragView = mDragObject.dragView = new DragView(mContext, b, registrationX,
+                registrationY, 0, 0, b.getWidth(), b.getHeight());
 
         final DragSource dragSource = source;
         dragView.setOnDrawRunnable(new Runnable() {
@@ -386,7 +374,7 @@
     public void cancelDrag() {
         if (mDragging) {
             // Should we also be calling onDragExit() here?
-            mDragSource.onDropCompleted(null, mDragInfo, false);
+            mDragObject.dragSource.onDropCompleted(null, mDragObject.dragInfo, false);
         }
         endDrag();
     }
@@ -400,9 +388,9 @@
             for (DragListener listener : mListeners) {
                 listener.onDragEnd();
             }
-            if (mDragView != null) {
-                mDragView.remove();
-                mDragView = null;
+            if (mDragObject.dragView != null) {
+                mDragObject.dragView.remove();
+                mDragObject.dragView = null;
             }
         }
     }
@@ -459,33 +447,29 @@
     }
 
     private void handleMoveEvent(int x, int y) {
-        mDragView.move(x, y);
+        mDragObject.dragView.move(x, y);
 
         // Drop on someone?
         final int[] coordinates = mCoordinatesTemp;
         DropTarget dropTarget = findDropTarget(x, y, coordinates);
+        mDragObject.x = coordinates[0];
+        mDragObject.y = coordinates[1];
         if (dropTarget != null) {
-            DropTarget delegate = dropTarget.getDropTargetDelegate(
-                    mDragSource, coordinates[0], coordinates[1],
-                    (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
+            DropTarget delegate = dropTarget.getDropTargetDelegate(mDragObject);
             if (delegate != null) {
                 dropTarget = delegate;
             }
 
             if (mLastDropTarget != dropTarget) {
                 if (mLastDropTarget != null) {
-                    mLastDropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],
-                        (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
+                    mLastDropTarget.onDragExit(mDragObject);
                 }
-                dropTarget.onDragEnter(mDragSource, coordinates[0], coordinates[1],
-                    (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
+                dropTarget.onDragEnter(mDragObject);
             }
-            dropTarget.onDragOver(mDragSource, coordinates[0], coordinates[1],
-                    (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
+            dropTarget.onDragOver(mDragObject);
         } else {
             if (mLastDropTarget != null) {
-                mLastDropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],
-                    (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
+                mLastDropTarget.onDragExit(mDragObject);
             }
         }
         mLastDropTarget = dropTarget;
@@ -578,18 +562,18 @@
         final int[] coordinates = mCoordinatesTemp;
         final DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);
 
+        mDragObject.x = coordinates[0];
+        mDragObject.y = coordinates[1];
         boolean accepted = false;
         if (dropTarget != null) {
-            dropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],
-                    (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
-            if (dropTarget.acceptDrop(mDragSource, coordinates[0], coordinates[1],
-                    (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo)) {
-                dropTarget.onDrop(mDragSource, coordinates[0], coordinates[1],
-                        (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
+            dropTarget.onDragExit(mDragObject);
+            if (dropTarget.acceptDrop(mDragObject)) {
+                dropTarget.onDrop(mDragObject);
                 accepted = true;
             }
         }
-        mDragSource.onDropCompleted((View) dropTarget, mDragInfo, accepted);
+        mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject.dragInfo, accepted);
+
     }
 
     private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {
@@ -608,9 +592,10 @@
             target.getLocationOnScreen(dropCoordinates);
             r.offset(dropCoordinates[0] - target.getLeft(), dropCoordinates[1] - target.getTop());
 
+            mDragObject.x = x;
+            mDragObject.y = y;
             if (r.contains(x, y)) {
-                DropTarget delegate = target.getDropTargetDelegate(mDragSource,
-                        x, y, (int)mTouchOffsetX, (int)mTouchOffsetY, mDragView, mDragInfo);
+                DropTarget delegate = target.getDropTargetDelegate(mDragObject);
                 if (delegate != null) {
                     target = delegate;
                     target.getLocationOnScreen(dropCoordinates);
@@ -701,7 +686,7 @@
     }
 
     DragView getDragView() {
-        return mDragView;
+        return mDragObject.dragView;
     }
 
     private class ScrollRunnable implements Runnable {
diff --git a/src/com/android/launcher2/DropTarget.java b/src/com/android/launcher2/DropTarget.java
index 308dbbe..9c0faf3 100644
--- a/src/com/android/launcher2/DropTarget.java
+++ b/src/com/android/launcher2/DropTarget.java
@@ -23,6 +23,30 @@
  *
  */
 public interface DropTarget {
+
+    class DragObject {
+        public int x = -1;
+        public int y = -1;
+
+        /** X offset from the upper-left corner of the cell to where we touched.  */
+        public int xOffset = -1;
+
+        /** Y offset from the upper-left corner of the cell to where we touched.  */
+        public int yOffset = -1;
+
+        /** The view that moves around while you drag.  */
+        public DragView dragView = null;
+
+        /** The data associated with the object being dragged */
+        public Object dragInfo = null;
+
+        /** Where the drag originated */
+        public DragSource dragSource = null;
+
+        public DragObject() {
+        }
+    }
+
     /**
      * Used to temporarily disable certain drop targets
      *
@@ -44,17 +68,13 @@
      * @param dragInfo Data associated with the object being dragged
      * 
      */
-    void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo);
-    
-    void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo);
+    void onDrop(DragObject dragObject);
 
-    void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo);
+    void onDragEnter(DragObject dragObject);
 
-    void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo);
+    void onDragOver(DragObject dragObject);
+
+    void onDragExit(DragObject dragObject);
 
     /**
      * Allows a DropTarget to delegate drag and drop events to another object.
@@ -73,8 +93,7 @@
      *
      * @return The DropTarget to delegate to, or null to not delegate to another object.
      */
-    DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo);
+    DropTarget getDropTargetDelegate(DragObject dragObject);
 
     /**
      * Check if a drop action can occur at, or near, the requested location.
@@ -91,8 +110,7 @@
      * @param dragInfo Data associated with the object being dragged
      * @return True if the drop will be accepted, false otherwise.
      */
-    boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo);
+    boolean acceptDrop(DragObject dragObject);
 
     // These methods are implemented in Views
     void getHitRect(Rect outRect);
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 0470e41..76e9b35 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -363,25 +363,23 @@
         bind(mInfo);
     }
 
-    public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-        final ItemInfo item = (ItemInfo) dragInfo;
+    public boolean acceptDrop(DragObject d) {
+        final ItemInfo item = (ItemInfo) d.dragInfo;
         final int itemType = item.itemType;
         return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
                     itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
                     !isFull());
     }
 
-    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDrop(DragObject d) {
         ShortcutInfo item;
-        if (dragInfo instanceof ApplicationInfo) {
+        if (d.dragInfo instanceof ApplicationInfo) {
             // Came from all apps -- make a copy
-            item = ((ApplicationInfo)dragInfo).makeShortcut();
+            item = ((ApplicationInfo) d.dragInfo).makeShortcut();
             item.spanX = 1;
             item.spanY = 1;
         } else {
-            item = (ShortcutInfo)dragInfo;
+            item = (ShortcutInfo) d.dragInfo;
         }
         mInfo.add(item);
         LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
@@ -417,19 +415,16 @@
         mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
     }
 
-    public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDragEnter(DragObject d) {
         mContent.onDragEnter();
     }
 
-    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-        float[] r = mapPointFromScreenToContent(x, y, null);
+    public void onDragOver(DragObject d) {
+        float[] r = mapPointFromScreenToContent(d.x, d.y, null);
         mContent.visualizeDropLocation(null, null, (int) r[0], (int) r[1], 1, 1);
     }
 
-    public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDragExit(DragObject d) {
         mContent.onDragExit();
     }
 
@@ -453,8 +448,7 @@
         return true;
     }
 
-    public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public DropTarget getDropTargetDelegate(DragObject d) {
         return null;
     }
 
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index 2a5a5a0..0091a28 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -58,8 +58,6 @@
 
     private int mOriginalWidth = -1;
     private int mOriginalHeight = -1;
-    private int mOriginalX = -1;
-    private int mOriginalY = -1;
 
     private int mFolderLocX;
     private int mFolderLocY;
@@ -121,9 +119,8 @@
                 !mFolder.isFull() && item != mInfo);
     }
 
-    public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-        final ItemInfo item = (ItemInfo) dragInfo;
+    public boolean acceptDrop(DragObject d) {
+        final ItemInfo item = (ItemInfo) d.dragInfo;
         return willAcceptItem(item);
     }
 
@@ -132,14 +129,13 @@
         LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
     }
 
-    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDrop(DragObject d) {
         ShortcutInfo item;
-        if (dragInfo instanceof ApplicationInfo) {
+        if (d.dragInfo instanceof ApplicationInfo) {
             // Came from all apps -- make a copy
-            item = ((ApplicationInfo)dragInfo).makeShortcut();
+            item = ((ApplicationInfo) d.dragInfo).makeShortcut();
         } else {
-            item = (ShortcutInfo)dragInfo;
+            item = (ShortcutInfo) d.dragInfo;
         }
         item.cellX = -1;
         item.cellY = -1;
@@ -149,8 +145,6 @@
     void saveState(CellLayout.LayoutParams lp) {
         mOriginalWidth = lp.width;
         mOriginalHeight = lp.height;
-        mOriginalX = lp.x;
-        mOriginalY = lp.y;
     }
 
     private void animateToAcceptState() {
@@ -213,27 +207,22 @@
         mFolderLocY = tvLocation[1] - wsLocation[1] + getMeasuredHeight() / 2;
     }
 
-    public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-        if (!willAcceptItem((ItemInfo) dragInfo)) return;
+    public void onDragEnter(DragObject d) {
+        if (!willAcceptItem((ItemInfo) d.dragInfo)) return;
         determineFolderLocationInWorkspace();
         mLauncher.getWorkspace().showFolderAccept(this);
         animateToAcceptState();
     }
 
-    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDragOver(DragObject d) {
     }
 
-    public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-        if (!willAcceptItem((ItemInfo) dragInfo)) return;
+    public void onDragExit(DragObject d) {
+        if (!willAcceptItem((ItemInfo) d.dragInfo)) return;
         animateToNaturalState();
     }
 
-    @Override
-    public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public DropTarget getDropTargetDelegate(DragObject d) {
         return null;
     }
 
diff --git a/src/com/android/launcher2/IconDropTarget.java b/src/com/android/launcher2/IconDropTarget.java
index 4d018e6..a091f6c 100644
--- a/src/com/android/launcher2/IconDropTarget.java
+++ b/src/com/android/launcher2/IconDropTarget.java
@@ -82,32 +82,27 @@
         mDragAndDropEnabled = enabled;
     }
 
-    public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public boolean acceptDrop(DragObject d) {
         return false;
     }
 
-    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDrop(DragObject d) {
         // Do nothing
     }
 
-    public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDragEnter(DragObject d) {
         if (mDragAndDropEnabled) {
-            dragView.setPaint(mHoverPaint);
+            d.dragView.setPaint(mHoverPaint);
         }
     }
 
-    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDragOver(DragObject d) {
         // Do nothing
     }
 
-    public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDragExit(DragObject d) {
         if (mDragAndDropEnabled) {
-            dragView.setPaint(null);
+            d.dragView.setPaint(null);
         }
     }
 
@@ -135,8 +130,7 @@
     }
 
     @Override
-    public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset,
-            int yOffset, DragView dragView, Object dragInfo) {
+    public DropTarget getDropTargetDelegate(DragObject d) {
         return null;
     }
 }
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 9dfed69..2a16e99 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -933,6 +933,7 @@
         if (mCustomizePagedView != null) {
             mCustomizePagedView.setLauncher(this);
             mCustomizePagedView.setDragController(dragController);
+            mCustomizePagedView.setAllAppsPagedView(mAllAppsPagedView);
         } else {
              ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left);
              hotseatLeft.setContentDescription(mHotseatLabels[0]);
@@ -3211,7 +3212,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) {
+        if (activityName != null && LauncherApplication.isScreenLarge()) {
             mAppMarketIntent = intent;
             sAppMarketIcon = updateTextButtonWithIconFromExternalActivity(
                     R.id.market_button, activityName, R.drawable.app_market_generic);
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 1180106..bd41e02 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -113,8 +113,8 @@
     protected int mPageLayoutWidthGap;
     protected int mPageLayoutHeightGap;
     protected int mPageLayoutMaxHeight;
-    protected int mCellCountX;
-    protected int mCellCountY;
+    protected int mCellCountX = -1;
+    protected int mCellCountY = -1;
     protected boolean mCenterPagesVertically;
     protected boolean mAllowOverScroll = true;
     protected int mUnboundedScrollX;
@@ -1549,7 +1549,7 @@
      */
     public abstract void syncPageItems(int page);
 
-    public void invalidatePageData() {
+    protected void invalidatePageData() {
         if (mContentIsRefreshable) {
             // Update all the pages
             syncPages();
diff --git a/src/com/android/launcher2/PagedViewCellLayout.java b/src/com/android/launcher2/PagedViewCellLayout.java
index 9022cac..0ae7a59 100644
--- a/src/com/android/launcher2/PagedViewCellLayout.java
+++ b/src/com/android/launcher2/PagedViewCellLayout.java
@@ -79,6 +79,14 @@
         addView(mHolographicChildren);
     }
 
+    public int getCellWidth() {
+        return mCellWidth;
+    }
+
+    public int getCellHeight() {
+        return mCellHeight;
+    }
+
     public void allowHardwareLayerCreation() {
         // This is called after the first time we launch into All Apps. Before that point,
         // there's no need for hardware layers here since there's a hardware layer set on the
@@ -278,11 +286,17 @@
     }
 
     int getContentHeight() {
-        return mCellCountY * mCellHeight + (mCellCountY - 1) * Math.max(0, mHeightGap);
+        if (mCellCountY > 0) {
+            return mCellCountY * mCellHeight + (mCellCountY - 1) * Math.max(0, mHeightGap);
+        }
+        return 0;
     }
 
     int getWidthBeforeFirstLayout() {
-        return mCellCountX * mCellWidth + (mCellCountX - 1) * Math.max(0, mWidthGap);
+        if (mCellCountX > 0) {
+            return mCellCountX * mCellWidth + (mCellCountX - 1) * Math.max(0, mWidthGap);
+        }
+        return 0;
     }
 
     @Override
diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java
index 306ff9e..30f0b1d 100644
--- a/src/com/android/launcher2/PagedViewIcon.java
+++ b/src/com/android/launcher2/PagedViewIcon.java
@@ -31,7 +31,6 @@
 import android.os.Message;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
-import android.view.View;
 import android.widget.Checkable;
 
 import com.android.launcher.R;
diff --git a/src/com/android/launcher2/ShortcutsAdapter.java b/src/com/android/launcher2/ShortcutsAdapter.java
deleted file mode 100644
index de73c3e..0000000
--- a/src/com/android/launcher2/ShortcutsAdapter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2008 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 java.util.ArrayList;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
-
-import com.android.launcher.R;
-
-/**
- * GridView adapter to show the list of applications and shortcuts
- */
-public class ShortcutsAdapter extends ArrayAdapter<ShortcutInfo> {
-    private final LayoutInflater mInflater;
-    private final IconCache mIconCache;
-
-    public ShortcutsAdapter(Context context, ArrayList<ShortcutInfo> apps) {
-        super(context, 0, apps);
-        mInflater = LayoutInflater.from(context);
-        mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        final ShortcutInfo info = getItem(position);
-
-        if (convertView == null) {
-            convertView = mInflater.inflate(R.layout.application_boxed, parent, false);
-        }
-
-        final TextView textView = (TextView) convertView;
-        textView.setCompoundDrawablesWithIntrinsicBounds(null,
-                new FastBitmapDrawable(info.getIcon(mIconCache)), null, null);
-        textView.setText(info.title);
-
-        return convertView;
-    }
-}
diff --git a/src/com/android/launcher2/Utilities.java b/src/com/android/launcher2/Utilities.java
index ba25893..04abd77 100644
--- a/src/com/android/launcher2/Utilities.java
+++ b/src/com/android/launcher2/Utilities.java
@@ -68,28 +68,6 @@
         sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
                 Paint.FILTER_BITMAP_FLAG));
     }
-
-    static Bitmap centerToFit(Bitmap bitmap, int width, int height, Context context) {
-        final int bitmapWidth = bitmap.getWidth();
-        final int bitmapHeight = bitmap.getHeight();
-
-        if (bitmapWidth < width || bitmapHeight < height) {
-            int color = context.getResources().getColor(R.color.window_background);
-
-            Bitmap centered = Bitmap.createBitmap(bitmapWidth < width ? width : bitmapWidth,
-                    bitmapHeight < height ? height : bitmapHeight, Bitmap.Config.RGB_565);
-            centered.setDensity(bitmap.getDensity());
-            Canvas canvas = new Canvas(centered);
-            canvas.drawColor(color);
-            canvas.drawBitmap(bitmap, (width - bitmapWidth) / 2.0f, (height - bitmapHeight) / 2.0f,
-                    null);
-
-            bitmap = centered;
-        }
-
-        return bitmap;
-    }
-
     static int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
     static int sColorIndex = 0;
 
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index bc15b32..7d2626d 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -80,10 +80,6 @@
     @SuppressWarnings({"UnusedDeclaration"})
     private static final String TAG = "Launcher.Workspace";
 
-    // This is how much the workspace shrinks when we enter all apps or
-    // customization mode
-    private static final float SHRINK_FACTOR = 0.16f;
-
     // How much the screens shrink when we enter spring loaded drag mode
     private static final float SPRING_LOADED_DRAG_SHRINK_FACTOR = 0.7f;
 
@@ -1512,12 +1508,15 @@
         final int screenWidth = getWidth();
         final int screenHeight = getHeight();
 
+        // How much the workspace shrinks when we enter all apps or customization mode
+        final float shrinkFactor = res.getInteger(R.integer.config_workspaceShrinkPercent) / 100.0f;
+
         // Making the assumption that all pages have the same width as the 0th
         final int pageWidth = getChildAt(0).getMeasuredWidth();
         final int pageHeight = getChildAt(0).getMeasuredHeight();
 
-        final int scaledPageWidth = (int) (SHRINK_FACTOR * pageWidth);
-        final int scaledPageHeight = (int) (SHRINK_FACTOR * pageHeight);
+        final int scaledPageWidth = (int) (shrinkFactor * pageWidth);
+        final int scaledPageHeight = (int) (shrinkFactor * pageHeight);
         final float extraScaledSpacing = res.getDimension(R.dimen.smallScreenExtraSpacing);
 
         final int screenCount = getChildCount();
@@ -1568,20 +1567,21 @@
 
         mAnimator = new AnimatorSet();
 
-        final float[] oldXs = new float[getChildCount()];
-        final float[] oldYs = new float[getChildCount()];
-        final float[] oldScaleXs = new float[getChildCount()];
-        final float[] oldScaleYs = new float[getChildCount()];
-        final float[] oldBackgroundAlphas = new float[getChildCount()];
-        final float[] oldAlphas = new float[getChildCount()];
-        final float[] oldRotationYs = new float[getChildCount()];
-        final float[] newXs = new float[getChildCount()];
-        final float[] newYs = new float[getChildCount()];
-        final float[] newScaleXs = new float[getChildCount()];
-        final float[] newScaleYs = new float[getChildCount()];
-        final float[] newBackgroundAlphas = new float[getChildCount()];
-        final float[] newAlphas = new float[getChildCount()];
-        final float[] newRotationYs = new float[getChildCount()];
+        final int childCount = getChildCount();
+        final float[] oldXs = new float[childCount];
+        final float[] oldYs = new float[childCount];
+        final float[] oldScaleXs = new float[childCount];
+        final float[] oldScaleYs = new float[childCount];
+        final float[] oldBackgroundAlphas = new float[childCount];
+        final float[] oldAlphas = new float[childCount];
+        final float[] oldRotationYs = new float[childCount];
+        final float[] newXs = new float[childCount];
+        final float[] newYs = new float[childCount];
+        final float[] newScaleXs = new float[childCount];
+        final float[] newScaleYs = new float[childCount];
+        final float[] newBackgroundAlphas = new float[childCount];
+        final float[] newAlphas = new float[childCount];
+        final float[] newRotationYs = new float[childCount];
 
         for (int i = 0; i < screenCount; i++) {
             final CellLayout cl = (CellLayout) getChildAt(i);
@@ -1606,15 +1606,15 @@
                 oldRotationYs[i] = cl.getRotationY();
                 newXs[i] = x;
                 newYs[i] = y;
-                newScaleXs[i] = SHRINK_FACTOR * rotationScaleX * extraShrinkFactor;
-                newScaleYs[i] = SHRINK_FACTOR * rotationScaleY * extraShrinkFactor;
+                newScaleXs[i] = shrinkFactor * rotationScaleX * extraShrinkFactor;
+                newScaleYs[i] = shrinkFactor * rotationScaleY * extraShrinkFactor;
                 newBackgroundAlphas[i] = finalAlpha;
                 newRotationYs[i] = rotation;
             } else {
                 cl.setX((int)x);
                 cl.setY((int)y);
-                cl.setScaleX(SHRINK_FACTOR * rotationScaleX * extraShrinkFactor);
-                cl.setScaleY(SHRINK_FACTOR * rotationScaleY * extraShrinkFactor);
+                cl.setScaleX(shrinkFactor * rotationScaleX * extraShrinkFactor);
+                cl.setScaleY(shrinkFactor * rotationScaleY * extraShrinkFactor);
                 cl.setBackgroundAlpha(finalAlpha);
                 cl.setAlpha(finalAlpha);
                 cl.setRotationY(rotation);
@@ -2379,11 +2379,10 @@
     /**
      * {@inheritDoc}
      */
-    public boolean acceptDrop(DragSource source, int x, int y,
-            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
+    public boolean acceptDrop(DragObject d) {
 
         // If it's an external drop (e.g. from All Apps), check if it should be accepted
-        if (source != this) {
+        if (d.dragSource != this) {
             // Don't accept the drop if we're not over a screen at time of drop
             if (mDragTargetLayout == null || !mDragTargetLayout.getAcceptsDrops()) {
                 return false;
@@ -2469,10 +2468,9 @@
         return false;
     }
 
-    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDrop(DragObject d) {
 
-        mDragViewVisualCenter = getDragViewVisualCenter(x, y, xOffset, yOffset, dragView,
+        mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView,
                 mDragViewVisualCenter);
 
         // We want the point to be mapped to the dragTarget.
@@ -2489,17 +2487,17 @@
             }
         }
 
-        if (source != this) {
+        if (d.dragSource != this) {
             final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
                     (int) mDragViewVisualCenter[1] };
             if (LauncherApplication.isScreenLarge() && (mIsSmall || mIsInUnshrinkAnimation)
                     && !mLauncher.isAllAppsVisible()) {
                 // When the workspace is shrunk and the drop comes from customize, don't actually
                 // add the item to the screen -- customize will do this itself
-                ((ItemInfo) dragInfo).dropPos = touchXY;
+                ((ItemInfo) d.dragInfo).dropPos = touchXY;
                 return;
             }
-            onDropExternal(touchXY, dragInfo, mDragTargetLayout, false, dragView);
+            onDropExternal(touchXY, d.dragInfo, mDragTargetLayout, false, d.dragView);
         } else if (mDragInfo != null) {
             final View cell = mDragInfo.cell;
             CellLayout dropTargetLayout = mDragTargetLayout;
@@ -2592,11 +2590,11 @@
             final CellLayout parent = (CellLayout) cell.getParent().getParent();
 
             int loc[] = new int[2];
-            getViewLocationRelativeToSelf(dragView, loc);
+            getViewLocationRelativeToSelf(d.dragView, loc);
 
             // Prepare it to be animated into its new position
             // This must be called after the view has been re-parented
-            setPositionForDropAnimation(dragView, loc[0], loc[1], parent, cell);
+            setPositionForDropAnimation(d.dragView, loc[0], loc[1], parent, cell);
             boolean animateDrop = !mWasSpringLoadedOnDragExit;
             parent.onDropChild(cell, animateDrop);
         }
@@ -2615,8 +2613,7 @@
         location[1] = vY - y;
     }
 
-    public void onDragEnter(DragSource source, int x, int y, int xOffset,
-            int yOffset, DragView dragView, Object dragInfo) {
+    public void onDragEnter(DragObject d) {
         mDragTargetLayout = null; // Reset the drag state
 
         if (!mIsSmall) {
@@ -2626,8 +2623,7 @@
         }
     }
 
-    public DropTarget getDropTargetDelegate(DragSource source, int x, int y,
-            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
+    public DropTarget getDropTargetDelegate(DragObject d) {
 
         if (mIsSmall || mIsInUnshrinkAnimation) {
             // If we're shrunken, don't let anyone drag on folders/etc that are on the mini-screens
@@ -2637,18 +2633,18 @@
         // would land in a cell occupied by a DragTarget (e.g. a Folder),
         // then drag events should be handled by that child.
 
-        ItemInfo item = (ItemInfo) dragInfo;
+        ItemInfo item = (ItemInfo) d.dragInfo;
         CellLayout currentLayout = getCurrentDropLayout();
 
         int dragPointX, dragPointY;
         if (item.spanX == 1 && item.spanY == 1) {
             // For a 1x1, calculate the drop cell exactly as in onDragOver
-            dragPointX = x - xOffset;
-            dragPointY = y - yOffset;
+            dragPointX = d.x - d.xOffset;
+            dragPointY = d.y - d.yOffset;
         } else {
             // Otherwise, use the exact drag coordinates
-            dragPointX = x;
-            dragPointY = y;
+            dragPointX = d.x;
+            dragPointY = d.y;
         }
         dragPointX += mScrollX - currentLayout.getLeft();
         dragPointY += mScrollY - currentLayout.getTop();
@@ -2660,7 +2656,7 @@
         View child = currentLayout.getChildAt(cellXY[0], cellXY[1]);
         if (child instanceof DropTarget) {
             DropTarget target = (DropTarget)child;
-            if (target.acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
+            if (target.acceptDrop(d)) {
                 return target;
             }
         }
@@ -2977,25 +2973,24 @@
         return res;
     }
 
-    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
+    public void onDragOver(DragObject d) {
         // When touch is inside the scroll area, skip dragOver actions for the current screen
         if (!mInScrollArea) {
             CellLayout layout;
-            int left = x - xOffset;
-            int top = y - yOffset;
+            int left = d.x - d.xOffset;
+            int top = d.y - d.yOffset;
 
-            mDragViewVisualCenter = getDragViewVisualCenter(x, y, xOffset, yOffset, dragView,
-                    mDragViewVisualCenter);
+            mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset,
+                    d.dragView, mDragViewVisualCenter);
 
             boolean shrunken = mIsSmall || mIsInUnshrinkAnimation;
             if (shrunken) {
-                mLastDragView = dragView;
+                mLastDragView = d.dragView;
                 mLastDragOriginX = left;
                 mLastDragOriginY = top;
-                mLastDragXOffset = xOffset;
-                mLastDragYOffset = yOffset;
-                layout = findMatchingPageForDragOver(dragView, left, top, xOffset, yOffset);
+                mLastDragXOffset = d.xOffset;
+                mLastDragYOffset = d.yOffset;
+                layout = findMatchingPageForDragOver(d.dragView, left, top, d.xOffset, d.yOffset);
 
                 if (layout != null && layout != mDragTargetLayout) {
                     if (mDragTargetLayout != null) {
@@ -3033,9 +3028,9 @@
             if (!shrunken || mShrinkState == ShrinkState.SPRING_LOADED) {
                 layout = getCurrentDropLayout();
 
-                final ItemInfo item = (ItemInfo)dragInfo;
-                if (dragInfo instanceof LauncherAppWidgetInfo) {
-                    LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
+                final ItemInfo item = (ItemInfo) d.dragInfo;
+                if (d.dragInfo instanceof LauncherAppWidgetInfo) {
+                    LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) d.dragInfo;
 
                     if (widgetInfo.spanX == -1) {
                         // Calculate the grid spans needed to fit this widget
@@ -3050,7 +3045,7 @@
                     final View child = (mDragInfo == null) ? null : mDragInfo.cell;
                     // We want the point to be mapped to the dragTarget.
                     mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
-                    ItemInfo info = (ItemInfo) dragInfo;
+                    ItemInfo info = (ItemInfo) d.dragInfo;
 
                     if (!willCreateUserFolder(info, mDragTargetLayout,
                             (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1])) {
@@ -3082,8 +3077,7 @@
         clearAllHovers();
     }
 
-    public void onDragExit(DragSource source, int x, int y, int xOffset,
-            int yOffset, DragView dragView, Object dragInfo) {
+    public void onDragExit(DragObject d) {
         doDragExit();
     }