Index: content/browser/renderer_host/gesture_event_filter.cc |
diff --git a/content/browser/renderer_host/gesture_event_filter.cc b/content/browser/renderer_host/gesture_event_filter.cc |
index 3c61cd412758e8c06fcadbc3d8dd98fc86479167..ff725d4f043995af0d9e388da43b316eb185ef33 100644 |
--- a/content/browser/renderer_host/gesture_event_filter.cc |
+++ b/content/browser/renderer_host/gesture_event_filter.cc |
@@ -12,6 +12,13 @@ using WebKit::WebInputEvent; |
namespace content { |
namespace { |
+ |
+// Default maximum time between the GestureRecognizer generating a |
+// GestureTapDown and when it is forwarded to the renderer. |
+// TODO(rjkroege): Make this configurable. |
+static const int kMaxiumTapGapTimeMs = 100; |
+ |
+// TODO(rjkroege): Coalesce pinch updates. |
// Returns |true| if two gesture events should be coalesced. |
bool ShouldCoalesceGestureEvents(const WebKit::WebGestureEvent& last_event, |
const WebKit::WebGestureEvent& new_event) { |
@@ -24,15 +31,14 @@ bool ShouldCoalesceGestureEvents(const WebKit::WebGestureEvent& last_event, |
GestureEventFilter::GestureEventFilter(RenderWidgetHostImpl* rwhv) |
: render_widget_host_(rwhv), |
fling_in_progress_(false), |
- gesture_event_pending_(false), |
- tap_suppression_controller_(new TapSuppressionController(rwhv)) { |
+ tap_suppression_controller_(new TapSuppressionController(rwhv)), |
+ maximum_tap_gap_time_ms_(kMaxiumTapGapTimeMs) { |
} |
GestureEventFilter::~GestureEventFilter() { } |
bool GestureEventFilter::ShouldDiscardFlingCancelEvent( |
const WebKit::WebGestureEvent& gesture_event) { |
- DCHECK(gesture_event.type == WebInputEvent::GestureFlingCancel); |
if (coalesced_gesture_events_.empty() && fling_in_progress_) |
return false; |
GestureEventQueue::reverse_iterator it = |
@@ -47,59 +53,64 @@ bool GestureEventFilter::ShouldDiscardFlingCancelEvent( |
return true; |
} |
+// TODO(rjkroege): separate touchpad and touchscreen events. |
bool GestureEventFilter::ShouldForward(const WebGestureEvent& gesture_event) { |
- if (gesture_event.type == WebInputEvent::GestureFlingCancel) { |
- if (ShouldDiscardFlingCancelEvent(gesture_event)) |
+ switch (gesture_event.type) { |
+ case WebInputEvent::GestureFlingCancel: |
+ if (!ShouldDiscardFlingCancelEvent(gesture_event)) { |
+ coalesced_gesture_events_.push_back(gesture_event); |
+ fling_in_progress_ = false; |
+ return ShouldHandleEventNow(); |
+ } |
return false; |
- fling_in_progress_ = false; |
- } |
- |
- if (gesture_event_pending_) { |
- if (coalesced_gesture_events_.empty() || |
- !ShouldCoalesceGestureEvents(coalesced_gesture_events_.back(), |
- gesture_event)) { |
- coalesced_gesture_events_.push_back(gesture_event); |
- } else { |
- WebGestureEvent* last_gesture_event = |
- &coalesced_gesture_events_.back(); |
- last_gesture_event->deltaX += gesture_event.deltaX; |
- last_gesture_event->deltaY += gesture_event.deltaY; |
- DCHECK_GE(gesture_event.timeStampSeconds, |
- last_gesture_event->timeStampSeconds); |
- last_gesture_event->timeStampSeconds = gesture_event.timeStampSeconds; |
- } |
- return false; |
- } |
- gesture_event_pending_ = true; |
- |
- if (gesture_event.type == WebInputEvent::GestureFlingCancel) { |
- tap_suppression_controller_->GestureFlingCancel( |
- gesture_event.timeStampSeconds); |
- } else if (gesture_event.type == WebInputEvent::GestureFlingStart) { |
- fling_in_progress_ = true; |
+ case WebInputEvent::GestureFlingStart: |
+ fling_in_progress_ = true; |
+ coalesced_gesture_events_.push_back(gesture_event); |
+ return ShouldHandleEventNow(); |
+ case WebInputEvent::GestureTapDown: |
+ deferred_tap_down_event_ = gesture_event; |
+ send_gtd_timer_.Start(FROM_HERE, |
+ base::TimeDelta::FromMilliseconds(maximum_tap_gap_time_ms_), |
+ this, |
+ &GestureEventFilter::SendGestureTapDownNow); |
+ return false; |
+ case WebInputEvent::GestureTap: |
+ send_gtd_timer_.Stop(); |
+ coalesced_gesture_events_.push_back(deferred_tap_down_event_); |
+ if (ShouldHandleEventNow()) { |
+ render_widget_host_->ForwardGestureEventImmediately( |
+ deferred_tap_down_event_); |
+ } |
+ coalesced_gesture_events_.push_back(gesture_event); |
+ return false; |
+ case WebInputEvent::GestureScrollBegin: |
+ case WebInputEvent::GesturePinchBegin: |
+ send_gtd_timer_.Stop(); |
+ coalesced_gesture_events_.push_back(gesture_event); |
+ return ShouldHandleEventNow(); |
+ case WebInputEvent::GestureScrollUpdate: |
+ MergeOrInsertScrollEvent(gesture_event); |
+ return ShouldHandleEventNow(); |
+ default: |
+ coalesced_gesture_events_.push_back(gesture_event); |
+ return ShouldHandleEventNow(); |
} |
- return true; |
+ NOTREACHED(); |
+ return false; |
} |
void GestureEventFilter::Reset() { |
fling_in_progress_ = false; |
coalesced_gesture_events_.clear(); |
- gesture_event_pending_ = false; |
+ // TODO(rjkroege): Reset the tap suppression controller. |
} |
void GestureEventFilter::ProcessGestureAck(bool processed, int type) { |
- if (type == WebInputEvent::GestureFlingCancel) |
- tap_suppression_controller_->GestureFlingCancelAck(processed); |
- |
- gesture_event_pending_ = false; |
- |
- // Now send the next (coalesced) gesture event. |
+ coalesced_gesture_events_.pop_front(); |
if (!coalesced_gesture_events_.empty()) { |
- WebGestureEvent next_gesture_event = |
- coalesced_gesture_events_.front(); |
- coalesced_gesture_events_.pop_front(); |
- render_widget_host_->ForwardGestureEvent(next_gesture_event); |
+ WebGestureEvent next_gesture_event = coalesced_gesture_events_.front(); |
+ render_widget_host_->ForwardGestureEventImmediately(next_gesture_event); |
} |
} |
@@ -111,4 +122,36 @@ void GestureEventFilter::FlingHasBeenHalted() { |
fling_in_progress_ = false; |
} |
+bool GestureEventFilter::ShouldHandleEventNow() { |
+ return coalesced_gesture_events_.size() == 1; |
+} |
+ |
+void GestureEventFilter::SendGestureTapDownNow() { |
+ coalesced_gesture_events_.push_back(deferred_tap_down_event_); |
+ if (ShouldHandleEventNow()) { |
+ render_widget_host_->ForwardGestureEventImmediately( |
+ deferred_tap_down_event_); |
+ } |
+} |
+ |
+void GestureEventFilter::MergeOrInsertScrollEvent( |
+ const WebGestureEvent& gesture_event) { |
+ WebGestureEvent* last_gesture_event = coalesced_gesture_events_.empty() ? 0 : |
+ &coalesced_gesture_events_.back(); |
+ if (coalesced_gesture_events_.size() > 1 && |
+ last_gesture_event->type == gesture_event.type && |
+ last_gesture_event->modifiers == gesture_event.modifiers) { |
+ last_gesture_event->deltaX += gesture_event.deltaX; |
+ last_gesture_event->deltaY += gesture_event.deltaY; |
+ DLOG_IF(WARNING, |
+ gesture_event.timeStampSeconds >= |
+ last_gesture_event->timeStampSeconds) |
+ << "Event time not monotonic?\n"; |
+ DCHECK(last_gesture_event->type == WebInputEvent::GestureScrollUpdate); |
+ last_gesture_event->timeStampSeconds = gesture_event.timeStampSeconds; |
+ } else { |
+ coalesced_gesture_events_.push_back(gesture_event); |
+ } |
+} |
+ |
} // namespace content |