Merge "Only delay pressed feedback for Views inside a scrolling parent"
diff --git a/api/current.txt b/api/current.txt
index a7f0368..950c130 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -21725,6 +21725,7 @@
     method public void setOnHierarchyChangeListener(android.view.ViewGroup.OnHierarchyChangeListener);
     method public void setPersistentDrawingCache(int);
     method protected void setStaticTransformationsEnabled(boolean);
+    method public boolean shouldDelayChildPressedState();
     method public boolean showContextMenuForChild(android.view.View);
     method public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback);
     method public void startLayoutAnimation();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e47b499..791ffb9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5138,9 +5138,7 @@
                         (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
                         (event.getRepeatCount() == 0)) {
                     setPressed(true);
-                    if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
-                        postCheckForLongClick(0);
-                    }
+                    checkForLongClick(0);
                     return true;
                 }
                 break;
@@ -5535,12 +5533,33 @@
                     break;
 
                 case MotionEvent.ACTION_DOWN:
-                    if (mPendingCheckForTap == null) {
-                        mPendingCheckForTap = new CheckForTap();
-                    }
-                    mPrivateFlags |= PREPRESSED;
                     mHasPerformedLongPress = false;
-                    postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
+
+                    // Walk up the hierarchy to determine if we're inside a scrolling container.
+                    boolean isInScrollingContainer = false;
+                    ViewParent p = getParent();
+                    while (p != null && p instanceof ViewGroup) {
+                        if (((ViewGroup) p).shouldDelayChildPressedState()) {
+                            isInScrollingContainer = true;
+                            break;
+                        }
+                        p = p.getParent();
+                    }
+
+                    // For views inside a scrolling container, delay the pressed feedback for
+                    // a short period in case this is a scroll.
+                    if (isInScrollingContainer) {
+                        mPrivateFlags |= PREPRESSED;
+                        if (mPendingCheckForTap == null) {
+                            mPendingCheckForTap = new CheckForTap();
+                        }
+                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
+                    } else {
+                        // Not inside a scrolling container, so show the feedback right away
+                        mPrivateFlags |= PRESSED;
+                        refreshDrawableState();
+                        checkForLongClick(0);
+                    }
                     break;
 
                 case MotionEvent.ACTION_CANCEL:
@@ -11846,15 +11865,17 @@
         }
     }
 
-    private void postCheckForLongClick(int delayOffset) {
-        mHasPerformedLongPress = false;
+    private void checkForLongClick(int delayOffset) {
+        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
+            mHasPerformedLongPress = false;
 
-        if (mPendingCheckForLongPress == null) {
-            mPendingCheckForLongPress = new CheckForLongPress();
+            if (mPendingCheckForLongPress == null) {
+                mPendingCheckForLongPress = new CheckForLongPress();
+            }
+            mPendingCheckForLongPress.rememberWindowAttachCount();
+            postDelayed(mPendingCheckForLongPress,
+                    ViewConfiguration.getLongPressTimeout() - delayOffset);
         }
-        mPendingCheckForLongPress.rememberWindowAttachCount();
-        postDelayed(mPendingCheckForLongPress,
-                ViewConfiguration.getLongPressTimeout() - delayOffset);
     }
 
     /**
@@ -12166,9 +12187,7 @@
             mPrivateFlags &= ~PREPRESSED;
             mPrivateFlags |= PRESSED;
             refreshDrawableState();
-            if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
-                postCheckForLongClick(ViewConfiguration.getTapTimeout());
-            }
+            checkForLongClick(ViewConfiguration.getTapTimeout());
         }
     }
 
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 94eb429..36bb046 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -95,7 +95,7 @@
      * is a tap or a scroll. If the user does not move within this interval, it is
      * considered to be a tap. 
      */
-    private static final int TAP_TIMEOUT = 115;
+    private static final int TAP_TIMEOUT = 180;
     
     /**
      * Defines the duration in milliseconds we will wait to see if a touch event 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7b8242d..35cca4f 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4973,6 +4973,19 @@
     }
 
     /**
+     * Return true if the pressed state should be delayed for children or descendants of this
+     * ViewGroup. Generally, this should be done for containers that can scroll, such as a List.
+     * This prevents the pressed state from appearing when the user is actually trying to scroll
+     * the content.
+     *
+     * The default implementation returns true for compatibility reasons. Subclasses that do
+     * not scroll should generally override this method and return false.
+     */
+    public boolean shouldDelayChildPressedState() {
+        return true;
+    }
+
+    /**
      * LayoutParams are used by views to tell their parents how they want to be
      * laid out. See
      * {@link android.R.styleable#ViewGroup_Layout ViewGroup Layout Attributes}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f99d895..0504532 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1194,6 +1194,11 @@
         mHTML5VideoViewProxy = null ;
     }
 
+    @Override
+    public boolean shouldDelayChildPressedState() {
+        return true;
+    }
+
     /**
      * Adds accessibility APIs to JavaScript.
      *
diff --git a/core/java/android/widget/AbsoluteLayout.java b/core/java/android/widget/AbsoluteLayout.java
index ac82af7..7df6aab 100644
--- a/core/java/android/widget/AbsoluteLayout.java
+++ b/core/java/android/widget/AbsoluteLayout.java
@@ -141,6 +141,11 @@
         return new LayoutParams(p);
     }
 
+    @Override
+    public boolean shouldDelayChildPressedState() {
+        return false;
+    }
+
     /**
      * Per-child layout information associated with AbsoluteLayout.
      * See
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 590a768..0659063 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -485,6 +485,11 @@
         return new FrameLayout.LayoutParams(getContext(), attrs);        
     }
 
+    @Override
+    public boolean shouldDelayChildPressedState() {
+        return false;
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 7838ec0..86fefaf 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -201,6 +201,11 @@
         mShowDividers = showDividers;
     }
 
+    @Override
+    public boolean shouldDelayChildPressedState() {
+        return false;
+    }
+
     /**
      * @return A flag set indicating how dividers should be shown around items.
      * @see #setShowDividers(int)
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index a47359f..9069283 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -186,6 +186,11 @@
         a.recycle();
     }
 
+    @Override
+    public boolean shouldDelayChildPressedState() {
+        return false;
+    }
+
     /**
      * Defines which View is ignored when the gravity is applied. This setting has no
      * effect if the gravity is <code>Gravity.LEFT | Gravity.TOP</code>.
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index ade3a0a..27edb88 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -162,6 +162,11 @@
     }
 
     @Override
+    public boolean shouldDelayChildPressedState() {
+        return true;
+    }
+
+    @Override
     protected float getTopFadingEdgeStrength() {
         if (getChildCount() == 0) {
             return 0.0f;
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index f45a3bb..c82323e 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -428,4 +428,9 @@
     @Override
     public void onAnimationRepeat(Animator animation) {
     }
+
+    @Override
+    public boolean shouldDelayChildPressedState() {
+        return false;
+    }
 }
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index d6f439a..13ccbba 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -228,6 +228,11 @@
         mHomeLayout.setFocusable(true);
     }
 
+    @Override
+    public boolean shouldDelayChildPressedState() {
+        return false;
+    }
+
     public void initProgress() {
         mProgressView = new ProgressBar(mContext, null, 0, mProgressStyle);
         mProgressView.setId(R.id.progress_horizontal);