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