Index: chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/ContextualSearchEventFilter.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/ContextualSearchEventFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/ContextualSearchEventFilter.java |
index f85861da782d3d42fee2f8813af5b14589f4e52d..231c50c3c21187dbd02b4e678ba562ec7e7b4b7b 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/ContextualSearchEventFilter.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/ContextualSearchEventFilter.java |
@@ -179,14 +179,7 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
public boolean onTouchEventInternal(MotionEvent e) { |
final int action = e.getActionMasked(); |
- if (action == MotionEvent.ACTION_POINTER_DOWN |
- && e.getPointerCount() == 2 |
- && !mSearchPanel.isMaximized()) { |
- // We don't want the Search Content View's zoom level to change when the Search Panel |
- // is expanded (that is, not maximized) so we'll forward the events to Panel to |
- // prevent it from happening. |
- setEventTarget(EventTarget.SEARCH_PANEL); |
- } else if (!mIsDeterminingEventTarget && action == MotionEvent.ACTION_DOWN) { |
+ if (!mIsDeterminingEventTarget && action == MotionEvent.ACTION_DOWN) { |
mInitialEventY = e.getY(); |
if (mSearchPanel.isYCoordinateInsideSearchContentView(mInitialEventY * mPxToDp)) { |
// If the DOWN event happened inside the Search Content View, we'll need |
@@ -262,17 +255,14 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
} |
if (mHasChangedEventTarget) { |
- // TODO(pedrosimonetti): handle cases with multiple pointers. |
- float y = e.getY(); |
// If the event target has changed since the beginning of the gesture, then we need |
// to send a ACTION_CANCEL to the previous event target to make sure it no longer |
// expects events. |
- propagateAndRecycleEvent(createEvent(e, MotionEvent.ACTION_CANCEL, y), |
- mPreviousEventTarget); |
+ propagateAndRecycleEvent(copyEvent(e, MotionEvent.ACTION_CANCEL), mPreviousEventTarget); |
// Similarly we need to send an ACTION_DOWN to the new event target so subsequent |
// events can be analyzed properly by the Gesture Detector. |
- MotionEvent syntheticActionDownEvent = createEvent(e, MotionEvent.ACTION_DOWN, y); |
+ MotionEvent syntheticActionDownEvent = copyEvent(e, MotionEvent.ACTION_DOWN); |
// Store the synthetic ACTION_DOWN coordinates to prevent unwanted taps from |
// happening. See {@link ContextualSearchEventFilter#propagateEventToSearchContentView}. |
@@ -304,7 +294,10 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
/** |
* Propagates the given {@link MotionEvent} to the given {@link EventTarget}, recycling it |
* afterwards. This is intended for synthetic events only, those create by |
- * {@link MotionEvent#obtain} or the helper {@link ContextualSearchEventFilter#createEvent}. |
+ * {@link MotionEvent#obtain} or the helper methods |
+ * {@link ContextualSearchEventFilter#lockEventHorizontallty} and |
+ * {@link ContextualSearchEventFilter#copyEvent}. |
+ * |
* @param e The {@link MotionEvent} to be propagated. |
* @param target The {@link EventTarget} to propagate events to. |
*/ |
@@ -333,17 +326,37 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
@VisibleForTesting |
protected void propagateEventToSearchContentView(MotionEvent e) { |
MotionEvent event = e; |
+ int action = event.getActionMasked(); |
boolean isSyntheticEvent = false; |
if (mGestureOrientation == GestureOrientation.HORIZONTAL |
&& !mSearchPanel.isMaximized()) { |
- // Lock horizontal motion, ignoring all vertical changes, when the Panel is not |
- // maximized. This is to prevent the Search Result Page from scrolling when |
- // side swiping on the expanded Panel. |
- event = createEvent(e, e.getAction(), mInitialEventY); |
+ // Ignores multitouch events to prevent the Search Result Page from from scrolling. |
+ if (action == MotionEvent.ACTION_POINTER_UP |
+ || action == MotionEvent.ACTION_POINTER_DOWN) { |
+ return; |
+ } |
+ |
+ // NOTE(pedrosimonetti): Lock horizontal motion, ignoring all vertical changes, |
+ // when the Panel is not maximized. This is to prevent the Search Result Page |
+ // from scrolling when side swiping on the expanded Panel. Also, note that the |
+ // method {@link ContextualSearchEventFilter#lockEventHorizontallty} will always |
+ // return an event with a single pointer, which is necessary to prevent |
+ // the app from crashing when the motion involves multiple pointers. |
+ // See: crbug.com/486901 |
+ event = MotionEvent.obtain( |
+ e.getDownTime(), |
+ e.getEventTime(), |
+ // NOTE(pedrosimonetti): Use getActionMasked() to make sure we're not |
+ // send any pointer information to the event, given that getAction() |
+ // may have the pointer Id associated to it. |
+ e.getActionMasked(), |
+ e.getX(), |
+ mInitialEventY, |
+ e.getMetaState()); |
+ |
isSyntheticEvent = true; |
} |
- int action = event.getActionMasked(); |
float searchContentViewOffsetYPx = mSearchPanel.getSearchContentViewOffsetY() / mPxToDp; |
// Adjust the offset to be relative to the Search Contents View. |
@@ -377,17 +390,12 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
* Creates a {@link MotionEvent} inheriting from a given |e| event. |
* @param e The {@link MotionEvent} to inherit properties from. |
* @param action The MotionEvent's Action to be used. |
- * @param y The y coordinate to be used. |
* @return A new {@link MotionEvent}. |
*/ |
- private MotionEvent createEvent(MotionEvent e, int action, float y) { |
- return MotionEvent.obtain( |
- e.getDownTime(), |
- e.getEventTime(), |
- action, |
- e.getX(), |
- y, |
- e.getMetaState()); |
+ private MotionEvent copyEvent(MotionEvent e, int action) { |
+ MotionEvent event = MotionEvent.obtain(e); |
+ event.setAction(action); |
+ return event; |
} |
/** |
@@ -422,8 +430,9 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
// if it hasn't been determined yet or if changing the event target during the |
// middle of the gesture is supported. This will allow a smooth transition from |
// swiping the Panel and scrolling the Search Content View. |
+ final boolean mayChangeEventTarget = mMayChangeEventTarget && e2.getPointerCount() == 1; |
if (mHasDeterminedGestureOrientation |
- && (!mHasDeterminedEventTarget || mMayChangeEventTarget)) { |
+ && (!mHasDeterminedEventTarget || mayChangeEventTarget)) { |
determineEventTarget(distanceY); |
} |
@@ -465,14 +474,21 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
// Only allow horizontal movements to be propagated to the Search Content View |
// when the Panel is expanded (that is, not maximized). |
shouldPropagateEventsToSearchPanel = isVertical; |
+ |
+ // If the gesture is horizontal, then we know that the event target won't change. |
+ if (!isVertical) mMayChangeEventTarget = false; |
} |
- mPreviousEventTarget = mEventTarget; |
- setEventTarget(shouldPropagateEventsToSearchPanel |
- ? EventTarget.SEARCH_PANEL : EventTarget.SEARCH_CONTENT_VIEW); |
+ EventTarget target = shouldPropagateEventsToSearchPanel |
+ ? EventTarget.SEARCH_PANEL : EventTarget.SEARCH_CONTENT_VIEW; |
- mHasChangedEventTarget = mEventTarget != mPreviousEventTarget |
- && mPreviousEventTarget != EventTarget.UNDETERMINED; |
+ if (target != mEventTarget) { |
+ mPreviousEventTarget = mEventTarget; |
+ setEventTarget(target); |
+ |
+ mHasChangedEventTarget = mEventTarget != mPreviousEventTarget |
+ && mPreviousEventTarget != EventTarget.UNDETERMINED; |
+ } |
} |
/** |