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 e5fc3edce90e0dcd6ab37758bb9594e8c946b7c8..02ed0c31cfdceae33470d2c4be1a953caeaee534 100644 |
--- a/content/browser/renderer_host/gesture_event_filter.cc |
+++ b/content/browser/renderer_host/gesture_event_filter.cc |
@@ -8,6 +8,7 @@ |
#include "base/string_number_conversions.h" |
#include "content/browser/renderer_host/render_widget_host_impl.h" |
#include "content/browser/renderer_host/touchpad_tap_suppression_controller.h" |
+#include "content/browser/renderer_host/touchscreen_tap_suppression_controller.h" |
#include "content/public/common/content_switches.h" |
using WebKit::WebGestureEvent; |
@@ -55,7 +56,7 @@ static int GetTapDownDeferralTimeMs() { |
switches::kTapDownDeferralTimeMs); |
return tap_down_deferral_time_window; |
} |
-} // namespace |
+} // namespace |
GestureEventFilter::GestureEventFilter(RenderWidgetHostImpl* rwhv) |
: render_widget_host_(rwhv), |
@@ -63,7 +64,10 @@ GestureEventFilter::GestureEventFilter(RenderWidgetHostImpl* rwhv) |
scrolling_in_progress_(false), |
ignore_next_ack_(false), |
combined_scroll_pinch_(gfx::Transform()), |
- tap_suppression_controller_(new TouchpadTapSuppressionController(rwhv)), |
+ touchpad_tap_suppression_controller_( |
+ new TouchpadTapSuppressionController(rwhv)), |
+ touchscreen_tap_suppression_controller_( |
+ new TouchscreenTapSuppressionController(this)), |
maximum_tap_gap_time_ms_(GetTapDownDeferralTimeMs()), |
debounce_interval_time_ms_(kDebouncingIntervalTimeMs) { |
} |
@@ -88,13 +92,16 @@ bool GestureEventFilter::ShouldDiscardFlingCancelEvent( |
bool GestureEventFilter::ShouldForwardForBounceReduction( |
const WebGestureEvent& gesture_event) { |
+ if (debounce_interval_time_ms_ == 0) |
+ return true; |
switch (gesture_event.type) { |
case WebInputEvent::GestureScrollUpdate: |
if (!scrolling_in_progress_) { |
- debounce_deferring_timer_.Start(FROM_HERE, |
- base::TimeDelta::FromMilliseconds(debounce_interval_time_ms_), |
- this, |
- &GestureEventFilter::SendScrollEndingEventsNow); |
+ debounce_deferring_timer_.Start( |
+ FROM_HERE, |
+ base::TimeDelta::FromMilliseconds(debounce_interval_time_ms_), |
+ this, |
+ &GestureEventFilter::SendScrollEndingEventsNow); |
} else { |
// Extend the bounce interval. |
debounce_deferring_timer_.Reset(); |
@@ -121,38 +128,63 @@ bool GestureEventFilter::ShouldForwardForBounceReduction( |
// NOTE: The filters are applied successively. This simplifies the change. |
bool GestureEventFilter::ShouldForward(const WebGestureEvent& gesture_event) { |
- // Discard a zero-velocity fling start from the trackpad. |
- if (gesture_event.type == WebInputEvent::GestureFlingStart && |
- gesture_event.sourceDevice == WebGestureEvent::Touchpad && |
- gesture_event.data.flingStart.velocityX == 0 && |
- gesture_event.data.flingStart.velocityY == 0) { |
- return false; |
- } |
+ return ShouldForwardForZeroVelocityFlingStart(gesture_event) && |
+ ShouldForwardForBounceReduction(gesture_event) && |
+ ShouldForwardForGFCFiltering(gesture_event) && |
+ ShouldForwardForTapSuppression(gesture_event) && |
+ ShouldForwardForTapDeferral(gesture_event) && |
+ ShouldForwardForCoalescing(gesture_event); |
+} |
+ |
+bool GestureEventFilter::ShouldForwardForZeroVelocityFlingStart( |
+ const WebGestureEvent& gesture_event) { |
+ return gesture_event.type != WebInputEvent::GestureFlingStart || |
+ gesture_event.sourceDevice != WebGestureEvent::Touchpad || |
+ gesture_event.data.flingStart.velocityX != 0 || |
+ gesture_event.data.flingStart.velocityY != 0; |
+} |
- if (debounce_interval_time_ms_ == 0 || |
- ShouldForwardForBounceReduction(gesture_event)) |
- return ShouldForwardForTapDeferral(gesture_event); |
+bool GestureEventFilter::ShouldForwardForGFCFiltering( |
+ const WebGestureEvent& gesture_event) { |
+ return gesture_event.type != WebInputEvent::GestureFlingCancel || |
+ !ShouldDiscardFlingCancelEvent(gesture_event); |
+} |
+ |
+bool GestureEventFilter::ShouldForwardForTapSuppression( |
+ const WebGestureEvent& gesture_event) { |
+ switch (gesture_event.type) { |
+ case WebInputEvent::GestureFlingCancel: |
+ if (gesture_event.sourceDevice == WebGestureEvent::Touchscreen) |
+ touchscreen_tap_suppression_controller_->GestureFlingCancel(); |
+ else |
+ touchpad_tap_suppression_controller_->GestureFlingCancel(); |
+ return true; |
+ case WebInputEvent::GestureTapDown: |
+ return !touchscreen_tap_suppression_controller_-> |
+ ShouldDeferGestureTapDown(gesture_event); |
+ case WebInputEvent::GestureTapCancel: |
+ return !touchscreen_tap_suppression_controller_-> |
+ ShouldSuppressGestureTapCancel(); |
+ case WebInputEvent::GestureTap: |
+ return !touchscreen_tap_suppression_controller_-> |
+ ShouldSuppressGestureTap(); |
+ default: |
+ return true; |
+ } |
+ NOTREACHED(); |
return false; |
} |
-// TODO(rjkroege): separate touchpad and touchscreen events. |
bool GestureEventFilter::ShouldForwardForTapDeferral( |
const WebGestureEvent& gesture_event) { |
switch (gesture_event.type) { |
- case WebInputEvent::GestureFlingCancel: |
- if (!ShouldDiscardFlingCancelEvent(gesture_event)) { |
- coalesced_gesture_events_.push_back(gesture_event); |
- fling_in_progress_ = false; |
- tap_suppression_controller_->GestureFlingCancel(); |
- return ShouldHandleEventNow(); |
- } |
- return false; |
case WebInputEvent::GestureTapDown: |
// GestureTapDown is always paired with either a Tap, or TapCancel, so it |
// should be impossible to have more than one outstanding at a time. |
DCHECK_EQ(deferred_tap_down_event_.type, WebInputEvent::Undefined); |
deferred_tap_down_event_ = gesture_event; |
- send_gtd_timer_.Start(FROM_HERE, |
+ send_gtd_timer_.Start( |
+ FROM_HERE, |
base::TimeDelta::FromMilliseconds(maximum_tap_gap_time_ms_), |
this, |
&GestureEventFilter::SendGestureTapDownNow); |
@@ -161,8 +193,7 @@ bool GestureEventFilter::ShouldForwardForTapDeferral( |
if (deferred_tap_down_event_.type == WebInputEvent::Undefined) { |
// The TapDown has already been put in the queue, must send the |
// corresponding TapCancel as well. |
- coalesced_gesture_events_.push_back(gesture_event); |
- return ShouldHandleEventNow(); |
+ return true; |
} |
// Cancelling a deferred TapDown, just drop them on the floor. |
send_gtd_timer_.Stop(); |
@@ -171,35 +202,42 @@ bool GestureEventFilter::ShouldForwardForTapDeferral( |
case WebInputEvent::GestureTap: |
send_gtd_timer_.Stop(); |
if (deferred_tap_down_event_.type != WebInputEvent::Undefined) { |
- coalesced_gesture_events_.push_back(deferred_tap_down_event_); |
- if (ShouldHandleEventNow()) |
- render_widget_host_->ForwardGestureEventImmediately( |
- deferred_tap_down_event_); |
+ ForwardGestureEventSkipDeferral(deferred_tap_down_event_); |
deferred_tap_down_event_.type = WebInputEvent::Undefined; |
- coalesced_gesture_events_.push_back(gesture_event); |
- return false; |
} |
- coalesced_gesture_events_.push_back(gesture_event); |
- return ShouldHandleEventNow(); |
+ return true; |
case WebInputEvent::GestureFlingStart: |
- fling_in_progress_ = true; |
case WebInputEvent::GestureScrollBegin: |
case WebInputEvent::GesturePinchBegin: |
send_gtd_timer_.Stop(); |
deferred_tap_down_event_.type = WebInputEvent::Undefined; |
- coalesced_gesture_events_.push_back(gesture_event); |
- return ShouldHandleEventNow(); |
+ return true; |
+ default: |
+ return true; |
+ } |
+ |
+ NOTREACHED(); |
+ return true; |
+} |
+ |
+bool GestureEventFilter::ShouldForwardForCoalescing( |
+ const WebGestureEvent& gesture_event) { |
+ switch (gesture_event.type) { |
+ case WebInputEvent::GestureFlingCancel: |
+ fling_in_progress_ = false; |
+ break; |
+ case WebInputEvent::GestureFlingStart: |
+ fling_in_progress_ = true; |
+ break; |
case WebInputEvent::GesturePinchUpdate: |
case WebInputEvent::GestureScrollUpdate: |
MergeOrInsertScrollAndPinchEvent(gesture_event); |
return ShouldHandleEventNow(); |
default: |
- coalesced_gesture_events_.push_back(gesture_event); |
- return ShouldHandleEventNow(); |
+ break; |
} |
- |
- NOTREACHED(); |
- return false; |
+ coalesced_gesture_events_.push_back(gesture_event); |
+ return ShouldHandleEventNow(); |
} |
void GestureEventFilter::Reset() { |
@@ -221,10 +259,17 @@ void GestureEventFilter::ProcessGestureAck(bool processed, int type) { |
return; |
} |
DCHECK_EQ(coalesced_gesture_events_.front().type, type); |
+ if (type == WebInputEvent::GestureFlingCancel) { |
+ if (coalesced_gesture_events_.front().sourceDevice == |
+ WebGestureEvent::Touchscreen) |
+ touchscreen_tap_suppression_controller_->GestureFlingCancelAck(processed); |
+ else |
+ touchpad_tap_suppression_controller_->GestureFlingCancelAck(processed); |
+ } |
coalesced_gesture_events_.pop_front(); |
- if (type == WebInputEvent::GestureFlingCancel) |
- tap_suppression_controller_->GestureFlingCancelAck(processed); |
- if (!coalesced_gesture_events_.empty() && !ignore_next_ack_) { |
+ if (ignore_next_ack_) { |
+ ignore_next_ack_ = false; |
+ } else if (!coalesced_gesture_events_.empty()) { |
const WebGestureEvent& next_gesture_event = |
coalesced_gesture_events_.front(); |
render_widget_host_->ForwardGestureEventImmediately(next_gesture_event); |
@@ -241,13 +286,12 @@ void GestureEventFilter::ProcessGestureAck(bool processed, int type) { |
combined_scroll_pinch_ = gfx::Transform(); |
} |
} |
- } else if (ignore_next_ack_) |
- ignore_next_ack_ = false; |
+ } |
} |
TouchpadTapSuppressionController* |
- GestureEventFilter::GetTapSuppressionController() { |
- return tap_suppression_controller_.get(); |
+ GestureEventFilter::GetTouchpadTapSuppressionController() { |
+ return touchpad_tap_suppression_controller_.get(); |
} |
bool GestureEventFilter::HasQueuedGestureEvents() const { |
@@ -271,16 +315,24 @@ bool GestureEventFilter::ShouldHandleEventNow() { |
return coalesced_gesture_events_.size() == 1; |
} |
+void GestureEventFilter::ForwardGestureEventForDeferral( |
+ const WebGestureEvent& gesture_event) { |
+ if (ShouldForwardForTapDeferral(gesture_event)) |
+ ForwardGestureEventSkipDeferral(gesture_event); |
+} |
+ |
+void GestureEventFilter::ForwardGestureEventSkipDeferral( |
+ const WebGestureEvent& gesture_event) { |
+ if (ShouldForwardForCoalescing(gesture_event)) |
+ render_widget_host_->ForwardGestureEventImmediately(gesture_event); |
+} |
+ |
void GestureEventFilter::SendGestureTapDownNow() { |
// We must not have already sent the deferred TapDown (if we did, we would |
// have stopped the timer, which prevents this task from running - even if |
// it's time had already elapsed). |
DCHECK_EQ(deferred_tap_down_event_.type, WebInputEvent::GestureTapDown); |
- coalesced_gesture_events_.push_back(deferred_tap_down_event_); |
- if (ShouldHandleEventNow()) { |
- render_widget_host_->ForwardGestureEventImmediately( |
- deferred_tap_down_event_); |
- } |
+ ForwardGestureEventSkipDeferral(deferred_tap_down_event_); |
deferred_tap_down_event_.type = WebInputEvent::Undefined; |
} |
@@ -289,7 +341,10 @@ void GestureEventFilter::SendScrollEndingEventsNow() { |
for (GestureEventQueue::iterator it = |
debouncing_deferral_queue_.begin(); |
it != debouncing_deferral_queue_.end(); it++) { |
- if (ShouldForwardForTapDeferral(*it)) { |
+ if (ShouldForwardForGFCFiltering(*it) && |
+ ShouldForwardForTapSuppression(*it) && |
+ ShouldForwardForTapDeferral(*it) && |
+ ShouldForwardForCoalescing(*it)) { |
render_widget_host_->ForwardGestureEventImmediately(*it); |
} |
} |
@@ -303,18 +358,18 @@ void GestureEventFilter::MergeOrInsertScrollAndPinchEvent( |
return; |
} |
WebGestureEvent* last_event = &coalesced_gesture_events_.back(); |
- if (coalesced_gesture_events_.size() > 1 && |
- gesture_event.type == WebInputEvent::GestureScrollUpdate && |
- last_event->type == WebInputEvent::GestureScrollUpdate && |
- last_event->modifiers == gesture_event.modifiers) { |
+ if (gesture_event.type == WebInputEvent::GestureScrollUpdate && |
+ last_event->type == WebInputEvent::GestureScrollUpdate && |
+ last_event->modifiers == gesture_event.modifiers) { |
last_event->data.scrollUpdate.deltaX += |
gesture_event.data.scrollUpdate.deltaX; |
last_event->data.scrollUpdate.deltaY += |
gesture_event.data.scrollUpdate.deltaY; |
return; |
- } else if (coalesced_gesture_events_.size() < 3 || |
+ } |
+ if (coalesced_gesture_events_.size() == 2 || |
(coalesced_gesture_events_.size() == 3 && ignore_next_ack_) || |
- !ShouldTryMerging(gesture_event,*last_event)) { |
+ !ShouldTryMerging(gesture_event, *last_event)) { |
coalesced_gesture_events_.push_back(gesture_event); |
return; |
} |
@@ -378,4 +433,4 @@ gfx::Transform GestureEventFilter::GetTransformForEvent( |
} |
return gesture_transform; |
} |
-} // namespace content |
+} // namespace content |