Initial changes to merged AllApps/Customize pane in the Phone UI.

Change-Id: Ifa1676736033fe617dd0cca965156c38fa452948
diff --git a/src/com/android/launcher2/AccessibleTabView.java b/src/com/android/launcher2/AccessibleTabView.java
index a419911..101f139 100644
--- a/src/com/android/launcher2/AccessibleTabView.java
+++ b/src/com/android/launcher2/AccessibleTabView.java
@@ -21,6 +21,9 @@
 import android.view.KeyEvent;
 import android.widget.TextView;
 
+/**
+ * We use a custom tab view to process our own focus traversals.
+ */
 public class AccessibleTabView extends TextView {
     public AccessibleTabView(Context context) {
         super(context);
diff --git a/src/com/android/launcher2/AllApps2D.java b/src/com/android/launcher2/AllApps2D.java
index 854c1ee..44af7b7 100644
--- a/src/com/android/launcher2/AllApps2D.java
+++ b/src/com/android/launcher2/AllApps2D.java
@@ -158,8 +158,10 @@
         this(context, attrs);
     }
 
-    public void setLauncher(Launcher launcher) {
+    @Override
+    public void setup(Launcher launcher, DragController dragController) {
         mLauncher = launcher;
+        mDragController = dragController;
     }
 
     public boolean onKey(View v, int keyCode, KeyEvent event) {
@@ -202,11 +204,6 @@
     }
 
     @Override
-    public void setDragController(DragController dragger) {
-        mDragController = dragger;
-    }
-
-    @Override
     public void onDragViewVisible() {
     }
 
diff --git a/src/com/android/launcher2/AllApps3D.java b/src/com/android/launcher2/AllApps3D.java
index a8aea18..4990254 100644
--- a/src/com/android/launcher2/AllApps3D.java
+++ b/src/com/android/launcher2/AllApps3D.java
@@ -208,8 +208,10 @@
         setSoundEffectsEnabled(old);
     }
 
-    public void setLauncher(Launcher launcher) {
+    @Override
+    public void setup(Launcher launcher, DragController dragController) {
         mLauncher = launcher;
+        mDragController = dragController;
     }
 
     @Override
@@ -739,11 +741,6 @@
     }
 
     @Override
-    public void setDragController(DragController dragger) {
-        mDragController = dragger;
-    }
-
-    @Override
     public void onDragViewVisible() {
     }
 
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index 3d3c1ff..7af5392 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -90,7 +90,7 @@
 
         Resources r = context.getResources();
         setDragSlopeThreshold(
-                r.getInteger(R.integer.config_allAppsDrawerDragSlopeThreshold) / 100.0f);
+                r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold) / 100.0f);
 
         // Create a dummy page and set it up to find out the content width (used by our parent)
         PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
@@ -121,14 +121,10 @@
     }
 
     @Override
-    public void setLauncher(Launcher launcher) {
+    public void setup(Launcher launcher, DragController dragController) {
         mLauncher = launcher;
         mLauncher.setAllAppsPagedView(this);
-    }
-
-    @Override
-    public void setDragController(DragController dragger) {
-        mDragController = dragger;
+        mDragController = dragController;
     }
 
     public void setAppFilter(int filterType) {
diff --git a/src/com/android/launcher2/AllAppsTabbed.java b/src/com/android/launcher2/AllAppsTabbed.java
index 2deec8e..96de5a7 100644
--- a/src/com/android/launcher2/AllAppsTabbed.java
+++ b/src/com/android/launcher2/AllAppsTabbed.java
@@ -103,7 +103,7 @@
             public void onTabChanged(String tabId) {
                 // 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_tabTransitionTime);
+                final int duration = res.getInteger(R.integer.config_tabTransitionDuration);
                 final float alpha = mAllApps.getAlpha();
                 ValueAnimator alphaAnim = ObjectAnimator.ofFloat(mAllApps, "alpha", alpha, 0.0f).
                         setDuration(duration);
@@ -143,14 +143,9 @@
     }
 
     @Override
-    public void setLauncher(Launcher launcher) {
-        mAllApps.setLauncher(launcher);
+    public void setup(Launcher launcher, DragController dragController) {
         mLauncher = launcher;
-    }
-
-    @Override
-    public void setDragController(DragController dragger) {
-        mAllApps.setDragController(dragger);
+        mAllApps.setup(launcher, dragController);
     }
 
     @Override
diff --git a/src/com/android/launcher2/AllAppsView.java b/src/com/android/launcher2/AllAppsView.java
index 3a74c71..e8ca61f 100644
--- a/src/com/android/launcher2/AllAppsView.java
+++ b/src/com/android/launcher2/AllAppsView.java
@@ -23,9 +23,7 @@
         public void zoomed(float zoom);
     }
 
-    public void setLauncher(Launcher launcher);
-
-    public void setDragController(DragController dragger);
+    public void setup(Launcher launcher, DragController dragController);
 
     public void zoom(float zoom, boolean animate);
 
diff --git a/src/com/android/launcher2/ApplicationInfoDropTarget.java b/src/com/android/launcher2/ApplicationInfoDropTarget.java
index 78a9d2d..ce359d4 100644
--- a/src/com/android/launcher2/ApplicationInfoDropTarget.java
+++ b/src/com/android/launcher2/ApplicationInfoDropTarget.java
@@ -162,10 +162,13 @@
         // Fade in the overlapping views
         if (mOverlappingViews != null) {
             for (View view : mOverlappingViews) {
-                ObjectAnimator oa = ObjectAnimator.ofFloat(view, "alpha", 1.0f);
-                oa.setDuration(sFadeInAnimationDuration);
-                mFadeAnimator.play(oa);
-                view.setVisibility(VISIBLE);
+                // Check whether the views are enabled first, before trying to fade them in
+                if (view.isEnabled()) {
+                    ObjectAnimator oa = ObjectAnimator.ofFloat(view, "alpha", 1.0f);
+                    oa.setDuration(sFadeInAnimationDuration);
+                    mFadeAnimator.play(oa);
+                    view.setVisibility(VISIBLE);
+                }
             }
         }
         mFadeAnimator.start();
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
new file mode 100644
index 0000000..6dc34ca
--- /dev/null
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Checkable;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.launcher.R;
+
+public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
+        AllAppsView, View.OnClickListener, DragSource {
+    static final String LOG_TAG = "AppsCustomizePagedView";
+
+    /**
+     * The different content types that this paged view can show.
+     */
+    public enum ContentType {
+        Applications,
+        Widgets
+    }
+
+    // Refs
+    private Launcher mLauncher;
+    private DragController mDragController;
+    private final LayoutInflater mLayoutInflater;
+    private final PackageManager mPackageManager;
+
+    // Content
+    private ContentType mContentType;
+    private ArrayList<ApplicationInfo> mApps;
+    private List<AppWidgetProviderInfo> mWidgets;
+    private List<ResolveInfo> mShortcuts;
+
+    // Dimens
+    private int mContentWidth;
+    private float mWidgetScale;
+    private PagedViewCellLayout mWidgetSpacingLayout;
+
+    public AppsCustomizePagedView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mLayoutInflater = LayoutInflater.from(context);
+        mPackageManager = context.getPackageManager();
+        mContentType = ContentType.Applications;
+        mApps = new ArrayList<ApplicationInfo>();
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, 0, 0);
+        mCellCountX = a.getInt(R.styleable.PagedView_cellCountX, 6);
+        mCellCountY = a.getInt(R.styleable.PagedView_cellCountY, 4);
+        a.recycle();
+
+        // Create a dummy page and set it up to find out the content width (used by our parent)
+        PagedViewCellLayout layout = new PagedViewCellLayout(context);
+        setupPage(layout);
+        mContentWidth = layout.getContentWidth();
+
+        // Create a dummy page that we can use to approximate the cell dimensions of widgets
+        mWidgetSpacingLayout = new PagedViewCellLayout(context);
+        mWidgetSpacingLayout.setCellCount(mCellCountX, mCellCountY);
+    }
+
+    @Override
+    protected void init() {
+        super.init();
+        mCenterPagesVertically = false;
+
+        Context context = getContext();
+        Resources r = context.getResources();
+        setDragSlopeThreshold(r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold)/100f);
+    }
+
+    public void onPackagesUpdated() {
+        // Get the list of widgets
+        mWidgets = AppWidgetManager.getInstance(mLauncher).getInstalledProviders();
+        Collections.sort(mWidgets, LauncherModel.WIDGET_NAME_COMPARATOR);
+
+        // Get the list of shortcuts
+        Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
+        mShortcuts = mPackageManager.queryIntentActivities(shortcutsIntent, 0);
+        Collections.sort(mShortcuts, new LauncherModel.ShortcutNameComparator(mPackageManager));
+    }
+
+    @Override
+    public void onClick(View v) {
+        // Animate some feedback to the click
+        final ApplicationInfo appInfo = (ApplicationInfo) v.getTag();
+        animateClickFeedback(v, new Runnable() {
+            @Override
+            public void run() {
+                mLauncher.startActivitySafely(appInfo.intent, appInfo);
+            }
+        });
+    }
+
+    /*
+     * PagedViewWithDraggableItems implementation
+     */
+    @Override
+    protected void determineDraggingStart(android.view.MotionEvent ev) {
+        // Disable dragging by pulling an app down for now.
+    }
+    @Override
+    protected boolean beginDragging(View v) {
+        if (!super.beginDragging(v)) return false;
+
+        // Make a copy of the ApplicationInfo
+        ApplicationInfo appInfo = new ApplicationInfo((ApplicationInfo) v.getTag());
+
+        // Show the uninstall button if the app is uninstallable.
+        if ((appInfo.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) {
+            DeleteZone allAppsDeleteZone = (DeleteZone)
+                    mLauncher.findViewById(R.id.all_apps_delete_zone);
+            allAppsDeleteZone.setDragAndDropEnabled(true);
+
+            if ((appInfo.flags & ApplicationInfo.UPDATED_SYSTEM_APP_FLAG) != 0) {
+                allAppsDeleteZone.setText(R.string.delete_zone_label_all_apps_system_app);
+            } else {
+                allAppsDeleteZone.setText(R.string.delete_zone_label_all_apps);
+            }
+        }
+
+        // Show the info button
+        ApplicationInfoDropTarget allAppsInfoButton =
+            (ApplicationInfoDropTarget) mLauncher.findViewById(R.id.all_apps_info_target);
+        allAppsInfoButton.setDragAndDropEnabled(true);
+
+        // Compose the drag image (top compound drawable, index is 1)
+        final TextView tv = (TextView) v;
+        final Drawable icon = tv.getCompoundDrawables()[1];
+        Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(),
+                Bitmap.Config.ARGB_8888);
+        Canvas c = new Canvas(b);
+        c.translate((v.getWidth() - icon.getIntrinsicWidth()) / 2, v.getPaddingTop());
+        icon.draw(c);
+
+        // Compose the visible rect of the drag image
+        Rect dragRect = null;
+        if (v instanceof TextView) {
+            int iconSize = getResources().getDimensionPixelSize(R.dimen.app_icon_size);
+            int top = v.getPaddingTop();
+            int left = (b.getWidth() - iconSize) / 2;
+            int right = left + iconSize;
+            int bottom = top + iconSize;
+            dragRect = new Rect(left, top, right, bottom);
+        }
+
+        // Start the drag
+        mLauncher.lockScreenOrientation();
+        mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
+        mDragController.startDrag(v, b, this, appInfo, DragController.DRAG_ACTION_COPY, dragRect);
+        b.recycle();
+
+        // Hide the pane so that the user can drop onto the workspace
+        mLauncher.showWorkspace(true);
+        return true;
+    }
+    private void endDragging(boolean success) {
+        post(new Runnable() {
+            // Once the drag operation has fully completed, hence the post, we want to disable the
+            // deleteZone and the appInfoButton in all apps, and re-enable the instance which
+            // live in the workspace
+            public void run() {
+                // if onDestroy was called on Launcher, we might have already deleted the
+                // all apps delete zone / info button, so check if they are null
+                DeleteZone allAppsDeleteZone =
+                        (DeleteZone) mLauncher.findViewById(R.id.all_apps_delete_zone);
+                ApplicationInfoDropTarget allAppsInfoButton =
+                    (ApplicationInfoDropTarget) mLauncher.findViewById(R.id.all_apps_info_target);
+
+                if (allAppsDeleteZone != null) allAppsDeleteZone.setDragAndDropEnabled(false);
+                if (allAppsInfoButton != null) allAppsInfoButton.setDragAndDropEnabled(false);
+            }
+        });
+        mLauncher.getWorkspace().onDragStopped(success);
+        mLauncher.unlockScreenOrientation();
+    }
+
+    /*
+     * DragSource implementation
+     */
+    @Override
+    public void onDragViewVisible() {}
+    @Override
+    public void onDropCompleted(View target, Object dragInfo, boolean success) {
+        endDragging(success);
+    }
+
+    public void setContentType(ContentType type) {
+        mContentType = type;
+        setCurrentPage(0);
+        invalidatePageData();
+    }
+
+    /*
+     * Apps PagedView implementation
+     */
+    private void setupPage(PagedViewCellLayout layout) {
+        layout.setCellCount(mCellCountX, mCellCountY);
+        layout.setGap(mPageLayoutWidthGap, mPageLayoutHeightGap);
+        layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
+                mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
+
+        // We force a measure here to get around the fact that when we do layout calculations
+        // immediately after syncing, we don't have a proper width.
+        int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
+        int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
+        layout.measure(widthSpec, heightSpec);
+    }
+    public void syncAppsPages() {
+        // Ensure that we have the right number of pages
+        Context context = getContext();
+        int numPages = (int) Math.ceil((float) mApps.size() / (mCellCountX * mCellCountY));
+        for (int i = 0; i < numPages; ++i) {
+            PagedViewCellLayout layout = new PagedViewCellLayout(context);
+            setupPage(layout);
+            addView(layout);
+        }
+    }
+    public void syncAppsPageItems(int page) {
+        // ensure that we have the right number of items on the pages
+        int numPages = getPageCount();
+        int numCells = mCellCountX * mCellCountY;
+        int startIndex = page * numCells;
+        int endIndex = Math.min(startIndex + numCells, mApps.size());
+        PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(page);
+        layout.removeAllViewsOnPage();
+        for (int i = startIndex; i < endIndex; ++i) {
+            ApplicationInfo info = mApps.get(i);
+            PagedViewIcon icon = (PagedViewIcon) mLayoutInflater.inflate(
+                    R.layout.apps_customize_application, layout, false);
+            icon.applyFromApplicationInfo(info, mPageViewIconCache, true, (numPages > 1));
+            icon.setOnClickListener(this);
+            icon.setOnLongClickListener(this);
+            icon.setOnTouchListener(this);
+
+            int index = i - startIndex;
+            int x = index % mCellCountX;
+            int y = index / mCellCountX;
+            setupPage(layout);
+            layout.addViewToCellLayout(icon, -1, i, new PagedViewCellLayout.LayoutParams(x,y, 1,1));
+        }
+    }
+    /*
+     * Widgets PagedView implementation
+     */
+    private void setupPage(PagedViewExtendedLayout layout) {
+        layout.setGravity(Gravity.LEFT);
+        layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
+                mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
+        layout.setMinimumWidth(getPageContentWidth());
+    }
+    private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h,
+            float scaleX, float scaleY) {
+        Canvas c = new Canvas();
+        if (bitmap != null) c.setBitmap(bitmap);
+        c.save();
+        c.scale(scaleX, scaleY);
+        Rect oldBounds = d.copyBounds();
+        d.setBounds(x, y, x + w, y + h);
+        d.draw(c);
+        d.setBounds(oldBounds); // Restore the bounds
+        c.restore();
+    }
+    private FastBitmapDrawable getWidgetPreview(AppWidgetProviderInfo info) {
+        // See CustomizePagedView.getWidgetPreview()
+        return null;
+    }
+    public void syncWidgetPages() {
+        // Ensure that we have the right number of pages
+        Context context = getContext();
+        int numPages = mWidgets.size();
+        for (int i = 0; i < numPages; ++i) {
+            PagedViewExtendedLayout layout = new PagedViewExtendedLayout(context);
+            setupPage(layout);
+            addView(layout);
+        }
+    }
+    public void syncWidgetPageItems(int page) {
+        PagedViewExtendedLayout layout = (PagedViewExtendedLayout) getChildAt(page);
+        layout.removeAllViewsOnPage();
+        for (int i = 0; i < 1; ++i) {
+            AppWidgetProviderInfo info = (AppWidgetProviderInfo) mWidgets.get(page);
+            FastBitmapDrawable icon = getWidgetPreview(info);
+
+            ImageView image = new ImageView(getContext());
+            image.setBackgroundColor(0x99FF0000);
+            image.setImageDrawable(icon);
+            layout.addView(image, new PagedViewExtendedLayout.LayoutParams());
+        }
+    }
+    @Override
+    public void syncPages() {
+        removeAllViews();
+        switch (mContentType) {
+        case Applications:
+            syncAppsPages();
+            break;
+        case Widgets:
+            syncWidgetPages();
+            break;
+        }
+    }
+    @Override
+    public void syncPageItems(int page) {
+        switch (mContentType) {
+        case Applications:
+            syncAppsPageItems(page);
+            break;
+        case Widgets:
+            syncWidgetPageItems(page);
+            break;
+        }
+    }
+
+    /**
+     * Used by the parent to get the content width to set the tab bar to
+     * @return
+     */
+    public int getPageContentWidth() {
+        return mContentWidth;
+    }
+
+    /*
+     * AllAppsView implementation
+     */
+    @Override
+    public void setup(Launcher launcher, DragController dragController) {
+        mLauncher = launcher;
+        mDragController = dragController;
+    }
+    @Override
+    public void zoom(float zoom, boolean animate) {
+        // TODO-APPS_CUSTOMIZE: Call back to mLauncher.zoomed()
+    }
+    @Override
+    public boolean isVisible() {
+        return (getVisibility() == VISIBLE);
+    }
+    @Override
+    public boolean isAnimating() {
+        return false;
+    }
+    @Override
+    public void setApps(ArrayList<ApplicationInfo> list) {
+        mApps = list;
+        Collections.sort(mApps, LauncherModel.APP_NAME_COMPARATOR);
+        invalidatePageData();
+    }
+    private void addAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
+        // We add it in place, in alphabetical order
+        int count = list.size();
+        for (int i = 0; i < count; ++i) {
+            ApplicationInfo info = list.get(i);
+            int index = Collections.binarySearch(mApps, info, LauncherModel.APP_NAME_COMPARATOR);
+            if (index < 0) {
+                mApps.add(-(index + 1), info);
+            }
+        }
+    }
+    @Override
+    public void addApps(ArrayList<ApplicationInfo> list) {
+        addAppsWithoutInvalidate(list);
+        invalidatePageData();
+    }
+    private int findAppByComponent(List<ApplicationInfo> list, ApplicationInfo item) {
+        ComponentName removeComponent = item.intent.getComponent();
+        int length = list.size();
+        for (int i = 0; i < length; ++i) {
+            ApplicationInfo info = list.get(i);
+            if (info.intent.getComponent().equals(removeComponent)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+    private void removeAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
+        // loop through all the apps and remove apps that have the same component
+        int length = list.size();
+        for (int i = 0; i < length; ++i) {
+            ApplicationInfo info = list.get(i);
+            int removeIndex = findAppByComponent(mApps, info);
+            if (removeIndex > -1) {
+                mApps.remove(removeIndex);
+                mPageViewIconCache.removeOutline(new PagedViewIconCache.Key(info));
+            }
+        }
+    }
+    @Override
+    public void removeApps(ArrayList<ApplicationInfo> list) {
+        removeAppsWithoutInvalidate(list);
+        invalidatePageData();
+    }
+    @Override
+    public void updateApps(ArrayList<ApplicationInfo> list) {
+        // We remove and re-add the updated applications list because it's properties may have
+        // changed (ie. the title), and this will ensure that the items will be in their proper
+        // place in the list.
+        removeAppsWithoutInvalidate(list);
+        addAppsWithoutInvalidate(list);
+        invalidatePageData();
+    }
+    @Override
+    public void reset() {
+        setCurrentPage(0);
+        invalidatePageData();
+    }
+    @Override
+    public void dumpState() {
+        // TODO: Dump information related to current list of Applications, Widgets, etc.
+        ApplicationInfo.dumpApplicationInfoList(LOG_TAG, "mApps", mApps);
+        dumpAppWidgetProviderInfoList(LOG_TAG, "mWidgets", mWidgets);
+    }
+    private void dumpAppWidgetProviderInfoList(String tag, String label,
+            List<AppWidgetProviderInfo> list) {
+        Log.d(tag, label + " size=" + list.size());
+        for (AppWidgetProviderInfo info: list) {
+            Log.d(tag, "   label=\"" + info.label + "\" previewImage=" + info.previewImage
+                    + " resizeMode=" + info.resizeMode + " configure=" + info.configure
+                    + " initialLayout=" + info.initialLayout
+                    + " minWidth=" + info.minWidth + " minHeight=" + info.minHeight);
+        }
+    }
+    @Override
+    public void surrender() {
+        // TODO: If we are in the middle of any process (ie. for holographic outlines, etc) we
+        // should stop this now.
+    }
+}
diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java
new file mode 100644
index 0000000..b484ad2
--- /dev/null
+++ b/src/com/android/launcher2/AppsCustomizeTabHost.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+import android.widget.TextView;
+
+import com.android.launcher.R;
+
+public class AppsCustomizeTabHost extends TabHost implements LauncherTransitionable,
+        TabHost.OnTabChangeListener  {
+    static final String LOG_TAG = "AppsCustomizeTabHost";
+
+    private static final String APPS_TAB_TAG = "APPS";
+    private static final String WIDGETS_TAB_TAG = "WIDGETS";
+
+    private final LayoutInflater mLayoutInflater;
+
+    public AppsCustomizeTabHost(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mLayoutInflater = LayoutInflater.from(context);
+    }
+
+    /**
+     * Setup the tab host and create all necessary tabs.
+     */
+    @Override
+    protected void onFinishInflate() {
+        // Setup the tab host
+        setup();
+
+        final ViewGroup tabs = (ViewGroup) findViewById(com.android.internal.R.id.tabs);
+        final AppsCustomizePagedView content = (AppsCustomizePagedView)
+                findViewById(R.id.apps_customize_pane_content);
+        if (tabs == null || content == null) throw new Resources.NotFoundException();
+
+        // Configure the tabs content factory to return the same paged view (that we change the
+        // content filter on)
+        TabContentFactory contentFactory = new TabContentFactory() {
+            public View createTabContent(String tag) {
+                return content;
+            }
+        };
+
+        // Create the tabs
+        TextView tabView;
+        tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
+        tabView.setText(mContext.getString(R.string.all_apps_button_label));
+        addTab(newTabSpec(APPS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
+        /** TODO-APPS_CUSTOMIZE: Re-enable widgets tab
+        tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
+        tabView.setText(mContext.getString(R.string.widgets_tab_label));
+        addTab(newTabSpec(WIDGETS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
+        */
+        setOnTabChangedListener(this);
+
+        // Set the width of the tab bar to match the content (for now)
+        tabs.getLayoutParams().width = content.getPageContentWidth();
+    }
+
+    @Override
+    public void onTabChanged(String tabId) {
+        final AppsCustomizePagedView content = (AppsCustomizePagedView)
+                findViewById(R.id.apps_customize_pane_content);
+        content.setContentType(getContentTypeForTabTag(tabId));
+    }
+
+    /**
+     * Returns the content type for the specified tab tag.
+     */
+    public AppsCustomizePagedView.ContentType getContentTypeForTabTag(String tag) {
+        if (tag.equals(APPS_TAB_TAG)) {
+            return AppsCustomizePagedView.ContentType.Applications;
+        } else if (tag.equals(WIDGETS_TAB_TAG)) {
+            return AppsCustomizePagedView.ContentType.Widgets;
+        }
+        return AppsCustomizePagedView.ContentType.Applications;
+    }
+
+    /**
+     * Disable focus on anything under this view in the hierarchy if we are not visible.
+     */
+    @Override
+    public int getDescendantFocusability() {
+        if (getVisibility() != View.VISIBLE) {
+            return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+        }
+        return super.getDescendantFocusability();
+    }
+
+    /* LauncherTransitionable overrides */
+    @Override
+    public void onLauncherTransitionStart(android.animation.Animator animation) {
+        // TODO-APPS_CUSTOMIZE: see AllAppsTabbed.onLauncherTransitionStart();
+    }
+    @Override
+    public void onLauncherTransitionEnd(android.animation.Animator animation) {
+        // TODO-APPS_CUSTOMIZE: see AllAppsTabbed.onLauncherTransitionEnd();
+    }
+}
diff --git a/src/com/android/launcher2/CustomizeTrayTabHost.java b/src/com/android/launcher2/CustomizeTrayTabHost.java
index 5c683c4..2c47895 100644
--- a/src/com/android/launcher2/CustomizeTrayTabHost.java
+++ b/src/com/android/launcher2/CustomizeTrayTabHost.java
@@ -94,7 +94,7 @@
                 if (newType != customizePagedView.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_tabTransitionTime);
+                    final int duration = res.getInteger(R.integer.config_tabTransitionDuration);
                     final float alpha = customizePagedView.getAlpha();
                     ValueAnimator alphaAnim = ObjectAnimator.ofFloat(customizePagedView,
                             "alpha", alpha, 0.0f);
diff --git a/src/com/android/launcher2/DragSource.java b/src/com/android/launcher2/DragSource.java
index 4dbdaf7..649120d 100644
--- a/src/com/android/launcher2/DragSource.java
+++ b/src/com/android/launcher2/DragSource.java
@@ -23,8 +23,6 @@
  *
  */
 public interface DragSource {
-    void setDragController(DragController dragger);
-
     /**
      * Callback from the DragController when it begins drawing the drag view.
      * This allows the DragSource to dim or hide the original view.
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index e00023f..7eb3bb1 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -101,7 +101,6 @@
         return true;
     }
 
-    @Override
     public void setDragController(DragController dragController) {
         mDragController = dragController;
     }
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 60cab8e..b2ec67c 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -169,7 +169,7 @@
     private static final String TOOLBAR_ICON_METADATA_NAME = "com.android.launcher.toolbar_icon";
 
     /** The different states that Launcher can be in. */
-    private enum State { WORKSPACE, ALL_APPS, CUSTOMIZE,
+    private enum State { WORKSPACE, APPS_CUSTOMIZE, ALL_APPS, CUSTOMIZE,
         CUSTOMIZE_SPRING_LOADED, ALL_APPS_SPRING_LOADED };
     private State mState = State.WORKSPACE;
     private AnimatorSet mStateAnimation;
@@ -202,6 +202,8 @@
     private DeleteZone mDeleteZone;
     private HandleView mHandleView;
     private AllAppsView mAllAppsGrid;
+    private AppsCustomizeTabHost mAppsCustomizeTabHost;
+    private AppsCustomizePagedView mAppsCustomizeContent;
     private CustomizeTrayTabHost mHomeCustomizationDrawer;
     private boolean mAutoAdvanceRunning = false;
 
@@ -328,6 +330,9 @@
         if (mCustomizePagedView != null) {
             mCustomizePagedView.update();
         }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.onPackagesUpdated();
+        }
 
         if (PROFILE_STARTUP) {
             android.os.Debug.stopMethodTracing();
@@ -361,21 +366,6 @@
         }
     }
 
-    @Override
-    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
-        super.dispatchPopulateAccessibilityEvent(event);
-
-        // we want to take over text population so it is context dependent
-        event.getText().clear();
-        if (mState == State.ALL_APPS) {
-            event.getText().add(getString(R.string.all_apps_button_label));
-        } else if (mState == State.WORKSPACE) {
-            event.getText().add(getString(R.string.all_apps_home_button_label));
-        }
-
-        return true;
-    }
-
     private void checkForLocaleChange() {
         if (sLocaleConfiguration == null) {
             new AsyncTask<Void, Void, LocaleConfiguration>() {
@@ -736,7 +726,12 @@
     public Object onRetainNonConfigurationInstance() {
         // Flag the loader to stop early before switching
         mModel.stopLoader();
-        mAllAppsGrid.surrender();
+        if (mAllAppsGrid != null) {
+            mAllAppsGrid.surrender();
+        }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.surrender();
+        }
         return Boolean.TRUE;
     }
 
@@ -832,7 +827,7 @@
 
         State state = intToState(savedState.getInt(RUNTIME_STATE, State.WORKSPACE.ordinal()));
 
-        if (state == State.ALL_APPS) {
+        if (state == State.ALL_APPS || state == State.APPS_CUSTOMIZE) {
             showAllApps(false);
         } else if (state == State.CUSTOMIZE) {
             showCustomizationDrawer(false);
@@ -885,6 +880,20 @@
             // Note: currently we do not restore the page for the customization tray because unlike
             // AllApps, the page content can change drastically
         }
+
+        // Restore the AppsCustomize tab
+        if (mAppsCustomizeTabHost != null) {
+            String curTab = savedState.getString("apps_customize_currentTab");
+            if (curTab != null) {
+             // We set this directly so that there is no delay before the tab is set
+                mAppsCustomizeContent.setContentType(
+                        mAppsCustomizeTabHost.getContentTypeForTabTag(curTab));
+                mAppsCustomizeTabHost.setCurrentTabByTag(curTab);
+            }
+
+            // Note: currently we do not restore the page for the AppsCustomize pane because the
+            // change in layout can drastically affect the saved page index
+        }
     }
 
     /**
@@ -896,18 +905,17 @@
         DragLayer dragLayer = (DragLayer) findViewById(R.id.drag_layer);
         dragLayer.setDragController(dragController);
 
-        mAllAppsGrid = (AllAppsView)dragLayer.findViewById(R.id.all_apps_view);
-        mAllAppsGrid.setLauncher(this);
-        mAllAppsGrid.setDragController(dragController);
-        ((View) mAllAppsGrid).setWillNotDraw(false); // We don't want a hole punched in our window.
-        // Manage focusability manually since this thing is always visible (in non-xlarge)
-        ((View) mAllAppsGrid).setFocusable(false);
-
         if (LauncherApplication.isScreenXLarge()) {
-            // They need to be INVISIBLE initially so that they will be measured in the layout.
-            // Otherwise the animations are messed up when we show them for the first time.
-            ((View) mAllAppsGrid).setVisibility(View.INVISIBLE);
-            mHomeCustomizationDrawer.setVisibility(View.INVISIBLE);
+            mAllAppsGrid = (AllAppsView)dragLayer.findViewById(R.id.all_apps_view);
+            mAllAppsGrid.setup(this, dragController);
+            // We don't want a hole punched in our window.
+            ((View) mAllAppsGrid).setWillNotDraw(false);
+        } else {
+            mAppsCustomizeTabHost = (AppsCustomizeTabHost)
+                    findViewById(R.id.apps_customize_pane);
+            mAppsCustomizeContent = (AppsCustomizePagedView)
+                    mAppsCustomizeTabHost.findViewById(R.id.apps_customize_pane_content);
+            mAppsCustomizeContent.setup(this, dragController);
         }
 
         mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
@@ -923,7 +931,6 @@
             // we don't use handle view in xlarge mode
             mHandleView = (HandleView)handleView;
             mHandleView.setLauncher(this);
-            mHandleView.setOnClickListener(this);
             mHandleView.setOnLongClickListener(this);
         }
 
@@ -985,15 +992,17 @@
             allAppsInfoTarget.setLauncher(this);
             dragController.addDragListener(allAppsInfoTarget);
             allAppsInfoTarget.setDragAndDropEnabled(false);
-            View marketButton = findViewById(R.id.market_button);
-            if (marketButton != null) {
+        }
+        View marketButton = findViewById(R.id.market_button);
+        if (marketButton != null) {
+            if (allAppsInfoTarget != null) {
                 allAppsInfoTarget.setOverlappingView(marketButton);
-                marketButton.setOnClickListener(new OnClickListener() {
-                    public void onClick(View v) {
-                        onClickAppMarketButton(v);
-                    }
-                });
             }
+            marketButton.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    onClickAppMarketButton(v);
+                }
+            });
         }
 
         dragController.setDragScoller(workspace);
@@ -1048,14 +1057,14 @@
 
     @SuppressWarnings({"UnusedDeclaration"})
     public void previousScreen(View v) {
-        if (mState != State.ALL_APPS) {
+        if (mState != State.ALL_APPS && mState != State.APPS_CUSTOMIZE) {
             mWorkspace.scrollLeft();
         }
     }
 
     @SuppressWarnings({"UnusedDeclaration"})
     public void nextScreen(View v) {
-        if (mState != State.ALL_APPS) {
+        if (mState != State.ALL_APPS && mState != State.APPS_CUSTOMIZE) {
             mWorkspace.scrollRight();
         }
     }
@@ -1263,6 +1272,9 @@
                 if (mAllAppsGrid != null) {
                     mAllAppsGrid.reset();
                 }
+                if (mAppsCustomizeContent != null) {
+                    mAppsCustomizeContent.reset();
+                }
             } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
                 mUserPresent = true;
                 updateRunning();
@@ -1417,11 +1429,7 @@
                         != Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
 
             // In all these cases, only animate if we're already on home
-
-            if (LauncherApplication.isScreenXLarge()) {
-                mWorkspace.unshrink(alreadyOnHome);
-            }
-
+            mWorkspace.unshrink(alreadyOnHome);
             mWorkspace.exitWidgetResizeMode();
             if (alreadyOnHome && mState == State.WORKSPACE && !mWorkspace.isTouchActive()) {
                 mWorkspace.moveToDefaultScreen(true);
@@ -1439,6 +1447,9 @@
             if (mAllAppsGrid != null) {
                 mAllAppsGrid.reset();
             }
+            if (mAppsCustomizeContent != null) {
+                mAppsCustomizeContent.reset();
+            }
         }
     }
 
@@ -1487,7 +1498,6 @@
                 outState.putInt("allapps_currentPage", mAllAppsPagedView.getCurrentPage());
             }
         }
-
         // Save the current customization drawer tab
         if (mHomeCustomizationDrawer != null) {
             String currentTabTag = mHomeCustomizationDrawer.getCurrentTabTag();
@@ -1495,6 +1505,13 @@
                 outState.putString("customize_currentTab", currentTabTag);
             }
         }
+        // Save the current AppsCustomize tab
+        if (mAppsCustomizeTabHost != null) {
+            String currentTabTag = mAppsCustomizeTabHost.getCurrentTabTag();
+            if (currentTabTag != null) {
+                outState.putString("apps_customize_currentTab", currentTabTag);
+            }
+        }
     }
 
     @Override
@@ -1603,22 +1620,28 @@
     public boolean onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
 
-        // If all apps is animating, don't show the menu, because we don't know
-        // which one to show.
-        if (mAllAppsGrid.isAnimating()) {
-            return false;
+        if (mAllAppsGrid != null) {
+            // If all apps is animating, don't show the menu, because we don't know
+            // which one to show.
+            if (mAllAppsGrid.isAnimating()) {
+                return false;
+            }
+
+            // Only show the add and wallpaper options when we're not in all apps.
+            boolean visible = !mAllAppsGrid.isVisible();
+            menu.setGroupVisible(MENU_GROUP_ADD, visible);
+            menu.setGroupVisible(MENU_GROUP_WALLPAPER, visible);
+
+            // Disable add if the workspace is full.
+            if (visible) {
+                CellLayout layout = (CellLayout) mWorkspace.getChildAt(mWorkspace.getCurrentPage());
+                menu.setGroupEnabled(MENU_GROUP_ADD, layout.existsEmptyCell());
+            }
         }
 
-        // Only show the add and wallpaper options when we're not in all apps.
-        boolean visible = !mAllAppsGrid.isVisible();
-        menu.setGroupVisible(MENU_GROUP_ADD, visible);
-        menu.setGroupVisible(MENU_GROUP_WALLPAPER, visible);
-
-        // Disable add if the workspace is full.
-        if (visible) {
-            CellLayout layout = (CellLayout) mWorkspace.getChildAt(mWorkspace.getCurrentPage());
-            menu.setGroupEnabled(MENU_GROUP_ADD, layout.existsEmptyCell());
-        }
+        // TODO-APPS_CUSTOMIZE: Remove this for the phone UI at some point, along with all the menu
+        // related code?
+        if (mAppsCustomizeContent != null && mAppsCustomizeContent.isAnimating()) return false;
 
         return true;
     }
@@ -1959,7 +1982,7 @@
 
     @Override
     public void onBackPressed() {
-        if (mState == State.ALL_APPS || mState == State.CUSTOMIZE) {
+        if (mState == State.ALL_APPS || mState == State.CUSTOMIZE || mState == State.APPS_CUSTOMIZE) {
             showWorkspace(true);
         } else if (mWorkspace.getOpenFolder() != null) {
             closeFolder();
@@ -2218,21 +2241,21 @@
 
         switch (v.getId()) {
             case R.id.previous_screen:
-                if (mState != State.ALL_APPS) {
+                if (mState != State.ALL_APPS && mState != State.APPS_CUSTOMIZE) {
                     mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                             HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
                     showPreviews(v);
                 }
                 return true;
             case R.id.next_screen:
-                if (mState != State.ALL_APPS) {
+                if (mState != State.ALL_APPS && mState != State.APPS_CUSTOMIZE) {
                     mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                             HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
                     showPreviews(v);
                 }
                 return true;
             case R.id.all_apps_button:
-                if (mState != State.ALL_APPS) {
+                if (mState != State.ALL_APPS && mState != State.APPS_CUSTOMIZE) {
                     mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                             HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
                     showPreviews(v);
@@ -2569,7 +2592,7 @@
 
     // Now a part of LauncherModel.Callbacks. Used to reorder loading steps.
     public boolean isAllAppsVisible() {
-        return mState == State.ALL_APPS;
+        return (mState == State.ALL_APPS) || (mState == State.APPS_CUSTOMIZE);
     }
 
     // AllAppsView.Watcher
@@ -2582,17 +2605,12 @@
     
     private void showAndEnableToolbarButton(View button) {
         button.setVisibility(View.VISIBLE);
-        button.setClickable(true);
     }
 
     private void hideToolbarButton(View button) {
-        button.setAlpha(0.0f);
         // We can't set it to GONE, otherwise the RelativeLayout gets screwed up
         button.setVisibility(View.INVISIBLE);
-    }
-
-    private void disableToolbarButton(View button) {
-        button.setClickable(false);
+        button.setAlpha(0.0f);
     }
 
     /**
@@ -2623,7 +2641,6 @@
                 @Override
                 public void onAnimationStart(Animator animation) {
                     if (showing) showAndEnableToolbarButton(view);
-                    if (hiding) disableToolbarButton(view);
                 }
                 @Override
                 public void onAnimationEnd(Animator animation) {
@@ -2636,7 +2653,6 @@
                 showAndEnableToolbarButton(view);
                 view.setAlpha(1f);
             } else {
-                disableToolbarButton(view);
                 hideToolbarButton(view);
             }
         }
@@ -2654,15 +2670,18 @@
         switch (newState) {
         case WORKSPACE:
             hideOrShowToolbarButton(true, mButtonCluster, showSeq);
-            mDeleteZone.setOverlappingViews(
-                    new View[] { mAllAppsButton, mDivider, mConfigureButton });
             mDeleteZone.setDragAndDropEnabled(true);
-            mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_workspace));
+            if (LauncherApplication.isScreenXLarge()) {
+                mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_workspace));
+            }
             break;
         case ALL_APPS:
+        case APPS_CUSTOMIZE:
             hideOrShowToolbarButton(false, mButtonCluster, hideSeq);
             mDeleteZone.setDragAndDropEnabled(false);
-            mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_all_apps));
+            if (LauncherApplication.isScreenXLarge()) {
+                mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_all_apps));
+            }
             break;
         case CUSTOMIZE:
             hideOrShowToolbarButton(false, mButtonCluster, hideSeq);
@@ -2684,7 +2703,7 @@
         // Set pivotY so that at the starting zoom factor, the view is partially
         // visible. Modifying initialHeightFactor changes how much of the view is
         // initially showing, and hence the perceived angle from which the view enters.
-        if (state == State.ALL_APPS) {
+        if (state == State.ALL_APPS || state == State.APPS_CUSTOMIZE) {
             final float initialHeightFactor = 0.175f;
             view.setPivotY((1 - initialHeightFactor) * height);
         } else {
@@ -2701,20 +2720,28 @@
      */
     private void cameraZoomOut(State toState, boolean animated, boolean springLoaded) {
         final Resources res = getResources();
-        final boolean toAllApps = (toState == State.ALL_APPS);
+        final boolean toAllApps = (toState == State.ALL_APPS)
+                || (toState == State.APPS_CUSTOMIZE);
 
-        final int duration = toAllApps ?
-                res.getInteger(R.integer.config_allAppsZoomInTime) :
-                res.getInteger(R.integer.config_customizeZoomInTime);
-        final int fadeDuration = toAllApps ?
-                res.getInteger(R.integer.config_allAppsFadeInTime) :
-                res.getInteger(R.integer.config_customizeFadeInTime);
+        final int duration = (toAllApps ?
+                res.getInteger(R.integer.config_appsCustomizeZoomInTime) :
+                res.getInteger(R.integer.config_customizeZoomInTime));
+        final int fadeDuration = (toAllApps ?
+                res.getInteger(R.integer.config_appsCustomizeFadeInTime) :
+                res.getInteger(R.integer.config_customizeFadeInTime));
 
         final float scale = toAllApps ?
-                (float) res.getInteger(R.integer.config_allAppsZoomScaleFactor) :
+                (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor) :
                 (float) res.getInteger(R.integer.config_customizeZoomScaleFactor);
 
-        final View toView = toAllApps ? (View) mAllAppsGrid : mHomeCustomizationDrawer;
+        View tmpView;
+        if (toAllApps) {
+            tmpView = (LauncherApplication.isScreenXLarge())
+                    ? (View) mAllAppsGrid : mAppsCustomizeTabHost;
+        } else {
+            tmpView = mHomeCustomizationDrawer;
+        }
+        final View toView = tmpView;
 
         setPivotsForZoom(toView, toState, scale);
 
@@ -2722,9 +2749,11 @@
             if (!springLoaded) {
                 mWorkspace.shrink(ShrinkState.BOTTOM_HIDDEN, animated);
 
-                // Everytime we launch into AllApps, we reset the successful drop flag which
-                // controls when it should hide/show the mini workspaces
-                mAllAppsPagedView.resetSuccessfulDropFlag();
+                if (LauncherApplication.isScreenXLarge()) {
+                    // Everytime we launch into AllApps, we reset the successful drop flag which
+                    // controls when it should hide/show the mini workspaces
+                    mAllAppsPagedView.resetSuccessfulDropFlag();
+                }
             } else {
                 mWorkspace.shrink(ShrinkState.BOTTOM_VISIBLE, animated);
             }
@@ -2766,6 +2795,7 @@
                     toView.setTranslationX(0.0f);
                     toView.setTranslationY(0.0f);
                     toView.setVisibility(View.VISIBLE);
+                    toView.bringToFront();
                     if (!toAllApps) {
                         toView.setFastAlpha(1.0f);
                     }
@@ -2805,6 +2835,7 @@
             toView.setScaleX(1.0f);
             toView.setScaleY(1.0f);
             toView.setVisibility(View.VISIBLE);
+            toView.bringToFront();
             if (toView instanceof LauncherTransitionable) {
                 ((LauncherTransitionable) toView).onLauncherTransitionStart(null);
                 ((LauncherTransitionable) toView).onLauncherTransitionEnd(null);
@@ -2821,20 +2852,30 @@
      */
     private void cameraZoomIn(State fromState, boolean animated, boolean springLoaded) {
         Resources res = getResources();
-        final boolean fromAllApps = (fromState == State.ALL_APPS);
+        final boolean fromAllApps = (fromState == State.ALL_APPS)
+                || (fromState == State.APPS_CUSTOMIZE);
 
         int duration = fromAllApps ?
-            res.getInteger(R.integer.config_allAppsZoomOutTime) :
+            res.getInteger(R.integer.config_appsCustomizeZoomOutTime) :
             res.getInteger(R.integer.config_customizeZoomOutTime);
 
         final float scaleFactor = fromAllApps ?
-            (float) res.getInteger(R.integer.config_allAppsZoomScaleFactor) :
+            (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor) :
             (float) res.getInteger(R.integer.config_customizeZoomScaleFactor);
 
-        final View fromView = fromAllApps ? (View) mAllAppsGrid : mHomeCustomizationDrawer;
+        View tmpView;
+        if (fromAllApps) {
+            tmpView = (LauncherApplication.isScreenXLarge())
+                    ? (View) mAllAppsGrid : mAppsCustomizeTabHost;
+        } else {
+            tmpView = mHomeCustomizationDrawer;
+        }
+        final View fromView = tmpView;
 
-        mCustomizePagedView.endChoiceMode();
-        mAllAppsPagedView.endChoiceMode();
+        if (LauncherApplication.isScreenXLarge()) {
+            mCustomizePagedView.endChoiceMode();
+            mAllAppsPagedView.endChoiceMode();
+        }
 
         setPivotsForZoom(fromView, fromState, scaleFactor);
 
@@ -2858,7 +2899,7 @@
                 }
             });
             final ValueAnimator alphaAnim = ValueAnimator.ofFloat(0f, 1f);
-            alphaAnim.setDuration(res.getInteger(R.integer.config_allAppsFadeOutTime));
+            alphaAnim.setDuration(res.getInteger(R.integer.config_appsCustomizeFadeOutTime));
             alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f));
             alphaAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
                 public void onAnimationUpdate(float a, float b) {
@@ -2904,34 +2945,6 @@
         }
     }
 
-    void showAllApps(boolean animated) {
-        if (mState != State.WORKSPACE) {
-            return;
-        }
-
-        if (LauncherApplication.isScreenXLarge()) {
-            cameraZoomOut(State.ALL_APPS, animated, false);
-        } else {
-            mAllAppsGrid.zoom(1.0f, animated);
-        }
-
-        ((View) mAllAppsGrid).setFocusable(true);
-        ((View) mAllAppsGrid).requestFocus();
-
-        // TODO: fade these two too
-        mDeleteZone.setVisibility(View.GONE);
-
-        // Change the state *after* we've called all the transition code
-        mState = State.ALL_APPS;
-
-        // Pause the auto-advance of widgets until we are out of AllApps
-        mUserPresent = false;
-        updateRunning();
-
-        // send an accessibility event to announce the context change
-        getWindow().getDecorView().sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
-    }
-
     void showWorkspace(boolean animated) {
         showWorkspace(animated, null);
     }
@@ -2944,7 +2957,7 @@
         } else {
             mWorkspace.unshrink(animated);
         }
-        if (mState == State.ALL_APPS) {
+        if (mState == State.ALL_APPS || mState == State.APPS_CUSTOMIZE) {
             closeAllApps(animated);
         } else if (mState == State.CUSTOMIZE) {
             hideCustomizationDrawer(animated);
@@ -2963,9 +2976,13 @@
 
     void enterSpringLoadedDragMode(CellLayout layout) {
         mWorkspace.enterSpringLoadedDragMode(layout);
-        if (mState == State.ALL_APPS) {
+        if (mState == State.ALL_APPS || mState == State.APPS_CUSTOMIZE) {
             mState = State.ALL_APPS_SPRING_LOADED;
-            cameraZoomIn(State.ALL_APPS, true, true);
+            if (LauncherApplication.isScreenXLarge()) {
+                cameraZoomIn(State.ALL_APPS, true, true);
+            } else {
+                cameraZoomIn(State.APPS_CUSTOMIZE, true, true);
+            }
         } else if (mState == State.CUSTOMIZE) {
             mState = State.CUSTOMIZE_SPRING_LOADED;
             cameraZoomIn(State.CUSTOMIZE, true, true);
@@ -2977,8 +2994,13 @@
     void exitSpringLoadedDragMode() {
         if (mState == State.ALL_APPS_SPRING_LOADED) {
             mWorkspace.exitSpringLoadedDragMode(Workspace.ShrinkState.BOTTOM_VISIBLE);
-            cameraZoomOut(State.ALL_APPS, true, true);
-            mState = State.ALL_APPS;
+            if (LauncherApplication.isScreenXLarge()) {
+                cameraZoomOut(State.ALL_APPS, true, true);
+                mState = State.ALL_APPS;
+            } else {
+                cameraZoomOut(State.APPS_CUSTOMIZE, true, true);
+                mState = State.APPS_CUSTOMIZE;
+            }
         } else if (mState == State.CUSTOMIZE_SPRING_LOADED) {
             mWorkspace.exitSpringLoadedDragMode(Workspace.ShrinkState.TOP);
             cameraZoomOut(State.CUSTOMIZE, true, true);
@@ -2988,6 +3010,34 @@
         }*/
     }
 
+    void showAllApps(boolean animated) {
+        if (mState != State.WORKSPACE) return;
+        if (LauncherApplication.isScreenXLarge()) {
+            cameraZoomOut(State.ALL_APPS, animated, false);
+            ((View) mAllAppsGrid).requestFocus();
+
+            // TODO: fade these two too
+            mDeleteZone.setVisibility(View.GONE);
+
+            // Change the state *after* we've called all the transition code
+            mState = State.ALL_APPS;
+        } else {
+            View appsCustomizePane = findViewById(R.id.apps_customize_pane);
+            cameraZoomOut(State.APPS_CUSTOMIZE, animated, false);
+            appsCustomizePane.requestFocus();
+
+            // Change the state *after* we've called all the transition code
+            mState = State.APPS_CUSTOMIZE;
+        }
+
+        // Pause the auto-advance of widgets until we are out of AllApps
+        mUserPresent = false;
+        updateRunning();
+
+        // Send an accessibility event to announce the context change
+        getWindow().getDecorView().sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+    }
+
     /**
      * Things to test when changing this code.
      *   - Home from workspace
@@ -3028,15 +3078,22 @@
      *          - From another workspace
      */
     void closeAllApps(boolean animated) {
-        if (mState == State.ALL_APPS || mState == State.ALL_APPS_SPRING_LOADED) {
-            mWorkspace.setVisibility(View.VISIBLE);
-            if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenXLarge()) {
+            if (mState == State.ALL_APPS || mState == State.ALL_APPS_SPRING_LOADED) {
+                mWorkspace.setVisibility(View.VISIBLE);
                 cameraZoomIn(State.ALL_APPS, animated, false);
-            } else {
-                mAllAppsGrid.zoom(0.0f, animated);
+
+                // Set focus to the AllApps button
+                findViewById(R.id.all_apps_button).requestFocus();
             }
-            ((View)mAllAppsGrid).setFocusable(false);
-            ((CellLayout) mWorkspace.getChildAt(mWorkspace.getCurrentPage())).getChildrenLayout().requestFocus();
+        } else {
+            if (mState == State.APPS_CUSTOMIZE || mState == State.ALL_APPS_SPRING_LOADED) {
+                mWorkspace.setVisibility(View.VISIBLE);
+                cameraZoomIn(State.APPS_CUSTOMIZE, animated, false);
+
+                // Set focus to the AllApps button
+                findViewById(R.id.all_apps_button).requestFocus();
+            }
         }
     }
 
@@ -3068,6 +3125,9 @@
     void hideCustomizationDrawer(boolean animated) {
         if (mState == State.CUSTOMIZE || mState == State.CUSTOMIZE_SPRING_LOADED) {
             cameraZoomIn(State.CUSTOMIZE, animated, false);
+
+            // Set focus to the customize button
+            findViewById(R.id.configure_button).requestFocus();
         }
     }
 
@@ -3199,16 +3259,21 @@
      * Sets the app market icon (shown when all apps is visible on x-large screens)
      */
     private void updateAppMarketIcon() {
-        if (LauncherApplication.isScreenXLarge()) {
-            Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_APP_MARKET);
-            // 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) {
-                mAppMarketIntent = intent;
-                sAppMarketIcon = updateTextButtonWithIconFromExternalActivity(
-                        R.id.market_button, activityName, R.drawable.app_market_generic);
-            }
+        final View marketButton = findViewById(R.id.market_button);
+        Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_APP_MARKET);
+        // 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) {
+            mAppMarketIntent = intent;
+            sAppMarketIcon = updateTextButtonWithIconFromExternalActivity(
+                    R.id.market_button, activityName, R.drawable.app_market_generic);
+            marketButton.setVisibility(View.VISIBLE);
+        } else {
+            // We should hide and disable the view so that we don't try and restore the visibility
+            // of it when we swap between drag & normal states from IconDropTarget subclasses.
+            marketButton.setVisibility(View.GONE);
+            marketButton.setEnabled(false);
         }
     }
 
@@ -3584,7 +3649,12 @@
      * Implementation of the method from LauncherModel.Callbacks.
      */
     public void bindAllApplications(ArrayList<ApplicationInfo> apps) {
-        mAllAppsGrid.setApps(apps);
+        if (mAllAppsGrid != null) {
+            mAllAppsGrid.setApps(apps);
+        }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.setApps(apps);
+        }
         if (mCustomizePagedView != null) {
             mCustomizePagedView.setApps(apps);
         }
@@ -3599,7 +3669,12 @@
     public void bindAppsAdded(ArrayList<ApplicationInfo> apps) {
         setLoadOnResume();
         removeDialog(DIALOG_CREATE_SHORTCUT);
-        mAllAppsGrid.addApps(apps);
+        if (mAllAppsGrid != null) {
+            mAllAppsGrid.addApps(apps);
+        }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.addApps(apps);
+        }
         if (mCustomizePagedView != null) {
             mCustomizePagedView.addApps(apps);
         }
@@ -3620,6 +3695,9 @@
         if (mAllAppsGrid != null) {
             mAllAppsGrid.updateApps(apps);
         }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.updateApps(apps);
+        }
         if (mCustomizePagedView != null) {
             mCustomizePagedView.updateApps(apps);
         }
@@ -3636,7 +3714,12 @@
         if (permanent) {
             mWorkspace.removeItems(apps);
         }
-        mAllAppsGrid.removeApps(apps);
+        if (mAllAppsGrid != null) {
+            mAllAppsGrid.removeApps(apps);
+        }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.removeApps(apps);
+        }
         if (mCustomizePagedView != null) {
             mCustomizePagedView.removeApps(apps);
         }
@@ -3651,6 +3734,9 @@
         if (mCustomizePagedView != null) {
             mCustomizePagedView.update();
         }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.onPackagesUpdated();
+        }
     }
 
     private int mapConfigurationOriActivityInfoOri(int configOri) {
@@ -3709,7 +3795,12 @@
         Log.d(TAG, "mDesktopItems.size=" + mDesktopItems.size());
         Log.d(TAG, "sFolders.size=" + sFolders.size());
         mModel.dumpState();
-        mAllAppsGrid.dumpState();
+        if (mAllAppsGrid != null) {
+            mAllAppsGrid.dumpState();
+        }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.dumpState();
+        }
         Log.d(TAG, "END launcher2 dump state");
     }
 }
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index e432733..9bf8838 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -1789,6 +1789,28 @@
             return 0;
         }
     };
+    public static final Comparator<AppWidgetProviderInfo> WIDGET_NAME_COMPARATOR
+            = new Comparator<AppWidgetProviderInfo>() {
+        public final int compare(AppWidgetProviderInfo a, AppWidgetProviderInfo b) {
+            return sCollator.compare(a.label.toString(), b.label.toString());
+        }
+    };
+    public static class ShortcutNameComparator implements Comparator<ResolveInfo> {
+        private PackageManager mPackageManager;
+        private HashMap<Object, String> mLabelCache;
+        ShortcutNameComparator(PackageManager pm) {
+            mPackageManager = pm;
+            mLabelCache = new HashMap<Object, String>();
+        }
+        public final int compare(ResolveInfo a, ResolveInfo b) {
+            String labelA, labelB;
+            if (mLabelCache.containsKey(a)) labelA = mLabelCache.get(a);
+            else labelA = a.loadLabel(mPackageManager).toString();
+            if (mLabelCache.containsKey(b)) labelB = mLabelCache.get(b);
+            else labelB = b.loadLabel(mPackageManager).toString();
+            return sCollator.compare(labelA, labelB);
+        }
+    };
 
     public void dumpState() {
         Log.d(TAG, "mCallbacks=" + mCallbacks);
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 9eae647..3bef69e 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -29,6 +29,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.ActionMode;
 import android.view.InputDevice;
 import android.view.KeyEvent;
@@ -50,6 +51,7 @@
  */
 public abstract class PagedView extends ViewGroup {
     private static final String TAG = "PagedView";
+    private static final boolean DEBUG = false;
     protected static final int INVALID_PAGE = -1;
 
     // the min drag distance for a fling to register, to prevent random page shifts
@@ -397,6 +399,7 @@
 
         // The children are given the same width and height as the workspace
         // unless they were set to WRAP_CONTENT
+        if (DEBUG) Log.d(TAG, "PagedView.onMeasure(): " + widthSize + ", " + heightSize);
         final int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             // disallowing padding in paged view (just pass 0)
@@ -424,6 +427,8 @@
 
             child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
             maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());
+            if (DEBUG) Log.d(TAG, "\tmeasure-child" + i + ": " + child.getMeasuredWidth() + ", "
+                    + child.getMeasuredHeight());
         }
 
         if (heightMode == MeasureSpec.AT_MOST) {
@@ -478,6 +483,7 @@
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (DEBUG) Log.d(TAG, "PagedView.onLayout()");
         if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
             setHorizontalScrollBarEnabled(false);
             int newX = getChildOffset(mCurrentPage) - getRelativeChildOffset(mCurrentPage);
@@ -491,6 +497,8 @@
         final int childCount = getChildCount();
         int childLeft = 0;
         if (childCount > 0) {
+            if (DEBUG) Log.d(TAG, "getRelativeChildOffset(): " + getMeasuredWidth() + ", "
+                    + getChildWidth(0));
             childLeft = getRelativeChildOffset(0);
         }
 
@@ -504,6 +512,7 @@
                     childTop += ((getMeasuredHeight() - verticalPadding) - childHeight) / 2;
                 }
 
+                if (DEBUG) Log.d(TAG, "\tlayout-child" + i + ": " + childLeft + ", " + childTop);
                 child.layout(childLeft, childTop,
                         childLeft + child.getMeasuredWidth(), childTop + childHeight);
                 childLeft += childWidth + mPageSpacing;
@@ -993,6 +1002,7 @@
                     mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
                     if (!mDeferScrollUpdate) {
                         scrollBy((int) deltaX, 0);
+                        if (DEBUG) Log.d(TAG, "onTouchEvent().Scrolling: " + deltaX);
                     } else {
                         invalidate();
                     }
@@ -1262,6 +1272,9 @@
         whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1));
         int halfScreenSize = getMeasuredWidth() / 2;
 
+        if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
+        if (DEBUG) Log.d(TAG, "snapToPageWithVelocity.getRelativeChildOffset(): "
+                + getMeasuredWidth() + ", " + getChildWidth(whichPage));
         final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
         int delta = newX - mUnboundedScrollX;
         int duration = 0;
@@ -1299,6 +1312,9 @@
     protected void snapToPage(int whichPage, int duration) {
         whichPage = Math.max(0, Math.min(whichPage, getPageCount() - 1));
 
+        if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
+        if (DEBUG) Log.d(TAG, "snapToPage.getRelativeChildOffset(): " + getMeasuredWidth() + ", "
+                + getChildWidth(whichPage));
         int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
         final int sX = mUnboundedScrollX;
         final int delta = newX - sX;
@@ -1410,6 +1426,8 @@
             if (page < count) {
                 int lowerPageBound = getAssociatedLowerPageBound(page);
                 int upperPageBound = getAssociatedUpperPageBound(page);
+                if (DEBUG) Log.d(TAG, "loadAssociatedPages: " + lowerPageBound + "/"
+                        + upperPageBound);
                 for (int i = 0; i < count; ++i) {
                     Page layout = (Page) getChildAt(i);
                     final int childCount = layout.getPageChildCount();
diff --git a/src/com/android/launcher2/PagedViewCellLayout.java b/src/com/android/launcher2/PagedViewCellLayout.java
index 28e092e..196063d 100644
--- a/src/com/android/launcher2/PagedViewCellLayout.java
+++ b/src/com/android/launcher2/PagedViewCellLayout.java
@@ -17,12 +17,15 @@
 package com.android.launcher2;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 
+import com.android.launcher.R;
+
 /**
  * An abstraction of the original CellLayout which supports laying out items
  * which span multiple cells into a grid-like layout.  Also supports dimming
@@ -37,7 +40,6 @@
     private int mCellHeight;
     private int mWidthGap;
     private int mHeightGap;
-    private static int sDefaultCellDimensions = 96;
     protected PagedViewCellLayoutChildren mChildren;
     private PagedViewCellLayoutChildren mHolographicChildren;
     private boolean mAllowHardwareLayerCreation = false;
@@ -57,7 +59,9 @@
         setAlwaysDrawnWithCacheEnabled(false);
 
         // setup default cell parameters
-        mCellWidth = mCellHeight = sDefaultCellDimensions;
+        Resources resources = context.getResources();
+        mCellWidth = resources.getDimensionPixelSize(R.dimen.apps_customize_cell_width);
+        mCellHeight = resources.getDimensionPixelSize(R.dimen.apps_customize_cell_height);
         mCellCountX = LauncherModel.getCellCountX();
         mCellCountY = LauncherModel.getCellCountY();
         mWidthGap = mHeightGap = -1;
@@ -252,11 +256,15 @@
     }
 
     int getContentWidth() {
-        // Return the distance from the left edge of the content of the leftmost icon to
-        // the right edge of the content of the rightmost icon
+        if (LauncherApplication.isScreenXLarge()) {
+            // Return the distance from the left edge of the content of the leftmost icon to
+            // the right edge of the content of the rightmost icon
 
-        // icons are centered within cells, find out how much padding that accounts for
-        return getWidthBeforeFirstLayout() - (mCellWidth - Utilities.getIconContentSize());
+            // icons are centered within cells, find out how much padding that accounts for
+            return getWidthBeforeFirstLayout() - (mCellWidth - Utilities.getIconContentSize());
+        } else {
+            return getWidthBeforeFirstLayout() + mPaddingLeft + mPaddingRight;
+        }
     }
 
     int getWidthBeforeFirstLayout() {
@@ -268,7 +276,12 @@
         int count = getChildCount();
         for (int i = 0; i < count; i++) {
             View child = getChildAt(i);
-            child.layout(0, 0, r - l, b - t);
+            if (LauncherApplication.isScreenXLarge()) {
+                child.layout(0, 0, r - l, b - t);
+            } else {
+                child.layout(mPaddingLeft, mPaddingTop, getMeasuredWidth() - mPaddingRight,
+                        getMeasuredHeight() - mPaddingBottom);
+            }
         }
     }
 
@@ -457,8 +470,13 @@
             height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
                     topMargin - bottomMargin;
 
-            x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
-            y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
+            if (LauncherApplication.isScreenXLarge()) {
+                x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
+                y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
+            } else {
+                x = myCellX * (cellWidth + widthGap) + leftMargin;
+                y = myCellY * (cellHeight + heightGap) + topMargin;
+            }
         }
 
         public Object getTag() {
diff --git a/src/com/android/launcher2/PagedViewExtendedLayout.java b/src/com/android/launcher2/PagedViewExtendedLayout.java
index 81f1498..776b99f 100644
--- a/src/com/android/launcher2/PagedViewExtendedLayout.java
+++ b/src/com/android/launcher2/PagedViewExtendedLayout.java
@@ -40,6 +40,22 @@
         super(context, attrs, defStyle);
     }
 
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (LauncherApplication.isScreenXLarge()) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        } else {
+            // PagedView currently has issues with different-sized pages since it calculates the
+            // offset of each page to scroll to before it updates the actual size of each page
+            // (which canchange depending on the content if the contains aren't a fixed size).
+            // We work around this by having a minimum size on each widget page).
+            int widthSpecSize = Math.max(getSuggestedMinimumWidth(),
+                    MeasureSpec.getSize(widthMeasureSpec));
+            int widthSpecMode = MeasureSpec.AT_MOST;
+            super.onMeasure(MeasureSpec.makeMeasureSpec(widthSpecSize, widthSpecMode),
+                    heightMeasureSpec);
+        }
+    }
+
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         // We eat up the touch events here, since the PagedView (which uses the same swiping
@@ -94,4 +110,11 @@
     public int indexOfChildOnPage(View v) {
         return indexOfChild(v);
     }
+
+    public static class LayoutParams extends LinearLayout.LayoutParams {
+        public LayoutParams() {
+            super(LinearLayout.LayoutParams.WRAP_CONTENT,
+                    LinearLayout.LayoutParams.MATCH_PARENT);
+        }
+    }
 }
diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java
index f46b63c..f1b8a01 100644
--- a/src/com/android/launcher2/PagedViewIcon.java
+++ b/src/com/android/launcher2/PagedViewIcon.java
@@ -122,11 +122,13 @@
 
         // Set up fade in/out constants
         final Resources r = context.getResources();
-        final int alpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha);
+        final int alpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha);
         if (alpha > 0) {
-            mCheckedAlpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha) / 256.0f;
-            mCheckedFadeInDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeInTime);
-            mCheckedFadeOutDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeOutTime);
+            mCheckedAlpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha) / 256.0f;
+            mCheckedFadeInDuration =
+                r.getInteger(R.integer.config_dragAppsCustomizeIconFadeInDuration);
+            mCheckedFadeOutDuration =
+                r.getInteger(R.integer.config_dragAppsCustomizeIconFadeOutDuration);
         }
 
         mHolographicOutlineView = new HolographicPagedViewIcon(context, this);
diff --git a/src/com/android/launcher2/PagedViewWidget.java b/src/com/android/launcher2/PagedViewWidget.java
index c2d609e..2dcceae 100644
--- a/src/com/android/launcher2/PagedViewWidget.java
+++ b/src/com/android/launcher2/PagedViewWidget.java
@@ -154,14 +154,15 @@
 
         // Set up fade in/out constants
         final Resources r = context.getResources();
-        final int alpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha);
+        final int alpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha);
         if (alpha > 0) {
-            mCheckedAlpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha) / 256.0f;
-            mCheckedFadeInDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeInTime);
-            mCheckedFadeOutDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeOutTime);
+            mCheckedAlpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha) / 256.0f;
+            mCheckedFadeInDuration =
+                r.getInteger(R.integer.config_dragAppsCustomizeIconFadeInDuration);
+            mCheckedFadeOutDuration =
+                r.getInteger(R.integer.config_dragAppsCustomizeIconFadeOutDuration);
         }
 
-        setFocusable(true);
         setWillNotDraw(false);
         setClipToPadding(false);
     }
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index b1aa410..49cab80 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -1059,6 +1059,8 @@
     @Override
     protected void screenScrolled(int screenCenter) {
         // If the screen is not xlarge, then don't rotate the CellLayouts
+        // NOTE: If we don't update the side pages alpha, then we should not hide the side pages.
+        //       see unshrink().
         if (!LauncherApplication.isScreenXLarge()) return;
 
         final int halfScreenSize = getMeasuredWidth() / 2;
@@ -1257,19 +1259,6 @@
         }
     }
 
-    @Override
-    public boolean dispatchTouchEvent(MotionEvent ev) {
-        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps
-            // ie when you click on a mini-screen, it zooms back to that screen)
-            if (!LauncherApplication.isScreenXLarge() && mLauncher.isAllAppsVisible()) {
-                return false;
-            }
-        }
-
-        return super.dispatchTouchEvent(ev);
-    }
-
     void enableChildrenCache(int fromPage, int toPage) {
         if (fromPage > toPage) {
             final int temp = fromPage;
@@ -1299,27 +1288,32 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        AllAppsPagedView allApps = (AllAppsPagedView)
-                mLauncher.findViewById(R.id.all_apps_paged_view);
-
-        if (mLauncher.isAllAppsVisible() && mShrinkState == ShrinkState.BOTTOM_HIDDEN
-                && allApps != null) {
-            if (ev.getAction() == MotionEvent.ACTION_UP &&
-                    allApps.getTouchState() == TOUCH_STATE_REST) {
-
-                // Cancel any scrolling that is in progress.
-                if (!mScroller.isFinished()) {
-                    mScroller.abortAnimation();
-                }
-                setCurrentPage(mCurrentPage);
-
-                if (mShrinkState == ShrinkState.BOTTOM_HIDDEN) {
-                    mLauncher.showWorkspace(true);
-                }
-                allApps.onTouchEvent(ev);
-                return true;
+        if (mLauncher.isAllAppsVisible() && mShrinkState == ShrinkState.BOTTOM_HIDDEN) {
+            PagedView appsPane;
+            if (LauncherApplication.isScreenXLarge()) {
+                appsPane = (PagedView) mLauncher.findViewById(R.id.all_apps_paged_view);
             } else {
-                return allApps.onTouchEvent(ev);
+                appsPane = (PagedView) mLauncher.findViewById(R.id.apps_customize_pane_content);
+            }
+
+            if (appsPane != null) {
+                if (ev.getAction() == MotionEvent.ACTION_UP &&
+                        appsPane.getTouchState() == TOUCH_STATE_REST) {
+
+                    // Cancel any scrolling that is in progress.
+                    if (!mScroller.isFinished()) {
+                        mScroller.abortAnimation();
+                    }
+                    setCurrentPage(mCurrentPage);
+
+                    if (mShrinkState == ShrinkState.BOTTOM_HIDDEN) {
+                        mLauncher.showWorkspace(true);
+                    }
+                    appsPane.onTouchEvent(ev);
+                    return true;
+                } else {
+                    return appsPane.onTouchEvent(ev);
+                }
             }
         }
         return super.onTouchEvent(ev);
@@ -1465,7 +1459,7 @@
 
         int duration;
         if (shrinkState == ShrinkState.BOTTOM_HIDDEN || shrinkState == ShrinkState.BOTTOM_VISIBLE) {
-            duration = res.getInteger(R.integer.config_allAppsWorkspaceShrinkTime);
+            duration = res.getInteger(R.integer.config_appsCustomizeWorkspaceShrinkTime);
         } else {
             duration = res.getInteger(R.integer.config_customizeWorkspaceShrinkTime);
         }
@@ -1859,17 +1853,24 @@
 
             for (int i = 0; i < screenCount; i++) {
                 final CellLayout cl = (CellLayout)getChildAt(i);
-                float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
+                float finalAlphaValue = 0f;
+                float rotation = 0f;
+                if (LauncherApplication.isScreenXLarge()) {
+                    finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
+
+                    if (i < mCurrentPage) {
+                        rotation = WORKSPACE_ROTATION;
+                    } else if (i > mCurrentPage) {
+                        rotation = -WORKSPACE_ROTATION;
+                    }
+                } else {
+                    // Don't hide the side panes on the phone if we don't also update the side pages
+                    // alpha.  See screenScrolled().
+                    finalAlphaValue = 1f;
+                }
                 float finalAlphaMultiplierValue =
                         ((i == mCurrentPage) && (mShrinkState != ShrinkState.SPRING_LOADED)) ?
                         0.0f : 1.0f;
-                float rotation = 0.0f;
-
-                if (i < mCurrentPage) {
-                    rotation = WORKSPACE_ROTATION;
-                } else if (i > mCurrentPage) {
-                    rotation = -WORKSPACE_ROTATION;
-                }
 
                 float translation = getOffsetXForRotation(rotation, cl.getWidth(), cl.getHeight());
 
@@ -2878,16 +2879,21 @@
                         mSpringLoadedDragController.onDragExit();
                     }
                     mDragTargetLayout = layout;
-                    // In spring-loaded mode, we still want the user to be able to hover over a
-                    // full screen (which is traditionally set to not accept drops) if they want to
-                    // get to pages beyond the screen that is full.
-                    boolean allowDragOver = (mDragTargetLayout != null) &&
-                            (mDragTargetLayout.getAcceptsDrops() ||
-                                    (mShrinkState == ShrinkState.SPRING_LOADED));
-                    if (allowDragOver) {
-                        mDragTargetLayout.setIsDragOverlapping(true);
-                        mSpringLoadedDragController.onDragEnter(
-                                mDragTargetLayout, mShrinkState == ShrinkState.SPRING_LOADED);
+
+                    // Workaround the fact that we don't actually want spring-loaded mode in phone
+                    // UI yet.
+                    if (LauncherApplication.isScreenXLarge()) {
+                        // In spring-loaded mode, we still want the user to be able to hover over a
+                        // full screen (which is traditionally set to not accept drops) if they want
+                        // to get to pages beyond the screen that is full.
+                        boolean allowDragOver = (mDragTargetLayout != null) &&
+                                (mDragTargetLayout.getAcceptsDrops() ||
+                                        (mShrinkState == ShrinkState.SPRING_LOADED));
+                        if (allowDragOver) {
+                            mDragTargetLayout.setIsDragOverlapping(true);
+                            mSpringLoadedDragController.onDragEnter(
+                                    mDragTargetLayout, mShrinkState == ShrinkState.SPRING_LOADED);
+                        }
                     }
                 }
             } else {