Chromium Code Reviews| Index: content/browser/renderer_host/input/touch_action_filter.cc |
| diff --git a/content/browser/renderer_host/input/touch_action_filter.cc b/content/browser/renderer_host/input/touch_action_filter.cc |
| index 665ff15bd30f77441f7d6fc095df4ea6c9cbf071..37fc1e6e5d976afbda28c40e908ce0e834e0cf0e 100644 |
| --- a/content/browser/renderer_host/input/touch_action_filter.cc |
| +++ b/content/browser/renderer_host/input/touch_action_filter.cc |
| @@ -4,6 +4,9 @@ |
| #include "content/browser/renderer_host/input/touch_action_filter.h" |
| +#include <math.h> |
| + |
| +#include "base/logging.h" |
| #include "third_party/WebKit/public/web/WebInputEvent.h" |
| using blink::WebInputEvent; |
| @@ -16,29 +19,43 @@ TouchActionFilter::TouchActionFilter() : |
| allowed_touch_action_(TOUCH_ACTION_AUTO) { |
| } |
| -bool TouchActionFilter::FilterGestureEvent( |
| - const WebGestureEvent& gesture_event) { |
| +bool TouchActionFilter::FilterGestureEvent(WebGestureEvent* gesture_event) { |
| // Filter for allowable touch actions first (eg. before the TouchEventQueue |
| // can decide to send a touch cancel event). |
| // TODO(rbyers): Add touch-action control over for pinch. crbug.com/247566. |
| - switch(gesture_event.type) { |
| + switch(gesture_event->type) { |
| case WebInputEvent::GestureScrollBegin: |
| - if (allowed_touch_action_ == TOUCH_ACTION_NONE) |
| - drop_scroll_gesture_events_ = true; |
| - // FALL THROUGH |
| + DCHECK(!drop_scroll_gesture_events_); |
| + drop_scroll_gesture_events_ = ShouldSuppressScroll(*gesture_event); |
| + return drop_scroll_gesture_events_; |
|
jdduke (slow)
2013/12/19 16:17:16
If a GSB is dropped, the pinch sequence wrapped by
Rick Byers
2013/12/19 16:35:09
Yes, thanks. As discussed I'll be dropping pinch
|
| + |
| case WebInputEvent::GestureScrollUpdate: |
| if (drop_scroll_gesture_events_) |
| return true; |
| + else { |
| + if (allowed_touch_action_ == TOUCH_ACTION_PAN_X) { |
| + gesture_event->data.scrollUpdate.deltaY = 0; |
| + gesture_event->data.scrollUpdate.velocityY = 0; |
| + } else if (allowed_touch_action_ == TOUCH_ACTION_PAN_Y) { |
| + gesture_event->data.scrollUpdate.deltaX = 0; |
| + gesture_event->data.scrollUpdate.velocityX = 0; |
| + } |
| + } |
| break; |
| - case WebInputEvent::GestureScrollEnd: |
| case WebInputEvent::GestureFlingStart: |
| - allowed_touch_action_ = content::TOUCH_ACTION_AUTO; |
| - if (drop_scroll_gesture_events_) { |
| - drop_scroll_gesture_events_ = false; |
| - return true; |
| + if (gesture_event->sourceDevice != WebGestureEvent::Touchscreen) |
| + break; |
| + if (!drop_scroll_gesture_events_) { |
| + if (allowed_touch_action_ == TOUCH_ACTION_PAN_X) |
| + gesture_event->data.flingStart.velocityY = 0; |
| + if (allowed_touch_action_ == TOUCH_ACTION_PAN_Y) |
| + gesture_event->data.flingStart.velocityX = 0; |
| } |
| - break; |
| + return FilterGestureEnd(); |
| + |
| + case WebInputEvent::GestureScrollEnd: |
| + return FilterGestureEnd(); |
| default: |
| // Gesture events unrelated to touch actions (panning/zooming) are left |
| @@ -49,15 +66,57 @@ bool TouchActionFilter::FilterGestureEvent( |
| return false; |
| } |
| -void TouchActionFilter::OnSetTouchAction( |
| - content::TouchAction touch_action) { |
| +bool TouchActionFilter::FilterGestureEnd() { |
| + allowed_touch_action_ = TOUCH_ACTION_AUTO; |
| + if (drop_scroll_gesture_events_) { |
| + drop_scroll_gesture_events_ = false; |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| +void TouchActionFilter::OnSetTouchAction(TouchAction touch_action) { |
| // For multiple fingers, we take the intersection of the touch actions for |
| // all fingers that have gone down during this action. |
| // TODO(rbyers): What exact multi-finger semantic do we want? This is left |
| // as implementation-defined in the pointer events specification. |
| // crbug.com/247566. |
| - if (touch_action == content::TOUCH_ACTION_NONE) |
| - allowed_touch_action_ = content::TOUCH_ACTION_NONE; |
| + allowed_touch_action_ = Intersect(allowed_touch_action_, touch_action); |
| +} |
| + |
| +bool TouchActionFilter::ShouldSuppressScroll( |
| + const blink::WebGestureEvent& gesture_event) { |
| + DCHECK_EQ(gesture_event.type, WebInputEvent::GestureScrollBegin); |
| + if (allowed_touch_action_ == TOUCH_ACTION_AUTO) |
| + return false; |
| + if (allowed_touch_action_ == TOUCH_ACTION_NONE) |
| + return true; |
| + |
| + // If there's no hint or it's perfectly diagonal, then allow the scroll. |
| + if (fabs(gesture_event.data.scrollBegin.deltaXHint) == |
| + fabs(gesture_event.data.scrollBegin.deltaYHint)) |
| + return false; |
| + |
| + // Determine the primary initial axis of the scroll, and check whether |
| + // panning along that axis is permitted. |
| + if (fabs(gesture_event.data.scrollBegin.deltaXHint) > |
| + fabs(gesture_event.data.scrollBegin.deltaYHint)) |
| + return !(allowed_touch_action_ & TOUCH_ACTION_PAN_X); |
| + return !(allowed_touch_action_ & TOUCH_ACTION_PAN_Y); |
| +} |
| + |
| +TouchAction TouchActionFilter::Intersect(TouchAction ta1, TouchAction ta2) { |
| + if (ta1 == TOUCH_ACTION_NONE || ta2 == TOUCH_ACTION_NONE) |
| + return TOUCH_ACTION_NONE; |
| + if (ta1 == TOUCH_ACTION_AUTO) |
| + return ta2; |
| + if (ta2 == TOUCH_ACTION_AUTO) |
| + return ta1; |
| + |
| + // Only the true flags are left - take their intersection. |
| + if (!(ta1 & ta2)) |
| + return TOUCH_ACTION_NONE; |
| + return static_cast<TouchAction>(ta1 & ta2); |
| } |
| } |