| 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;
|
|
|