Index: chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/OverlayPanelEventFilter.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/OverlayPanelEventFilter.java |
similarity index 69% |
copy from chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/ContextualSearchEventFilter.java |
copy to chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/OverlayPanelEventFilter.java |
index 18fceee3e01af3e0e3e75075e3ade859025c330c..b7f91518c32c9ff741bde10a1251080a9263868d 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/OverlayPanelEventFilter.java |
@@ -1,4 +1,4 @@ |
-// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
@@ -8,28 +8,31 @@ import android.content.Context; |
import android.view.GestureDetector; |
import android.view.MotionEvent; |
import android.view.ViewConfiguration; |
+import android.view.ViewGroup; |
import org.chromium.base.VisibleForTesting; |
import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel; |
+import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.PanelState; |
import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager; |
+import org.chromium.chrome.browser.contextualsearch.SwipeRecognizer; |
+import org.chromium.content.browser.ContentViewCore; |
import java.util.ArrayList; |
/** |
- * The {@link GestureEventFilter} used when Contextual Search Layout is being shown. It filters |
- * events that happen in the Search Content View area and propagates them to the appropriate |
- * Content View Core via {@link EventFilterHost}. Events that happen outside that area are |
- * propagated to the {@code ContextualSearchLayout} via {@code LayoutManagerPhone}. |
+ * The {@link GestureEventFilter} used when an overlay panel is being shown. It filters |
+ * events that happen in the Content View area and propagates them to the appropriate |
+ * ContentViewCore via {@link EventFilterHost}. |
*/ |
-public class ContextualSearchEventFilter extends GestureEventFilter { |
+public class OverlayPanelEventFilter extends GestureEventFilter { |
/** |
* The targets that can handle MotionEvents. |
*/ |
private enum EventTarget { |
UNDETERMINED, |
- SEARCH_PANEL, |
- SEARCH_CONTENT_VIEW |
+ PANEL, |
+ CONTENT_VIEW |
} |
/** |
@@ -46,39 +49,25 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
*/ |
private static final float VERTICAL_DETERMINATION_BOOST = 1.25f; |
- /** |
- * Manager to get the active OverlayPanel from. |
- */ |
- private OverlayPanelManager mPanelManager; |
+ /** The OverlayPanel that this filter is for. */ |
+ private OverlayPanel mPanel; |
- /** |
- * The {@link GestureDetector} used to distinguish tap and scroll gestures. |
- */ |
+ /** The {@link GestureDetector} used to distinguish tap and scroll gestures. */ |
private final GestureDetector mGestureDetector; |
- /** |
- * The target to propagate events to. |
- */ |
+ /** The target to propagate events to. */ |
private EventTarget mEventTarget; |
- /** |
- * Whether the code is in the middle of the process of determining the event target. |
- */ |
+ /** Whether the code is in the middle of the process of determining the event target. */ |
private boolean mIsDeterminingEventTarget; |
- /** |
- * Whether the event target has been determined. |
- */ |
+ /** Whether the event target has been determined. */ |
private boolean mHasDeterminedEventTarget; |
- /** |
- * The previous target the events were propagated to. |
- */ |
+ /** The previous target the events were propagated to. */ |
private EventTarget mPreviousEventTarget; |
- /** |
- * Whether the event target has changed since the last touch event. |
- */ |
+ /** Whether the event target has changed since the last touch event. */ |
private boolean mHasChangedEventTarget; |
/** |
@@ -88,44 +77,28 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
*/ |
private boolean mMayChangeEventTarget; |
- /** |
- * Whether the gesture orientation has been determined. |
- */ |
+ /** Whether the gesture orientation has been determined. */ |
private boolean mHasDeterminedGestureOrientation; |
- /** |
- * The current gesture orientation. |
- */ |
+ /** The current gesture orientation. */ |
private GestureOrientation mGestureOrientation; |
- /** |
- * Whether the events are being recorded. |
- */ |
+ /** Whether the events are being recorded. */ |
private boolean mIsRecordingEvents; |
- /** |
- * Whether the ACTION_DOWN that initiated the MotionEvent's stream was synthetic. |
- */ |
+ /** Whether the ACTION_DOWN that initiated the MotionEvent's stream was synthetic. */ |
private boolean mWasActionDownEventSynthetic; |
- /** |
- * The X coordinate of the synthetic ACTION_DOWN MotionEvent. |
- */ |
+ /** The X coordinate of the synthetic ACTION_DOWN MotionEvent. */ |
private float mSyntheticActionDownX; |
- /** |
- * The Y coordinate of the synthetic ACTION_DOWN MotionEvent. |
- */ |
+ /** The Y coordinate of the synthetic ACTION_DOWN MotionEvent. */ |
private float mSyntheticActionDownY; |
- /** |
- * The list of recorded events. |
- */ |
+ /** The list of recorded events. */ |
private final ArrayList<MotionEvent> mRecordedEvents = new ArrayList<MotionEvent>(); |
- /** |
- * The initial Y position of the current gesture. |
- */ |
+ /** The initial Y position of the current gesture. */ |
private float mInitialEventY; |
/** |
@@ -134,22 +107,39 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
*/ |
private final float mTouchSlopSquarePx; |
+ /** The @{link SwipeRecognizer} that recognizes directional swipe gestures. */ |
+ private final SwipeRecognizer mSwipeRecognizer; |
+ |
+ private class SwipeRecognizerImpl extends SwipeRecognizer { |
+ public SwipeRecognizerImpl(Context context) { |
+ super(context); |
+ setSwipeHandler(mPanel); |
+ } |
+ |
+ @Override |
+ public boolean onSingleTapUp(MotionEvent event) { |
+ mPanel.handleClick(event.getEventTime(), event.getX() * mPxToDp, |
+ event.getY() * mPxToDp); |
+ return true; |
+ } |
+ } |
+ |
/** |
* Creates a {@link GestureEventFilter} with offset touch events. |
* @param context The {@link Context} for Android. |
* @param host The {@link EventFilterHost} for this event filter. |
- * @param handler The {@link GestureHandler} for this event filter. |
* @param panelManager The {@link OverlayPanelManager} responsible for showing panels. |
*/ |
- public ContextualSearchEventFilter(Context context, EventFilterHost host, |
- GestureHandler handler, OverlayPanelManager panelManager) { |
- super(context, host, handler, false, false); |
+ public OverlayPanelEventFilter(Context context, EventFilterHost host, OverlayPanel panel) { |
+ super(context, host, panel, false, false); |
mGestureDetector = new GestureDetector(context, new InternalGestureDetector()); |
- mPanelManager = panelManager; |
+ mPanel = panel; |
+ |
+ mSwipeRecognizer = new SwipeRecognizerImpl(context); |
// Store the square of the platform touch slop in pixels to use in the scroll detection. |
- // See {@link ContextualSearchEventFilter#isDistanceGreaterThanTouchSlop}. |
+ // See {@link OverlayPanelEventFilter#isDistanceGreaterThanTouchSlop}. |
float touchSlopPx = ViewConfiguration.get(context).getScaledTouchSlop(); |
mTouchSlopSquarePx = touchSlopPx * touchSlopPx; |
@@ -157,37 +147,61 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
} |
/** |
- * Gets the Search Content View's vertical scroll position. If the Search Content View |
+ * Gets the Content View's vertical scroll position. If the Content View |
* is not available it returns -1. |
- * @return The Search Content View scroll position. |
+ * @return The Content View scroll position. |
*/ |
@VisibleForTesting |
- protected float getSearchContentViewVerticalScroll() { |
- OverlayPanel panel = mPanelManager.getActivePanel(); |
- if (panel == null) return 0; |
+ protected float getContentViewVerticalScroll() { |
+ return mPanel.getContentVerticalScroll(); |
+ } |
- return panel.getContentVerticalScroll(); |
+ @Override |
+ public boolean onInterceptTouchEventInternal(MotionEvent e, boolean isKeyboardShowing) { |
+ boolean touchIsOnPanel = |
+ mPanel.isCoordinateInsideBar(e.getX() * mPxToDp, e.getY() * mPxToDp) |
+ || mPanel.isCoordinateInsideContent(e.getX() * mPxToDp, e.getY() * mPxToDp); |
+ boolean panelIsShowing = mPanel.getPanelState() != PanelState.CLOSED |
+ && mPanel.getPanelState() != PanelState.UNDEFINED; |
+ |
+ // If the panel is showing and being touched or is opened past the peek state, intercept |
+ // the touch. |
+ if ((panelIsShowing && touchIsOnPanel) || mPanel.isPanelOpened()) { |
+ return super.onInterceptTouchEventInternal(e, isKeyboardShowing); |
+ } |
+ return false; |
} |
@Override |
public boolean onTouchEventInternal(MotionEvent e) { |
final int action = e.getActionMasked(); |
+ if (mPanel.getPanelState() == PanelState.PEEKED) { |
+ if (action == MotionEvent.ACTION_DOWN) { |
+ // To avoid a gray flash of empty content, show the search content |
+ // view immediately on tap rather than waiting for panel expansion. |
+ // TODO(pedrosimonetti): Once we implement "side-swipe to dismiss" |
+ // we'll have to revisit this because we don't want to set the |
+ // Content View visibility to true when the side-swipe is detected. |
+ mPanel.notifyBarTouched(e.getX() * mPxToDp); |
+ } |
+ mSwipeRecognizer.onTouchEvent(e); |
+ return true; |
+ } |
+ |
if (!mIsDeterminingEventTarget && action == MotionEvent.ACTION_DOWN) { |
mInitialEventY = e.getY(); |
- OverlayPanel panel = mPanelManager.getActivePanel(); |
- if (panel != null && panel.isCoordinateInsideContent( |
- e.getX() * mPxToDp, mInitialEventY * mPxToDp)) { |
- // If the DOWN event happened inside the Search Content View, we'll need |
+ if (mPanel.isCoordinateInsideContent(e.getX() * mPxToDp, mInitialEventY * mPxToDp)) { |
+ // If the DOWN event happened inside the Content View, we'll need |
// to wait until the user has moved the finger beyond a certain threshold, |
// so we can determine the gesture's orientation and consequently be able |
// to tell if the Content View will accept the gesture. |
mIsDeterminingEventTarget = true; |
mMayChangeEventTarget = true; |
} else { |
- // If the DOWN event happened outside the Search Content View, then we know |
- // that the Search Panel will start handling the event right away. |
- setEventTarget(EventTarget.SEARCH_PANEL); |
+ // If the DOWN event happened outside the Content View, then we know |
+ // that the Panel will start handling the event right away. |
+ setEventTarget(EventTarget.PANEL); |
mMayChangeEventTarget = false; |
} |
} |
@@ -246,9 +260,6 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
* @param e The {@link MotionEvent} to be propagated after resuming the pending events. |
*/ |
private void resumeAndPropagateEvent(MotionEvent e) { |
- OverlayPanel panel = mPanelManager.getActivePanel(); |
- if (panel == null) return; |
- |
if (mIsRecordingEvents) { |
resumeRecordedEvents(); |
} |
@@ -264,10 +275,11 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
MotionEvent syntheticActionDownEvent = copyEvent(e, MotionEvent.ACTION_DOWN); |
// Store the synthetic ACTION_DOWN coordinates to prevent unwanted taps from |
- // happening. See {@link ContextualSearchEventFilter#propagateEventToSearchContentView}. |
+ // happening. See {@link OverlayPanelEventFilter#propagateEventToContentViewCore}. |
mWasActionDownEventSynthetic = true; |
mSyntheticActionDownX = syntheticActionDownEvent.getX(); |
- mSyntheticActionDownY = syntheticActionDownEvent.getY() - panel.getContentY() / mPxToDp; |
+ mSyntheticActionDownY = |
+ syntheticActionDownEvent.getY() - mPanel.getContentY() / mPxToDp; |
propagateAndRecycleEvent(syntheticActionDownEvent, mEventTarget); |
@@ -293,8 +305,8 @@ 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 methods |
- * {@link ContextualSearchEventFilter#lockEventHorizontallty} and |
- * {@link ContextualSearchEventFilter#copyEvent}. |
+ * {@link OverlayPanelEventFilter#lockEventHorizontallty} and |
+ * {@link OverlayPanelEventFilter#copyEvent}. |
* |
* @param e The {@link MotionEvent} to be propagated. |
* @param target The {@link EventTarget} to propagate events to. |
@@ -310,36 +322,32 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
* @param target The {@link EventTarget} to propagate events to. |
*/ |
private void propagateEvent(MotionEvent e, EventTarget target) { |
- if (target == EventTarget.SEARCH_PANEL) { |
+ if (target == EventTarget.PANEL) { |
super.onTouchEventInternal(e); |
- } else if (target == EventTarget.SEARCH_CONTENT_VIEW) { |
- propagateEventToSearchContentView(e); |
+ } else if (target == EventTarget.CONTENT_VIEW) { |
+ propagateEventToContentViewCore(e); |
} |
} |
/** |
- * Propagates the given {@link MotionEvent} to the Search Content View. |
+ * Propagates the given {@link MotionEvent} to the {@link ContentViewCore}. |
* @param e The {@link MotionEvent} to be propagated. |
*/ |
- @VisibleForTesting |
- protected void propagateEventToSearchContentView(MotionEvent e) { |
- OverlayPanel panel = mPanelManager.getActivePanel(); |
- if (panel == null) return; |
- |
+ protected void propagateEventToContentViewCore(MotionEvent e) { |
MotionEvent event = e; |
int action = event.getActionMasked(); |
boolean isSyntheticEvent = false; |
- if (mGestureOrientation == GestureOrientation.HORIZONTAL && !panel.isMaximized()) { |
- // Ignores multitouch events to prevent the Search Result Page from from scrolling. |
+ if (mGestureOrientation == GestureOrientation.HORIZONTAL && !mPanel.isMaximized()) { |
+ // Ignores multitouch events to prevent the Content View 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 |
+ // when the Panel is not maximized. This is to prevent the Content View |
// from scrolling when side swiping on the expanded Panel. Also, note that the |
- // method {@link ContextualSearchEventFilter#lockEventHorizontallty} will always |
+ // method {@link OverlayPanelEventFilter#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 |
@@ -357,31 +365,34 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
isSyntheticEvent = true; |
} |
- final float contentViewOffsetXPx = panel.getContentX() / mPxToDp; |
- final float contentViewOffsetYPx = panel.getContentY() / mPxToDp; |
+ final float contentViewOffsetXPx = mPanel.getContentX() / mPxToDp; |
+ final float contentViewOffsetYPx = mPanel.getContentY() / mPxToDp; |
- // Adjust the offset to be relative to the Search Contents View. |
+ // Adjust the offset to be relative to the Content View. |
event.offsetLocation(-contentViewOffsetXPx, -contentViewOffsetYPx); |
+ // Get the container view to propagate the event to. |
+ ContentViewCore cvc = mPanel.getContentViewCore(); |
+ ViewGroup containerView = cvc == null ? null : cvc.getContainerView(); |
+ |
boolean wasEventCanceled = false; |
if (mWasActionDownEventSynthetic && action == MotionEvent.ACTION_UP) { |
float deltaX = event.getX() - mSyntheticActionDownX; |
float deltaY = event.getY() - mSyntheticActionDownY; |
// NOTE(pedrosimonetti): If the ACTION_DOWN event was synthetic and the distance |
// between it and the ACTION_UP event was short, then we should synthesize an |
- // ACTION_CANCEL event to prevent a Tap gesture from being triggered on the Search |
+ // ACTION_CANCEL event to prevent a Tap gesture from being triggered on the |
// Content View. See crbug.com/408654 |
if (!isDistanceGreaterThanTouchSlop(deltaX, deltaY)) { |
event.setAction(MotionEvent.ACTION_CANCEL); |
- mHost.propagateEvent(event); |
+ if (containerView != null) containerView.dispatchTouchEvent(event); |
wasEventCanceled = true; |
} |
} else if (action == MotionEvent.ACTION_DOWN) { |
- panel.onTouchSearchContentViewAck(); |
+ mPanel.onTouchSearchContentViewAck(); |
} |
- // Propagate the event to the appropriate view |
- if (!wasEventCanceled) mHost.propagateEvent(event); |
+ if (!wasEventCanceled && containerView != null) containerView.dispatchTouchEvent(event); |
// Synthetic events should be recycled. |
if (isSyntheticEvent) event.recycle(); |
@@ -404,13 +415,10 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
* @param e The tap {@link MotionEvent}. |
* @return Whether the event has been consumed. |
*/ |
- private boolean handleSingleTapUp(MotionEvent e) { |
- OverlayPanel panel = mPanelManager.getActivePanel(); |
- if (panel != null) { |
- setEventTarget(panel.isCoordinateInsideContent( |
- e.getX() * mPxToDp, e.getY() * mPxToDp) |
- ? EventTarget.SEARCH_CONTENT_VIEW : EventTarget.SEARCH_PANEL); |
- } |
+ protected boolean handleSingleTapUp(MotionEvent e) { |
+ setEventTarget(mPanel.isCoordinateInsideContent( |
+ e.getX() * mPxToDp, e.getY() * mPxToDp) |
+ ? EventTarget.CONTENT_VIEW : EventTarget.PANEL); |
return false; |
} |
@@ -423,7 +431,7 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
* to handleScroll. |
* @return Whether the event has been consumed. |
*/ |
- private boolean handleScroll(MotionEvent e1, MotionEvent e2, float distanceY) { |
+ protected boolean handleScroll(MotionEvent e1, MotionEvent e2, float distanceY) { |
// Only determines the gesture orientation if it hasn't been determined yet, |
// affectively "locking" the orientation once the gesture has started. |
if (!mHasDeterminedGestureOrientation && isDistanceGreaterThanTouchSlop(e1, e2)) { |
@@ -433,7 +441,7 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
// Only determines the event target after determining the gesture orientation and |
// 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. |
+ // swiping the Panel and scrolling the Content View. |
final boolean mayChangeEventTarget = mMayChangeEventTarget && e2.getPointerCount() == 1; |
if (mHasDeterminedGestureOrientation |
&& (!mHasDeterminedEventTarget || mayChangeEventTarget)) { |
@@ -466,26 +474,24 @@ public class ContextualSearchEventFilter extends GestureEventFilter { |
private void determineEventTarget(float distanceY) { |
boolean isVertical = mGestureOrientation == GestureOrientation.VERTICAL; |
- boolean shouldPropagateEventsToSearchPanel; |
- OverlayPanel panel = mPanelManager.getActivePanel(); |
- if (panel != null && panel.isMaximized()) { |
- // Allow overscroll in the Search Content View to move the Search Panel instead |
- // of scrolling the Search Result Page. |
+ boolean shouldPropagateEventsToPanel; |
+ if (mPanel.isMaximized()) { |
+ // Allow overscroll in the Content View to move the Panel. |
boolean isMovingDown = distanceY < 0; |
- shouldPropagateEventsToSearchPanel = isVertical |
+ shouldPropagateEventsToPanel = isVertical |
&& isMovingDown |
- && getSearchContentViewVerticalScroll() == 0; |
+ && getContentViewVerticalScroll() == 0; |
} else { |
- // Only allow horizontal movements to be propagated to the Search Content View |
+ // Only allow horizontal movements to be propagated to the Content View |
// when the Panel is expanded (that is, not maximized). |
- shouldPropagateEventsToSearchPanel = isVertical; |
+ shouldPropagateEventsToPanel = isVertical; |
// If the gesture is horizontal, then we know that the event target won't change. |
if (!isVertical) mMayChangeEventTarget = false; |
} |
- EventTarget target = shouldPropagateEventsToSearchPanel |
- ? EventTarget.SEARCH_PANEL : EventTarget.SEARCH_CONTENT_VIEW; |
+ EventTarget target = shouldPropagateEventsToPanel |
+ ? EventTarget.PANEL : EventTarget.CONTENT_VIEW; |
if (target != mEventTarget) { |
mPreviousEventTarget = mEventTarget; |