Initial changes to add configurable hotseat.

Change-Id: I4c2ed4a1c122c057662fabc70bfef7c5c088460b
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index ae22507..bd2a949 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -1863,6 +1863,7 @@
         int spanX;
         int spanY;
         int screen;
+        long container;
         boolean valid;
 
         @Override
diff --git a/src/com/android/launcher2/FocusHelper.java b/src/com/android/launcher2/FocusHelper.java
index d45c9ac..2a5f9c4 100644
--- a/src/com/android/launcher2/FocusHelper.java
+++ b/src/com/android/launcher2/FocusHelper.java
@@ -41,13 +41,13 @@
 }
 
 /**
- * A keyboard listener we set on all the dock buttons.
+ * A keyboard listener we set on all the hotseat buttons.
  */
-class DockKeyEventListener implements View.OnKeyListener {
+class HotseatKeyEventListener implements View.OnKeyListener {
     @Override
     public boolean onKey(View v, int keyCode, KeyEvent event) {
         final Configuration configuration = v.getResources().getConfiguration();
-        return FocusHelper.handleDockButtonKeyEvent(v, keyCode, event, configuration.orientation);
+        return FocusHelper.handleHotseatButtonKeyEvent(v, keyCode, event, configuration.orientation);
     }
 }
 
@@ -535,9 +535,9 @@
     }
 
     /**
-     * Handles key events in the workspace dock (bottom of the screen).
+     * Handles key events in the workspace hotseat (bottom of the screen).
      */
-    static boolean handleDockButtonKeyEvent(View v, int keyCode, KeyEvent e, int orientation) {
+    static boolean handleHotseatButtonKeyEvent(View v, int keyCode, KeyEvent e, int orientation) {
         final ViewGroup parent = (ViewGroup) v.getParent();
         final ViewGroup launcher = (ViewGroup) parent.getParent();
         final Workspace workspace = (Workspace) launcher.findViewById(R.id.workspace);
@@ -547,7 +547,7 @@
         final int pageCount = workspace.getChildCount();
 
         // NOTE: currently we don't special case for the phone UI in different
-        // orientations, even though the dock is on the side in landscape mode.  This
+        // orientations, even though the hotseat is on the side in landscape mode.  This
         // is to ensure that accessibility consistency is maintained across rotations.
 
         final int action = e.getAction();
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 7641fe7..96cd22b 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -732,8 +732,7 @@
         int centeredTop = centerY - height / 2;
 
         // We first fetch the currently visible CellLayoutChildren
-        int page = mLauncher.getWorkspace().getCurrentPage();
-        CellLayout currentPage = (CellLayout) mLauncher.getWorkspace().getChildAt(page);
+        CellLayout currentPage = mLauncher.getWorkspace().getCurrentDropLayout();
         CellLayoutChildren boundingLayout = currentPage.getChildrenLayout();
         Rect bounds = new Rect();
         parent.getDescendantRectRelativeToSelf(boundingLayout, bounds);
@@ -851,8 +850,7 @@
         }
 
         // Remove the folder completely
-        final CellLayout cellLayout = (CellLayout)
-                mLauncher.getWorkspace().getChildAt(mInfo.screen);
+        CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screen);
         cellLayout.removeView(mFolderIcon);
         if (mFolderIcon instanceof DropTarget) {
             mDragController.removeDropTarget((DropTarget) mFolderIcon);
@@ -860,9 +858,8 @@
         mLauncher.removeFolder(mInfo);
 
         if (finalItem != null) {
-            LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem,
-                    LauncherSettings.Favorites.CONTAINER_DESKTOP, mInfo.screen,
-                    mInfo.cellX, mInfo.cellY);
+            LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem, mInfo.container,
+                    mInfo.screen, mInfo.cellX, mInfo.cellY);
         }
         LauncherModel.deleteItemFromDatabase(mLauncher, mInfo);
 
@@ -871,8 +868,8 @@
             View child = mLauncher.createShortcut(R.layout.application, cellLayout,
                     (ShortcutInfo) finalItem);
 
-            mLauncher.getWorkspace().addInScreen(child, mInfo.screen, mInfo.cellX, mInfo.cellY, 
-                    mInfo.spanX, mInfo.spanY);
+            mLauncher.getWorkspace().addInScreen(child, mInfo.container, mInfo.screen, mInfo.cellX,
+                    mInfo.cellY, mInfo.spanX, mInfo.spanY);
         }
     }
 
diff --git a/src/com/android/launcher2/Hotseat.java b/src/com/android/launcher2/Hotseat.java
new file mode 100644
index 0000000..deab131
--- /dev/null
+++ b/src/com/android/launcher2/Hotseat.java
@@ -0,0 +1,114 @@
+/*
+ * 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.Configuration;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.launcher.R;
+
+public class Hotseat extends FrameLayout {
+    static final String TAG = "Hotseat";
+
+    private Launcher mLauncher;
+    private CellLayout mContent;
+
+    private int mCellCountX;
+    private int mCellCountY;
+    private boolean mIsLandscape;
+
+    public Hotseat(Context context) {
+        this(context, null);
+    }
+
+    public Hotseat(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public Hotseat(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.Hotseat, defStyle, 0);
+        mCellCountX = a.getInt(R.styleable.Hotseat_cellCountX, -1);
+        mCellCountY = a.getInt(R.styleable.Hotseat_cellCountY, -1);
+        mIsLandscape = context.getResources().getConfiguration().orientation ==
+            Configuration.ORIENTATION_LANDSCAPE;
+    }
+
+    public void setup(Launcher launcher) {
+        mLauncher = launcher;
+    }
+
+    CellLayout getLayout() {
+        return mContent;
+    }
+
+    /* Get the orientation invariant order of the item in the hotseat for persistence. */
+    int getOrderInHotseat(int x, int y) {
+        return mIsLandscape ? (mContent.getCountY() - y - 1) : x;
+    }
+    /* Get the orientation specific coordinates given an invariant order in the hotseat. */
+    int getCellXFromOrder(int rank) {
+        return mIsLandscape ? 0 : rank;
+    }
+    int getCellYFromOrder(int rank) {
+        return mIsLandscape ? (mContent.getCountY() - (rank + 1)) : 0;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        if (mCellCountX < 0) mCellCountX = LauncherModel.getCellCountX();
+        if (mCellCountY < 0) mCellCountY = LauncherModel.getCellCountY();
+        mContent = (CellLayout) findViewById(R.id.layout);
+        mContent.setGridSize(mCellCountX, mCellCountY);
+
+        resetLayout();
+    }
+
+    void resetLayout() {
+        mContent.removeAllViewsInLayout();
+
+        // Add the Apps button
+        Context context = getContext();
+        LayoutInflater inflater = LayoutInflater.from(context);
+        BubbleTextView allAppsButton = (BubbleTextView)
+                inflater.inflate(R.layout.application, mContent, false);
+        allAppsButton.setCompoundDrawablesWithIntrinsicBounds(null,
+                context.getResources().getDrawable(R.drawable.apps_hotseat_button), null, null);
+        // button.setText(context.getString(R.string.all_apps_button_label));
+        allAppsButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(android.view.View v) {
+                mLauncher.showAllApps(true);
+            }
+        });
+
+        // Note: We do this to ensure that the hotseat is always laid out in the orientation of
+        // the hotseat in order regardless of which orientation they were added
+        int x = getCellXFromOrder(0);
+        int y = getCellYFromOrder(0);
+        mContent.addViewToCellLayout(allAppsButton, -1, 0, new CellLayout.LayoutParams(x,y,1,1),
+                true);
+    }
+}
diff --git a/src/com/android/launcher2/InstallShortcutReceiver.java b/src/com/android/launcher2/InstallShortcutReceiver.java
index c67e90e..9d7054c 100644
--- a/src/com/android/launcher2/InstallShortcutReceiver.java
+++ b/src/com/android/launcher2/InstallShortcutReceiver.java
@@ -65,7 +65,8 @@
                 boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
                 if (duplicate || !LauncherModel.shortcutExists(context, name, intent)) {
                     LauncherApplication app = (LauncherApplication) context.getApplicationContext();
-                    app.getModel().addShortcut(context, data, screen, mCoordinates[0], 
+                    app.getModel().addShortcut(context, data,
+                            LauncherSettings.Favorites.CONTAINER_DESKTOP, screen, mCoordinates[0],
                             mCoordinates[1], true);
                     Toast.makeText(context, context.getString(R.string.shortcut_installed, name),
                             Toast.LENGTH_SHORT).show();
@@ -94,14 +95,16 @@
         int cellX, cellY, spanX, spanY;
         for (int i = 0; i < items.size(); ++i) {
             item = items.get(i);
-            if (item.screen == screen) {
-                cellX = item.cellX;
-                cellY = item.cellY;
-                spanX = item.spanX;
-                spanY = item.spanY;
-                for (int x = cellX; x < cellX + spanX && x < xCount; x++) {
-                    for (int y = cellY; y < cellY + spanY && y < yCount; y++) {
-                        occupied[x][y] = true;
+            if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                if (item.screen == screen) {
+                    cellX = item.cellX;
+                    cellY = item.cellY;
+                    spanX = item.spanX;
+                    spanY = item.spanY;
+                    for (int x = cellX; x < cellX + spanX && x < xCount; x++) {
+                        for (int y = cellY; y < cellY + spanY && y < yCount; y++) {
+                            occupied[x][y] = true;
+                        }
                     }
                 }
             }
diff --git a/src/com/android/launcher2/InstallWidgetReceiver.java b/src/com/android/launcher2/InstallWidgetReceiver.java
index b4ce038..6b3763c 100644
--- a/src/com/android/launcher2/InstallWidgetReceiver.java
+++ b/src/com/android/launcher2/InstallWidgetReceiver.java
@@ -188,7 +188,8 @@
 
             final PendingAddWidgetInfo createInfo = new PendingAddWidgetInfo(widgetInfo, mMimeType,
                     mClipData);
-            mLauncher.addAppWidgetFromDrop(createInfo, mTargetLayoutScreen, null, mTargetLayoutPos);
+            mLauncher.addAppWidgetFromDrop(createInfo, LauncherSettings.Favorites.CONTAINER_DESKTOP,
+                    mTargetLayoutScreen, null, mTargetLayoutPos);
         }
     }
 }
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 26f41fa..90bd151 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -115,7 +115,6 @@
 
     static final boolean PROFILE_STARTUP = false;
     static final boolean DEBUG_WIDGETS = false;
-    static final boolean DEBUG_USER_INTERFACE = false;
 
     private static final int MENU_GROUP_ADD = 1;
     private static final int MENU_GROUP_WALLPAPER = MENU_GROUP_ADD + 1;
@@ -149,6 +148,8 @@
     // Type: int
     private static final String RUNTIME_STATE = "launcher.state";
     // Type: int
+    private static final String RUNTIME_STATE_PENDING_ADD_CONTAINER = "launcher.add_container";
+    // Type: int
     private static final String RUNTIME_STATE_PENDING_ADD_SCREEN = "launcher.add_screen";
     // Type: int
     private static final String RUNTIME_STATE_PENDING_ADD_CELL_X = "launcher.add_cell_x";
@@ -185,16 +186,14 @@
     private AppWidgetManager mAppWidgetManager;
     private LauncherAppWidgetHost mAppWidgetHost;
 
-    private int mAddScreen = -1;
-    private int mAddCellX = -1;
-    private int mAddCellY = -1;
-    private int[] mAddDropPosition;
+    private ItemInfo mPendingAddInfo = new ItemInfo();
     private int[] mTmpAddItemCellCoordinates = new int[2];
 
     private FolderInfo mFolderInfo;
 
-    private ViewGroup mButtonCluster;
+    private Hotseat mHotseat;
     private View mAllAppsButton;
+
     private SearchDropTargetBar mSearchDeleteBar;
     private AppsCustomizeTabHost mAppsCustomizeTabHost;
     private AppsCustomizePagedView mAppsCustomizeContent;
@@ -259,6 +258,7 @@
     private static class PendingAddArguments {
         int requestCode;
         Intent intent;
+        long container;
         int screen;
         int cellX;
         int cellY;
@@ -600,20 +600,22 @@
     private boolean completeAdd(PendingAddArguments args) {
         switch (args.requestCode) {
             case REQUEST_PICK_APPLICATION:
-                completeAddApplication(args.intent, args.screen, args.cellX, args.cellY);
+                completeAddApplication(args.intent, args.container, args.screen, args.cellX,
+                        args.cellY);
                 break;
             case REQUEST_PICK_SHORTCUT:
                 processShortcut(args.intent);
                 break;
             case REQUEST_CREATE_SHORTCUT:
-                completeAddShortcut(args.intent, args.screen, args.cellX, args.cellY);
+                completeAddShortcut(args.intent, args.container, args.screen, args.cellX,
+                        args.cellY);
                 return true;
             case REQUEST_PICK_APPWIDGET:
                 addAppWidgetFromPick(args.intent);
                 break;
             case REQUEST_CREATE_APPWIDGET:
                 int appWidgetId = args.intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
-                completeAddAppWidget(appWidgetId, args.screen);
+                completeAddAppWidget(appWidgetId, args.container, args.screen);
                 return true;
             case REQUEST_PICK_WALLPAPER:
                 // We just wanted the activity result here so we can clear mWaitingForResult
@@ -632,13 +634,15 @@
 
         // For example, the user would PICK_SHORTCUT for "Music playlist", and we
         // launch over to the Music app to actually CREATE_SHORTCUT.
-        if (resultCode == RESULT_OK && mAddScreen != -1) {
+        if (resultCode == RESULT_OK && mPendingAddInfo.container != ItemInfo.NO_ID  &&
+                mPendingAddInfo.screen > -1) {
             final PendingAddArguments args = new PendingAddArguments();
             args.requestCode = requestCode;
             args.intent = data;
-            args.screen = mAddScreen;
-            args.cellX = mAddCellX;
-            args.cellY = mAddCellY;
+            args.container = mPendingAddInfo.container;
+            args.screen = mPendingAddInfo.screen;
+            args.cellX = mPendingAddInfo.cellX;
+            args.cellY = mPendingAddInfo.cellY;
 
             // If the loader is still running, defer the add until it is done.
             if (isWorkspaceLocked()) {
@@ -797,12 +801,15 @@
             mWorkspace.setCurrentPage(currentScreen);
         }
 
-        final int addScreen = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SCREEN, -1);
+        final long pendingAddContainer = savedState.getLong(RUNTIME_STATE_PENDING_ADD_CONTAINER, -1);
+        final int pendingAddScreen = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SCREEN, -1);
 
-        if (addScreen > -1) {
-            mAddScreen = addScreen;
-            mAddCellX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_X);
-            mAddCellY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_Y);
+
+        if (pendingAddContainer != ItemInfo.NO_ID && pendingAddScreen > -1) {
+            mPendingAddInfo.container = pendingAddContainer;
+            mPendingAddInfo.screen = pendingAddScreen;
+            mPendingAddInfo.cellX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_X);
+            mPendingAddInfo.cellY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_Y);
             mRestoring = true;
         }
 
@@ -841,6 +848,12 @@
         // Setup the drag layer
         mDragLayer.setup(this, dragController);
 
+        // Setup the hotseat
+        mHotseat = (Hotseat) findViewById(R.id.hotseat);
+        if (mHotseat != null) {
+            mHotseat.setup(this);
+        }
+
         // Setup the workspace
         mWorkspace.setHapticFeedbackEnabled(false);
         mWorkspace.setOnLongClickListener(this);
@@ -857,47 +870,9 @@
                 mAppsCustomizeTabHost.findViewById(R.id.apps_customize_pane_content);
         mAppsCustomizeContent.setup(this, dragController);
 
-        // Setup AppsCustomize button
-        mAllAppsButton = mDragLayer.findViewById(R.id.all_apps_button);
-        mAllAppsButton.setOnClickListener(new OnClickListener() {
-            public void onClick(View v) {
-                onClickAllAppsButton(v);
-            }
-        });
 
-        if (!LauncherApplication.isScreenLarge()) {
-            // Setup AppsCustomize button on the phone
-            HandleView handleView = (HandleView) mAllAppsButton;
-            handleView.setLauncher(this);
-            handleView.setOnLongClickListener(this);
 
-            // Setup Hotseat
-            ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left);
-            hotseatLeft.setContentDescription(mHotseatLabels[0]);
-            hotseatLeft.setImageDrawable(mHotseatIcons[0]);
-            ImageView hotseatRight = (ImageView) findViewById(R.id.hotseat_right);
-            hotseatRight.setContentDescription(mHotseatLabels[1]);
-            hotseatRight.setImageDrawable(mHotseatIcons[1]);
-        }
-
-        if (!LauncherApplication.isScreenLarge()) {
-            // Setup keylistener for button cluster
-            mButtonCluster = (ViewGroup) findViewById(R.id.all_apps_button_cluster);
-            View.OnKeyListener listener = null;
-            if (LauncherApplication.isScreenLarge()) {
-                // For tablets, AllApps lives in the button bar at the top
-                listener = new ButtonBarKeyEventListener();
-            } else {
-                // For phones, AppsCustomize lives in the "dock" at the bottom
-                listener = new DockKeyEventListener();
-            }
-            int buttonCount = mButtonCluster.getChildCount();
-            for (int i = 0; i < buttonCount; ++i) {
-                mButtonCluster.getChildAt(i).setOnKeyListener(listener);
-            }
-        }
-
-        // Setup the drag controller (the drop targets have to be added in reverse order)
+        // Setup the drag controller (drop targets have to be added in reverse order in priority)
         dragController.setDragScoller(mWorkspace);
         dragController.setScrollView(mDragLayer);
         dragController.setMoveTarget(mWorkspace);
@@ -907,40 +882,7 @@
         }
     }
 
-    @SuppressWarnings({"UnusedDeclaration"})
-    public void previousScreen(View v) {
-        if (mState != State.APPS_CUSTOMIZE) {
-            mWorkspace.scrollLeft();
-        }
-    }
 
-    @SuppressWarnings({"UnusedDeclaration"})
-    public void nextScreen(View v) {
-        if (mState != State.APPS_CUSTOMIZE) {
-            mWorkspace.scrollRight();
-        }
-    }
-
-    @SuppressWarnings({"UnusedDeclaration"})
-    public void launchHotSeat(View v) {
-        if (mState == State.APPS_CUSTOMIZE) return;
-
-        int index = -1;
-        if (v.getId() == R.id.hotseat_left) {
-            index = 0;
-        } else if (v.getId() == R.id.hotseat_right) {
-            index = 1;
-        }
-
-        // reload these every tap; you never know when they might change
-        loadHotseats();
-        if (index >= 0 && index < mHotseats.length && mHotseats[index] != null) {
-            startActivitySafely(
-                mHotseats[index],
-                "hotseat"
-            );
-        }
-    }
 
     /**
      * Creates a view representing a shortcut.
@@ -976,9 +918,9 @@
      * @param data The intent describing the application.
      * @param cellInfo The position on screen where to create the shortcut.
      */
-    void completeAddApplication(Intent data, int screen, int cellX, int cellY) {
+    void completeAddApplication(Intent data, long container, int screen, int cellX, int cellY) {
         final int[] cellXY = mTmpAddItemCellCoordinates;
-        final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
+        final CellLayout layout = getCellLayout(container, screen);
 
         // First we check if we already know the exact location where we want to add this item.
         if (cellX >= 0 && cellY >= 0) {
@@ -995,7 +937,7 @@
             info.setActivity(data.getComponent(), Intent.FLAG_ACTIVITY_NEW_TASK |
                     Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
             info.container = ItemInfo.NO_ID;
-            mWorkspace.addApplicationShortcut(info, screen, cellXY[0], cellXY[1],
+            mWorkspace.addApplicationShortcut(info, layout, container, screen, cellXY[0], cellXY[1],
                     isWorkspaceLocked(), cellX, cellY);
         } else {
             Log.e(TAG, "Couldn't find ActivityInfo for selected application: " + data);
@@ -1008,11 +950,12 @@
      * @param data The intent describing the shortcut.
      * @param cellInfo The position on screen where to create the shortcut.
      */
-    private void completeAddShortcut(Intent data, int screen, int cellX, int cellY) {
-        final int[] cellXY = mTmpAddItemCellCoordinates;
-        final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
+    private void completeAddShortcut(Intent data, long container, int screen, int cellX,
+            int cellY) {
+        int[] cellXY = mTmpAddItemCellCoordinates;
+        int[] touchXY = mPendingAddInfo.dropPos;
+        CellLayout layout = getCellLayout(container, screen);
 
-        int[] touchXY = mAddDropPosition;
         boolean foundCellSpan = false;
 
         // First we check if we already know the exact location where we want to add this item.
@@ -1022,9 +965,7 @@
             foundCellSpan = true;
         } else if (touchXY != null) {
             // when dragging and dropping, just find the closest free spot
-            CellLayout screenLayout = (CellLayout) mWorkspace.getChildAt(screen);
-            int[] result = screenLayout.findNearestVacantArea(
-                    touchXY[0], touchXY[1], 1, 1, cellXY);
+            int[] result = layout.findNearestVacantArea(touchXY[0], touchXY[1], 1, 1, cellXY);
             foundCellSpan = (result != null);
         } else {
             foundCellSpan = layout.findCellForSpan(cellXY, 1, 1);
@@ -1036,11 +977,12 @@
         }
 
         final ShortcutInfo info = mModel.addShortcut(
-                this, data, screen, cellXY[0], cellXY[1], false);
+                this, data, container, screen, cellXY[0], cellXY[1], false);
 
         if (!mRestoring) {
             final View view = createShortcut(info);
-            mWorkspace.addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, isWorkspaceLocked());
+            mWorkspace.addInScreen(view, container, screen, cellXY[0], cellXY[1], 1, 1,
+                    isWorkspaceLocked());
         }
     }
 
@@ -1050,11 +992,11 @@
      * @param appWidgetId The app widget id
      * @param cellInfo The position on screen where to create the widget.
      */
-    private void completeAddAppWidget(final int appWidgetId, int screen) {
+    private void completeAddAppWidget(final int appWidgetId, long container, int screen) {
         AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
 
         // Calculate the grid spans needed to fit this widget
-        CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
+        CellLayout layout = getCellLayout(container, screen);
 
         // We want to account for the extra amount of padding that we are adding to the widget
         // to ensure that it gets the full amount of space that it has requested
@@ -1070,18 +1012,16 @@
         // Try finding open space on Launcher screen
         // We have saved the position to which the widget was dragged-- this really only matters
         // if we are placing widgets on a "spring-loaded" screen
-        final int[] cellXY = mTmpAddItemCellCoordinates;
-
-        int[] touchXY = mAddDropPosition;
+        int[] cellXY = mTmpAddItemCellCoordinates;
+        int[] touchXY = mPendingAddInfo.dropPos;
         boolean foundCellSpan = false;
-        if (mAddCellX >= 0 && mAddCellY >= 0) {
-            cellXY[0] = mAddCellX;
-            cellXY[1] = mAddCellY;
+        if (mPendingAddInfo.cellX >= 0 && mPendingAddInfo.cellY >= 0) {
+            cellXY[0] = mPendingAddInfo.cellX;
+            cellXY[1] = mPendingAddInfo.cellY;
             foundCellSpan = true;
         } else if (touchXY != null) {
             // when dragging and dropping, just find the closest free spot
-            CellLayout screenLayout = (CellLayout) mWorkspace.getChildAt(screen);
-            int[] result = screenLayout.findNearestVacantArea(
+            int[] result = layout.findNearestVacantArea(
                     touchXY[0], touchXY[1], spanXY[0], spanXY[1], cellXY);
             foundCellSpan = (result != null);
         } else {
@@ -1108,8 +1048,7 @@
         launcherInfo.spanY = spanXY[1];
 
         LauncherModel.addItemToDatabase(this, launcherInfo,
-                LauncherSettings.Favorites.CONTAINER_DESKTOP,
-                screen, cellXY[0], cellXY[1], false);
+                container, screen, cellXY[0], cellXY[1], false);
 
         if (!mRestoring) {
             // Perform actual inflation because we're live
@@ -1118,7 +1057,7 @@
             launcherInfo.hostView.setAppWidget(appWidgetId, appWidgetInfo);
             launcherInfo.hostView.setTag(launcherInfo);
 
-            mWorkspace.addInScreen(launcherInfo.hostView, screen, cellXY[0], cellXY[1],
+            mWorkspace.addInScreen(launcherInfo.hostView, container, screen, cellXY[0], cellXY[1],
                     launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked());
 
             addWidgetToAutoAdvanceIfNeeded(launcherInfo.hostView, appWidgetInfo);
@@ -1331,10 +1270,12 @@
         // this state is reflected.
         closeFolder();
 
-        if (mAddScreen > -1 && mWaitingForResult) {
-            outState.putInt(RUNTIME_STATE_PENDING_ADD_SCREEN, mAddScreen);
-            outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_X, mAddCellX);
-            outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_Y, mAddCellY);
+        if (mPendingAddInfo.container != ItemInfo.NO_ID && mPendingAddInfo.screen > -1 &&
+                mWaitingForResult) {
+            outState.putLong(RUNTIME_STATE_PENDING_ADD_CONTAINER, mPendingAddInfo.container);
+            outState.putInt(RUNTIME_STATE_PENDING_ADD_SCREEN, mPendingAddInfo.screen);
+            outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_X, mPendingAddInfo.cellX);
+            outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_Y, mPendingAddInfo.cellY);
         }
 
         if (mFolderInfo != null && mWaitingForResult) {
@@ -1372,7 +1313,7 @@
         TextKeyListener.getInstance().release();
 
 
-        unbindWorkspaceItems();
+        unbindWorkspaceAndHotseatItems();
 
         getContentResolver().unregisterContentObserver(mWidgetObserver);
         unregisterReceiver(mCloseSystemDialogsReceiver);
@@ -1507,10 +1448,11 @@
     }
 
     private void resetAddInfo() {
-        mAddScreen = -1;
-        mAddCellX = -1;
-        mAddCellY = -1;
-        mAddDropPosition = null;
+        mPendingAddInfo.container = ItemInfo.NO_ID;
+        mPendingAddInfo.screen = -1;
+        mPendingAddInfo.cellX = mPendingAddInfo.cellY = -1;
+        mPendingAddInfo.spanX = mPendingAddInfo.spanY = -1;
+        mPendingAddInfo.dropPos = null;
     }
 
     private void manageApps() {
@@ -1566,7 +1508,7 @@
             startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET);
         } else {
             // Otherwise just add it
-            completeAddAppWidget(appWidgetId, mAddScreen);
+            completeAddAppWidget(appWidgetId, info.container, info.screen);
 
             // Exit spring loaded mode if necessary after adding the widget
             exitSpringLoadedDragModeDelayed(false);
@@ -1581,14 +1523,16 @@
      * @param cell The cell it should be added to, optional
      * @param position The location on the screen where it was dropped, optional
      */
-    void processShortcutFromDrop(ComponentName componentName, int screen, int[] cell, int[] loc) {
+    void processShortcutFromDrop(ComponentName componentName, long container, int screen,
+            int[] cell, int[] loc) {
         resetAddInfo();
-        mAddScreen = screen;
-        mAddDropPosition = loc;
+        mPendingAddInfo.container = container;
+        mPendingAddInfo.screen = screen;
+        mPendingAddInfo.dropPos = loc;
 
         if (cell != null) {
-            mAddCellX = cell[0];
-            mAddCellY = cell[1];
+            mPendingAddInfo.cellX = cell[0];
+            mPendingAddInfo.cellY = cell[1];
         }
 
         Intent createShortcutIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
@@ -1604,14 +1548,15 @@
      * @param cell The cell it should be added to, optional
      * @param position The location on the screen where it was dropped, optional
      */
-    void addAppWidgetFromDrop(PendingAddWidgetInfo info, int screen, int[] cell, int[] loc) {
+    void addAppWidgetFromDrop(PendingAddWidgetInfo info, long container, int screen,
+            int[] cell, int[] loc) {
         resetAddInfo();
-        mAddScreen = screen;
-        mAddDropPosition = loc;
-
+        mPendingAddInfo.container = info.container = container;
+        mPendingAddInfo.screen = info.screen = screen;
+        mPendingAddInfo.dropPos = loc;
         if (cell != null) {
-            mAddCellX = cell[0];
-            mAddCellY = cell[1];
+            mPendingAddInfo.cellX = cell[0];
+            mPendingAddInfo.cellY = cell[1];
         }
 
         int appWidgetId = getAppWidgetHost().allocateAppWidgetId();
@@ -1641,21 +1586,21 @@
         startActivityForResult(intent, REQUEST_PICK_WALLPAPER);
     }
 
-    FolderIcon addFolder(final int screen, int cellX, int cellY) {
+    FolderIcon addFolder(CellLayout layout, long container, final int screen, int cellX,
+            int cellY) {
         final FolderInfo folderInfo = new FolderInfo();
         folderInfo.title = getText(R.string.folder_name);
 
         // Update the model
-        LauncherModel.addItemToDatabase(Launcher.this, folderInfo,
-                LauncherSettings.Favorites.CONTAINER_DESKTOP,
-                screen, cellX, cellY, false);
+        LauncherModel.addItemToDatabase(Launcher.this, folderInfo, container, screen, cellX, cellY,
+                false);
         sFolders.put(folderInfo.id, folderInfo);
 
         // Create the view
-        FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
-                (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()),
-                folderInfo, mIconCache);
-        mWorkspace.addInScreen(newFolder, screen, cellX, cellY, 1, 1, isWorkspaceLocked());
+        FolderIcon newFolder =
+            FolderIcon.fromXml(R.layout.folder_icon, this, layout, folderInfo, mIconCache);
+        mWorkspace.addInScreen(newFolder, container, screen, cellX, cellY, 1, 1,
+                isWorkspaceLocked());
         return newFolder;
     }
 
@@ -1753,8 +1698,7 @@
 
         ViewGroup parent = (ViewGroup) folder.getParent().getParent();
         if (parent != null) {
-            CellLayout cl = (CellLayout) mWorkspace.getChildAt(folder.mInfo.screen);
-            FolderIcon fi = (FolderIcon) cl.getChildAt(folder.mInfo.cellX, folder.mInfo.cellY);
+            FolderIcon fi = (FolderIcon) mWorkspace.getViewForTag(folder.mInfo);
             shrinkAndFadeInFolderIcon(fi);
             mDragController.removeDropTarget((DropTarget)folder);
         }
@@ -1774,7 +1718,7 @@
      * Go through the and disconnect any of the callbacks in the drawables and the views or we
      * leak the previous Home screen on orientation change.
      */
-    private void unbindWorkspaceItems() {
+    private void unbindWorkspaceAndHotseatItems() {
         LauncherModel.unbindWorkspaceItems();
     }
 
@@ -1995,16 +1939,6 @@
             return false;
         }
 
-        switch (v.getId()) {
-            case R.id.all_apps_button:
-                if (mState != State.APPS_CUSTOMIZE) {
-                    mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
-                            HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
-                    showPreviews(v);
-                }
-                return true;
-        }
-
         if (isWorkspaceLocked()) {
             return false;
         }
@@ -2020,12 +1954,13 @@
             return true;
         }
 
+        // The hotseat touch handling does not go through Workspace, and we always allow long press
+        // on hotseat items.
         final View itemUnderLongClick = longClickCellInfo.cell;
-
-        if (mWorkspace.allowLongPress() && !mDragController.isDragging()) {
+        boolean allowLongPress = isHotseatLayout(v) || mWorkspace.allowLongPress();
+        if (allowLongPress && !mDragController.isDragging()) {
             if (itemUnderLongClick == null) {
                 // User long pressed on empty space
-                mWorkspace.setAllowLongPress(false);
                 mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                         HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
                 addItems();
@@ -2041,137 +1976,26 @@
         return true;
     }
 
-    @SuppressWarnings({"unchecked"})
-    private void dismissPreview(final View v) {
-        final PopupWindow window = (PopupWindow) v.getTag();
-        if (window != null) {
-            window.setOnDismissListener(new PopupWindow.OnDismissListener() {
-                public void onDismiss() {
-                    ViewGroup group = (ViewGroup) v.getTag(R.id.workspace);
-                    int count = group.getChildCount();
-                    for (int i = 0; i < count; i++) {
-                        ((ImageView) group.getChildAt(i)).setImageDrawable(null);
-                    }
-                    ArrayList<Bitmap> bitmaps =
-                        (ArrayList<Bitmap>) v.getTag(R.id.all_apps_button_cluster);
-                    for (Bitmap bitmap : bitmaps) bitmap.recycle();
-
-                    v.setTag(R.id.workspace, null);
-                    v.setTag(R.id.all_apps_button_cluster, null);
-                    window.setOnDismissListener(null);
-                }
-            });
-            window.dismiss();
-        }
-        v.setTag(null);
+    boolean isHotseatLayout(View layout) {
+        return mHotseat != null && layout != null &&
+                (layout instanceof CellLayout) && (layout == mHotseat.getLayout());
+    }
+    Hotseat getHotseat() {
+        return mHotseat;
     }
 
-    private void showPreviews(View anchor) {
-        showPreviews(anchor, 0, mWorkspace.getChildCount());
-    }
-
-    private void showPreviews(final View anchor, int start, int end) {
-        final Resources resources = getResources();
-        final Workspace workspace = mWorkspace;
-
-        CellLayout cell = ((CellLayout) workspace.getChildAt(start));
-
-        float max = workspace.getChildCount();
-
-        final Rect r = new Rect();
-        resources.getDrawable(R.drawable.preview_background).getPadding(r);
-        int extraW = (int) ((r.left + r.right) * max);
-        int extraH = r.top + r.bottom;
-
-        int aW = cell.getWidth() - extraW;
-        float w = aW / max;
-
-        int width = cell.getWidth();
-        int height = cell.getHeight();
-        int x = cell.getPaddingLeft();
-        int y = cell.getPaddingTop();
-        width -= (x + cell.getPaddingRight());
-        height -= (y + cell.getPaddingBottom());
-
-        float scale = w / width;
-
-        int count = end - start;
-
-        final float sWidth = width * scale;
-        float sHeight = height * scale;
-
-        LinearLayout preview = new LinearLayout(this);
-
-        PreviewTouchHandler handler = new PreviewTouchHandler(anchor);
-        ArrayList<Bitmap> bitmaps = new ArrayList<Bitmap>(count);
-
-        for (int i = start; i < end; i++) {
-            ImageView image = new ImageView(this);
-            cell = (CellLayout) workspace.getChildAt(i);
-
-            final Bitmap bitmap = Bitmap.createBitmap((int) sWidth, (int) sHeight,
-                    Bitmap.Config.ARGB_8888);
-
-            final Canvas c = new Canvas(bitmap);
-            c.scale(scale, scale);
-            c.translate(-cell.getPaddingLeft(), -cell.getPaddingTop());
-            cell.drawChildren(c);
-
-            image.setBackgroundDrawable(resources.getDrawable(R.drawable.preview_background));
-            image.setImageBitmap(bitmap);
-            image.setTag(i);
-            image.setOnClickListener(handler);
-            image.setOnFocusChangeListener(handler);
-            image.setFocusable(true);
-            if (i == mWorkspace.getCurrentPage()) image.requestFocus();
-
-            preview.addView(image,
-                    LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
-
-            bitmaps.add(bitmap);
-        }
-
-        final PopupWindow p = new PopupWindow(this);
-        p.setContentView(preview);
-        p.setWidth((int) (sWidth * count + extraW));
-        p.setHeight((int) (sHeight + extraH));
-        p.setAnimationStyle(R.style.AnimationPreview);
-        p.setOutsideTouchable(true);
-        p.setFocusable(true);
-        p.setBackgroundDrawable(new ColorDrawable(0));
-        p.showAsDropDown(anchor, 0, 0);
-
-        p.setOnDismissListener(new PopupWindow.OnDismissListener() {
-            public void onDismiss() {
-                dismissPreview(anchor);
+    /**
+     * Returns the CellLayout of the specified container at the specified screen.
+     */
+    CellLayout getCellLayout(long container, int screen) {
+        if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+            if (mHotseat != null) {
+                return mHotseat.getLayout();
+            } else {
+                return null;
             }
-        });
-
-        anchor.setTag(p);
-        anchor.setTag(R.id.workspace, preview);
-        anchor.setTag(R.id.all_apps_button_cluster, bitmaps);
-    }
-
-    class PreviewTouchHandler implements View.OnClickListener, Runnable, View.OnFocusChangeListener {
-        private final View mAnchor;
-
-        public PreviewTouchHandler(View anchor) {
-            mAnchor = anchor;
-        }
-
-        public void onClick(View v) {
-            mWorkspace.snapToPage((Integer) v.getTag());
-            v.post(this);
-        }
-
-        public void run() {
-            dismissPreview(mAnchor);
-        }
-
-        public void onFocusChange(View v, boolean hasFocus) {
-            if (hasFocus) {
-                mWorkspace.snapToPage((Integer) v.getTag());
-            }
+        } else {
+            return (CellLayout) mWorkspace.getChildAt(screen);
         }
     }
 
@@ -2215,7 +2039,8 @@
 
     private void showAddDialog() {
         resetAddInfo();
-        mAddScreen = mWorkspace.getCurrentPage();
+        mPendingAddInfo.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
+        mPendingAddInfo.screen = mWorkspace.getCurrentPage();
         mWaitingForResult = true;
         showDialog(DIALOG_CREATE_SHORTCUT);
     }
@@ -2594,29 +2419,29 @@
     }
 
     /**
-     * Shows the dock/hotseat area.
+     * Shows the hotseat area.
      */
-    void showDock(boolean animated) {
+    void showHotseat(boolean animated) {
         if (!LauncherApplication.isScreenLarge()) {
             if (animated) {
                 int duration = mSearchDeleteBar.getTransitionInDuration();
-                mButtonCluster.animate().alpha(1f).setDuration(duration);
+                mHotseat.animate().alpha(1f).setDuration(duration);
             } else {
-                mButtonCluster.setAlpha(1f);
+                mHotseat.setAlpha(1f);
             }
         }
     }
 
     /**
-     * Hides the dock/hotseat area.
+     * Hides the hotseat area.
      */
-    void hideDock(boolean animated) {
+    void hideHotseat(boolean animated) {
         if (!LauncherApplication.isScreenLarge()) {
             if (animated) {
                 int duration = mSearchDeleteBar.getTransitionOutDuration();
-                mButtonCluster.animate().alpha(0f).setDuration(duration);
+                mHotseat.animate().alpha(0f).setDuration(duration);
             } else {
-                mButtonCluster.setAlpha(0f);
+                mHotseat.setAlpha(0f);
             }
         }
     }
@@ -2627,9 +2452,9 @@
         cameraZoomOut(State.APPS_CUSTOMIZE, animated, false);
         mAppsCustomizeTabHost.requestFocus();
 
-        // Hide the search bar and dock
+        // Hide the search bar and hotseat
         mSearchDeleteBar.hideSearchBar(animated);
-        hideDock(animated);
+        hideHotseat(animated);
 
         // Change the state *after* we've called all the transition code
         mState = State.APPS_CUSTOMIZE;
@@ -2686,12 +2511,14 @@
             mWorkspace.setVisibility(View.VISIBLE);
             cameraZoomIn(State.APPS_CUSTOMIZE, animated, false);
 
-            // Show the search bar and dock
+            // Show the search bar and hotseat
             mSearchDeleteBar.showSearchBar(animated);
-            showDock(animated);
+            showHotseat(animated);
 
             // Set focus to the AppsCustomize button
-            findViewById(R.id.all_apps_button).requestFocus();
+            if (mAllAppsButton != null) {
+                mAllAppsButton.requestFocus();
+            }
         }
     }
 
@@ -3024,21 +2851,12 @@
             final CellLayout layoutParent = (CellLayout) workspace.getChildAt(i);
             layoutParent.removeAllViewsInLayout();
         }
-
-        if (DEBUG_USER_INTERFACE) {
-            android.widget.Button finishButton = new android.widget.Button(this);
-            finishButton.setText("Finish");
-            workspace.addInScreen(finishButton, 1, 0, 0, 1, 1);
-
-            finishButton.setOnClickListener(new android.widget.Button.OnClickListener() {
-                public void onClick(View v) {
-                    finish();
-                }
-            });
+        if (mHotseat != null) {
+            mHotseat.resetLayout();
         }
 
         // This wasn't being called before which resulted in a leak of AppWidgetHostViews
-        unbindWorkspaceItems();
+        unbindWorkspaceAndHotseatItems();
     }
 
     /**
@@ -3047,30 +2865,27 @@
      * Implementation of the method from LauncherModel.Callbacks.
      */
     public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end) {
-
         setLoadOnResume();
 
         final Workspace workspace = mWorkspace;
-
         for (int i=start; i<end; i++) {
             final ItemInfo item = shortcuts.get(i);
             switch (item.itemType) {
                 case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                 case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
-                    final View shortcut = createShortcut((ShortcutInfo)item);
-                    workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 1, 1,
-                            false);
+                    View shortcut = createShortcut((ShortcutInfo)item);
+                    workspace.addInScreen(shortcut, item.container, item.screen, item.cellX,
+                            item.cellY, 1, 1, false);
                     break;
                 case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
-                    final FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
+                    FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
                             (ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
                             (FolderInfo) item, mIconCache);
-                    workspace.addInScreen(newFolder, item.screen, item.cellX, item.cellY, 1, 1,
-                            false);
+                    workspace.addInScreen(newFolder, item.container, item.screen, item.cellX,
+                            item.cellY, 1, 1, false);
                     break;
             }
         }
-
         workspace.requestLayout();
     }
 
@@ -3108,7 +2923,7 @@
         item.hostView.setAppWidget(appWidgetId, appWidgetInfo);
         item.hostView.setTag(item);
 
-        workspace.addInScreen(item.hostView, item.screen, item.cellX,
+        workspace.addInScreen(item.hostView, item.container, item.screen, item.cellX,
                 item.cellY, item.spanX, item.spanY, false);
 
         addWidgetToAutoAdvanceIfNeeded(item.hostView, appWidgetInfo);
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index b4e632a..c8cf1f8 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -178,17 +178,24 @@
     static void moveItemInDatabase(Context context, final ItemInfo item, final long container,
             final int screen, final int cellX, final int cellY) {
         item.container = container;
-        item.screen = screen;
         item.cellX = cellX;
         item.cellY = cellY;
+        // We store hotseat items in canonical form which is this orientation invariant position
+        // in the hotseat
+        if (context instanceof Launcher && screen < 0 &&
+                container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+            item.screen = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
+        } else {
+            item.screen = screen;
+        }
 
         final Uri uri = LauncherSettings.Favorites.getContentUri(item.id, false);
         final ContentValues values = new ContentValues();
         final ContentResolver cr = context.getContentResolver();
 
         values.put(LauncherSettings.Favorites.CONTAINER, item.container);
-        values.put(LauncherSettings.Favorites.CELLX, cellX);
-        values.put(LauncherSettings.Favorites.CELLY, cellY);
+        values.put(LauncherSettings.Favorites.CELLX, item.cellX);
+        values.put(LauncherSettings.Favorites.CELLY, item.cellY);
         values.put(LauncherSettings.Favorites.SCREEN, item.screen);
 
         sWorker.post(new Runnable() {
@@ -205,7 +212,8 @@
                     // Items are added/removed from the corresponding FolderInfo elsewhere, such
                     // as in Workspace.onDrop. Here, we just add/remove them from the list of items
                     // that are on the desktop, as appropriate
-                    if (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                    if (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
+                            modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
                         if (!sWorkspaceItems.contains(modelItem)) {
                             sWorkspaceItems.add(modelItem);
                         }
@@ -356,12 +364,19 @@
      * Add an item to the database in a specified container. Sets the container, screen, cellX and
      * cellY fields of the item. Also assigns an ID to the item.
      */
-    static void addItemToDatabase(Context context, final ItemInfo item, long container,
-            int screen, int cellX, int cellY, final boolean notify) {
+    static void addItemToDatabase(Context context, final ItemInfo item, final long container,
+            final int screen, final int cellX, final int cellY, final boolean notify) {
         item.container = container;
-        item.screen = screen;
         item.cellX = cellX;
         item.cellY = cellY;
+        // We store hotseat items in canonical form which is this orientation invariant position
+        // in the hotseat
+        if (context instanceof Launcher && screen < 0 &&
+                container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+            item.screen = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
+        } else {
+            item.screen = screen;
+        }
 
         final ContentValues values = new ContentValues();
         final ContentResolver cr = context.getContentResolver();
@@ -371,7 +386,7 @@
         LauncherApplication app = (LauncherApplication) l.getApplication();
         item.id = app.getLauncherProvider().generateNewId();
         values.put(LauncherSettings.Favorites._ID, item.id);
-        item.updateValuesWithCoordinates(values, cellX, cellY);
+        item.updateValuesWithCoordinates(values, item.cellX, item.cellY);
 
         sWorker.post(new Runnable() {
             public void run() {
@@ -382,13 +397,11 @@
                 switch (item.itemType) {
                     case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
                         sFolders.put(item.id, (FolderInfo) item);
-                        if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
-                            sWorkspaceItems.add(item);
-                        }
-                        break;
+                        // Fall through
                     case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                     case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
-                        if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                        if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
+                                item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
                             sWorkspaceItems.add(item);
                         }
                         break;
@@ -404,8 +417,8 @@
      * Creates a new unique child id, for a given cell span across all layouts.
      */
     static int getCellLayoutChildId(
-            int cellId, int screen, int localCellX, int localCellY, int spanX, int spanY) {
-        return ((cellId & 0xFF) << 24)
+            long container, int screen, int localCellX, int localCellY, int spanX, int spanY) {
+        return (((int) container & 0xFF) << 24)
                 | (screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);
     }
 
@@ -928,6 +941,7 @@
 
                                 switch (container) {
                                 case LauncherSettings.Favorites.CONTAINER_DESKTOP:
+                                case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
                                     sWorkspaceItems.add(info);
                                     break;
                                 default:
@@ -972,6 +986,7 @@
                             }
                             switch (container) {
                                 case LauncherSettings.Favorites.CONTAINER_DESKTOP:
+                                case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
                                     sWorkspaceItems.add(folderInfo);
                                     break;
                             }
@@ -1003,9 +1018,10 @@
                                 appWidgetInfo.spanY = c.getInt(spanYIndex);
 
                                 container = c.getInt(containerIndex);
-                                if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                                if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&
+                                    container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
                                     Log.e(TAG, "Widget found where container "
-                                            + "!= CONTAINER_DESKTOP -- ignoring!");
+                                        + "!= CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");
                                     continue;
                                 }
                                 appWidgetInfo.container = c.getInt(containerIndex);
@@ -1607,12 +1623,10 @@
         }
     }
 
-    ShortcutInfo addShortcut(Context context, Intent data,
-            int screen, int cellX, int cellY, boolean notify) {
-
+    ShortcutInfo addShortcut(Context context, Intent data, long container, int screen,
+            int cellX, int cellY, boolean notify) {
         final ShortcutInfo info = infoFromShortcutIntent(context, data, null);
-        addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
-                screen, cellX, cellY, notify);
+        addItemToDatabase(context, info, container, screen, cellX, cellY, notify);
 
         return info;
     }
diff --git a/src/com/android/launcher2/LauncherProvider.java b/src/com/android/launcher2/LauncherProvider.java
index 5ffd984..96cc63c 100644
--- a/src/com/android/launcher2/LauncherProvider.java
+++ b/src/com/android/launcher2/LauncherProvider.java
@@ -65,11 +65,11 @@
     private static final boolean LOGD = false;
 
     private static final String DATABASE_NAME = "launcher.db";
-    
-    private static final int DATABASE_VERSION = 8;
+
+    private static final int DATABASE_VERSION = 9;
 
     static final String AUTHORITY = "com.android.launcher2.settings";
-    
+
     static final String TABLE_FAVORITES = "favorites";
     static final String PARAMETER_NOTIFY = "notify";
 
@@ -199,7 +199,7 @@
         private static final String TAG_SEARCH = "search";
         private static final String TAG_APPWIDGET = "appwidget";
         private static final String TAG_SHORTCUT = "shortcut";
-        
+
         private final Context mContext;
         private final AppWidgetHost mAppWidgetHost;
         private long mMaxId = -1;
@@ -208,7 +208,12 @@
             super(context, DATABASE_NAME, null, DATABASE_VERSION);
             mContext = context;
             mAppWidgetHost = new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID);
-            mMaxId = initializeMaxId(getWritableDatabase());
+
+            // In the case where neither onCreate nor onUpgrade gets called, we read the maxId from
+            // the DB here
+            if (mMaxId == -1) {
+                mMaxId = initializeMaxId(getWritableDatabase());
+            }
         }
 
         /**
@@ -254,10 +259,10 @@
                 mAppWidgetHost.deleteHost();
                 sendAppWidgetResetNotify();
             }
-            
+
             if (!convertDatabase(db)) {
                 // Populate favorites table with initial favorites
-                loadFavorites(db);
+                loadFavorites(db, ItemInfo.NO_ID);
             }
         }
 
@@ -427,6 +432,18 @@
                 version = 8;
             }
 
+            if (version < 9) {
+                // The max id is not yet set at this point (onUpgrade is triggered in the ctor
+                // before it gets a change to get set, so we need to read it here when we use it)
+                if (mMaxId == -1) {
+                    mMaxId = initializeMaxId(db);
+                }
+
+                // Add default hotseat icons
+                loadFavorites(db, LauncherSettings.Favorites.CONTAINER_HOTSEAT);
+                version = 9;
+            }
+
             if (version != DATABASE_VERSION) {
                 Log.w(TAG, "Destroying all old data.");
                 db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
@@ -672,8 +689,9 @@
          * Loads the default set of favorite packages from an xml file.
          *
          * @param db The database to write the values into
+         * @param filterContainerId The specific container id of items to load
          */
-        private int loadFavorites(SQLiteDatabase db) {
+        private int loadFavorites(SQLiteDatabase db, long filterContainerId) {
             Intent intent = new Intent(Intent.ACTION_MAIN, null);
             intent.addCategory(Intent.CATEGORY_LAUNCHER);
             ContentValues values = new ContentValues();
@@ -700,26 +718,42 @@
 
                     TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.Favorite);
 
-                    values.clear();                    
-                    values.put(LauncherSettings.Favorites.CONTAINER,
-                            LauncherSettings.Favorites.CONTAINER_DESKTOP);
-                    values.put(LauncherSettings.Favorites.SCREEN,
-                            a.getString(R.styleable.Favorite_screen));
-                    values.put(LauncherSettings.Favorites.CELLX,
-                            a.getString(R.styleable.Favorite_x));
-                    values.put(LauncherSettings.Favorites.CELLY,
-                            a.getString(R.styleable.Favorite_y));
+                    long container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
+                    if (a.hasValue(R.styleable.Favorite_container)) {
+                        container = Long.valueOf(a.getString(R.styleable.Favorite_container));
+                    }
+                    if (filterContainerId == ItemInfo.NO_ID || filterContainerId == container) {
+                        String screen = a.getString(R.styleable.Favorite_screen);
+                        String x = a.getString(R.styleable.Favorite_x);
+                        String y = a.getString(R.styleable.Favorite_y);
 
-                    if (TAG_FAVORITE.equals(name)) {
-                        added = addAppShortcut(db, values, a, packageManager, intent);
-                    } else if (TAG_SEARCH.equals(name)) {
-                        added = addSearchWidget(db, values);
-                    } else if (TAG_CLOCK.equals(name)) {
-                        added = addClockWidget(db, values);
-                    } else if (TAG_APPWIDGET.equals(name)) {
-                        added = addAppWidget(db, values, a, packageManager);
-                    } else if (TAG_SHORTCUT.equals(name)) {
-                        added = addUriShortcut(db, values, a);
+                        // If we are adding to the hotset, the screen is used as the position in the
+                        // hotset. This screen can't be at position 0 because AllApps is in the
+                        // zeroth position.
+                        if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
+                                Integer.valueOf(screen) <= 0) {
+                            throw new RuntimeException("Invalid screen position for hotseat item");
+                        }
+
+                        values.clear();
+                        values.put(LauncherSettings.Favorites.CONTAINER, container);
+                        values.put(LauncherSettings.Favorites.SCREEN, screen);
+                        values.put(LauncherSettings.Favorites.CELLX, x);
+                        values.put(LauncherSettings.Favorites.CELLY, y);
+
+                        System.out.println("Adding item to container: " + container);
+
+                        if (TAG_FAVORITE.equals(name)) {
+                            added = addAppShortcut(db, values, a, packageManager, intent);
+                        } else if (TAG_SEARCH.equals(name)) {
+                            added = addSearchWidget(db, values);
+                        } else if (TAG_CLOCK.equals(name)) {
+                            added = addClockWidget(db, values);
+                        } else if (TAG_APPWIDGET.equals(name)) {
+                            added = addAppWidget(db, values, a, packageManager);
+                        } else if (TAG_SHORTCUT.equals(name)) {
+                            added = addUriShortcut(db, values, a);
+                        }
                     }
 
                     if (added) i++;
@@ -730,6 +764,8 @@
                 Log.w(TAG, "Got exception parsing favorites.", e);
             } catch (IOException e) {
                 Log.w(TAG, "Got exception parsing favorites.", e);
+            } catch (RuntimeException e) {
+                Log.w(TAG, "Got exception parsing favorites.", e);
             }
 
             return i;
diff --git a/src/com/android/launcher2/LauncherSettings.java b/src/com/android/launcher2/LauncherSettings.java
index c378405..fcacdec 100644
--- a/src/com/android/launcher2/LauncherSettings.java
+++ b/src/com/android/launcher2/LauncherSettings.java
@@ -133,6 +133,7 @@
          * The icon is a resource identified by a package name and an integer id.
          */
         static final int CONTAINER_DESKTOP = -100;
+        static final int CONTAINER_HOTSEAT = -101;
 
         /**
          * The screen holding the favorite (if container is CONTAINER_DESKTOP)
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 4fbf70f..ed4ae20 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -424,12 +424,8 @@
      * @param spanX The number of cells spanned horizontally by the child.
      * @param spanY The number of cells spanned vertically by the child.
      */
-    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
-        addInScreen(child, screen, x, y, spanX, spanY, false);
-    }
-
-    void addInFullScreen(View child, int screen) {
-        addInScreen(child, screen, 0, 0, -1, -1);
+    void addInScreen(View child, long container, int screen, int x, int y, int spanX, int spanY) {
+        addInScreen(child, container, screen, x, y, spanX, spanY, false);
     }
 
     /**
@@ -444,14 +440,32 @@
      * @param spanY The number of cells spanned vertically by the child.
      * @param insert When true, the child is inserted at the beginning of the children list.
      */
-    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
-        if (screen < 0 || screen >= getChildCount()) {
-            Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
-                + " (was " + screen + "); skipping child");
-            return;
+    void addInScreen(View child, long container, int screen, int x, int y, int spanX, int spanY,
+            boolean insert) {
+        if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+            if (screen < 0 || screen >= getChildCount()) {
+                Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
+                    + " (was " + screen + "); skipping child");
+                return;
+            }
         }
 
-        final CellLayout group = (CellLayout) getChildAt(screen);
+        final CellLayout layout;
+        if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+            layout = mLauncher.getHotseat().getLayout();
+
+            if (screen < 0) {
+                screen = mLauncher.getHotseat().getOrderInHotseat(x, y);
+            } else {
+                // Note: We do this to ensure that the hotseat is always laid out in the orientation
+                // of the hotseat in order regardless of which orientation they were added
+                x = mLauncher.getHotseat().getCellXFromOrder(screen);
+                y = mLauncher.getHotseat().getCellYFromOrder(screen);
+            }
+        } else {
+            layout = (CellLayout) getChildAt(screen);
+        }
+
         CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
         if (lp == null) {
             lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
@@ -467,9 +481,9 @@
         }
 
         // Get the canonical child id to uniquely represent this view in this screen
-        int childId = LauncherModel.getCellLayoutChildId(-1, screen, x, y, spanX, spanY);
+        int childId = LauncherModel.getCellLayoutChildId(container, screen, x, y, spanX, spanY);
         boolean markCellsAsOccupied = !(child instanceof Folder);
-        if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) {
+        if (!layout.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) {
             // TODO: This branch occurs when the workspace is adding views
             // outside of the defined grid
             // maybe we should be deleting these items from the LauncherModel?
@@ -1959,7 +1973,7 @@
 
         mDragInfo = cellInfo;
 
-        CellLayout current = (CellLayout) getChildAt(cellInfo.screen);
+        CellLayout current = getParentCellLayoutForView(cellInfo.cell);
         current.onDragChild(child);
 
         child.clearFocus();
@@ -2008,17 +2022,15 @@
         b.recycle();
     }
 
-    void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
-            boolean insertAtFirst, int intersectX, int intersectY) {
-        final CellLayout cellLayout = (CellLayout) getChildAt(screen);
-        View view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo) info);
+    void addApplicationShortcut(ShortcutInfo info, CellLayout target, long container, int screen,
+            int cellX, int cellY, boolean insertAtFirst, int intersectX, int intersectY) {
+        View view = mLauncher.createShortcut(R.layout.application, target, (ShortcutInfo) info);
 
         final int[] cellXY = new int[2];
-        cellLayout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
-        addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
-        LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
-                LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
-                cellXY[0], cellXY[1]);
+        target.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
+        addInScreen(view, container, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
+        LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screen, cellXY[0],
+                cellXY[1]);
     }
 
     /**
@@ -2051,7 +2063,6 @@
 
             mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
                     (int) mDragViewVisualCenter[1], spanX, spanY, mDragTargetLayout, mTargetCell);
-
             if (willCreateUserFolder((ItemInfo) d.dragInfo, mDragTargetLayout, mTargetCell, true)) {
                 return true;
             }
@@ -2074,8 +2085,12 @@
             boolean considerTimeout) {
         View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
 
-        boolean hasntMoved = mDragInfo != null && (mDragInfo.cellX == targetCell[0] &&
-                mDragInfo.cellY == targetCell[1]) && mDragInfo.screen == indexOfChild(target);
+        boolean hasntMoved = false;
+        if (mDragInfo != null) {
+            CellLayout cellParent = getParentCellLayoutForView(mDragInfo.cell);
+            hasntMoved = (mDragInfo.cellX == targetCell[0] &&
+                    mDragInfo.cellY == targetCell[1]) && (cellParent == target);
+        }
 
         if (dropOverView == null || hasntMoved || (considerTimeout && !mCreateUserFolderOnDrop)) {
             return false;
@@ -2100,7 +2115,7 @@
         return false;
     }
 
-    boolean createUserFolderIfNecessary(View newView, CellLayout target,
+    boolean createUserFolderIfNecessary(View newView, long container, CellLayout target,
             int[] targetCell, boolean external, DragView dragView, Runnable postAnimationRunnable) {
         View v = target.getChildAt(targetCell[0], targetCell[1]);
         boolean hasntMoved = mDragInfo != null
@@ -2118,16 +2133,15 @@
             ShortcutInfo destInfo = (ShortcutInfo) v.getTag();
             // if the drag started here, we need to remove it from the workspace
             if (!external) {
-                int fromScreen = mDragInfo.screen;
-                CellLayout sourceLayout = (CellLayout) getChildAt(fromScreen);
-                sourceLayout.removeView(newView);
+                getParentCellLayoutForView(mDragInfo.cell).removeView(mDragInfo.cell);
             }
 
             Rect folderLocation = new Rect();
             float scale = mLauncher.getDragLayer().getDescendantRectRelativeToSelf(v, folderLocation);
             target.removeView(v);
 
-            FolderIcon fi = mLauncher.addFolder(screen, targetCell[0], targetCell[1]);
+            FolderIcon fi =
+                mLauncher.addFolder(target, container, screen, targetCell[0], targetCell[1]);
             destInfo.cellX = -1;
             destInfo.cellY = -1;
             sourceInfo.cellX = -1;
@@ -2150,9 +2164,7 @@
 
                 // if the drag started here, we need to remove it from the workspace
                 if (!external) {
-                    int fromScreen = mDragInfo.screen;
-                    CellLayout sourceLayout = (CellLayout) getChildAt(fromScreen);
-                    sourceLayout.removeView(newView);
+                    getParentCellLayoutForView(mDragInfo.cell).removeView(mDragInfo.cell);
                 }
                 return true;
             }
@@ -2166,7 +2178,11 @@
 
         // We want the point to be mapped to the dragTarget.
         if (mDragTargetLayout != null) {
-            mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
+            if (mLauncher.isHotseatLayout(mDragTargetLayout)) {
+                mapPointFromSelfToSibling(mLauncher.getHotseat(), mDragViewVisualCenter);
+            } else {
+                mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
+            }
         }
 
         // When you are in customization mode and drag to a particular screen, make that the
@@ -2186,11 +2202,23 @@
         } else if (mDragInfo != null) {
             final View cell = mDragInfo.cell;
 
-            if (dropTargetLayout != null) {
-                // Move internally
-                final int screen = (mTargetCell[0] < 0) ?
-                        mDragInfo.screen : indexOfChild(dropTargetLayout);
+            boolean continueDrop = true;
+            if (mLauncher.isHotseatLayout(mDragTargetLayout) && d.dragInfo instanceof ItemInfo) {
+                ItemInfo info = (ItemInfo) d.dragInfo;
+                if (info.spanX > 1 || info.spanY > 1) {
+                    continueDrop = false;
+                    Toast.makeText(getContext(), R.string.invalid_hotseat_item,
+                            Toast.LENGTH_SHORT).show();
+                }
+            }
 
+            if (continueDrop && dropTargetLayout != null) {
+                // Move internally
+                long container = mLauncher.isHotseatLayout(dropTargetLayout) ?
+                        LauncherSettings.Favorites.CONTAINER_HOTSEAT :
+                        LauncherSettings.Favorites.CONTAINER_DESKTOP;
+                int screen = (mTargetCell[0] < 0) ?
+                        mDragInfo.screen : indexOfChild(dropTargetLayout);
                 int spanX = mDragInfo != null ? mDragInfo.spanX : 1;
                 int spanY = mDragInfo != null ? mDragInfo.spanY : 1;
                 // First we find the cell nearest to point at which the item is
@@ -2199,10 +2227,10 @@
                         mDragViewVisualCenter[1], spanX, spanY, dropTargetLayout, mTargetCell);
                 // If the item being dropped is a shortcut and the nearest drop
                 // cell also contains a shortcut, then create a folder with the two shortcuts.
-                boolean dropInscrollArea = mCurrentPage != screen;
+                boolean dropInscrollArea = mCurrentPage != screen && screen > -1;
 
-                if (!dropInscrollArea && createUserFolderIfNecessary(cell, dropTargetLayout,
-                        mTargetCell, false, d.dragView, null)) {
+                if (!dropInscrollArea && createUserFolderIfNecessary(cell, container,
+                        dropTargetLayout, mTargetCell, false, d.dragView, null)) {
                     return;
                 }
 
@@ -2220,25 +2248,26 @@
                     snapToPage(screen);
                 }
 
+
                 if (mTargetCell[0] >= 0 && mTargetCell[1] >= 0) {
                     if (screen != mDragInfo.screen) {
                         // Reparent the view
-                        ((CellLayout) getChildAt(mDragInfo.screen)).removeView(cell);
-                        addInScreen(cell, screen, mTargetCell[0], mTargetCell[1], mDragInfo.spanX,
-                                mDragInfo.spanY);
+                        getParentCellLayoutForView(cell).removeView(cell);
+                        addInScreen(cell, container, screen, mTargetCell[0], mTargetCell[1],
+                                mDragInfo.spanX, mDragInfo.spanY);
                     }
 
-
                     // update the item's position after drop
                     final ItemInfo info = (ItemInfo) cell.getTag();
                     CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
                     dropTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
                     lp.cellX = mTargetCell[0];
                     lp.cellY = mTargetCell[1];
-                    cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
+                    cell.setId(LauncherModel.getCellLayoutChildId(container, mDragInfo.screen,
                             mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
 
-                    if (cell instanceof LauncherAppWidgetHostView) {
+                    if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
+                            cell instanceof LauncherAppWidgetHostView) {
                         final CellLayout cellLayout = dropTargetLayout;
                         // We post this call so that the widget has a chance to be placed
                         // in its final location
@@ -2264,9 +2293,8 @@
                         }
                     }
 
-                    LauncherModel.moveItemInDatabase(mLauncher, info,
-                            LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
-                            lp.cellX, lp.cellY);
+                    LauncherModel.moveItemInDatabase(mLauncher, info, container, screen, lp.cellX,
+                            lp.cellY);
                 }
             }
 
@@ -2446,7 +2474,8 @@
                         final AppWidgetProviderInfo widgetInfo = widgets.get(0).widgetInfo;
                         final PendingAddWidgetInfo createInfo =
                                 new PendingAddWidgetInfo(widgetInfo, mimeType, data);
-                        mLauncher.addAppWidgetFromDrop(createInfo, mCurrentPage, null, pos);
+                        mLauncher.addAppWidgetFromDrop(createInfo,
+                            LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentPage, null, pos);
                     } else {
                         // Show the widget picker dialog if there is more than one widget
                         // that can handle this data type
@@ -2507,6 +2536,15 @@
    }
 
    /*
+    * Maps a point from the Workspace's coordinate system to another sibling view's. (Workspace
+    * covers the full screen)
+    */
+   void mapPointFromSelfToSibling(View v, float[] xy) {
+       xy[0] = xy[0] - v.getLeft();
+       xy[1] = xy[1] - v.getTop();
+   }
+
+   /*
     *
     * Convert the 2D coordinate xy from this CellLayout's coordinate space to
     * the parent View's coordinate space. The argument xy is modified with the return result.
@@ -2581,7 +2619,7 @@
         float smallestDistSoFar = Float.MAX_VALUE;
 
         for (int i = 0; i < screenCount; i++) {
-            CellLayout cl = (CellLayout)getChildAt(i);
+            CellLayout cl = (CellLayout) getChildAt(i);
 
             final float[] touchXy = mTempTouchCoordinates;
             touchXy[0] = originX + offsetX;
@@ -2657,7 +2695,7 @@
         if (mInScrollArea) return;
         if (mIsSwitchingState) return;
 
-        CellLayout layout;
+        CellLayout layout = null;
         ItemInfo item = (ItemInfo) d.dragInfo;
 
         // Ensure that we have proper spans for the item that we are dropping
@@ -2690,7 +2728,17 @@
                 }
             }
         } else {
-            layout = getCurrentDropLayout();
+            // Test to see if we are over the hotseat otherwise just use the current page
+            Rect r = new Rect();
+            if (mLauncher.getHotseat() != null) {
+                mLauncher.getHotseat().getHitRect(r);
+                if (r.contains(d.x, d.y)) {
+                    layout = mLauncher.getHotseat().getLayout();
+                }
+            }
+            if (layout == null) {
+                layout = getCurrentDropLayout();
+            }
             if (layout != mDragTargetLayout) {
                 if (mDragTargetLayout != null) {
                     mDragTargetLayout.setIsDragOverlapping(false);
@@ -2710,7 +2758,11 @@
                     d.dragView, mDragViewVisualCenter);
 
             // We want the point to be mapped to the dragTarget.
-            mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
+            if (mLauncher.isHotseatLayout(mDragTargetLayout)) {
+                mapPointFromSelfToSibling(mLauncher.getHotseat(), mDragViewVisualCenter);
+            } else {
+                mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
+            }
             ItemInfo info = (ItemInfo) d.dragInfo;
 
             mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
@@ -2845,8 +2897,12 @@
             spanY = mDragInfo.spanY;
         }
 
+        final long container = mLauncher.isHotseatLayout(cellLayout) ?
+                LauncherSettings.Favorites.CONTAINER_HOTSEAT :
+                    LauncherSettings.Favorites.CONTAINER_DESKTOP;
         final int screen = indexOfChild(cellLayout);
-        if (screen != mCurrentPage && mState != State.SPRING_LOADED) {
+        if (!mLauncher.isHotseatLayout(cellLayout) && screen != mCurrentPage
+                && mState != State.SPRING_LOADED) {
             snapToPage(screen);
         }
 
@@ -2863,11 +2919,11 @@
                     switch (pendingInfo.itemType) {
                     case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
                         mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) pendingInfo,
-                                screen, mTargetCell, null);
+                                container, screen, mTargetCell, null);
                         break;
                     case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                         mLauncher.processShortcutFromDrop(pendingInfo.componentName,
-                                screen, mTargetCell, null);
+                                container, screen, mTargetCell, null);
                         break;
                     default:
                         throw new IllegalStateException("Unknown item type: " +
@@ -2923,8 +2979,8 @@
                 mTargetCell = findNearestArea((int) touchXY[0], (int) touchXY[1], spanX, spanY,
                         cellLayout, mTargetCell);
                 d.postAnimationRunnable = exitSpringLoadedRunnable;
-                if (createUserFolderIfNecessary(view, cellLayout, mTargetCell, true, d.dragView,
-                        d.postAnimationRunnable)) {
+                if (createUserFolderIfNecessary(view, container, cellLayout, mTargetCell, true,
+                        d.dragView, d.postAnimationRunnable)) {
                     return;
                 }
                 if (addToExistingFolderIfNecessary(view, cellLayout, mTargetCell, d, true)) {
@@ -2939,15 +2995,14 @@
             } else {
                 cellLayout.findCellForSpan(mTargetCell, 1, 1);
             }
-            addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
-                    mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
+            addInScreen(view, container, screen, mTargetCell[0], mTargetCell[1], info.spanX,
+                    info.spanY, insertAtFirst);
             cellLayout.onDropChild(view);
             cellLayout.animateDrop();
             CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
             cellLayout.getChildrenLayout().measureChild(view);
 
-            LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
-                    LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
+            LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screen,
                     lp.cellX, lp.cellY);
 
             if (d.dragView != null) {
@@ -3016,8 +3071,7 @@
         if (success) {
             if (target != this) {
                 if (mDragInfo != null) {
-                    final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
-                    cellLayout.removeView(mDragInfo.cell);
+                    getParentCellLayoutForView(mDragInfo.cell).removeView(mDragInfo.cell);
                     if (mDragInfo.cell instanceof DropTarget) {
                         mDragController.removeDropTarget((DropTarget) mDragInfo.cell);
                     }
@@ -3028,7 +3082,13 @@
             // calling onDropCompleted(). We call it ourselves here, but maybe this should be
             // moved into DragController.cancelDrag().
             doDragExit(null);
-            ((CellLayout) getChildAt(mDragInfo.screen)).onDropChild(mDragInfo.cell);
+            CellLayout cellLayout;
+            if (mLauncher.isHotseatLayout(target)) {
+                cellLayout = mLauncher.getHotseat().getLayout();
+            } else {
+                cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
+            }
+            cellLayout.onDropChild(mDragInfo.cell);
         }
         mDragOutline = null;
         mDragInfo = null;
@@ -3125,15 +3185,58 @@
         mInScrollArea = false;
     }
 
-    public Folder getFolderForTag(Object tag) {
-        final int screenCount = getChildCount();
+    /**
+     * Returns a specific CellLayout
+     */
+    CellLayout getParentCellLayoutForView(View v) {
+        ArrayList<CellLayout> layouts = getWorkspaceAndHotseatCellLayouts();
+        for (CellLayout layout : layouts) {
+            if (layout.getChildrenLayout().indexOfChild(v) > -1) {
+                return layout;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a list of all the CellLayouts in the workspace.
+     */
+    ArrayList<CellLayout> getWorkspaceAndHotseatCellLayouts() {
+        ArrayList<CellLayout> layouts = new ArrayList<CellLayout>();
+        int screenCount = getChildCount();
         for (int screen = 0; screen < screenCount; screen++) {
-            ViewGroup currentScreen = ((CellLayout) getChildAt(screen)).getChildrenLayout();
-            int count = currentScreen.getChildCount();
+            layouts.add(((CellLayout) getChildAt(screen)));
+        }
+        if (mLauncher.getHotseat() != null) {
+            layouts.add(mLauncher.getHotseat().getLayout());
+        }
+        return layouts;
+    }
+
+    /**
+     * We should only use this to search for specific children.  Do not use this method to modify
+     * CellLayoutChildren directly.
+     */
+    ArrayList<CellLayoutChildren> getWorkspaceAndHotseatCellLayoutChildren() {
+        ArrayList<CellLayoutChildren> childrenLayouts = new ArrayList<CellLayoutChildren>();
+        int screenCount = getChildCount();
+        for (int screen = 0; screen < screenCount; screen++) {
+            childrenLayouts.add(((CellLayout) getChildAt(screen)).getChildrenLayout());
+        }
+        if (mLauncher.getHotseat() != null) {
+            childrenLayouts.add(mLauncher.getHotseat().getLayout().getChildrenLayout());
+        }
+        return childrenLayouts;
+    }
+
+    public Folder getFolderForTag(Object tag) {
+        ArrayList<CellLayoutChildren> childrenLayouts = getWorkspaceAndHotseatCellLayoutChildren();
+        for (CellLayoutChildren layout: childrenLayouts) {
+            int count = layout.getChildCount();
             for (int i = 0; i < count; i++) {
-                View child = currentScreen.getChildAt(i);
+                View child = layout.getChildAt(i);
                 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
-                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
+                if (child instanceof Folder) {
                     Folder f = (Folder) child;
                     if (f.getInfo() == tag && f.getInfo().opened) {
                         return f;
@@ -3145,12 +3248,11 @@
     }
 
     public View getViewForTag(Object tag) {
-        int screenCount = getChildCount();
-        for (int screen = 0; screen < screenCount; screen++) {
-            ViewGroup currentScreen = ((CellLayout) getChildAt(screen)).getChildrenLayout();
-            int count = currentScreen.getChildCount();
+        ArrayList<CellLayoutChildren> childrenLayouts = getWorkspaceAndHotseatCellLayoutChildren();
+        for (CellLayoutChildren layout: childrenLayouts) {
+            int count = layout.getChildCount();
             for (int i = 0; i < count; i++) {
-                View child = currentScreen.getChildAt(i);
+                View child = layout.getChildAt(i);
                 if (child.getTag() == tag) {
                     return child;
                 }
@@ -3160,11 +3262,8 @@
     }
 
     void clearDropTargets() {
-        final int screenCount = getChildCount();
-
-        for (int i = 0; i < screenCount; i++) {
-            final CellLayout layoutParent = (CellLayout) getChildAt(i);
-            final ViewGroup layout = layoutParent.getChildrenLayout();
+        ArrayList<CellLayoutChildren> childrenLayouts = getWorkspaceAndHotseatCellLayoutChildren();
+        for (CellLayoutChildren layout: childrenLayouts) {
             int childCount = layout.getChildCount();
             for (int j = 0; j < childCount; j++) {
                 View v = layout.getChildAt(j);
@@ -3185,8 +3284,8 @@
             packageNames.add(apps.get(i).componentName.getPackageName());
         }
 
-        for (int i = 0; i < screenCount; i++) {
-            final CellLayout layoutParent = (CellLayout) getChildAt(i);
+        ArrayList<CellLayout> cellLayouts = getWorkspaceAndHotseatCellLayouts();
+        for (final CellLayout layoutParent: cellLayouts) {
             final ViewGroup layout = layoutParent.getChildrenLayout();
 
             // Avoid ANRs by treating each screen separately
@@ -3273,9 +3372,8 @@
     }
 
     void updateShortcuts(ArrayList<ApplicationInfo> apps) {
-        final int screenCount = getChildCount();
-        for (int i = 0; i < screenCount; i++) {
-            final ViewGroup layout = ((CellLayout) getChildAt(i)).getChildrenLayout();
+        ArrayList<CellLayoutChildren> childrenLayouts = getWorkspaceAndHotseatCellLayoutChildren();
+        for (CellLayoutChildren layout: childrenLayouts) {
             int childCount = layout.getChildCount();
             for (int j = 0; j < childCount; j++) {
                 final View view = layout.getChildAt(j);
@@ -3307,7 +3405,7 @@
 
     void moveToDefaultScreen(boolean animate) {
         if (isSmall() || mIsSwitchingState) {
-            mLauncher.showWorkspace(animate, (CellLayout)getChildAt(mDefaultPage));
+            mLauncher.showWorkspace(animate, (CellLayout) getChildAt(mDefaultPage));
         } else if (animate) {
             snapToPage(mDefaultPage);
         } else {