Merge "Adding scroll disambiguation between Workspace and AppWidgets" into honeycomb
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 92b09f4..6138b86 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -825,11 +825,15 @@
         anim.start();
     }
 
+    protected void determineScrollingStart(MotionEvent ev) {
+        determineScrollingStart(ev, 1.0f);
+    }
+
     /*
      * Determines if we should change the touch state to start scrolling after the
      * user moves their touch point too far.
      */
-    protected void determineScrollingStart(MotionEvent ev) {
+    protected void determineScrollingStart(MotionEvent ev, float touchSlopScale) {
         /*
          * Locally do absolute value. mLastMotionX is set to the y value
          * of the down event.
@@ -840,12 +844,12 @@
         final int xDiff = (int) Math.abs(x - mLastMotionX);
         final int yDiff = (int) Math.abs(y - mLastMotionY);
 
-        final int touchSlop = mTouchSlop;
+        final int touchSlop = Math.round(touchSlopScale * mTouchSlop);
         boolean xPaged = xDiff > mPagingTouchSlop;
         boolean xMoved = xDiff > touchSlop;
         boolean yMoved = yDiff > touchSlop;
 
-        if (xMoved || yMoved) {
+        if (xMoved || xPaged || yMoved) {
             if (mUsePagingTouchSlop ? xPaged : xMoved) {
                 // Scroll if the user moved far enough along the X axis
                 mTouchState = TOUCH_STATE_SCROLLING;
@@ -855,15 +859,19 @@
                 pageBeginMoving();
             }
             // Either way, cancel any pending longpress
-            if (mAllowLongPress) {
-                mAllowLongPress = false;
-                // Try canceling the long press. It could also have been scheduled
-                // by a distant descendant, so use the mAllowLongPress flag to block
-                // everything
-                final View currentPage = getPageAt(mCurrentPage);
-                if (currentPage != null) {
-                    currentPage.cancelLongPress();
-                }
+            cancelCurrentPageLongPress();
+        }
+    }
+
+    protected void cancelCurrentPageLongPress() {
+        if (mAllowLongPress) {
+            mAllowLongPress = false;
+            // Try canceling the long press. It could also have been scheduled
+            // by a distant descendant, so use the mAllowLongPress flag to block
+            // everything
+            final View currentPage = getPageAt(mCurrentPage);
+            if (currentPage != null) {
+                currentPage.cancelLongPress();
             }
         }
     }
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 765e4d6..2800b02 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -217,6 +217,13 @@
     private int mLastDragXOffset;
     private int mLastDragYOffset;
 
+    // Variables relating to touch disambiguation (scrolling workspace vs. scrolling a widget)
+    private float mXDown;
+    private float mYDown;
+    final static float START_DAMPING_TOUCH_SLOP_ANGLE = (float) Math.PI / 6;
+    final static float MAX_SWIPE_ANGLE = (float) Math.PI / 3;
+    final static float TOUCH_SLOP_DAMPING_FACTOR = 4;
+
     /**
      * Used to inflate the Workspace from XML.
      *
@@ -532,6 +539,11 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            mXDown = ev.getX();
+            mYDown = ev.getY();
+        }
+
         if (mIsSmall || mIsInUnshrinkAnimation) {
             if (mLauncher.isAllAppsVisible() &&
                     mShrinkState == ShrinkState.BOTTOM_HIDDEN) {
@@ -551,7 +563,34 @@
 
     @Override
     protected void determineScrollingStart(MotionEvent ev) {
-        if (!mIsSmall && !mIsInUnshrinkAnimation) super.determineScrollingStart(ev);
+        float deltaX = Math.abs(ev.getX() - mXDown);
+        float deltaY = Math.abs(ev.getY() - mYDown);
+
+        if (Float.compare(deltaX, 0f) == 0) return;
+
+        float slope = deltaY / deltaX;
+        float theta = (float) Math.atan(slope);
+
+        if (deltaX > mTouchSlop || deltaY > mTouchSlop) {
+            cancelCurrentPageLongPress();
+        }
+
+        if (theta > MAX_SWIPE_ANGLE) {
+            // Above MAX_SWIPE_ANGLE, we don't want to ever start scrolling the workspace
+            return;
+        } else if (theta > START_DAMPING_TOUCH_SLOP_ANGLE) {
+            // Above START_DAMPING_TOUCH_SLOP_ANGLE and below MAX_SWIPE_ANGLE, we want to increase
+            // the touch slop to make it harder to begin scrolling the workspace. This results
+            // in vertically scrolling widgets to more easily. The higher the angle, the
+            // more we increase touch slop.
+            theta -= START_DAMPING_TOUCH_SLOP_ANGLE;
+            float extraRatio = (float)
+                    Math.sqrt((theta / (MAX_SWIPE_ANGLE - START_DAMPING_TOUCH_SLOP_ANGLE)));
+            super.determineScrollingStart(ev, 1 + TOUCH_SLOP_DAMPING_FACTOR * extraRatio);
+        } else {
+            // Below START_DAMPING_TOUCH_SLOP_ANGLE, we don't do anything special
+            super.determineScrollingStart(ev);
+        }
     }
 
     protected void onPageBeginMoving() {