Merge change 24743 into eclair

* changes:
  First crack at a Gallery-based live wallpaper picker.
diff --git a/res/drawable-hdpi/trashcan.png b/res/drawable-hdpi/trashcan.png
new file mode 100644
index 0000000..8d3d8e4
--- /dev/null
+++ b/res/drawable-hdpi/trashcan.png
Binary files differ
diff --git a/res/drawable-hdpi/trashcan_hover.png b/res/drawable-hdpi/trashcan_hover.png
new file mode 100644
index 0000000..59f2741
--- /dev/null
+++ b/res/drawable-hdpi/trashcan_hover.png
Binary files differ
diff --git a/res/drawable/delete_zone_selector.xml b/res/drawable/delete_zone_selector.xml
index 6c917da..0c54b1d7 100644
--- a/res/drawable/delete_zone_selector.xml
+++ b/res/drawable/delete_zone_selector.xml
@@ -19,6 +19,6 @@
 -->
 
 <transition xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@drawable/delete_handle_normal"  />
-    <item android:drawable="@drawable/delete_handle"  />
+    <item android:drawable="@drawable/trashcan"  />
+    <item android:drawable="@drawable/trashcan_hover"  />
 </transition>
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index f6f383f..38b5c26 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -63,13 +63,12 @@
 
     <com.android.launcher2.DeleteZone
         android:id="@+id/delete_zone"
-        android:layout_width="wrap_content"
+        android:layout_width="fill_parent"
         android:layout_height="49dip"
         android:layout_gravity="bottom|center_horizontal"
 
         android:scaleType="center"
-        android:src="@drawable/ic_delete"
-        android:background="@drawable/delete_zone_selector"
+        android:src="@drawable/delete_zone_selector"
 
         android:visibility="invisible"
         
diff --git a/res/raw/rollo.c b/res/raw/rollo.c
index dc1199e..98f1e3e 100644
--- a/res/raw/rollo.c
+++ b/res/raw/rollo.c
@@ -39,6 +39,16 @@
 // Drawing constants, should be parameters ======
 #define VIEW_ANGLE 1.28700222f
 
+int g_lastFrameTime = 0;
+void print_frame_rate()
+{
+    int now = uptimeMillis();
+    if (g_lastFrameTime != 0) {
+        debugI32("frame_rate", 1000/(now-g_lastFrameTime));
+    }
+    g_lastFrameTime = now;
+}
+
 int
 count_pages(int iconCount)
 {
@@ -138,7 +148,7 @@
                     iconLeftX, iconTextureBottom, iconLeftZ,    0.0f, 1.0f);
 
             // label
-            if (scale <= 1.04f) {
+            if (scale <= 0.1f) {
                 float labelLeftX = centerX - farLabelWidth * 0.5f;
                 float labelRightX = centerX + farLabelWidth * 0.5f;
 
@@ -343,6 +353,8 @@
     drawRect(handleLeft, handleTop, handleLeft+handleWidth, handleTop+handleHeight, 0.0f);
     */
 
+    print_frame_rate();
+
     return !done;
 }
 
diff --git a/src/com/android/launcher2/AllAppsGridView.java b/src/com/android/launcher2/AllAppsGridView.java
index 23d4a7a..6606cc9 100644
--- a/src/com/android/launcher2/AllAppsGridView.java
+++ b/src/com/android/launcher2/AllAppsGridView.java
@@ -66,7 +66,7 @@
         app = new ApplicationInfo(app);
 
         mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
-        mLauncher.closeAllAppsDialog(true);
+        mLauncher.closeAllApps(true);
         mDraw = false;
         invalidate();
         return true;
@@ -84,7 +84,7 @@
     }
 
     public void onDropCompleted(View target, boolean success) {
-        mLauncher.closeAllAppsDialog(false);
+        mLauncher.closeAllApps(false);
     }
 
     void setLauncher(Launcher launcher) {
diff --git a/src/com/android/launcher2/AllAppsView.java b/src/com/android/launcher2/AllAppsView.java
index 5128db3..7bb6c8f 100644
--- a/src/com/android/launcher2/AllAppsView.java
+++ b/src/com/android/launcher2/AllAppsView.java
@@ -64,9 +64,18 @@
         implements View.OnClickListener, View.OnLongClickListener, DragSource {
     private static final String TAG = "Launcher.AllAppsView";
 
+    /** Bit for mLocks for when there are icons being loaded. */
+    private static final int LOCK_ICONS_PENDING = 1;
+
+    /** Bit for mLocks for when the enter/exit is going. */
+    private static final int LOCK_ZOOMING = 2;
+
     private Launcher mLauncher;
     private DragController mDragController;
-    private boolean mLocked = true;
+
+    /** When this is 0, modifications are allowed, when it's not, they're not.
+     * TODO: What about scrolling? */
+    private int mLocks = LOCK_ICONS_PENDING;
 
     private RenderScript mRS;
     private RolloRS mRollo;
@@ -80,7 +89,6 @@
     private int mLastMotionX;
     private int mMotionDownRawX;
     private int mMotionDownRawY;
-    private TouchHandler mTouchHandler;
     private int mScrollHandleTop;
 
     static class Defines {
@@ -168,95 +176,74 @@
             return true;
         }
 
-        if (mLocked) {
+        if (mLocks != 0) {
             return true;
         }
 
         super.onTouchEvent(ev);
 
-        mTouchHandler = mFlingHandler;
-        /*
-        int action = ev.getAction();
-        if (action == MotionEvent.ACTION_DOWN) {
-            if (ev.getY() > mScrollHandleTop) {
-                mTouchHandler = mScrollHandler;
+        int x = (int)ev.getX();
+        int deltaX;
+        switch (ev.getAction()) {
+        case MotionEvent.ACTION_DOWN:
+            mMotionDownRawX = (int)ev.getRawX();
+            mMotionDownRawY = (int)ev.getRawY();
+            mLastMotionX = x;
+            mRollo.mState.read();
+            mRollo.mState.startScrollX = mRollo.mState.scrollX = mLastScrollX
+                    = mRollo.mState.currentScrollX;
+            if (mRollo.mState.flingVelocityX != 0) {
+                mRollo.clearSelectedIcon();
             } else {
-                mTouchHandler = mFlingHandler;
+                mRollo.selectIcon(x, (int)ev.getY(), mRollo.mState.startScrollX,
+                        (-mRollo.mState.startScrollX / Defines.SCREEN_WIDTH_PX));
             }
+            mRollo.mState.flingVelocityX = 0;
+            mRollo.mState.adjustedDeceleration = 0;
+            mRollo.mState.save();
+            mVelocity = VelocityTracker.obtain();
+            mVelocity.addMovement(ev);
+            mStartedScrolling = false;
+            break;
+        case MotionEvent.ACTION_MOVE:
+        case MotionEvent.ACTION_OUTSIDE:
+            int slop = Math.abs(x - mLastMotionX);
+            if (!mStartedScrolling && slop < mConfig.getScaledTouchSlop()) {
+                // don't update mLastMotionX so slop is right and when we do start scrolling
+                // below, we get the right delta.
+            } else {
+                mStartedScrolling = true;
+                mRollo.clearSelectedIcon();
+                deltaX = x - mLastMotionX;
+                mVelocity.addMovement(ev);
+                mRollo.mState.currentScrollX = mLastScrollX;
+                mLastScrollX += deltaX;
+                mRollo.mState.scrollX = mLastScrollX;
+                mRollo.mState.save();
+                mLastMotionX = x;
+            }
+            break;
+        case MotionEvent.ACTION_UP:
+        case MotionEvent.ACTION_CANCEL:
+            mVelocity.computeCurrentVelocity(1000 /* px/sec */,
+                    mConfig.getScaledMaximumFlingVelocity());
+            mRollo.mState.flingTimeMs = (int)SystemClock.uptimeMillis(); // TODO: use long
+            mRollo.mState.flingVelocityX = (int)mVelocity.getXVelocity();
+            mRollo.clearSelectedIcon();
+            mRollo.mState.save();
+            mLastMotionX = -10000;
+            mVelocity.recycle();
+            mVelocity = null;
+            break;
         }
-        */
-        mTouchHandler.onTouchEvent(ev);
 
         return true;
     }
 
-    private abstract class TouchHandler {
-        abstract boolean onTouchEvent(MotionEvent ev);
-    };
-
-    private TouchHandler mFlingHandler = new TouchHandler() {
-        @Override
-        public boolean onTouchEvent(MotionEvent ev)
-        {
-            int x = (int)ev.getX();
-            int deltaX;
-            switch (ev.getAction()) {
-                case MotionEvent.ACTION_DOWN:
-                    mMotionDownRawX = (int)ev.getRawX();
-                    mMotionDownRawY = (int)ev.getRawY();
-                    mLastMotionX = x;
-                    mRollo.mState.read();
-                    mRollo.mState.startScrollX = mRollo.mState.scrollX = mLastScrollX
-                            = mRollo.mState.currentScrollX;
-                    if (mRollo.mState.flingVelocityX != 0) {
-                        mRollo.clearSelectedIcon();
-                    } else {
-                        mRollo.selectIcon(x, (int)ev.getY(), mRollo.mState.startScrollX,
-                                (-mRollo.mState.startScrollX / Defines.SCREEN_WIDTH_PX));
-                    }
-                    mRollo.mState.flingVelocityX = 0;
-                    mRollo.mState.adjustedDeceleration = 0;
-                    mRollo.mState.save();
-                    mVelocity = VelocityTracker.obtain();
-                    mVelocity.addMovement(ev);
-                    mStartedScrolling = false;
-                    break;
-                case MotionEvent.ACTION_MOVE:
-                case MotionEvent.ACTION_OUTSIDE:
-                    int slop = Math.abs(x - mLastMotionX);
-                    if (!mStartedScrolling && slop < mConfig.getScaledTouchSlop()) {
-                        // don't update mLastMotionX so slop is right and when we do start scrolling
-                        // below, we get the right delta.
-                    } else {
-                        mStartedScrolling = true;
-                        mRollo.clearSelectedIcon();
-                        deltaX = x - mLastMotionX;
-                        mVelocity.addMovement(ev);
-                        mRollo.mState.currentScrollX = mLastScrollX;
-                        mLastScrollX += deltaX;
-                        mRollo.mState.scrollX = mLastScrollX;
-                        mRollo.mState.save();
-                        mLastMotionX = x;
-                    }
-                    break;
-                case MotionEvent.ACTION_UP:
-                case MotionEvent.ACTION_CANCEL:
-                    mVelocity.computeCurrentVelocity(1000 /* px/sec */,
-                            mConfig.getScaledMaximumFlingVelocity());
-                    mRollo.mState.flingTimeMs = (int)SystemClock.uptimeMillis(); // TODO: use long
-                    mRollo.mState.flingVelocityX = (int)mVelocity.getXVelocity();
-                    mRollo.clearSelectedIcon();
-                    mRollo.mState.save();
-                    mLastMotionX = -10000;
-                    mVelocity.recycle();
-                    mVelocity = null;
-                    break;
-            }
-            return true;
-        }
-    };
-
     public void onClick(View v) {
+        if (mLocks != 0) {
+            return;
+        }
         int index = mRollo.mState.selectedIconIndex;
         if (mRollo.mState.flingVelocityX == 0 && index >= 0 && index < mAllAppsList.size()) {
             ApplicationInfo app = mAllAppsList.get(index);
@@ -265,6 +252,9 @@
     }
 
     public boolean onLongClick(View v) {
+        if (mLocks != 0) {
+            return true;
+        }
         int index = mRollo.mState.selectedIconIndex;
         Log.d(TAG, "long click! velocity=" + mRollo.mState.flingVelocityX + " index=" + index);
         if (mRollo.mState.flingVelocityX == 0 && index >= 0 && index < mAllAppsList.size()) {
@@ -280,7 +270,7 @@
                     left, top, Defines.ICON_WIDTH_PX, Defines.ICON_HEIGHT_PX,
                     this, app, DragController.DRAG_ACTION_COPY);
 
-            mLauncher.closeAllAppsDialog(true);
+            mLauncher.closeAllApps(true);
         }
         return true;
     }
@@ -294,15 +284,10 @@
 
     private static final int SCALE_SCALE = 100000;
 
-    public void show() {
-        mRollo.mState.read();
-        mRollo.mState.visible = 1;
-        mRollo.mState.zoom = SCALE_SCALE;
-        mRollo.mState.save();
-    }
-
     public void setScale(float amount) {
+        cancelLongPress();
         mRollo.mState.read();
+        mRollo.clearSelectedIcon();
         if (amount > 0.001f) {
             mRollo.mState.visible = 1;
             mRollo.mState.zoom = (int)(SCALE_SCALE*amount);
@@ -310,37 +295,21 @@
             mRollo.mState.visible = 0;
             mRollo.mState.zoom = 0;
         }
-        mRollo.mState.save();
-    }
-
-    public void hide() {
-        mRollo.mState.read();
-        mRollo.mState.visible = 0;
-        mRollo.mState.zoom = 0;
-        mRollo.mState.save();
-    }
-
-    /*
-    private TouchHandler mScrollHandler = new TouchHandler() {
-        @Override
-        public boolean onTouchEvent(MotionEvent ev)
-        {
-            int x = (int)ev.getX();
-            int w = getWidth();
-
-            float percent = x / (float)w;
-
-            mRollo.mState.read();
-
-            mRollo.mState.scrollX = mLastScrollX = -(int)(mPageCount * w * percent);
-            mRollo.mState.flingVelocityX = 0;
-            mRollo.mState.adjustedDeceleration = 0;
-            mRollo.mState.save();
-
-            return true;
+        if (amount > 0.001f && amount < 0.999f) {
+            mLocks |= LOCK_ZOOMING;
+        } else {
+            mLocks &= ~LOCK_ZOOMING;
         }
-    };
-    */
+        mRollo.mState.save();
+    }
+
+    public boolean isZooming() {
+        return (mLocks & LOCK_ZOOMING) != 0;
+    }
+
+    public boolean isVisible() {
+        return mRollo != null && mRollo.mState.visible != 0;
+    }
 
     @Override
     public boolean onTrackballEvent(MotionEvent ev)
@@ -362,7 +331,7 @@
         }
         mPageCount = countPages(list.size());
         Log.d(TAG, "setApps mRollo=" + mRollo + " list=" + list);
-        mLocked = false;
+        mLocks &= ~LOCK_ICONS_PENDING;
     }
 
     private void invokeIcon(int index) {
diff --git a/src/com/android/launcher2/DeleteZone.java b/src/com/android/launcher2/DeleteZone.java
index ed4cba9..ec4bc53 100644
--- a/src/com/android/launcher2/DeleteZone.java
+++ b/src/com/android/launcher2/DeleteZone.java
@@ -74,7 +74,7 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mTransition = (TransitionDrawable) getBackground();
+        mTransition = (TransitionDrawable) getDrawable();
     }
 
     public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
diff --git a/src/com/android/launcher2/HandleView.java b/src/com/android/launcher2/HandleView.java
index 98b3a37..eebc3ab 100644
--- a/src/com/android/launcher2/HandleView.java
+++ b/src/com/android/launcher2/HandleView.java
@@ -49,7 +49,7 @@
     @Override
     public View focusSearch(int direction) {
         View newFocus = super.focusSearch(direction);
-        if (newFocus == null && mLauncher.isDrawerDown()) {
+        if (newFocus == null && !mLauncher.isAllAppsVisible()) {
             final Workspace workspace = mLauncher.getWorkspace();
             workspace.dispatchUnhandledMove(null, direction);
             return (mOrientation == ORIENTATION_HORIZONTAL && direction == FOCUS_DOWN) ?
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index ec3622c..3e3ff06 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -177,7 +177,6 @@
     private DeleteZone mDeleteZone;
     private HandleView mHandleView;
     private AllAppsView mAllAppsGrid;
-    private boolean mAllAppsVisible; // if it's visible at all
     private int mMode = MODE_WORKSPACE;
 
     private Bundle mSavedState;
@@ -424,7 +423,7 @@
     @Override
     protected void onPause() {
         super.onPause();
-        closeAllAppsDialog(false);
+        closeAllApps(false);
     }
 
     @Override
@@ -812,7 +811,7 @@
                     mWorkspace.moveToDefaultScreen();
                 }
 
-                closeAllAppsDialog(true);
+                closeAllApps(true);
 
                 final View v = getWindow().peekDecorView();
                 if (v != null && v.getWindowToken() != null) {
@@ -821,7 +820,7 @@
                     imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                 }
             } else {
-                closeAllAppsDialog(false);
+                closeAllApps(false);
             }
         }
     }
@@ -853,7 +852,8 @@
 
         // When the drawer is opened and we are saving the state because of a
         // configuration change
-        if (mAllAppsVisible && isConfigurationChange) {
+        // TODO should not do this if the drawer is currently closing.
+        if (isAllAppsVisible() && isConfigurationChange) {
             outState.putBoolean(RUNTIME_STATE_ALL_APPS_FOLDER, true);
         }
 
@@ -906,7 +906,7 @@
     public void startSearch(String initialQuery, boolean selectInitialQuery,
             Bundle appSearchData, boolean globalSearch) {
 
-        closeAllAppsDialog(false);
+        closeAllApps(false);
 
         // Slide the search widget to the top, if it's on the current screen,
         // otherwise show the search dialog immediately.
@@ -1282,8 +1282,8 @@
                 case KeyEvent.KEYCODE_BACK:
                     if (!event.isCanceled()) {
                         mWorkspace.dispatchKeyEvent(event);
-                        if (mAllAppsVisible) {
-                            closeAllAppsDialog(true);
+                        if (isAllAppsVisible()) {
+                            closeAllApps(true);
                         } else {
                             closeFolder();
                         }
@@ -1341,10 +1341,11 @@
         } else if (tag instanceof FolderInfo) {
             handleFolderClick((FolderInfo) tag);
         } else if (v == mHandleView) {
-            if (mAllAppsVisible) {
-                // TODO how can we be here?
+            Log.d(TAG, "onClick");
+            if (isAllAppsVisible()) {
+                closeAllApps(true);
             } else {
-                showAllAppsDialog();
+                showAllApps(true);
             }
         }
     }
@@ -1432,6 +1433,7 @@
         }
 
         if (mWorkspace.allowLongPress()) {
+        Log.d(TAG, "there");
             mSwipeController.cancelSwipe();
             if (cellInfo.cell == null) {
                 if (cellInfo.valid) {
@@ -1453,10 +1455,6 @@
         return mHandleView;
     }
 
-    boolean isDrawerDown() { // TODO rename to isAllAppsVisible()
-        return /* TODO !mDrawer.isMoving() && */ !mAllAppsVisible;
-    }
-
     Workspace getWorkspace() {
         return mWorkspace;
     }
@@ -1605,26 +1603,44 @@
         }
     }
 
-    void showAllAppsDialog() {
-        mAllAppsVisible = true;
-        mAllAppsGrid.show();
+    boolean isAllAppsVisible() {
+        return mAllAppsGrid.isZooming() || mAllAppsGrid.isVisible();
+    }
+
+    void showAllApps(boolean animated) {
+        if (mMode == MODE_ALL_APPS) {
+            return;
+        }
+
+        mSwipeController.setRange(-1, 0);
+        if (animated) {
+            mSwipeController.animate(-1);
+        } else {
+            mSwipeController.setImmediate(-1);
+        }
+
         mWorkspace.hide();
         
         // TODO: fade these two too
         mDeleteZone.setVisibility(View.GONE);
-        mHandleView.setVisibility(View.GONE);
+        //mHandleView.setVisibility(View.GONE);
     }
 
-    void closeAllAppsDialog(boolean animated) {
-        if (mAllAppsVisible) {
-            mAllAppsGrid.hide();
-            mAllAppsVisible = false;
+    void closeAllApps(boolean animated) {
+        if (mAllAppsGrid.isVisible()) {
+            mSwipeController.setRange(0, 1);
+            if (animated) {
+                mSwipeController.animate(1);
+            } else {
+                mSwipeController.setImmediate(1);
+            }
             mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus();
-            mWorkspace.show();
 
             // TODO: fade these two too
+            /*
             mDeleteZone.setVisibility(View.VISIBLE);
             mHandleView.setVisibility(View.VISIBLE);
+            */
         }
     }
 
@@ -1777,6 +1793,7 @@
         switch (mMode) {
         case MODE_WORKSPACE:
             if (amount == -1) {
+                setWorkspaceAndAllAppsScale(-amount);
                 mWorkspace.clearChildrenCache();
                 mMode = MODE_ALL_APPS;
                 mSwipeController.setRange(0, 1);
@@ -1784,6 +1801,7 @@
             break;
         case MODE_ALL_APPS:
             if (amount == 1) {
+                setWorkspaceAndAllAppsScale(1-amount);
                 mWorkspace.clearChildrenCache();
                 mMode = MODE_WORKSPACE;
                 mSwipeController.setRange(-1, 0);
@@ -1983,7 +2001,7 @@
 
             final boolean allApps = mSavedState.getBoolean(RUNTIME_STATE_ALL_APPS_FOLDER, false);
             if (allApps) {
-                showAllAppsDialog();
+                showAllApps(false);
             }
 
             mSavedState = null;
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index b261a75..fae1d17 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -310,7 +310,7 @@
                 mAllAppsList.modified = new ArrayList();
             }
 
-            final Callbacks callbacks = mCallbacks.get();
+            final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
             if (callbacks == null) {
                 return;
             }
diff --git a/src/com/android/launcher2/SwipeController.java b/src/com/android/launcher2/SwipeController.java
index 7443b3b..41a02f0 100644
--- a/src/com/android/launcher2/SwipeController.java
+++ b/src/com/android/launcher2/SwipeController.java
@@ -143,6 +143,41 @@
         return mTracking || mCanceled;
     }
 
+    /**
+     * Set the value, performing an animation.  Make sure that you have set the
+     * range properly first, otherwise the value may be clamped.
+     */
+    public void animate(float dest) {
+        go(dest, 0);
+    }
+
+    /**
+     * Set the value, but don't perform an animation.  Make sure that you have set the
+     * range properly first, otherwise the value may be clamped.
+     */
+    public void setImmediate(float dest) {
+        go(dest, dest);
+    }
+
+    /**
+     * Externally start a swipe.  If dest == amount, this will end up just immediately
+     * setting the value, but it will perform the proper start and finish callbacks.
+     */
+    private void go(float dest, float amount) {
+        mListener.onStartSwipe();
+
+        dest = clamp(dest);
+        mDirection = dest > amount ? 1 : -1; // if they're equal it doesn't matter
+        mVelocity = mDirection * 0.002f; // TODO: density.
+        mAmount = amount;
+        mDest = dest;
+
+        mFlingTime = SystemClock.uptimeMillis();
+        mLastTime = 0;
+
+        scheduleAnim();
+    }
+
     private float clamp(float v) {
         if (v < mMinDest) {
             return mMinDest;
@@ -165,6 +200,7 @@
         mVelocityTracker.computeCurrentVelocity(1);
 
         mVelocity = mVelocityTracker.getYVelocity() / mSwipeDistance;
+        Log.d(TAG, "mVelocity=" + mVelocity);
         mDirection = mVelocity >= 0.0f ? 1 : -1;
         mAmount = clamp((screenY-mDownY)/mSwipeDistance);
         if (mAmount < 0) {
diff --git a/src/com/android/launcher2/WallpaperChooser.java b/src/com/android/launcher2/WallpaperChooser.java
index 8919ece..386ae97 100644
--- a/src/com/android/launcher2/WallpaperChooser.java
+++ b/src/com/android/launcher2/WallpaperChooser.java
@@ -23,6 +23,7 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.AsyncTask;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -31,7 +32,6 @@
 import android.view.View.OnClickListener;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
-import android.widget.Button;
 import android.widget.Gallery;
 import android.widget.ImageView;
 
@@ -45,11 +45,11 @@
     private ImageView mImageView;
     private boolean mIsWallpaperSet;
 
-    private BitmapFactory.Options mOptions;
     private Bitmap mBitmap;
 
     private ArrayList<Integer> mThumbs;
     private ArrayList<Integer> mImages;
+    private AsyncTask<Integer,Void,Bitmap> mLoader;
 
     @Override
     public void onCreate(Bundle icicle) {
@@ -60,17 +60,12 @@
 
         setContentView(R.layout.wallpaper_chooser);
 
-        mOptions = new BitmapFactory.Options();
-        mOptions.inDither = false;
-        mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
-
         mGallery = (Gallery) findViewById(R.id.gallery);
         mGallery.setAdapter(new ImageAdapter(this));
         mGallery.setOnItemSelectedListener(this);
         mGallery.setCallbackDuringFling(false);
 
-        Button b = (Button) findViewById(R.id.set);
-        b.setOnClickListener(this);
+        findViewById(R.id.set).setOnClickListener(this);
 
         mImageView = (ImageView) findViewById(R.id.wallpaper);
     }
@@ -108,20 +103,21 @@
         mIsWallpaperSet = false;
     }
 
-    public void onItemSelected(AdapterView parent, View v, int position, long id) {
-        final ImageView view = mImageView;
-        Bitmap b = BitmapFactory.decodeResource(getResources(), mImages.get(position), mOptions);
-        view.setImageBitmap(b);
-
-        // Help the GC
-        if (mBitmap != null) {
-            mBitmap.recycle();
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        
+        if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
+            mLoader.cancel(true);
+            mLoader = null;
         }
-        mBitmap = b;
+    }
 
-        final Drawable drawable = view.getDrawable();
-        drawable.setFilterBitmap(true);
-        drawable.setDither(true);
+    public void onItemSelected(AdapterView parent, View v, int position, long id) {
+        if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
+            mLoader.cancel(true);
+        }
+        mLoader = new WallpaperLoader().execute(position);
     }
 
     /*
@@ -185,4 +181,38 @@
     public void onClick(View v) {
         selectWallpaper(mGallery.getSelectedItemPosition());
     }
+
+    class WallpaperLoader extends AsyncTask<Integer, Void, Bitmap> {
+        protected Bitmap doInBackground(Integer... params) {
+            if (isCancelled()) return null;
+            return BitmapFactory.decodeResource(getResources(), mImages.get(params[0]), null);
+        }
+
+        @Override
+        protected void onPostExecute(Bitmap b) {
+            if (b == null) return;
+
+            if (!isCancelled()) {
+                // Help the GC
+                if (mBitmap != null) {
+                    mBitmap.recycle();
+                }
+    
+                final ImageView view = mImageView;
+                view.setImageBitmap(b);
+    
+                mBitmap = b;
+    
+                final Drawable drawable = view.getDrawable();
+                drawable.setFilterBitmap(true);
+                drawable.setDither(true);
+
+                view.postInvalidate();
+
+                mLoader = null;
+            } else {
+               b.recycle(); 
+            }
+        }
+    }
 }
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index c6def18..9191bc6 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -27,7 +27,6 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
@@ -47,8 +46,6 @@
  * A workspace is meant to be used with a fixed width only.
  */
 public class Workspace extends ViewGroup implements DropTarget, DragSource, DragScroller {
-    private static final String TAG = "Launcher.Workspace";
-
     private static final int INVALID_SCREEN = -1;
     
     /**
@@ -98,7 +95,7 @@
     private int[] mTempCell = new int[2];
     private int[] mTempEstimate = new int[2];
 
-    private boolean mAllowLongPress;
+    private boolean mAllowLongPress = true;
 
     private int mTouchSlop;
     private int mMaximumVelocity;
@@ -603,7 +600,7 @@
 
     @Override
     protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
-        if (mLauncher.isDrawerDown()) {
+        if (!mLauncher.isAllAppsVisible()) {
             final Folder openFolder = getOpenFolder();
             if (openFolder != null) {
                 return openFolder.requestFocus(direction, previouslyFocusedRect);
@@ -638,7 +635,7 @@
 
     @Override
     public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
-        if (mLauncher.isDrawerDown()) {
+        if (!mLauncher.isAllAppsVisible()) {
             final Folder openFolder = getOpenFolder();
             if (openFolder == null) {
                 getChildAt(mCurrentScreen).addFocusables(views, direction);
@@ -659,7 +656,7 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (mLauncher.isWorkspaceLocked() || !mLauncher.isDrawerDown()) {
+        if (mLauncher.isWorkspaceLocked() || mLauncher.isAllAppsVisible()) {
             return false; // We don't want the events.  Let them fall through to the all apps view.
         }
 
@@ -769,7 +766,7 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
 
-        if (mLauncher.isWorkspaceLocked() || !mLauncher.isDrawerDown()) {
+        if (mLauncher.isWorkspaceLocked() || mLauncher.isAllAppsVisible()) {
             return false; // We don't want the events.  Let them fall through to the all apps view.
         }
 
@@ -932,7 +929,8 @@
             // Move internally
             if (mDragInfo != null) {
                 final View cell = mDragInfo.cell;
-                if (mCurrentScreen != mDragInfo.screen) {
+                int index = mScroller.isFinished() ? mCurrentScreen : mNextScreen;                
+                if (index != mDragInfo.screen) {
                     final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
                     originalCellLayout.removeView(cell);
                     cellLayout.addView(cell);
@@ -944,7 +942,7 @@
                 final ItemInfo info = (ItemInfo)cell.getTag();
                 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
                 LauncherModel.moveItemInDatabase(mLauncher, info,
-                        LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY);
+                        LauncherSettings.Favorites.CONTAINER_DESKTOP, index, lp.cellX, lp.cellY);
             }
         }
     }