merge in ics-release history after reset to master
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 4bb64f7..c4aef8b 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -37,6 +37,8 @@
     <dimen name="workspace_divider_padding_top">12dp</dimen>
     <dimen name="workspace_divider_padding_bottom">12dp</dimen>
 
+    <dimen name="app_icon_padding_top">6dp</dimen>
+
     <!-- height of the bottom row of controls -->
     <dimen name="button_bar_height">68dip</dimen>
     <!-- Because portal animations go beyond the bounds of an icon, we need
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 1b806a6..544b970 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -29,6 +29,8 @@
     <dimen name="folder_cell_width">96dp</dimen>
     <dimen name="folder_cell_height">96dp</dimen>
 
+    <dimen name="app_icon_padding_top">4dp</dimen>
+
 <!-- AppsCustomize -->
     <dimen name="apps_customize_tab_bar_height">56dp</dimen>
     <dimen name="apps_customize_cell_width">96dp</dimen>
diff --git a/res/values-sw600dp/styles.xml b/res/values-sw600dp/styles.xml
index 31c2abd..0609002 100644
--- a/res/values-sw600dp/styles.xml
+++ b/res/values-sw600dp/styles.xml
@@ -23,7 +23,7 @@
         <item name="android:drawablePadding">0dp</item>
         <item name="android:paddingLeft">4dp</item>
         <item name="android:paddingRight">4dp</item>
-        <item name="android:paddingTop">4dp</item>
+        <item name="android:paddingTop">@dimen/app_icon_padding_top</item>
         <item name="android:paddingBottom">4dp</item>
         <item name="android:textSize">13sp</item>
     </style>
@@ -38,7 +38,7 @@
         <item name="android:drawablePadding">0dp</item>
         <item name="android:paddingLeft">4dp</item>
         <item name="android:paddingRight">4dp</item>
-        <item name="android:paddingTop">4dp</item>
+        <item name="android:paddingTop">@dimen/app_icon_padding_top</item>
         <item name="android:paddingBottom">4dp</item>
         <item name="android:textSize">13sp</item>
     </style>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 27e00b3..124cf16 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -42,6 +42,8 @@
     <dimen name="hotseat_height_gap">-1dp</dimen>
     <dimen name="workspace_overscroll_drawable_padding">0dp</dimen>
 
+    <dimen name="app_icon_padding_top">8dp</dimen>
+
 <!-- QSB -->
     <dimen name="toolbar_button_vertical_padding">0dip</dimen>
     <dimen name="toolbar_button_horizontal_padding">12dip</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6f6a158..3f77ce1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -27,19 +27,19 @@
     <!-- Default folder name -->
     <string name="folder_name"></string>
     <!-- Title of dialog that appears after user selects Wallpaper from menu -->
-    <string name="chooser_wallpaper">Select wallpaper from</string>
+    <string name="chooser_wallpaper">Choose wallpaper from</string>
     <!-- Button label on Wallpaper Gallery screen; user selects this button to set a specific wallpaper -->
     <string name="wallpaper_instructions">Set wallpaper</string>
     <!-- Option in "Select wallpaper from" dialog box -->
     <string name="pick_wallpaper">Wallpapers</string>
     <!-- Displayed when user selects a shortcut for an app that was uninstalled [CHAR_LIMIT=none]-->
-    <string name="activity_not_found">Application is not installed.</string>
+    <string name="activity_not_found">App isn\'t installed.</string>
     <!--  Labels for the tabs in the customize drawer -->
     <string name="widgets_tab_label">Widgets</string>
 
     <!-- AppsCustomize pane -->
     <!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] -->
-    <string name="long_press_widget_to_add">Touch &amp; hold to pick up a widget</string>
+    <string name="long_press_widget_to_add">Touch &amp; hold to pick up a widget.</string>
     <!-- Market button text.  The market button text is removed in Launcher.java 
          in the Phone UI. [CHAR LIMIT=32] -->
     <string name="market">Shop</string>
@@ -51,11 +51,11 @@
     <!-- External-drop widget error string.  This is the error that is shown
          when you drag and item into the homescreen and it is unable to fit,
          or an error is encountered. [CHAR_LIMIT=50] -->
-    <string name="external_drop_widget_error">Could not drop item onto this homescreen</string>
+    <string name="external_drop_widget_error">Couldn\'t drop item onto this Home screen.</string>
     <!-- External-drop widget pick title.  This is shown as the title of the
          dialog which allows you to pick which widgets to handle a particular
          drop if there are multiple choices. [CHAR_LIMIT=35] -->
-    <string name="external_drop_widget_pick_title">Select widget to create</string>
+    <string name="external_drop_widget_pick_title">Choose widget to create</string>
 
     <!-- Folders -->
     <skip />
@@ -73,7 +73,7 @@
     <!-- Title of dialog box -->
     <string name="menu_item_add_item">Add to Home screen</string>
     <!-- Options in "Add to Home" dialog box; Title of the group containing the list of all apps -->
-    <string name="group_applications">Applications</string>
+    <string name="group_applications">Apps</string>
     <!-- Options in "Add to Home" dialog box; Title of the group containing the list of all shortcut
 s -->
     <string name="group_shortcuts">Shortcuts</string>
@@ -95,7 +95,7 @@
     <!-- Title of dialog when user is selecting shortcut to add to homescreen -->
     <string name="title_select_shortcut">Select shortcut</string>
     <!-- Title of dialog when user is selecting an application to add to homescreen -->
-    <string name="title_select_application">Select application</string>
+    <string name="title_select_application">Choose app</string>
 
     <!-- All applications label -->
     <string name="all_apps_button_label">Apps</string>
@@ -121,7 +121,7 @@
     <!-- Accessibility: Voice Search button -->
     <string name="accessibility_voice_search_button">Voice Search</string>
     <!-- Accessibility: AllApps button -->
-    <string name="accessibility_all_apps_button">Applications</string>
+    <string name="accessibility_all_apps_button">Apps</string>
     <!-- Accessibility: Delete button -->
     <string name="accessibility_delete_button">Remove</string>
 
@@ -153,12 +153,12 @@
     <skip />
     <!-- Describes the button for uninstalling the currently selected application.
          Text is not displayed, but provided for accessibility. [CHAR_LIMIT=none] -->
-    <string name="cab_menu_delete_app">Uninstall application</string>
+    <string name="cab_menu_delete_app">Uninstall app</string>
     <!-- Describes the button for getting details/info about currently selected application.
          Text is not displayed, but provided for accessibility. [CHAR_LIMIT=none] -->
-    <string name="cab_menu_app_info">Application details</string>
+    <string name="cab_menu_app_info">App details</string>
     <!-- Appears in the CAB when an app is selected in All Apps or Customize mode. [CHAR_LIMIT=50] -->
-    <string name="cab_app_selection_text">1 application selected</string>
+    <string name="cab_app_selection_text">1 app selected</string>
     <!-- Appears in the CAB when a widget is selected in Customize mode. [CHAR_LIMIT=50] -->
     <string name="cab_widget_selection_text">1 widget selected</string>
     <!-- Appears in the CAB when a folder is selected in Customize mode. [CHAR_LIMIT=50] -->
@@ -171,22 +171,22 @@
     <!-- Permission short label -->
     <string name="permlab_install_shortcut">install shortcuts</string>
     <!-- Permission description -->
-    <string name="permdesc_install_shortcut">Allows an application to add
+    <string name="permdesc_install_shortcut">Allows an app to add
         shortcuts without user intervention.</string>
     <!-- Permission short label -->
     <string name="permlab_uninstall_shortcut">uninstall shortcuts</string>
     <!-- Permission description -->
-    <string name="permdesc_uninstall_shortcut">Allows an application to remove
+    <string name="permdesc_uninstall_shortcut">Allows an app to remove
         shortcuts without user intervention.</string>
     <!-- Permission short label -->
     <string name="permlab_read_settings">read Home settings and shortcuts</string>
     <!-- Permission description -->
-    <string name="permdesc_read_settings">Allows an application to read the settings and
+    <string name="permdesc_read_settings">Allows an app to read the settings and
         shortcuts in Home.</string>
     <!-- Permission short label -->
     <string name="permlab_write_settings">write Home settings and shortcuts</string>
     <!-- Permission description -->
-    <string name="permdesc_write_settings">Allows an application to change the settings and
+    <string name="permdesc_write_settings">Allows an app to change the settings and
         shortcuts in Home.</string>
 
     <!-- Widgets: -->
@@ -196,7 +196,7 @@
     <string name="gadget_error_text">Problem loading widget</string>
 
     <!-- Text to inform the user that they can't uninstall a system application -->
-    <string name="uninstall_system_app_text">This is a system application and cannot be uninstalled.</string>
+    <string name="uninstall_system_app_text">This is a system app and can\'t be uninstalled.</string>
 
     <!-- Title of the Android Dreams (screensaver) module -->
     <string name="dream_name">Rocket Launcher</string>
@@ -226,13 +226,13 @@
     <!-- The title text for the All Apps cling [CHAR_LIMIT=none] -->
     <string name="all_apps_cling_title">Choose some apps</string>
     <!-- The description of how to pick up and add an item to the workspace [CHAR_LIMIT=none] -->
-    <string name="all_apps_cling_add_item">To add an app to your home screen, touch &amp; hold it.</string>
+    <string name="all_apps_cling_add_item">To add an app to your Home screen, touch &amp; hold it.</string>
     <!-- The title text for the Folder cling [CHAR_LIMIT=none] -->
     <string name="folder_cling_title">Organize your apps with folders</string>
     <!-- The description of how to move an app [CHAR_LIMIT=none] -->
     <string name="folder_cling_move_item">To move an app, touch &amp; hold it.</string>
     <!-- The description of how to create a folder [CHAR_LIMIT=none] -->
-    <string name="folder_cling_create_folder">To make a new folder on your home screen, stack one app on top of another.</string>
+    <string name="folder_cling_create_folder">To make a new folder on your Home screen, stack one app on top of another.</string>
     <!-- The text on the button to dismiss a cling [CHAR_LIMIT=none] -->
     <string name="cling_dismiss">OK</string>
     <add-resource type="string" name="default_folder_name" />
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 04bddf1..f575f00 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -72,7 +72,7 @@
         <item name="android:drawablePadding">8dp</item>
         <item name="android:paddingLeft">4dp</item>
         <item name="android:paddingRight">4dp</item>
-        <item name="android:paddingTop">8dp</item>
+        <item name="android:paddingTop">@dimen/app_icon_padding_top</item>
         <item name="android:paddingBottom">4dp</item>
     </style>
 
@@ -80,7 +80,7 @@
         <item name="android:drawablePadding">2dp</item>
         <item name="android:paddingLeft">4dp</item>
         <item name="android:paddingRight">4dp</item>
-        <item name="android:paddingTop">6dp</item>
+        <item name="android:paddingTop">@dimen/app_icon_padding_top</item>
         <item name="android:paddingBottom">4dp</item>
     </style>
 
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index ed9d0cf..d8ff73c 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -643,12 +643,14 @@
     private void updateCurrentTab(int currentPage) {
         AppsCustomizeTabHost tabHost = getTabHost();
         String tag = tabHost.getCurrentTabTag();
-        if (currentPage >= mNumAppsPages &&
-                !tag.equals(tabHost.getTabTagForContentType(ContentType.Widgets))) {
-            tabHost.setCurrentTabFromContent(ContentType.Widgets);
-        } else if (currentPage < mNumAppsPages &&
-                !tag.equals(tabHost.getTabTagForContentType(ContentType.Applications))) {
-            tabHost.setCurrentTabFromContent(ContentType.Applications);
+        if (tag != null) {
+            if (currentPage >= mNumAppsPages &&
+                    !tag.equals(tabHost.getTabTagForContentType(ContentType.Widgets))) {
+                tabHost.setCurrentTabFromContent(ContentType.Widgets);
+            } else if (currentPage < mNumAppsPages &&
+                    !tag.equals(tabHost.getTabTagForContentType(ContentType.Applications))) {
+                tabHost.setCurrentTabFromContent(ContentType.Applications);
+            }
         }
     }
 
@@ -1195,6 +1197,11 @@
         return getChildAt(getChildCount() - index - 1);
     }
 
+    @Override
+    protected int indexToPage(int index) {
+        return getChildCount() - index - 1;
+    }
+
     // In apps customize, we have a scrolling effect which emulates pulling cards off of a stack.
     @Override
     protected void screenScrolled(int screenCenter) {
@@ -1362,8 +1369,10 @@
     public void reset() {
         AppsCustomizeTabHost tabHost = getTabHost();
         String tag = tabHost.getCurrentTabTag();
-        if (!tag.equals(tabHost.getTabTagForContentType(ContentType.Applications))) {
-            tabHost.setCurrentTabFromContent(ContentType.Applications);
+        if (tag != null) {
+            if (!tag.equals(tabHost.getTabTagForContentType(ContentType.Applications))) {
+                tabHost.setCurrentTabFromContent(ContentType.Applications);
+            }
         }
         if (mCurrentPage != 0) {
             invalidatePageData(0);
diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java
index 3690c12..688ea15 100644
--- a/src/com/android/launcher2/AppsCustomizeTabHost.java
+++ b/src/com/android/launcher2/AppsCustomizeTabHost.java
@@ -167,6 +167,14 @@
         mAppsCustomizePane.hideScrollingIndicator(false);
     }
 
+    private void reloadCurrentPage() {
+        if (!LauncherApplication.isScreenLarge()) {
+            mAppsCustomizePane.flashScrollingIndicator();
+        }
+        mAppsCustomizePane.loadAssociatedPages(mAppsCustomizePane.getCurrentPage());
+        mAppsCustomizePane.requestFocus();
+    }
+
     private void onTabChangedEnd(AppsCustomizePagedView.ContentType type) {
         mAppsCustomizePane.setContentType(type);
     }
@@ -188,6 +196,12 @@
         post(new Runnable() {
             @Override
             public void run() {
+                if (mAppsCustomizePane.getMeasuredWidth() <= 0 ||
+                        mAppsCustomizePane.getMeasuredHeight() <= 0) {
+                    reloadCurrentPage();
+                    return;
+                }
+
                 // Setup the animation buffer
                 Bitmap b = Bitmap.createBitmap(mAppsCustomizePane.getMeasuredWidth(),
                         mAppsCustomizePane.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
@@ -217,11 +231,7 @@
                 inAnim.addListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationEnd(Animator animation) {
-                        if (!LauncherApplication.isScreenLarge()) {
-                            mAppsCustomizePane.flashScrollingIndicator();
-                        }
-                        mAppsCustomizePane.loadAssociatedPages(
-                                mAppsCustomizePane.getCurrentPage());
+                        reloadCurrentPage();
                     }
                 });
                 AnimatorSet animSet = new AnimatorSet();
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index ad87fa6..54fdcc5 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -218,6 +218,7 @@
         });
         mCrosshairsAnimator.getAnimator().setInterpolator(mEaseOutInterpolator);
 
+        mDragCell[0] = mDragCell[1] = -1;
         for (int i = 0; i < mDragOutlines.length; i++) {
             mDragOutlines[i] = new Point(-1, -1);
         }
@@ -1171,13 +1172,13 @@
         result[1] = Math.max(0, result[1]); // Snap to top
     }
 
-    void visualizeDropLocation(
-            View v, Bitmap dragOutline, int originX, int originY, int spanX, int spanY) {
+    void visualizeDropLocation(View v, Bitmap dragOutline, int originX, int originY,
+            int spanX, int spanY, Point dragOffset, Rect dragRegion) {
 
         final int oldDragCellX = mDragCell[0];
         final int oldDragCellY = mDragCell[1];
         final int[] nearest = findNearestVacantArea(originX, originY, spanX, spanY, v, mDragCell);
-        if (v != null) {
+        if (v != null && dragOffset == null) {
             mDragCenter.set(originX + (v.getWidth() / 2), originY + (v.getHeight() / 2));
         } else {
             mDragCenter.set(originX, originY);
@@ -1198,7 +1199,7 @@
             int left = topLeft[0];
             int top = topLeft[1];
 
-            if (v != null) {
+            if (v != null && dragOffset == null) {
                 // When drawing the drag outline, it did not account for margin offsets
                 // added by the view's parent.
                 MarginLayoutParams lp = (MarginLayoutParams) v.getLayoutParams();
@@ -1213,11 +1214,19 @@
                 left += ((mCellWidth * spanX) + ((spanX - 1) * mWidthGap)
                         - dragOutline.getWidth()) / 2;
             } else {
-                // Center the drag outline in the cell
-                left += ((mCellWidth * spanX) + ((spanX - 1) * mWidthGap)
-                        - dragOutline.getWidth()) / 2;
-                top += ((mCellHeight * spanY) + ((spanY - 1) * mHeightGap)
-                        - dragOutline.getHeight()) / 2;
+                if (dragOffset != null && dragRegion != null) {
+                    // Center the drag region *horizontally* in the cell and apply a drag
+                    // outline offset
+                    left += dragOffset.x + ((mCellWidth * spanX) + ((spanX - 1) * mWidthGap)
+                             - dragRegion.width()) / 2;
+                    top += dragOffset.y;
+                } else {
+                    // Center the drag outline in the cell
+                    left += ((mCellWidth * spanX) + ((spanX - 1) * mWidthGap)
+                            - dragOutline.getWidth()) / 2;
+                    top += ((mCellHeight * spanY) + ((spanY - 1) * mHeightGap)
+                            - dragOutline.getHeight()) / 2;
+                }
             }
 
             final int oldIndex = mDragOutlineCurrent;
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 82aa30f..ee054ab 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -16,10 +16,9 @@
 
 package com.android.launcher2;
 
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProviderInfo;
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.Handler;
@@ -187,7 +186,7 @@
         int dragLayerX = loc[0];
         int dragLayerY = loc[1];
 
-        startDrag(b, dragLayerX, dragLayerY, source, dragInfo, dragAction, dragRegion);
+        startDrag(b, dragLayerX, dragLayerY, source, dragInfo, dragAction, null, dragRegion);
         b.recycle();
 
         if (dragAction == DRAG_ACTION_MOVE) {
@@ -214,7 +213,7 @@
         int dragLayerX = loc[0];
         int dragLayerY = loc[1];
 
-        startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, dragAction, dragRegion);
+        startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, dragAction, null, dragRegion);
 
         if (dragAction == DRAG_ACTION_MOVE) {
             v.setVisibility(View.GONE);
@@ -235,7 +234,7 @@
      */
     public void startDrag(Bitmap b, int dragLayerX, int dragLayerY,
             DragSource source, Object dragInfo, int dragAction) {
-        startDrag(b, dragLayerX, dragLayerY, source, dragInfo, dragAction, null);
+        startDrag(b, dragLayerX, dragLayerY, source, dragInfo, dragAction, null, null);
     }
 
     /**
@@ -253,7 +252,7 @@
      *          Makes dragging feel more precise, e.g. you can clip out a transparent border
      */
     public void startDrag(Bitmap b, int dragLayerX, int dragLayerY,
-            DragSource source, Object dragInfo, int dragAction, Rect dragRegion) {
+            DragSource source, Object dragInfo, int dragAction, Point dragOffset, Rect dragRegion) {
         if (PROFILE_DRAWING_DURING_DRAG) {
             android.os.Debug.startMethodTracing("Launcher");
         }
@@ -290,6 +289,9 @@
         final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX,
                 registrationY, 0, 0, b.getWidth(), b.getHeight());
 
+        if (dragOffset != null) {
+            dragView.setDragVisualizeOffset(new Point(dragOffset));
+        }
         if (dragRegion != null) {
             dragView.setDragRegion(new Rect(dragRegion));
         }
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index 386cb55..dd94175 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -24,11 +24,9 @@
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Paint;
+import android.graphics.Point;
 import android.graphics.Rect;
-import android.os.IBinder;
 import android.view.View;
-import android.view.WindowManager;
-import android.view.WindowManagerImpl;
 import android.view.animation.DecelerateInterpolator;
 
 import com.android.launcher.R;
@@ -39,6 +37,7 @@
     private int mRegistrationX;
     private int mRegistrationY;
 
+    private Point mDragVisualizeOffset = null;
     private Rect mDragRegion = null;
     private DragLayer mDragLayer = null;
     private boolean mHasDrawn = false;
@@ -135,6 +134,14 @@
         return mDragRegion.height();
     }
 
+    public void setDragVisualizeOffset(Point p) {
+        mDragVisualizeOffset = p;
+    }
+
+    public Point getDragVisualizeOffset() {
+        return mDragVisualizeOffset;
+    }
+
     public void setDragRegion(Rect r) {
         mDragRegion = r;
     }
diff --git a/src/com/android/launcher2/FocusHelper.java b/src/com/android/launcher2/FocusHelper.java
index 967b02f..1a7416a 100644
--- a/src/com/android/launcher2/FocusHelper.java
+++ b/src/com/android/launcher2/FocusHelper.java
@@ -125,18 +125,30 @@
     }
 
     /**
+     * Returns the Viewgroup containing page contents for the page at the index specified.
+     */
+    private static ViewGroup getAppsCustomizePage(ViewGroup container, int index) {
+        ViewGroup page = (ViewGroup) ((PagedView) container).getPageAt(index);
+        if (page instanceof PagedViewCellLayout) {
+            // There are two layers, a PagedViewCellLayout and PagedViewCellLayoutChildren
+            page = (ViewGroup) page.getChildAt(0);
+        }
+        return page;
+    }
+
+    /**
      * Handles key events in a PageViewExtendedLayout containing PagedViewWidgets.
      */
     static boolean handlePagedViewGridLayoutWidgetKeyEvent(PagedViewWidget w, int keyCode,
             KeyEvent e) {
 
         final PagedViewGridLayout parent = (PagedViewGridLayout) w.getParent();
-        final ViewGroup container = (ViewGroup) parent.getParent();
+        final PagedView container = (PagedView) parent.getParent();
         final TabHost tabHost = findTabHostParent(container);
         final TabWidget tabs = (TabWidget) tabHost.findViewById(com.android.internal.R.id.tabs);
         final int widgetIndex = parent.indexOfChild(w);
         final int widgetCount = parent.getChildCount();
-        final int pageIndex = container.indexOfChild(parent);
+        final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parent));
         final int pageCount = container.getChildCount();
         final int cellCountX = parent.getCellCountX();
         final int cellCountY = parent.getCellCountY();
@@ -145,7 +157,7 @@
 
         final int action = e.getAction();
         final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
-        PagedViewGridLayout newParent = null;
+        ViewGroup newParent = null;
         // Now that we load items in the bg asynchronously, we can't just focus
         // child siblings willy-nilly
         View child = null;
@@ -158,10 +170,11 @@
                         parent.getChildAt(widgetIndex - 1).requestFocus();
                     } else {
                         if (pageIndex > 0) {
-                            newParent = (PagedViewGridLayout)
-                                    container.getChildAt(pageIndex - 1);
-                            child = newParent.getChildAt(newParent.getChildCount() - 1);
-                            if (child != null) child.requestFocus();
+                            newParent = getAppsCustomizePage(container, pageIndex - 1);
+                            if (newParent != null) {
+                                child = newParent.getChildAt(newParent.getChildCount() - 1);
+                                if (child != null) child.requestFocus();
+                            }
                         }
                     }
                 }
@@ -174,10 +187,11 @@
                         parent.getChildAt(widgetIndex + 1).requestFocus();
                     } else {
                         if (pageIndex < (pageCount - 1)) {
-                            newParent = (PagedViewGridLayout)
-                                    container.getChildAt(pageIndex + 1);
-                            child = newParent.getChildAt(0);
-                            if (child != null) child.requestFocus();
+                            newParent = getAppsCustomizePage(container, pageIndex + 1);
+                            if (newParent != null) {
+                                child = newParent.getChildAt(0);
+                                if (child != null) child.requestFocus();
+                            }
                         }
                     }
                 }
@@ -221,8 +235,10 @@
                     // Select the first item on the previous page, or the first item on this page
                     // if there is no previous page
                     if (pageIndex > 0) {
-                        newParent = (PagedViewGridLayout) container.getChildAt(pageIndex - 1);
-                        child = newParent.getChildAt(0);
+                        newParent = getAppsCustomizePage(container, pageIndex - 1);
+                        if (newParent != null) {
+                            child = newParent.getChildAt(0);
+                        }
                     } else {
                         child = parent.getChildAt(0);
                     }
@@ -235,8 +251,10 @@
                     // Select the first item on the next page, or the last item on this page
                     // if there is no next page
                     if (pageIndex < (pageCount - 1)) {
-                        newParent = (PagedViewGridLayout) container.getChildAt(pageIndex + 1);
-                        child = newParent.getChildAt(0);
+                        newParent = getAppsCustomizePage(container, pageIndex + 1);
+                        if (newParent != null) {
+                            child = newParent.getChildAt(0);
+                        }
                     } else {
                         child = parent.getChildAt(widgetCount - 1);
                     }
@@ -265,38 +283,40 @@
     }
 
     /**
-     * Private helper method to get the PagedViewCellLayoutChildren given a PagedViewCellLayout
-     * index.
-     */
-    private static PagedViewCellLayoutChildren getPagedViewCellLayoutChildrenForIndex(
-            ViewGroup container, int i) {
-        ViewGroup parent = (ViewGroup) container.getChildAt(i);
-        return (PagedViewCellLayoutChildren) parent.getChildAt(0);
-    }
-
-    /**
      * Handles key events in a PageViewCellLayout containing PagedViewIcons.
      */
-    static boolean handlePagedViewIconKeyEvent(PagedViewIcon v, int keyCode, KeyEvent e) {
-        final PagedViewCellLayoutChildren parent = (PagedViewCellLayoutChildren) v.getParent();
-        final PagedViewCellLayout parentLayout = (PagedViewCellLayout) parent.getParent();
+    static boolean handleAppsCustomizeKeyEvent(View v, int keyCode, KeyEvent e) {
+        ViewGroup parentLayout;
+        ViewGroup itemContainer;
+        int countX;
+        int countY;
+        if (v.getParent() instanceof PagedViewCellLayoutChildren) {
+            itemContainer = (ViewGroup) v.getParent();
+            parentLayout = (ViewGroup) itemContainer.getParent();
+            countX = ((PagedViewCellLayout) parentLayout).getCellCountX();
+            countY = ((PagedViewCellLayout) parentLayout).getCellCountY();
+        } else {
+            itemContainer = parentLayout = (ViewGroup) v.getParent();
+            countX = ((PagedViewGridLayout) parentLayout).getCellCountX();
+            countY = ((PagedViewGridLayout) parentLayout).getCellCountY();
+        }
+
         // Note we have an extra parent because of the
         // PagedViewCellLayout/PagedViewCellLayoutChildren relationship
-        final ViewGroup container = (ViewGroup) parentLayout.getParent();
+        final PagedView container = (PagedView) parentLayout.getParent();
         final TabHost tabHost = findTabHostParent(container);
         final TabWidget tabs = (TabWidget) tabHost.findViewById(com.android.internal.R.id.tabs);
-        final int iconIndex = parent.indexOfChild(v);
-        final int widgetCount = parent.getChildCount();
-        final int pageIndex = container.indexOfChild(parentLayout);
+        final int iconIndex = itemContainer.indexOfChild(v);
+        final int itemCount = itemContainer.getChildCount();
+        final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parentLayout));
         final int pageCount = container.getChildCount();
-        final int cellCountX = parentLayout.getCellCountX();
-        final int cellCountY = parentLayout.getCellCountY();
-        final int x = iconIndex % cellCountX;
-        final int y = iconIndex / cellCountX;
+
+        final int x = iconIndex % countX;
+        final int y = iconIndex / countX;
 
         final int action = e.getAction();
         final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
-        PagedViewCellLayoutChildren newParent = null;
+        ViewGroup newParent = null;
         // Side pages do not always load synchronously, so check before focusing child siblings
         // willy-nilly
         View child = null;
@@ -306,12 +326,12 @@
                 if (handleKeyEvent) {
                     // Select the previous icon or the last icon on the previous page
                     if (iconIndex > 0) {
-                        parent.getChildAt(iconIndex - 1).requestFocus();
+                        itemContainer.getChildAt(iconIndex - 1).requestFocus();
                     } else {
                         if (pageIndex > 0) {
-                            newParent = getPagedViewCellLayoutChildrenForIndex(container,
-                                    pageIndex - 1);
+                            newParent = getAppsCustomizePage(container, pageIndex - 1);
                             if (newParent != null) {
+                                container.snapToPage(pageIndex - 1);
                                 child = newParent.getChildAt(newParent.getChildCount() - 1);
                                 if (child != null) child.requestFocus();
                             }
@@ -323,13 +343,13 @@
             case KeyEvent.KEYCODE_DPAD_RIGHT:
                 if (handleKeyEvent) {
                     // Select the next icon or the first icon on the next page
-                    if (iconIndex < (widgetCount - 1)) {
-                        parent.getChildAt(iconIndex + 1).requestFocus();
+                    if (iconIndex < (itemCount - 1)) {
+                        itemContainer.getChildAt(iconIndex + 1).requestFocus();
                     } else {
                         if (pageIndex < (pageCount - 1)) {
-                            newParent = getPagedViewCellLayoutChildrenForIndex(container,
-                                    pageIndex + 1);
+                            newParent = getAppsCustomizePage(container, pageIndex + 1);
                             if (newParent != null) {
+                                container.snapToPage(pageIndex + 1);
                                 child = newParent.getChildAt(0);
                                 if (child != null) child.requestFocus();
                             }
@@ -342,8 +362,8 @@
                 if (handleKeyEvent) {
                     // Select the closest icon in the previous row, otherwise select the tab bar
                     if (y > 0) {
-                        int newiconIndex = ((y - 1) * cellCountX) + x;
-                        parent.getChildAt(newiconIndex).requestFocus();
+                        int newiconIndex = ((y - 1) * countX) + x;
+                        itemContainer.getChildAt(newiconIndex).requestFocus();
                     } else {
                         tabs.requestFocus();
                     }
@@ -353,9 +373,9 @@
             case KeyEvent.KEYCODE_DPAD_DOWN:
                 if (handleKeyEvent) {
                     // Select the closest icon in the previous row, otherwise do nothing
-                    if (y < (cellCountY - 1)) {
-                        int newiconIndex = Math.min(widgetCount - 1, ((y + 1) * cellCountX) + x);
-                        parent.getChildAt(newiconIndex).requestFocus();
+                    if (y < (countY - 1)) {
+                        int newiconIndex = Math.min(itemCount - 1, ((y + 1) * countX) + x);
+                        itemContainer.getChildAt(newiconIndex).requestFocus();
                     }
                 }
                 wasHandled = true;
@@ -374,14 +394,14 @@
                     // Select the first icon on the previous page, or the first icon on this page
                     // if there is no previous page
                     if (pageIndex > 0) {
-                        newParent = getPagedViewCellLayoutChildrenForIndex(container,
-                                pageIndex - 1);
+                        newParent = getAppsCustomizePage(container, pageIndex - 1);
                         if (newParent != null) {
+                            container.snapToPage(pageIndex - 1);
                             child = newParent.getChildAt(0);
                             if (child != null) child.requestFocus();
                         }
                     } else {
-                        parent.getChildAt(0).requestFocus();
+                        itemContainer.getChildAt(0).requestFocus();
                     }
                 }
                 wasHandled = true;
@@ -391,14 +411,14 @@
                     // Select the first icon on the next page, or the last icon on this page
                     // if there is no next page
                     if (pageIndex < (pageCount - 1)) {
-                        newParent = getPagedViewCellLayoutChildrenForIndex(container,
-                                pageIndex + 1);
+                        newParent = getAppsCustomizePage(container, pageIndex + 1);
                         if (newParent != null) {
+                            container.snapToPage(pageIndex + 1);
                             child = newParent.getChildAt(0);
                             if (child != null) child.requestFocus();
                         }
                     } else {
-                        parent.getChildAt(widgetCount - 1).requestFocus();
+                        itemContainer.getChildAt(itemCount - 1).requestFocus();
                     }
                 }
                 wasHandled = true;
@@ -406,14 +426,14 @@
             case KeyEvent.KEYCODE_MOVE_HOME:
                 if (handleKeyEvent) {
                     // Select the first icon on this page
-                    parent.getChildAt(0).requestFocus();
+                    itemContainer.getChildAt(0).requestFocus();
                 }
                 wasHandled = true;
                 break;
             case KeyEvent.KEYCODE_MOVE_END:
                 if (handleKeyEvent) {
                     // Select the last icon on this page
-                    parent.getChildAt(widgetCount - 1).requestFocus();
+                    itemContainer.getChildAt(itemCount - 1).requestFocus();
                 }
                 wasHandled = true;
                 break;
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 8121d3b..7be19bf 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -270,6 +270,10 @@
         return getChildAt(index);
     }
 
+    protected int indexToPage(int index) {
+        return index;
+    }
+
     /**
      * Updates the scroll of the current page immediately to its final scroll position.  We use this
      * in CustomizePagedView to allow tabs to share the same PagedView while resetting the scroll of
@@ -714,7 +718,7 @@
 
     @Override
     public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
-        int page = indexOfChild(child);
+        int page = indexToPage(indexOfChild(child));
         if (page != mCurrentPage || !mScroller.isFinished()) {
             snapToPage(page);
             return true;
@@ -1287,7 +1291,7 @@
     @Override
     public void requestChildFocus(View child, View focused) {
         super.requestChildFocus(child, focused);
-        int page = indexOfChild(child);
+        int page = indexToPage(indexOfChild(child));
         if (page >= 0 && page != getCurrentPage() && !isInTouchMode()) {
             snapToPage(page);
         }
diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java
index 3ae978d..3cc7786 100644
--- a/src/com/android/launcher2/PagedViewIcon.java
+++ b/src/com/android/launcher2/PagedViewIcon.java
@@ -156,13 +156,13 @@
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
+        return FocusHelper.handleAppsCustomizeKeyEvent(this, keyCode, event)
                 || super.onKeyDown(keyCode, event);
     }
 
     @Override
     public boolean onKeyUp(int keyCode, KeyEvent event) {
-        return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
+        return FocusHelper.handleAppsCustomizeKeyEvent(this, keyCode, event)
                 || super.onKeyUp(keyCode, event);
     }
 
diff --git a/src/com/android/launcher2/PagedViewWidget.java b/src/com/android/launcher2/PagedViewWidget.java
index 4d5fd7b..12c98b2 100644
--- a/src/com/android/launcher2/PagedViewWidget.java
+++ b/src/com/android/launcher2/PagedViewWidget.java
@@ -167,13 +167,13 @@
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        return FocusHelper.handlePagedViewGridLayoutWidgetKeyEvent(this, keyCode, event)
+        return FocusHelper.handleAppsCustomizeKeyEvent(this, keyCode, event)
                 || super.onKeyDown(keyCode, event);
     }
 
     @Override
     public boolean onKeyUp(int keyCode, KeyEvent event) {
-        return FocusHelper.handlePagedViewGridLayoutWidgetKeyEvent(this, keyCode, event)
+        return FocusHelper.handleAppsCustomizeKeyEvent(this, keyCode, event)
                 || super.onKeyUp(keyCode, event);
     }
 
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index d1f9617..e4f1fe8 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -17,12 +17,12 @@
 package com.android.launcher2;
 
 import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
-import android.animation.Animator.AnimatorListener;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.app.AlertDialog;
 import android.app.WallpaperManager;
@@ -40,6 +40,7 @@
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Paint;
+import android.graphics.Point;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -1784,7 +1785,7 @@
                 v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888);
 
         canvas.setBitmap(b);
-        drawDragView(v, canvas, padding, false);
+        drawDragView(v, canvas, padding, true);
         mOutlineHelper.applyMediumExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor);
         canvas.setBitmap(null);
         return b;
@@ -1866,6 +1867,8 @@
     }
 
     public void beginDragShared(View child, DragSource source) {
+        Resources r = getResources();
+
         // We need to add extra padding to the bitmap to make room for the glow effect
         final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
 
@@ -1878,17 +1881,22 @@
         final int dragLayerX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
         int dragLayerY = mTempXY[1] - bitmapPadding / 2;
 
+        Point dragVisualizeOffset = null;
         Rect dragRect = null;
-        if (child instanceof BubbleTextView) {
-            int iconSize = getResources().getDimensionPixelSize(R.dimen.app_icon_size);
+        if (child instanceof BubbleTextView || child instanceof PagedViewIcon) {
+            int iconSize = r.getDimensionPixelSize(R.dimen.app_icon_size);
+            int iconPaddingTop = r.getDimensionPixelSize(R.dimen.app_icon_padding_top);
             int top = child.getPaddingTop();
             int left = (bmpWidth - iconSize) / 2;
             int right = left + iconSize;
             int bottom = top + iconSize;
             dragLayerY += top;
+            // Note: The drag region is used to calculate drag layer offsets, but the
+            // dragVisualizeOffset in addition to the dragRect (the size) to position the outline.
+            dragVisualizeOffset = new Point(-bitmapPadding / 2, iconPaddingTop - bitmapPadding / 2);
             dragRect = new Rect(left, top, right, bottom);
         } else if (child instanceof FolderIcon) {
-            int previewSize = getResources().getDimensionPixelSize(R.dimen.folder_preview_size);
+            int previewSize = r.getDimensionPixelSize(R.dimen.folder_preview_size);
             dragRect = new Rect(0, 0, child.getWidth(), previewSize);
         }
 
@@ -1899,7 +1907,7 @@
         }
 
         mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
-                DragController.DRAG_ACTION_MOVE, dragRect);
+                DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect);
         b.recycle();
     }
 
@@ -2354,13 +2362,13 @@
             showOutlines();
             layout.setIsDragOccuring(true);
             layout.onDragEnter();
-            layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1);
+            layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1, null, null);
 
             return true;
         }
         case DragEvent.ACTION_DRAG_LOCATION:
             // Visualize the drop location
-            layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1);
+            layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1, null, null);
             return true;
         case DragEvent.ACTION_DROP: {
             // Try and add any shortcuts
@@ -2727,7 +2735,8 @@
             if (!mCreateUserFolderOnDrop && !isOverFolder) {
                 mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
                         (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1],
-                        item.spanX, item.spanY);
+                        item.spanX, item.spanY, d.dragView.getDragVisualizeOffset(),
+                        d.dragView.getDragRegion());
             }
         }
     }