Fix touch handling in DragLayout.

Fixes: 33104074

-Only accept drags on HistoryFrame when isOpen()
-requestDisallowInterceptTouchEvent() in CalculatorResult to prevent
DragLayout from scrolling when a CalculatorResult is the target

Change-Id: If0dfbccc2fc05a90383a03cf397e6becd4496554
diff --git a/src/com/android/calculator2/Calculator.java b/src/com/android/calculator2/Calculator.java
index 8452566..156d1b5 100644
--- a/src/com/android/calculator2/Calculator.java
+++ b/src/com/android/calculator2/Calculator.java
@@ -241,13 +241,11 @@
         }
 
         @Override
-        public boolean allowDrag(MotionEvent event) {
-            return isViewTarget(mHistoryFrame, event) || isViewTarget(mDisplayView, event);
-        }
-
-        @Override
         public boolean shouldInterceptTouchEvent(MotionEvent event) {
-            return isViewTarget(mHistoryFrame, event) || isViewTarget(mDisplayView, event);
+            if (!mDragLayout.isOpen()) {
+                return isViewTarget(mDisplayView, event);
+            }
+            return true;
         }
 
         @Override
diff --git a/src/com/android/calculator2/CalculatorResult.java b/src/com/android/calculator2/CalculatorResult.java
index 83758b8..e33117f 100644
--- a/src/com/android/calculator2/CalculatorResult.java
+++ b/src/com/android/calculator2/CalculatorResult.java
@@ -43,6 +43,7 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.widget.OverScroller;
 import android.widget.Toast;
 
@@ -153,6 +154,10 @@
     private ActionMode.Callback mCopyActionModeCallback;
     private ContextMenu mContextMenu;
 
+    // Used to determine whether a touch event should be intercepted.
+    private float mInitialDownX;
+    private float mInitialDownY;
+
     // The user requested that the result currently being evaluated should be stored to "memory".
     private boolean mStoreToMemoryRequested = false;
 
@@ -169,8 +174,8 @@
                     return true;
                 }
                 @Override
-                public boolean onFling(MotionEvent e1, MotionEvent e2,
-                                       float velocityX, float velocityY) {
+                public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
+                        float velocityY) {
                     if (!mScroller.isFinished()) {
                         mCurrentPos = mScroller.getFinalX();
                     }
@@ -185,8 +190,8 @@
                     return true;
                 }
                 @Override
-                public boolean onScroll(MotionEvent e1, MotionEvent e2,
-                                        float distanceX, float distanceY) {
+                public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
+                        float distanceY) {
                     int distance = (int)distanceX;
                     if (!mScroller.isFinished()) {
                         mCurrentPos = mScroller.getFinalX();
@@ -216,6 +221,24 @@
         setOnTouchListener(new View.OnTouchListener() {
             @Override
             public boolean onTouch(View v, MotionEvent event) {
+                final int action = event.getActionMasked();
+
+                final float x = event.getX();
+                final float y = event.getY();
+                switch (action) {
+                    case MotionEvent.ACTION_DOWN:
+                        mInitialDownX = x;
+                        mInitialDownY = y;
+                        break;
+                    case MotionEvent.ACTION_MOVE:
+                        final float deltaX = Math.abs(x - mInitialDownX);
+                        final float deltaY = Math.abs(y - mInitialDownY);
+                        final int slop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
+                        if (deltaX > slop && deltaX > deltaY) {
+                            // Prevent the DragLayout from intercepting horizontal scrolls.
+                            getParent().requestDisallowInterceptTouchEvent(true);
+                        }
+                }
                 return mGestureDetector.onTouchEvent(event);
             }
         });
diff --git a/src/com/android/calculator2/DragLayout.java b/src/com/android/calculator2/DragLayout.java
index b07d087..c96d139 100644
--- a/src/com/android/calculator2/DragLayout.java
+++ b/src/com/android/calculator2/DragLayout.java
@@ -108,11 +108,17 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
-        // First verify that we don't have a large deltaX (that the user is not trying to
-        // horizontally scroll).
+        final int action = event.getActionMasked();
+
+        // Always handle the case of the touch gesture being complete.
+        if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
+            // Release the scroll.
+            mDragHelper.cancel();
+            return false; // Do not intercept touch event, let the child handle it
+        }
+
         final float x = event.getX();
         final float y = event.getY();
-        final int action = event.getAction();
 
         switch (action) {
             case MotionEvent.ACTION_DOWN:
@@ -123,31 +129,23 @@
                 final float deltaX = Math.abs(x - mInitialDownX);
                 final float deltaY = Math.abs(y - mInitialDownY);
                 final int slop = mDragHelper.getTouchSlop();
-                if (deltaY > slop && deltaX > deltaY) {
-                    mDragHelper.cancel();
+                if (deltaY > slop && deltaY > deltaX) {
+                    break;
+                } else {
                     return false;
                 }
         }
-
         boolean doDrag = true;
         for (DragCallback c : mDragCallbacks) {
-            doDrag &= c.allowDrag(event);
+            doDrag &= c.shouldInterceptTouchEvent(event);
         }
         return doDrag && mDragHelper.shouldInterceptTouchEvent(event);
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        boolean doIntercept = true;
-        for (DragCallback c : mDragCallbacks) {
-            doIntercept &= c.shouldInterceptTouchEvent(event);
-        }
-        if (doIntercept || isMoving()) {
-            mDragHelper.processTouchEvent(event);
-            return true;
-        } else {
-            return super.onTouchEvent(event);
-        }
+        mDragHelper.processTouchEvent(event);
+        return super.onTouchEvent(event);
     }
 
     @Override
@@ -215,9 +213,6 @@
         // Animate the RecyclerView text.
         void whileDragging(float yFraction);
 
-        // Whether we should allow the drag to happen
-        boolean allowDrag(MotionEvent event);
-
         // Whether we should intercept the touch event
         boolean shouldInterceptTouchEvent(MotionEvent event);
 
diff --git a/src/com/android/calculator2/HistoryFragment.java b/src/com/android/calculator2/HistoryFragment.java
index a96444d..6e54d9f 100644
--- a/src/com/android/calculator2/HistoryFragment.java
+++ b/src/com/android/calculator2/HistoryFragment.java
@@ -52,14 +52,8 @@
                 }
 
                 @Override
-                public boolean allowDrag(MotionEvent event) {
-                    // Do not allow drag if the recycler view can move down more
-                    return !mRecyclerView.canScrollVertically(1);
-                }
-
-                @Override
                 public boolean shouldInterceptTouchEvent(MotionEvent event) {
-                    return true;
+                    return !mRecyclerView.canScrollVertically(1);
                 }
 
                 @Override