merge in jb-release history after reset to jb-dev
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 2c13cf1..29b8f7d 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -40,8 +40,7 @@
     <string name="group_shortcuts" msgid="9133529424900391877">"Pintasan"</string>
     <string name="group_widgets" msgid="6704978494073105844">"Widget"</string>
     <string name="group_wallpapers" msgid="1568191644272224858">"Kertas dinding"</string>
-    <!-- no translation found for completely_out_of_space (1759078539443491182) -->
-    <skip />
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Tiada lagi ruang pada skrin Utama anda."</string>
     <string name="out_of_space" msgid="8365249326091984698">"Tiada lagi ruang pada skrin Utama ini"</string>
     <string name="hotseat_out_of_space" msgid="6304886797358479361">"Tiada lagi ruang pada kerusi panas."</string>
     <string name="invalid_hotseat_item" msgid="6545340627805449250">"Widget ini terlalu besar untuk kerusi panas."</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 7a15e41..2e434bd 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -40,8 +40,7 @@
     <string name="group_shortcuts" msgid="9133529424900391877">"Skróty"</string>
     <string name="group_widgets" msgid="6704978494073105844">"Widżety"</string>
     <string name="group_wallpapers" msgid="1568191644272224858">"Tapety"</string>
-    <!-- no translation found for completely_out_of_space (1759078539443491182) -->
-    <skip />
+    <string name="completely_out_of_space" msgid="1759078539443491182">"Brak miejsca na Twoich ekranach głównych."</string>
     <string name="out_of_space" msgid="8365249326091984698">"Brak miejsca na tej stronie głównej"</string>
     <string name="hotseat_out_of_space" msgid="6304886797358479361">"Brak miejsca w kieszonce."</string>
     <string name="invalid_hotseat_item" msgid="6545340627805449250">"Ten widżet jest za duży, aby umieścić go w kieszonce."</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index a79c704..e430420 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -40,8 +40,7 @@
     <string name="group_shortcuts" msgid="9133529424900391877">"快捷方式"</string>
     <string name="group_widgets" msgid="6704978494073105844">"窗口小部件"</string>
     <string name="group_wallpapers" msgid="1568191644272224858">"壁纸"</string>
-    <!-- no translation found for completely_out_of_space (1759078539443491182) -->
-    <skip />
+    <string name="completely_out_of_space" msgid="1759078539443491182">"您的主屏幕上没有空间了。"</string>
     <string name="out_of_space" msgid="8365249326091984698">"此主屏幕上已没有空间。"</string>
     <string name="hotseat_out_of_space" msgid="6304886797358479361">"底部区域已无空间。"</string>
     <string name="invalid_hotseat_item" msgid="6545340627805449250">"该窗口小部件太大,超出基座区域可用空间。"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7e9d12c..d9fbba2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -22,6 +22,8 @@
     <skip />
     <!-- Application name -->
     <string name="application_name">Launcher</string>
+    <!-- Accessibility-facing application name -->
+    <string name="home">Home</string>
     <!-- Name for all applications running as this uid. -->
     <string name="uid_name">Android Core Apps</string>
     <!-- Default folder name -->
diff --git a/src/com/android/launcher2/AppWidgetResizeFrame.java b/src/com/android/launcher2/AppWidgetResizeFrame.java
index 9df6f32..7281a6f 100644
--- a/src/com/android/launcher2/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher2/AppWidgetResizeFrame.java
@@ -307,11 +307,38 @@
             lp.cellVSpan = spanY;
             mRunningVInc += vSpanDelta;
             mRunningHInc += hSpanDelta;
+            if (!onDismiss) {
+                updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY);
+            }
         }
-
         mWidgetView.requestLayout();
     }
 
+    static void updateWidgetSizeRanges(AppWidgetHostView widgetView, Launcher launcher,
+            int spanX, int spanY) {
+        Rect landMetrics = Workspace.getCellLayoutMetrics(launcher, CellLayout.LANDSCAPE);
+        Rect portMetrics = Workspace.getCellLayoutMetrics(launcher, CellLayout.PORTRAIT);
+        final float density = launcher.getResources().getDisplayMetrics().density;
+
+        // Compute landscape size
+        int cellWidth = landMetrics.left;
+        int cellHeight = landMetrics.top;
+        int widthGap = landMetrics.right;
+        int heightGap = landMetrics.bottom;
+        int landWidth = (int) ((spanX * cellWidth + (spanX - 1) * widthGap) / density);
+        int landHeight = (int) ((spanY * cellHeight + (spanY - 1) * heightGap) / density);
+
+        // Compute portrait size
+        cellWidth = portMetrics.left;
+        cellHeight = portMetrics.top;
+        widthGap = portMetrics.right;
+        heightGap = portMetrics.bottom;
+        int portWidth = (int) ((spanX * cellWidth + (spanX - 1) * widthGap) / density);
+        int portHeight = (int) ((spanY * cellHeight + (spanY - 1) * heightGap) / density);
+
+        widgetView.updateAppWidgetSize(null, portWidth, landHeight, landWidth, portHeight);
+    }
+
     /**
      * This is the final step of the resize. Here we save the new widget size and position
      * to LauncherModel and animate the resize frame.
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 24e4047..2772d5c 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -146,6 +146,9 @@
     private static final boolean DESTRUCTIVE_REORDER = false;
     private static final boolean DEBUG_VISUALIZE_OCCUPIED = false;
 
+    static final int LANDSCAPE = 0;
+    static final int PORTRAIT = 1;
+
     private static final float REORDER_HINT_MAGNITUDE = 0.27f;
     private static final int REORDER_ANIMATION_DURATION = 150;
     private float mReorderHintAnimationMagnitude;
@@ -910,11 +913,10 @@
         return r;
     }
 
-    final int LANDSCAPE = 0;
-    final int PORTRAIT = 1;
-    void getCellLayoutMetrics(int measureWidth, int measureHeight, int orientation, Rect metrics) {
-        int numWidthGaps = mCountX - 1;
-        int numHeightGaps = mCountY - 1;
+    static void getMetrics(Rect metrics, Resources res, int measureWidth, int measureHeight,
+            int countX, int countY, int orientation) {
+        int numWidthGaps = countX - 1;
+        int numHeightGaps = countY - 1;
 
         int widthGap;
         int heightGap;
@@ -925,7 +927,7 @@
         int paddingTop;
         int paddingBottom;
 
-        Resources res = getContext().getResources();
+        int maxGap = res.getDimensionPixelSize(R.dimen.workspace_max_gap);
         if (orientation == LANDSCAPE) {
             cellWidth = res.getDimensionPixelSize(R.dimen.workspace_cell_width_land);
             cellHeight = res.getDimensionPixelSize(R.dimen.workspace_cell_height_land);
@@ -950,18 +952,16 @@
         if (widthGap < 0 || heightGap < 0) {
             int hSpace = measureWidth - paddingLeft - paddingRight;
             int vSpace = measureHeight - paddingTop - paddingBottom;
-            int hFreeSpace = hSpace - (mCountX * cellWidth);
-            int vFreeSpace = vSpace - (mCountY * cellHeight);
-            widthGap = Math.min(mMaxGap, numWidthGaps > 0 ? (hFreeSpace / numWidthGaps) : 0);
-            heightGap = Math.min(mMaxGap, numHeightGaps > 0 ? (vFreeSpace / numHeightGaps) : 0);
+            int hFreeSpace = hSpace - (countX * cellWidth);
+            int vFreeSpace = vSpace - (countY * cellHeight);
+            widthGap = Math.min(maxGap, numWidthGaps > 0 ? (hFreeSpace / numWidthGaps) : 0);
+            heightGap = Math.min(maxGap, numHeightGaps > 0 ? (vFreeSpace / numHeightGaps) : 0);
         }
         metrics.set(cellWidth, cellHeight, widthGap, heightGap);
     }
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        // TODO: currently ignoring padding
-
         int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
         int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
 
diff --git a/src/com/android/launcher2/DeleteDropTarget.java b/src/com/android/launcher2/DeleteDropTarget.java
index d8ea6ef..eb831f6 100644
--- a/src/com/android/launcher2/DeleteDropTarget.java
+++ b/src/com/android/launcher2/DeleteDropTarget.java
@@ -91,7 +91,17 @@
         return (source instanceof AppsCustomizePagedView) && (info instanceof ApplicationInfo);
     }
     private boolean isAllAppsWidget(DragSource source, Object info) {
-        return (source instanceof AppsCustomizePagedView) && (info instanceof PendingAddWidgetInfo);
+        if (source instanceof AppsCustomizePagedView) {
+            if (info instanceof PendingAddItemInfo) {
+                PendingAddItemInfo addInfo = (PendingAddItemInfo) info;
+                switch (addInfo.itemType) {
+                    case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+                    case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+                        return true;
+                }
+            }
+        }
+        return false;
     }
     private boolean isDragSourceWorkspaceOrFolder(DragObject d) {
         return (d.dragSource instanceof Workspace) || (d.dragSource instanceof Folder);
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index d63743f..b9d7dd4 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -380,10 +380,13 @@
                     // Added null checks to prevent NPE we've seen in the wild
                     if (dragInfo != null &&
                         dragInfo.intent != null &&
-                        info.intent != null &&
-                        dragInfo.intent.getComponent().equals(info.intent.getComponent())) {
-                        cancelDrag();
-                        return;
+                        info.intent != null) {
+                        boolean isSamePackage = dragInfo.intent.getPackage().equals(
+                                info.intent.getPackage());
+                        if (isSamePackage) {
+                            cancelDrag();
+                            return;
+                        }
                     }
                 }
             }
diff --git a/src/com/android/launcher2/InfoDropTarget.java b/src/com/android/launcher2/InfoDropTarget.java
index 2e0b5c8..134f4cb 100644
--- a/src/com/android/launcher2/InfoDropTarget.java
+++ b/src/com/android/launcher2/InfoDropTarget.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher2;
 
+import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -62,8 +63,8 @@
         }
     }
 
-    private boolean isAllAppsApplication(DragSource source, Object info) {
-        return (source instanceof AppsCustomizePagedView) && (info instanceof ApplicationInfo);
+    private boolean isFromAllApps(DragSource source) {
+        return (source instanceof AppsCustomizePagedView);
     }
 
     @Override
@@ -76,6 +77,8 @@
             componentName = ((ApplicationInfo) d.dragInfo).componentName;
         } else if (d.dragInfo instanceof ShortcutInfo) {
             componentName = ((ShortcutInfo) d.dragInfo).intent.getComponent();
+        } else if (d.dragInfo instanceof PendingAddItemInfo) {
+            componentName = ((PendingAddItemInfo) d.dragInfo).componentName;
         }
         if (componentName != null) {
             mLauncher.startApplicationDetailsActivity(componentName);
@@ -90,8 +93,8 @@
     public void onDragStart(DragSource source, Object info, int dragAction) {
         boolean isVisible = true;
 
-        // If we are dragging a widget or shortcut, hide the info target
-        if (!isAllAppsApplication(source, info)) {
+        // Hide this button unless we are dragging something from AllApps
+        if (!isFromAllApps(source)) {
             isVisible = false;
         }
 
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index fb27d02..cb737ff 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -105,6 +105,7 @@
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -161,6 +162,10 @@
     private static final String RUNTIME_STATE_PENDING_FOLDER_RENAME_ID = "launcher.rename_folder_id";
 
     private static final String TOOLBAR_ICON_METADATA_NAME = "com.android.launcher.toolbar_icon";
+    private static final String TOOLBAR_SEARCH_ICON_METADATA_NAME =
+            "com.android.launcher.toolbar_search_icon";
+    private static final String TOOLBAR_VOICE_SEARCH_ICON_METADATA_NAME =
+            "com.android.launcher.toolbar_voice_search_icon";
 
     /** The different states that Launcher can be in. */
     private enum State { WORKSPACE, APPS_CUSTOMIZE, APPS_CUSTOMIZE_SPRING_LOADED };
@@ -1079,7 +1084,8 @@
         }
 
         // Build Launcher-specific widget info and save to database
-        LauncherAppWidgetInfo launcherInfo = new LauncherAppWidgetInfo(appWidgetId);
+        LauncherAppWidgetInfo launcherInfo = new LauncherAppWidgetInfo(appWidgetId,
+                appWidgetInfo.provider);
         launcherInfo.spanX = spanXY[0];
         launcherInfo.spanY = spanXY[1];
         launcherInfo.minSpanX = mPendingAddInfo.minSpanX;
@@ -1100,6 +1106,8 @@
 
             launcherInfo.hostView.setTag(launcherInfo);
             launcherInfo.hostView.setVisibility(View.VISIBLE);
+            AppWidgetResizeFrame.updateWidgetSizeRanges(launcherInfo.hostView,
+                    this, launcherInfo.spanX, launcherInfo.spanY);
             mWorkspace.addInScreen(launcherInfo.hostView, container, screen, cellXY[0], cellXY[1],
                     launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked());
 
@@ -1148,7 +1156,6 @@
     public void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         mVisible = false;
-        mDragLayer.clearAllResizeFrames();
 
         if (mAttached) {
             unregisterReceiver(mReceiver);
@@ -1389,6 +1396,7 @@
         getContentResolver().unregisterContentObserver(mWidgetObserver);
         unregisterReceiver(mCloseSystemDialogsReceiver);
 
+        mDragLayer.clearAllResizeFrames();
         ((ViewGroup) mWorkspace.getParent()).removeAllViews();
         mWorkspace.removeAllViews();
         mWorkspace = null;
@@ -1845,9 +1853,23 @@
     public void onClickVoiceButton(View v) {
         v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
 
-        Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-        startActivitySafely(null, intent, "onClickVoiceButton");
+        try {
+            final SearchManager searchManager =
+                    (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+            ComponentName activityName = searchManager.getGlobalSearchActivity();
+            Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+            if (activityName != null) {
+                intent.setPackage(activityName.getPackageName());
+            }
+            startActivitySafely(null, intent, "onClickVoiceButton");
+        } catch (ActivityNotFoundException e) {
+            Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+            startActivitySafely(null, intent, "onClickVoiceButton");
+        }
     }
 
     /**
@@ -2693,14 +2715,14 @@
         }
     }
 
-    private Drawable getExternalPackageToolbarIcon(ComponentName activityName) {
+    private Drawable getExternalPackageToolbarIcon(ComponentName activityName, String resourceName) {
         try {
             PackageManager packageManager = getPackageManager();
             // Look for the toolbar icon specified in the activity meta-data
             Bundle metaData = packageManager.getActivityInfo(
                     activityName, PackageManager.GET_META_DATA).metaData;
             if (metaData != null) {
-                int iconResId = metaData.getInt(TOOLBAR_ICON_METADATA_NAME);
+                int iconResId = metaData.getInt(resourceName);
                 if (iconResId != 0) {
                     Resources res = packageManager.getResourcesForActivity(activityName);
                     return res.getDrawable(iconResId);
@@ -2720,8 +2742,9 @@
 
     // if successful in getting icon, return it; otherwise, set button to use default drawable
     private Drawable.ConstantState updateTextButtonWithIconFromExternalActivity(
-            int buttonId, ComponentName activityName, int fallbackDrawableId) {
-        Drawable toolbarIcon = getExternalPackageToolbarIcon(activityName);
+            int buttonId, ComponentName activityName, int fallbackDrawableId,
+            String toolbarResourceName) {
+        Drawable toolbarIcon = getExternalPackageToolbarIcon(activityName, toolbarResourceName);
         Resources r = getResources();
         int w = r.getDimensionPixelSize(R.dimen.toolbar_external_icon_width);
         int h = r.getDimensionPixelSize(R.dimen.toolbar_external_icon_height);
@@ -2746,9 +2769,10 @@
 
     // if successful in getting icon, return it; otherwise, set button to use default drawable
     private Drawable.ConstantState updateButtonWithIconFromExternalActivity(
-            int buttonId, ComponentName activityName, int fallbackDrawableId) {
+            int buttonId, ComponentName activityName, int fallbackDrawableId,
+            String toolbarResourceName) {
         ImageView button = (ImageView) findViewById(buttonId);
-        Drawable toolbarIcon = getExternalPackageToolbarIcon(activityName);
+        Drawable toolbarIcon = getExternalPackageToolbarIcon(activityName, toolbarResourceName);
 
         if (button != null) {
             // If we were unable to find the icon via the meta-data, use a
@@ -2798,7 +2822,14 @@
         if (activityName != null) {
             int coi = getCurrentOrientationIndexForGlobalIcons();
             sGlobalSearchIcon[coi] = updateButtonWithIconFromExternalActivity(
-                    R.id.search_button, activityName, R.drawable.ic_home_search_normal_holo);
+                    R.id.search_button, activityName, R.drawable.ic_home_search_normal_holo,
+                    TOOLBAR_SEARCH_ICON_METADATA_NAME);
+            if (sGlobalSearchIcon[coi] == null) {
+                sGlobalSearchIcon[coi] = updateButtonWithIconFromExternalActivity(
+                        R.id.search_button, activityName, R.drawable.ic_home_search_normal_holo,
+                        TOOLBAR_ICON_METADATA_NAME);
+            }
+
             if (searchDivider != null) searchDivider.setVisibility(View.VISIBLE);
             if (searchButtonContainer != null) searchButtonContainer.setVisibility(View.VISIBLE);
             searchButton.setVisibility(View.VISIBLE);
@@ -2830,12 +2861,34 @@
         final View voiceButtonProxy = findViewById(R.id.voice_button_proxy);
 
         // We only show/update the voice search icon if the search icon is enabled as well
-        Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
-        ComponentName activityName = intent.resolveActivity(getPackageManager());
+        final SearchManager searchManager =
+                (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+        ComponentName globalSearchActivity = searchManager.getGlobalSearchActivity();
+
+        ComponentName activityName = null;
+        if (globalSearchActivity != null) {
+            // Check if the global search activity handles voice search
+            Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+            intent.setPackage(globalSearchActivity.getPackageName());
+            activityName = intent.resolveActivity(getPackageManager());
+        }
+
+        if (activityName == null) {
+            // Fallback: check if an activity other than the global search activity
+            // resolves this
+            Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+            activityName = intent.resolveActivity(getPackageManager());
+        }
         if (searchVisible && activityName != null) {
             int coi = getCurrentOrientationIndexForGlobalIcons();
             sVoiceSearchIcon[coi] = updateButtonWithIconFromExternalActivity(
-                    R.id.voice_button, activityName, R.drawable.ic_home_voice_search_holo);
+                    R.id.voice_button, activityName, R.drawable.ic_home_voice_search_holo,
+                    TOOLBAR_VOICE_SEARCH_ICON_METADATA_NAME);
+            if (sVoiceSearchIcon[coi] == null) {
+                sVoiceSearchIcon[coi] = updateButtonWithIconFromExternalActivity(
+                        R.id.voice_button, activityName, R.drawable.ic_home_voice_search_holo,
+                        TOOLBAR_ICON_METADATA_NAME);
+            }
             if (searchDivider != null) searchDivider.setVisibility(View.VISIBLE);
             if (voiceButtonContainer != null) voiceButtonContainer.setVisibility(View.VISIBLE);
             voiceButton.setVisibility(View.VISIBLE);
@@ -2875,7 +2928,8 @@
             int coi = getCurrentOrientationIndexForGlobalIcons();
             mAppMarketIntent = intent;
             sAppMarketIcon[coi] = updateTextButtonWithIconFromExternalActivity(
-                    R.id.market_button, activityName, R.drawable.ic_launcher_market_holo);
+                    R.id.market_button, activityName, R.drawable.ic_launcher_market_holo,
+                    TOOLBAR_ICON_METADATA_NAME);
             marketButton.setVisibility(View.VISIBLE);
         } else {
             // We should hide and disable the view so that we don't try and restore the visibility
@@ -2889,6 +2943,15 @@
         updateTextButtonWithDrawable(R.id.market_button, d);
     }
 
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        boolean result = super.dispatchPopulateAccessibilityEvent(event);
+        final List<CharSequence> text = event.getText();
+        text.clear();
+        text.add(getString(R.string.home));
+        return result;
+    }
+
     /**
      * Receives notifications when system dialogs are to be closed.
      */
diff --git a/src/com/android/launcher2/LauncherAppWidgetInfo.java b/src/com/android/launcher2/LauncherAppWidgetInfo.java
index 844abb5..e5b9473 100644
--- a/src/com/android/launcher2/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher2/LauncherAppWidgetInfo.java
@@ -48,11 +48,9 @@
      */
     AppWidgetHostView hostView = null;
 
-    /**
-     * Constructor for use with AppWidgets that haven't been instantiated yet.
-     */
-    LauncherAppWidgetInfo(ComponentName providerName) {
+    LauncherAppWidgetInfo(int appWidgetId, ComponentName providerName) {
         itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
+        this.appWidgetId = appWidgetId;
         this.providerName = providerName;
 
         // Since the widget isn't instantiated yet, we don't know these values. Set them to -1
@@ -61,11 +59,6 @@
         spanY = -1;
     }
 
-    LauncherAppWidgetInfo(int appWidgetId) {
-        itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
-        this.appWidgetId = appWidgetId;
-    }
-
     @Override
     void onAddToDatabase(ContentValues values) {
         super.onAddToDatabase(values);
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 8f6ca4f..6d1cc75 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -1167,7 +1167,8 @@
                                 Launcher.sDumpLogs.add(log);
                                 itemsToRemove.add(id);
                             } else {
-                                appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId);
+                                appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
+                                        provider.provider);
                                 appWidgetInfo.id = id;
                                 appWidgetInfo.screen = c.getInt(screenIndex);
                                 appWidgetInfo.cellX = c.getInt(cellXIndex);
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 4bcb4c7..adfe0de 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -292,7 +292,9 @@
      * the previous tab page.
      */
     protected void updateCurrentPageScroll() {
-        int newX = getChildOffset(mCurrentPage) - getRelativeChildOffset(mCurrentPage);
+        int offset = getChildOffset(mCurrentPage);
+        int relOffset = getRelativeChildOffset(mCurrentPage);
+        int newX = offset - relOffset;
         scrollTo(newX, 0);
         mScroller.setFinalX(newX);
         mScroller.forceFinished(true);
@@ -505,6 +507,23 @@
 
         setMeasuredDimension(widthSize, heightSize);
 
+        if (childCount > 0) {
+            if (DEBUG) Log.d(TAG, "getRelativeChildOffset(): " + getMeasuredWidth() + ", "
+                    + getChildWidth(0));
+
+            // Calculate the variable page spacing if necessary
+            if (mPageSpacing < 0) {
+                // The gap between pages in the PagedView should be equal to the gap from the page
+                // to the edge of the screen (so it is not visible in the current screen).  To
+                // account for unequal padding on each side of the paged view, we take the maximum
+                // of the left/right gap and use that as the gap between each page.
+                int offset = getRelativeChildOffset(0);
+                int spacing = Math.max(offset, widthSize - offset -
+                        getChildAt(0).getMeasuredWidth());
+                setPageSpacing(spacing);
+            }
+        }
+
         // We can't call getChildOffset/getRelativeChildOffset until we set the measured dimensions.
         // We also wait until we set the measured dimensions before flushing the cache as well, to
         // ensure that the cache is filled with good values.
@@ -577,24 +596,7 @@
         if (DEBUG) Log.d(TAG, "PagedView.onLayout()");
         final int verticalPadding = getPaddingTop() + getPaddingBottom();
         final int childCount = getChildCount();
-        int childLeft = 0;
-        if (childCount > 0) {
-            if (DEBUG) Log.d(TAG, "getRelativeChildOffset(): " + getMeasuredWidth() + ", "
-                    + getChildWidth(0));
-            childLeft = getRelativeChildOffset(0);
-
-            // Calculate the variable page spacing if necessary
-            if (mPageSpacing < 0) {
-                // The gap between pages in the PagedView should be equal to the gap from the page
-                // to the edge of the screen (so it is not visible in the current screen).  To
-                // account for unequal padding on each side of the paged view, we take the maximum
-                // of the left/right gap and use that as the gap between each page.
-                int offset = getRelativeChildOffset(0);
-                int spacing = Math.max(offset, (right - left) - offset -
-                        getChildAt(0).getMeasuredWidth());
-                setPageSpacing(spacing);
-            }
-        }
+        int childLeft = getRelativeChildOffset(0);
 
         for (int i = 0; i < childCount; i++) {
             final View child = getPageAt(i);
@@ -619,10 +621,6 @@
             setHorizontalScrollBarEnabled(true);
             mFirstLayout = false;
         }
-
-        if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
-            mFirstLayout = false;
-        }
     }
 
     protected void screenScrolled(int screenCenter) {
@@ -709,13 +707,6 @@
         }
     }
 
-    protected int getScaledRelativeChildOffset(int index) {
-        final int padding = getPaddingLeft() + getPaddingRight();
-        final int offset = getPaddingLeft() + (getMeasuredWidth() - padding -
-                getScaledMeasuredWidth(getPageAt(index))) / 2;
-        return offset;
-    }
-
     protected int getScaledMeasuredWidth(View child) {
         // This functions are called enough times that it actually makes a difference in the
         // profiler -- so just inline the max() here
@@ -1702,10 +1693,12 @@
         // found
         if (mHasScrollIndicator && mScrollIndicator == null) {
             ViewGroup parent = (ViewGroup) getParent();
-            mScrollIndicator = (View) (parent.findViewById(R.id.paged_view_indicator));
-            mHasScrollIndicator = mScrollIndicator != null;
-            if (mHasScrollIndicator) {
-                mScrollIndicator.setVisibility(View.VISIBLE);
+            if (parent != null) {
+                mScrollIndicator = (View) (parent.findViewById(R.id.paged_view_indicator));
+                mHasScrollIndicator = mScrollIndicator != null;
+                if (mHasScrollIndicator) {
+                    mScrollIndicator.setVisibility(View.VISIBLE);
+                }
             }
         }
         return mScrollIndicator;
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index e9dffc5..404efc2 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -122,6 +122,9 @@
     private int mDragOverX = -1;
     private int mDragOverY = -1;
 
+    static Rect mLandscapeCellLayoutMetrics = null;
+    static Rect mPortraitCellLayoutMetrics = null;
+
     /**
      * The CellLayout that is currently being dragged over
      */
@@ -2389,6 +2392,44 @@
         }
     }
 
+    static Rect getCellLayoutMetrics(Launcher launcher, int orientation) {
+        Resources res = launcher.getResources();
+        Display display = launcher.getWindowManager().getDefaultDisplay();
+        Point smallestSize = new Point();
+        Point largestSize = new Point();
+        display.getCurrentSizeRange(smallestSize, largestSize);
+        if (orientation == CellLayout.LANDSCAPE) {
+            if (mLandscapeCellLayoutMetrics == null) {
+                int paddingLeft = res.getDimensionPixelSize(R.dimen.workspace_left_padding_land);
+                int paddingRight = res.getDimensionPixelSize(R.dimen.workspace_right_padding_land);
+                int paddingTop = res.getDimensionPixelSize(R.dimen.workspace_top_padding_land);
+                int paddingBottom = res.getDimensionPixelSize(R.dimen.workspace_bottom_padding_land);
+                int width = largestSize.x - paddingLeft - paddingRight;
+                int height = smallestSize.y - paddingTop - paddingBottom;
+                mLandscapeCellLayoutMetrics = new Rect();
+                CellLayout.getMetrics(mLandscapeCellLayoutMetrics, res,
+                        width, height, LauncherModel.getCellCountX(), LauncherModel.getCellCountY(),
+                        orientation);
+            }
+            return mLandscapeCellLayoutMetrics;
+        } else if (orientation == CellLayout.PORTRAIT) {
+            if (mPortraitCellLayoutMetrics == null) {
+                int paddingLeft = res.getDimensionPixelSize(R.dimen.workspace_left_padding_land);
+                int paddingRight = res.getDimensionPixelSize(R.dimen.workspace_right_padding_land);
+                int paddingTop = res.getDimensionPixelSize(R.dimen.workspace_top_padding_land);
+                int paddingBottom = res.getDimensionPixelSize(R.dimen.workspace_bottom_padding_land);
+                int width = smallestSize.x - paddingLeft - paddingRight;
+                int height = largestSize.y - paddingTop - paddingBottom;
+                mPortraitCellLayoutMetrics = new Rect();
+                CellLayout.getMetrics(mPortraitCellLayoutMetrics, res,
+                        width, height, LauncherModel.getCellCountX(), LauncherModel.getCellCountY(),
+                        orientation);
+            }
+            return mPortraitCellLayoutMetrics;
+        }
+        return null;
+    }
+
     public void onDragExit(DragObject d) {
         mDragEnforcer.onDragExit();
 
@@ -3572,7 +3613,7 @@
                             final Intent intent = info.intent;
                             final ComponentName name = intent.getComponent();
 
-                            if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
+                            if (name != null) {
                                 for (String packageName: packageNames) {
                                     if (packageName.equals(name.getPackageName())) {
                                         LauncherModel.deleteItemFromDatabase(mLauncher, info);
@@ -3592,7 +3633,7 @@
                                 final Intent intent = appInfo.intent;
                                 final ComponentName name = intent.getComponent();
 
-                                if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
+                                if (name != null) {
                                     for (String packageName: packageNames) {
                                         if (packageName.equals(name.getPackageName())) {
                                             appsToRemoveFromFolder.add(appInfo);
@@ -3606,11 +3647,10 @@
                             }
                         } else if (tag instanceof LauncherAppWidgetInfo) {
                             final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
-                            final AppWidgetProviderInfo provider =
-                                    widgets.getAppWidgetInfo(info.appWidgetId);
+                            final ComponentName provider = info.providerName;
                             if (provider != null) {
                                 for (String packageName: packageNames) {
-                                    if (packageName.equals(provider.provider.getPackageName())) {
+                                    if (packageName.equals(provider.getPackageName())) {
                                         LauncherModel.deleteItemFromDatabase(mLauncher, info);
                                         childrenToRemove.add(view);
                                     }