work around and fix bugs

- Make rollo always draw.  This works around the bug somewhere that makes
  it show gray when all apps shold be closed
- Simplify the SwipeController now that we're not zooming the workspace.
- Make the readback data sane by splitting it to a different allocation.
  Now there is one allocation for each direction of data flow.
- Make AllAppsView.isVisible return the correct value.
diff --git a/res/raw/rollo.c b/res/raw/rollo.c
index cff4620..59862bc 100644
--- a/res/raw/rollo.c
+++ b/res/raw/rollo.c
@@ -24,22 +24,6 @@
 // Drawing constants, should be parameters ======
 #define VIEW_ANGLE 1.28700222f
 
-int g_oneLastFrame = 1;
-int one_last_frame(int more) {
-    if (more) {
-        g_oneLastFrame = 1;
-        return 1;
-    } else {
-        if (g_oneLastFrame) {
-            g_oneLastFrame = 0;
-            return 1;
-        } else {
-            g_oneLastFrame = 1;
-            return 0;
-        }
-    }
-}
-
 void init() {
     g_AttractionTable[0] = 4.5f;
     g_AttractionTable[1] = 4.5f;
@@ -108,12 +92,16 @@
     //g_Zoom += (maxf(fabsf(g_PosVelocity), 3) - 3) / 2.f;
 }
 
-
 void setZoomTarget() {
-    g_ZoomTarget = state->zoom;
+    g_ZoomTarget = state->zoomTarget;
     //debugF("zoom target", g_ZoomTarget);
 }
 
+void setZoom() {
+    readback->zoom = g_Zoom = g_ZoomTarget = state->zoom;
+    //debugF("zoom", g_ZoomTarget);
+}
+
 int
 count_pages(int iconCount)
 {
@@ -326,16 +314,17 @@
         } else {
             g_Zoom += dz;
         }
+        readback->zoom = g_Zoom;
     }
 
     // Set clear value to dim the background based on the zoom position.
-    if (g_Zoom < 0.8f) {
+    if (g_Zoom < 0.001f) {
+        pfClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        // Nothing else to do if fully zoomed out.
+        g_PosPage = roundf(g_PosPage);
+        return 1; // 0;
+    } else if (g_Zoom < 0.8f) {
         pfClearColor(0.0f, 0.0f, 0.0f, g_Zoom);
-        if (g_Zoom == 0) {
-            // Nothing else to do if fully zoomed out.
-            g_PosPage = roundf(g_PosPage);
-            return one_last_frame(0);
-        }
     } else {
         pfClearColor(0.0f, 0.0f, 0.0f, 0.80f);
     }
@@ -347,8 +336,8 @@
     g_PageCount = count_pages(iconCount);
 
     updatePos(0.1f);
-    state->readPosX = g_PosPage;
-    state->readVel = g_PosVelocity;
+    readback->posX = g_PosPage;
+    readback->velocity = g_PosVelocity;
 
     //debugF("    draw g_PosPage", g_PosPage);
 
@@ -387,6 +376,6 @@
 
     // Bug workaround where the last frame is not always displayed
     // So we keep rendering until the bug is fixed.
-    return one_last_frame((g_PosVelocity != 0) || fracf(g_PosPage) || g_Zoom != g_ZoomTarget);
+    return 1; //(g_PosVelocity != 0) || fracf(g_PosPage) || g_Zoom != g_ZoomTarget);
 }
 
diff --git a/src/com/android/launcher2/AllAppsView.java b/src/com/android/launcher2/AllAppsView.java
index e2f3be3..388a9bf 100644
--- a/src/com/android/launcher2/AllAppsView.java
+++ b/src/com/android/launcher2/AllAppsView.java
@@ -67,9 +67,6 @@
     /** 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;
 
@@ -98,10 +95,11 @@
 
         public static final int ALLOC_PARAMS = 0;
         public static final int ALLOC_STATE = 1;
-        public static final int ALLOC_ICON_IDS = 2;
-        public static final int ALLOC_LABEL_IDS = 3;
-        public static final int ALLOC_X_BORDERS = 4;
-        public static final int ALLOC_Y_BORDERS = 5;
+        public static final int ALLOC_READBACK = 2;
+        public static final int ALLOC_ICON_IDS = 3;
+        public static final int ALLOC_LABEL_IDS = 4;
+        public static final int ALLOC_X_BORDERS = 5;
+        public static final int ALLOC_Y_BORDERS = 6;
 
         public static final int COLUMNS_PER_PAGE = 4;
         public static final int ROWS_PER_PAGE = 4;
@@ -143,6 +141,15 @@
     }
 
     @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        super.surfaceDestroyed(holder);
+
+        destroyRenderScript();
+        mRS = null;
+        mRollo = null;
+    }
+
+    @Override
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
         super.surfaceChanged(holder, format, w, h);
 
@@ -174,7 +181,7 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev)
     {
-        if (mRollo.mState.visible == 0) {
+        if (!isVisible()) {
             return true;
         }
 
@@ -191,15 +198,15 @@
             mMotionDownRawX = (int)ev.getRawX();
             mMotionDownRawY = (int)ev.getRawY();
             mLastMotionX = x;
-            mRollo.mState.read();
+            mRollo.mReadback.read();
 
             mRollo.mState.newPositionX = ev.getRawX() / Defines.SCREEN_WIDTH_PX;
             mRollo.mState.newTouchDown = 1;
 
-            if (mRollo.mState.readVel != 0) {
+            if (mRollo.mReadback.velocity != 0) {
                 mRollo.clearSelectedIcon();
             } else {
-                mRollo.selectIcon(x, (int)ev.getY(), mRollo.mState.readPosX);
+                mRollo.selectIcon(x, (int)ev.getY(), mRollo.mReadback.posX);
             }
             mRollo.mState.save();
             mRollo.mInvokeMove.execute();
@@ -249,7 +256,7 @@
     }
 
     public void onClick(View v) {
-        if (mLocks != 0) {
+        if (mLocks != 0 || !isVisible()) {
             return;
         }
         int index = mRollo.mState.selectedIconIndex;
@@ -260,7 +267,7 @@
     }
 
     public boolean onLongClick(View v) {
-        if (mLocks != 0) {
+        if (mLocks != 0 || !isVisible()) {
             return true;
         }
         int index = mRollo.mState.selectedIconIndex;
@@ -278,7 +285,7 @@
                     left, top, Defines.ICON_WIDTH_PX, Defines.ICON_HEIGHT_PX,
                     this, app, DragController.DRAG_ACTION_COPY);
 
-            mLauncher.closeAllApps();
+            mLauncher.closeAllApps(true);
         }
         return true;
     }
@@ -290,38 +297,49 @@
     public void onDropCompleted(View target, boolean success) {
     }
 
-    public void setZoom(float v) {
-        mRollo.mState.zoom = v;
-        mRollo.mState.save();
-        mRollo.mInvokeZoom.execute();
+    public void setZoomTarget(float amount) {
+        zoom(amount, true);
     }
 
-    public void setScale(float amount) {
+    public void setZoom(float amount) {
+        zoom(amount, false);
+    }
+
+    private void zoom(float amount, boolean animate) {
+        if (mRollo == null) {
+            return;
+        }
+
         cancelLongPress();
-        mRollo.mState.read();
         mRollo.clearSelectedIcon();
         if (amount > 0.001f) {
-            mRollo.mState.visible = 1;
-            mRollo.mState.zoom = amount;
+            mRollo.mState.zoomTarget = amount;
+            if (!animate) {
+                // set in readback, so we're correct even before the next frame
+                mRollo.mReadback.zoom = mRollo.mState.zoom = amount;
+                mRollo.mReadback.save();
+            }
         } else {
-            mRollo.mState.visible = 0;
-            mRollo.mState.zoom = 0;
-        }
-        if (amount > 0.001f && amount < 0.999f) {
-            mLocks |= LOCK_ZOOMING;
-        } else {
-            mLocks &= ~LOCK_ZOOMING;
+            mRollo.mState.zoomTarget = 0;
+            if (!animate) {
+                mRollo.mReadback.zoom = mRollo.mState.zoom = 0;
+                mRollo.mReadback.save();
+            }
         }
         mRollo.mState.save();
-        mRollo.mInvokeZoom.execute();
-    }
-
-    public boolean isZooming() {
-        return (mLocks & LOCK_ZOOMING) != 0;
+        if (!animate) {
+            mRollo.mInvokeSetZoom.execute();
+        } else {
+            mRollo.mInvokeSetZoomTarget.execute();
+        }
     }
 
     public boolean isVisible() {
-        return mRollo != null && mRollo.mState.visible != 0;
+        if (mRollo == null) {
+            return false;
+        }
+        mRollo.mReadback.read();
+        return mRollo.mReadback.zoom > 0.001f;
     }
 
     @Override
@@ -372,7 +390,8 @@
 
         private Script.Invokable mInvokeMove;
         private Script.Invokable mInvokeFling;
-        private Script.Invokable mInvokeZoom;
+        private Script.Invokable mInvokeSetZoomTarget;
+        private Script.Invokable mInvokeSetZoom;
 
         private Sampler mSampler;
         private Sampler mSamplerText;
@@ -407,6 +426,7 @@
 
         Params mParams;
         State mState;
+        Readback mReadback;
 
         class BaseAlloc {
             Allocation mAlloc;
@@ -415,10 +435,6 @@
             void save() {
                 mAlloc.data(this);
             }
-
-            void read() {
-                mAlloc.read(this);
-            }
         }
 
         class Params extends BaseAlloc {
@@ -439,14 +455,12 @@
         class State extends BaseAlloc {
             public float newPositionX;
             public int newTouchDown;
-            public float readPosX;
-            public float readVel;
             public float flingVelocityX;
             public int iconCount;
             public int scrollX;
             public int selectedIconIndex = -1;
             public int selectedIconTexture;
-            public int visible;
+            public float zoomTarget;
             public float zoom;
 
             State() {
@@ -456,6 +470,22 @@
             }
         }
 
+        class Readback extends BaseAlloc {
+            public float posX;
+            public float velocity;
+            public float zoom;
+
+            Readback() {
+                mType = Type.createFromClass(mRS, Readback.class, 1, "ReadbackClass");
+                mAlloc = Allocation.createTyped(mRS, mType);
+                save();
+            }
+
+            void read() {
+                mAlloc.read(this);
+            }
+        }
+
         public RolloRS() {
         }
 
@@ -548,6 +578,7 @@
         private void initData() {
             mParams = new Params();
             mState = new State();
+            mReadback = new Readback();
 
             final Utilities.BubbleText bubble = new Utilities.BubbleText(getContext());
 
@@ -567,6 +598,7 @@
 
             mParams.save();
             mState.save();
+            mReadback.save();
 
             mSelectionBitmap = Bitmap.createBitmap(Defines.ICON_TEXTURE_WIDTH_PX,
                     Defines.ICON_TEXTURE_HEIGHT_PX, Bitmap.Config.ARGB_8888);
@@ -583,14 +615,17 @@
             sb.addDefines(Defines.class);
             sb.setType(mParams.mType, "params", Defines.ALLOC_PARAMS);
             sb.setType(mState.mType, "state", Defines.ALLOC_STATE);
+            sb.setType(mReadback.mType, "readback", Defines.ALLOC_READBACK);
             mInvokeMove = sb.addInvokable("move");
             mInvokeFling = sb.addInvokable("fling");
-            mInvokeZoom = sb.addInvokable("setZoomTarget");
+            mInvokeSetZoomTarget = sb.addInvokable("setZoomTarget");
+            mInvokeSetZoom = sb.addInvokable("setZoom");
             mScript = sb.create();
             mScript.setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
             mScript.bindAllocation(mParams.mAlloc, Defines.ALLOC_PARAMS);
             mScript.bindAllocation(mState.mAlloc, Defines.ALLOC_STATE);
+            mScript.bindAllocation(mReadback.mAlloc, Defines.ALLOC_READBACK);
             mScript.bindAllocation(mAllocIconID, Defines.ALLOC_ICON_IDS);
             mScript.bindAllocation(mAllocLabelID, Defines.ALLOC_LABEL_IDS);
             mScript.bindAllocation(mAllocTouchXBorders, Defines.ALLOC_X_BORDERS);
diff --git a/src/com/android/launcher2/HandleView.java b/src/com/android/launcher2/HandleView.java
index eebc3ab..e6d940d 100644
--- a/src/com/android/launcher2/HandleView.java
+++ b/src/com/android/launcher2/HandleView.java
@@ -21,8 +21,9 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
-import android.view.View;
+import android.view.MotionEvent;
 import android.view.KeyEvent;
+import android.view.View;
 
 public class HandleView extends ImageView {
     private static final int ORIENTATION_HORIZONTAL = 1;
@@ -84,6 +85,14 @@
         return handled;
     }
 
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN && mLauncher.isAllAppsVisible()) {
+            return false;
+        }
+        return super.onTouchEvent(ev);
+    }
+
     private static boolean isDirectionKey(int keyCode) {
         return keyCode == KeyEvent.KEYCODE_DPAD_DOWN || keyCode == KeyEvent.KEYCODE_DPAD_LEFT ||
                 keyCode == KeyEvent.KEYCODE_DPAD_RIGHT || keyCode == KeyEvent.KEYCODE_DPAD_UP;
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 3813afe..7075b5f 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -82,8 +82,7 @@
  * Default launcher application.
  */
 public final class Launcher extends Activity
-        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
-        SwipeController.SwipeListener {
+        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks {
     static final String LOG_TAG = "Launcher";
     static final String TAG = LOG_TAG;
     static final boolean LOGD = false;
@@ -109,10 +108,6 @@
     private static final int REQUEST_PICK_LIVE_FOLDER = 8;
     private static final int REQUEST_PICK_APPWIDGET = 9;
 
-    private static final int MODE_WORKSPACE = 0;
-    private static final int MODE_ALL_APPS = 1;
-    private static final int MODE_ALL_APPS_ZOOMED = 2;
-
     static final String EXTRA_SHORTCUT_DUPLICATE = "duplicate";
 
     static final String EXTRA_CUSTOM_WIDGET = "custom_widget";
@@ -177,7 +172,6 @@
     private DeleteZone mDeleteZone;
     private HandleView mHandleView;
     private AllAppsView mAllAppsGrid;
-    private int mMode = MODE_WORKSPACE;
 
     private Bundle mSavedState;
 
@@ -423,7 +417,7 @@
     @Override
     protected void onPause() {
         super.onPause();
-        closeAllApps();
+        closeAllApps(false);
     }
 
     @Override
@@ -519,9 +513,8 @@
     private void setupViews() {
         mDragController = new DragController(this);
         DragController dragController = mDragController;
-        mSwipeController = new SwipeController(this, this);
+        mSwipeController = new SwipeController(this);
         SwipeController swipeController = mSwipeController;
-        swipeController.setRange(-1, 0);
 
         DragLayer dragLayer = (DragLayer) findViewById(R.id.drag_layer);
         dragLayer.setDragController(dragController);
@@ -531,6 +524,7 @@
         mAllAppsGrid.setLauncher(this);
         mAllAppsGrid.setDragController(dragController);
         mAllAppsGrid.setWillNotDraw(false); // We don't want a hole punched in our window.
+        swipeController.setAllAppsView(mAllAppsGrid);
 
         mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
         final Workspace workspace = mWorkspace;
@@ -811,7 +805,7 @@
                     mWorkspace.moveToDefaultScreen();
                 }
 
-                closeAllApps();
+                closeAllApps(true);
 
                 final View v = getWindow().peekDecorView();
                 if (v != null && v.getWindowToken() != null) {
@@ -820,7 +814,7 @@
                     imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                 }
             } else {
-                closeAllApps();
+                closeAllApps(false);
             }
         }
     }
@@ -906,7 +900,7 @@
     public void startSearch(String initialQuery, boolean selectInitialQuery,
             Bundle appSearchData, boolean globalSearch) {
 
-        closeAllApps();
+        closeAllApps(true);
 
         // Slide the search widget to the top, if it's on the current screen,
         // otherwise show the search dialog immediately.
@@ -1283,7 +1277,7 @@
                     if (!event.isCanceled()) {
                         mWorkspace.dispatchKeyEvent(event);
                         if (isAllAppsVisible()) {
-                            closeAllApps();
+                            closeAllApps(true);
                         } else {
                             closeFolder();
                         }
@@ -1343,7 +1337,7 @@
         } else if (v == mHandleView) {
             Log.d(TAG, "onClick");
             if (isAllAppsVisible()) {
-                closeAllApps();
+                closeAllApps(true);
             } else {
                 showAllApps();
             }
@@ -1433,7 +1427,6 @@
         }
 
         if (mWorkspace.allowLongPress()) {
-        Log.d(TAG, "there");
             mSwipeController.cancelSwipe();
             if (cellInfo.cell == null) {
                 if (cellInfo.valid) {
@@ -1604,27 +1597,21 @@
     }
 
     boolean isAllAppsVisible() {
-        return mAllAppsGrid.isZooming() || mAllAppsGrid.isVisible();
+        return mAllAppsGrid.isVisible();
     }
 
     void showAllApps() {
-        if (mMode == MODE_ALL_APPS) {
-            return;
-        }
-
-        mSwipeController.setRange(-1, 0);
-        mSwipeController.setImmediate(-1);
-        mWorkspace.hide();
+        mSwipeController.setMode(SwipeController.MODE_ALL_APPS, true);
+        //mWorkspace.hide();
 
         // TODO: fade these two too
         mDeleteZone.setVisibility(View.GONE);
         //mHandleView.setVisibility(View.GONE);
     }
 
-    void closeAllApps() {
+    void closeAllApps(boolean animated) {
         if (mAllAppsGrid.isVisible()) {
-            mSwipeController.setRange(0, 1);
-            mSwipeController.setImmediate(1);
+            mSwipeController.setMode(SwipeController.MODE_WORKSPACE, animated);
             mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus();
 
             // TODO: fade these two too
@@ -1761,91 +1748,6 @@
     }
 
     /**
-     * Implementation of the method from SwipeController.SwipeListener.
-     */
-    public void onStartSwipe() {
-        switch (mMode) {
-        case MODE_WORKSPACE:
-            mWorkspace.enableChildrenCache();
-            break;
-        case MODE_ALL_APPS:
-            break;
-        case MODE_ALL_APPS_ZOOMED:
-            break;
-        }
-    }
-
-    /**
-     * Implementation of the method from SwipeController.SwipeListener.
-     *
-     * @param amount The final value of the swipe (-1, 0 or 1)
-     */
-    public void onFinishSwipe(int amount) {
-        switch (mMode) {
-        case MODE_WORKSPACE:
-            if (amount == -1) {
-                setWorkspaceAndAllAppsScale(-amount);
-                mWorkspace.clearChildrenCache();
-                mMode = MODE_ALL_APPS;
-                mSwipeController.setRange(0, 1);
-            }
-            break;
-        case MODE_ALL_APPS:
-            if (amount == 1) {
-                setWorkspaceAndAllAppsScale(1-amount);
-                mWorkspace.clearChildrenCache();
-                mMode = MODE_WORKSPACE;
-                mSwipeController.setRange(-1, 0);
-            }
-            break;
-        case MODE_ALL_APPS_ZOOMED:
-            break;
-        }
-    }
-
-    /**
-     * Implementation of the method from SwipeController.SwipeListener.
-     */
-    public void onSwipe(float amount) {
-        switch (mMode) {
-        case MODE_WORKSPACE:
-            // We can open the all apps view.
-            //   0 == workspace is showing
-            //  -1 == all apps is showing
-            setWorkspaceAndAllAppsScale(-amount);
-            break;
-        case MODE_ALL_APPS:
-            // We can close it, or (someday) zoom it further
-            //   0 == all apps showing
-            //   1 == workspace is showing
-            setWorkspaceAndAllAppsScale(1-amount);
-            break;
-        }
-    }
-
-    /**
-     * Set the scale factor for the workspace and the all apps grid.
-     *
-     * @param amount A float between 0 and 1, where:
-     *                  0 == workspace is showing and
-     *                  1 == the all apps grid is showing.
-     */
-    private void setWorkspaceAndAllAppsScale(float amount) {
-        //Log.d("setWorkspaceAndAllAppsScale", "setWorkspaceAndAllAppsScale amount=" + amount);
-        if (amount < 0.001f) {
-            amount = 0.0f;
-        }
-        if (amount > 0.999f) {
-            amount = 1.0f;
-            mWorkspace.setVisibility(View.INVISIBLE);
-        } else {
-            mWorkspace.setVisibility(View.VISIBLE);
-        }
-        //mWorkspace.setScale(1-amount);
-        mAllAppsGrid.setScale(amount);
-    }
-
-    /**
      * Implementation of the method from LauncherModel.Callbacks.
      */
     public int getCurrentWorkspaceScreen() {
diff --git a/src/com/android/launcher2/SwipeController.java b/src/com/android/launcher2/SwipeController.java
index 41a02f0..7617fe0 100644
--- a/src/com/android/launcher2/SwipeController.java
+++ b/src/com/android/launcher2/SwipeController.java
@@ -31,15 +31,20 @@
 public class SwipeController {
     private static final String TAG = "Launcher.SwipeController";
 
+    public static final int MODE_WORKSPACE = 0;
+    public static final int MODE_ALL_APPS = 1;
+    public static final int MODE_ALL_APPS_ZOOMED = 2;
+
     private static final int FRAME_DELAY = 1000 / 30;
     private static final float DECAY_CONSTANT = 0.65f;
     private static final float SPRING_CONSTANT = 0.0009f;
 
     // configuration
-    private SwipeListener mListener;
     private int mSlop;
     private float mSwipeDistance;
 
+    private AllAppsView mAllAppsView;
+
     // state
     private VelocityTracker mVelocityTracker;
     private boolean mCanceled;
@@ -47,52 +52,59 @@
     private int mDownX;
     private int mDownY;
 
-    private float mMinDest;
-    private float mMaxDest;
-    private long mFlingTime;
-    private long mLastTime;
-    private int mDirection;
-    private float mVelocity;
-    private float mDest;
+    private int mMode;
+    private int mMinDest;
+    private int mMaxDest;
     private float mAmount;
 
-    public interface SwipeListener {
-        public void onStartSwipe();
-        public void onFinishSwipe(int amount);
-        public void onSwipe(float amount);
-    }
-
-    public SwipeController(Context context, SwipeListener listener) {
+    public SwipeController(Context context) {
         ViewConfiguration config = ViewConfiguration.get(context);
         mSlop = config.getScaledTouchSlop();
         
         DisplayMetrics display = context.getResources().getDisplayMetrics();
         mSwipeDistance = display.heightPixels / 2; // one half of the screen
 
-        mListener = listener;
+        setMode(MODE_WORKSPACE, false);
     }
 
-    public void setRange(float min, float max) {
-        mMinDest = min;
-        mMaxDest = max;
+    public void setAllAppsView(AllAppsView allAppsView) {
+        mAllAppsView = allAppsView;
     }
 
-    public void cancelSwipe() {
+    public void setMode(int mode, boolean animate) {
+        mMinDest = mode - 1;
+        if (mMinDest < MODE_WORKSPACE) {
+            mMinDest = MODE_WORKSPACE;
+        }
+        mMaxDest = mode + 1;
+        if (mMaxDest > MODE_ALL_APPS) { // TODO: support _ZOOMED
+            mMaxDest = MODE_ALL_APPS;
+        }
         mCanceled = true;
+        if (mAllAppsView != null) {
+            // TODO: do something with the wallpaper
+            if (animate) {
+                mAllAppsView.setZoomTarget(mode);
+            } else {
+                mAllAppsView.setZoom(mode);
+            }
+        }
+        mMode = mode;
+    }
+
+    /**
+     * Cancels the current swipe, if there is one, and animates back to wherever we were before.
+     */
+    public void cancelSwipe() {
+         mCanceled = true;
+         mAllAppsView.setZoomTarget(mMode);
     }
 
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         onTouchEvent(ev);
-
-        // After we return true, onIntercept doesn't get called any more, so this is
-        // a good place to do the callback.
-        if (mTracking) {
-            mListener.onStartSwipe();
-        }
-
         return mTracking;
     }
-
+ 
     public boolean onTouchEvent(MotionEvent ev) {
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
@@ -143,41 +155,6 @@
         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;
@@ -188,71 +165,42 @@
         }
     }
 
-    /**
-     * Perform the callbacks.
-     */
+    private float dist(int screenY) {
+        return clamp(mMode - ((screenY - mDownY) / mSwipeDistance));
+    }
+
     private void track(int screenY) {
-        mAmount = clamp((screenY - mDownY) / mSwipeDistance);
-        mListener.onSwipe(mAmount);
+        mAmount = dist(screenY);
+
+        //Log.d(TAG, "mAmount=" + mAmount);
+        mAllAppsView.setZoom(mAmount);
     }
 
     private void fling(int screenY) {
+        mAmount = dist(screenY);
+
         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) {
-            mDest = clamp(mVelocity < 0 ? -1.0f : 0.0f);
-        } else {
-            mDest = clamp(mVelocity < 0 ? 0.0f : 1.0f);
-        }
+        float velocity = mVelocityTracker.getYVelocity() / mSwipeDistance;
+        int direction = velocity >= 0.0f ? 1 : -1;
+        mAmount = dist(screenY);
 
-        mFlingTime = SystemClock.uptimeMillis();
-        mLastTime = 0;
-
-        scheduleAnim();
-    }
-
-    private void scheduleAnim() {
-        boolean send = true;
-        if (mDirection > 0) {
-            if (mAmount > (mDest - 0.01f)) {
-                send = false;
+        int dest = mMode;
+        if (mMode < mAmount) {
+            if (velocity < 0) { // up
+                dest = mMode + 1;
             }
         } else {
-            if (mAmount < (mDest + 0.01f)) {
-                send = false;
+            if (velocity > 0) { // down
+                dest = mMode - 1;
             }
         }
-        if (send) {
-            mHandler.sendEmptyMessageDelayed(1, FRAME_DELAY);
-        } else {
-            mListener.onFinishSwipe((int)(mAmount >= 0 ? (mAmount+0.5f) : (mAmount-0.5f)));
-        }
+        // else dest == mMode, so go back to where we started
+
+        //Log.d(TAG, "velocity=" + velocity + " mAmount=" + mAmount + " dest=" + dest);
+        mAllAppsView.setZoomTarget(dest);
+        mMode = dest;
+        mCanceled = true;
     }
-
-    Handler mHandler = new Handler() {
-        public void handleMessage(Message msg) {
-            long now = SystemClock.uptimeMillis();
-
-            final long t = now - mFlingTime;
-            final long dt = t - mLastTime;
-            mLastTime = t;
-            final float timeSlices = dt / (float)FRAME_DELAY;
-
-            float distance = mDest - mAmount;
-
-            mVelocity += timeSlices * mDirection * SPRING_CONSTANT * distance * distance / 2;
-            mVelocity *= (timeSlices * DECAY_CONSTANT);
-
-            mAmount += timeSlices * mVelocity;
-            mAmount += distance * timeSlices * 0.2f; // cheat
-
-            mListener.onSwipe(mAmount);
-            scheduleAnim();
-        }
-    };
 }
 
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 37a2444..cc09bdb 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -37,6 +37,7 @@
 import android.widget.TextView;
 import android.os.Parcelable;
 import android.os.Parcel;
+import android.util.Log;
 
 import java.util.ArrayList;
 
@@ -46,6 +47,7 @@
  * 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;
     
     /**
@@ -647,6 +649,16 @@
     }
 
     @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            if (mLauncher.isWorkspaceLocked() || mLauncher.isAllAppsVisible()) {
+                return false;
+            }
+        }
+        return super.dispatchTouchEvent(ev);
+    }
+
+    @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (mLauncher.isWorkspaceLocked() || mLauncher.isAllAppsVisible()) {
             return false; // We don't want the events.  Let them fall through to the all apps view.