| 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
|
| deleted file mode 100644
|
| index bdf360ddb633a932391827024ffba8cb2523cb83..0000000000000000000000000000000000000000
|
| --- a/content/browser/renderer_host/gesture_event_filter.cc
|
| +++ /dev/null
|
| @@ -1,434 +0,0 @@
|
| -// Copyright (c) 2012 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.
|
| -
|
| -#include "content/browser/renderer_host/gesture_event_filter.h"
|
| -
|
| -#include "base/command_line.h"
|
| -#include "base/strings/string_number_conversions.h"
|
| -#include "content/browser/renderer_host/input/input_router.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;
|
| -using WebKit::WebInputEvent;
|
| -
|
| -namespace content {
|
| -namespace {
|
| -
|
| -// Default maximum time between the GestureRecognizer generating a
|
| -// GestureTapDown and when it is forwarded to the renderer.
|
| -#if !defined(OS_ANDROID)
|
| -static const int kTapDownDeferralTimeMs = 150;
|
| -#else
|
| -// Android OS sends this gesture with a delay already.
|
| -static const int kTapDownDeferralTimeMs = 0;
|
| -#endif
|
| -
|
| -// Default debouncing interval duration: if a scroll is in progress, non-scroll
|
| -// events during this interval are deferred to either its end or discarded on
|
| -// receipt of another GestureScrollUpdate.
|
| -static const int kDebouncingIntervalTimeMs = 30;
|
| -
|
| -// Sets |*value| to |switchKey| if it exists or sets it to |defaultValue|.
|
| -static void GetParamHelper(int* value,
|
| - int defaultValue,
|
| - const char switchKey[]) {
|
| - if (*value < 0) {
|
| - *value = defaultValue;
|
| - CommandLine* command_line = CommandLine::ForCurrentProcess();
|
| - std::string command_line_param =
|
| - command_line->GetSwitchValueASCII(switchKey);
|
| - if (!command_line_param.empty()) {
|
| - int v;
|
| - if (base::StringToInt(command_line_param, &v))
|
| - *value = v;
|
| - }
|
| - DCHECK_GE(*value, 0);
|
| - }
|
| -}
|
| -
|
| -static int GetTapDownDeferralTimeMs() {
|
| - static int tap_down_deferral_time_window = -1;
|
| - GetParamHelper(&tap_down_deferral_time_window,
|
| - kTapDownDeferralTimeMs,
|
| - switches::kTapDownDeferralTimeMs);
|
| - return tap_down_deferral_time_window;
|
| -}
|
| -} // namespace
|
| -
|
| -GestureEventFilter::GestureEventFilter(InputRouter* input_router)
|
| - : input_router_(input_router),
|
| - fling_in_progress_(false),
|
| - scrolling_in_progress_(false),
|
| - ignore_next_ack_(false),
|
| - combined_scroll_pinch_(gfx::Transform()),
|
| - touchpad_tap_suppression_controller_(
|
| - new TouchpadTapSuppressionController(input_router)),
|
| - touchscreen_tap_suppression_controller_(
|
| - new TouchscreenTapSuppressionController(this)),
|
| - maximum_tap_gap_time_ms_(GetTapDownDeferralTimeMs()),
|
| - debounce_interval_time_ms_(kDebouncingIntervalTimeMs) {
|
| -}
|
| -
|
| -GestureEventFilter::~GestureEventFilter() { }
|
| -
|
| -bool GestureEventFilter::ShouldDiscardFlingCancelEvent(
|
| - const GestureEventWithLatencyInfo& gesture_event) {
|
| - if (coalesced_gesture_events_.empty() && fling_in_progress_)
|
| - return false;
|
| - GestureEventQueue::reverse_iterator it =
|
| - coalesced_gesture_events_.rbegin();
|
| - while (it != coalesced_gesture_events_.rend()) {
|
| - if (it->event.type == WebInputEvent::GestureFlingStart)
|
| - return false;
|
| - if (it->event.type == WebInputEvent::GestureFlingCancel)
|
| - return true;
|
| - it++;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool GestureEventFilter::ShouldForwardForBounceReduction(
|
| - const GestureEventWithLatencyInfo& gesture_event) {
|
| - if (debounce_interval_time_ms_ == 0)
|
| - return true;
|
| - switch (gesture_event.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);
|
| - } else {
|
| - // Extend the bounce interval.
|
| - debounce_deferring_timer_.Reset();
|
| - }
|
| - scrolling_in_progress_ = true;
|
| - debouncing_deferral_queue_.clear();
|
| - return true;
|
| - case WebInputEvent::GesturePinchBegin:
|
| - case WebInputEvent::GesturePinchEnd:
|
| - case WebInputEvent::GesturePinchUpdate:
|
| - // TODO(rjkroege): Debounce pinch (http://crbug.com/147647)
|
| - return true;
|
| - default:
|
| - if (scrolling_in_progress_) {
|
| - debouncing_deferral_queue_.push_back(gesture_event);
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - NOTREACHED();
|
| - return false;
|
| -}
|
| -
|
| -// NOTE: The filters are applied successively. This simplifies the change.
|
| -bool GestureEventFilter::ShouldForward(
|
| - const GestureEventWithLatencyInfo& gesture_event) {
|
| - return ShouldForwardForZeroVelocityFlingStart(gesture_event) &&
|
| - ShouldForwardForBounceReduction(gesture_event) &&
|
| - ShouldForwardForGFCFiltering(gesture_event) &&
|
| - ShouldForwardForTapSuppression(gesture_event) &&
|
| - ShouldForwardForTapDeferral(gesture_event) &&
|
| - ShouldForwardForCoalescing(gesture_event);
|
| -}
|
| -
|
| -bool GestureEventFilter::ShouldForwardForZeroVelocityFlingStart(
|
| - const GestureEventWithLatencyInfo& gesture_event) {
|
| - return gesture_event.event.type != WebInputEvent::GestureFlingStart ||
|
| - gesture_event.event.sourceDevice != WebGestureEvent::Touchpad ||
|
| - gesture_event.event.data.flingStart.velocityX != 0 ||
|
| - gesture_event.event.data.flingStart.velocityY != 0;
|
| -}
|
| -
|
| -bool GestureEventFilter::ShouldForwardForGFCFiltering(
|
| - const GestureEventWithLatencyInfo& gesture_event) {
|
| - return gesture_event.event.type != WebInputEvent::GestureFlingCancel ||
|
| - !ShouldDiscardFlingCancelEvent(gesture_event);
|
| -}
|
| -
|
| -bool GestureEventFilter::ShouldForwardForTapSuppression(
|
| - const GestureEventWithLatencyInfo& gesture_event) {
|
| - switch (gesture_event.event.type) {
|
| - case WebInputEvent::GestureFlingCancel:
|
| - if (gesture_event.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:
|
| - case WebInputEvent::GestureTapUnconfirmed:
|
| - return !touchscreen_tap_suppression_controller_->
|
| - ShouldSuppressGestureTap();
|
| - default:
|
| - return true;
|
| - }
|
| - NOTREACHED();
|
| - return false;
|
| -}
|
| -
|
| -bool GestureEventFilter::ShouldForwardForTapDeferral(
|
| - const GestureEventWithLatencyInfo& gesture_event) {
|
| - switch (gesture_event.event.type) {
|
| - 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_.event.type, WebInputEvent::Undefined);
|
| - 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::GestureTapCancel:
|
| - if (deferred_tap_down_event_.event.type == WebInputEvent::Undefined) {
|
| - // The TapDown has already been put in the queue, must send the
|
| - // corresponding TapCancel as well.
|
| - return true;
|
| - }
|
| - // Cancelling a deferred TapDown, just drop them on the floor.
|
| - send_gtd_timer_.Stop();
|
| - deferred_tap_down_event_.event.type = WebInputEvent::Undefined;
|
| - return false;
|
| - case WebInputEvent::GestureTap:
|
| - send_gtd_timer_.Stop();
|
| - if (deferred_tap_down_event_.event.type != WebInputEvent::Undefined) {
|
| - ForwardGestureEventSkipDeferral(deferred_tap_down_event_);
|
| - deferred_tap_down_event_.event.type = WebInputEvent::Undefined;
|
| - }
|
| - return true;
|
| - case WebInputEvent::GestureFlingStart:
|
| - case WebInputEvent::GestureScrollBegin:
|
| - case WebInputEvent::GesturePinchBegin:
|
| - send_gtd_timer_.Stop();
|
| - deferred_tap_down_event_.event.type = WebInputEvent::Undefined;
|
| - return true;
|
| - default:
|
| - return true;
|
| - }
|
| -
|
| - NOTREACHED();
|
| - return true;
|
| -}
|
| -
|
| -bool GestureEventFilter::ShouldForwardForCoalescing(
|
| - const GestureEventWithLatencyInfo& gesture_event) {
|
| - switch (gesture_event.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:
|
| - break;
|
| - }
|
| - coalesced_gesture_events_.push_back(gesture_event);
|
| - return ShouldHandleEventNow();
|
| -}
|
| -
|
| -void GestureEventFilter::ProcessGestureAck(bool processed, int type) {
|
| - if (coalesced_gesture_events_.empty()) {
|
| - DLOG(ERROR) << "Received unexpected ACK for event type " << type;
|
| - return;
|
| - }
|
| - DCHECK_EQ(coalesced_gesture_events_.front().event.type, type);
|
| - if (type == WebInputEvent::GestureFlingCancel) {
|
| - if (coalesced_gesture_events_.front().event.sourceDevice ==
|
| - WebGestureEvent::Touchscreen)
|
| - touchscreen_tap_suppression_controller_->GestureFlingCancelAck(processed);
|
| - else
|
| - touchpad_tap_suppression_controller_->GestureFlingCancelAck(processed);
|
| - }
|
| - coalesced_gesture_events_.pop_front();
|
| - if (ignore_next_ack_) {
|
| - ignore_next_ack_ = false;
|
| - } else if (!coalesced_gesture_events_.empty()) {
|
| - const GestureEventWithLatencyInfo& next_gesture_event =
|
| - coalesced_gesture_events_.front();
|
| - input_router_->SendGestureEventImmediately(next_gesture_event);
|
| - // TODO(yusufo): Introduce GesturePanScroll so that these can be combined
|
| - // into one gesture and kept inside the queue that way.
|
| - if (coalesced_gesture_events_.size() > 1) {
|
| - const GestureEventWithLatencyInfo& second_gesture_event =
|
| - coalesced_gesture_events_[1];
|
| - if (next_gesture_event.event.type ==
|
| - WebInputEvent::GestureScrollUpdate &&
|
| - second_gesture_event.event.type ==
|
| - WebInputEvent::GesturePinchUpdate) {
|
| - input_router_->SendGestureEventImmediately(second_gesture_event);
|
| - ignore_next_ack_ = true;
|
| - combined_scroll_pinch_ = gfx::Transform();
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -TouchpadTapSuppressionController*
|
| - GestureEventFilter::GetTouchpadTapSuppressionController() {
|
| - return touchpad_tap_suppression_controller_.get();
|
| -}
|
| -
|
| -bool GestureEventFilter::HasQueuedGestureEvents() const {
|
| - return !coalesced_gesture_events_.empty();
|
| -}
|
| -
|
| -const WebKit::WebGestureEvent&
|
| -GestureEventFilter::GetGestureEventAwaitingAck() const {
|
| - DCHECK(!coalesced_gesture_events_.empty());
|
| - if (!ignore_next_ack_)
|
| - return coalesced_gesture_events_.front().event;
|
| - else
|
| - return coalesced_gesture_events_.at(1).event;
|
| -}
|
| -
|
| -void GestureEventFilter::FlingHasBeenHalted() {
|
| - fling_in_progress_ = false;
|
| -}
|
| -
|
| -bool GestureEventFilter::ShouldHandleEventNow() {
|
| - return coalesced_gesture_events_.size() == 1;
|
| -}
|
| -
|
| -void GestureEventFilter::ForwardGestureEventForDeferral(
|
| - const GestureEventWithLatencyInfo& gesture_event) {
|
| - if (ShouldForwardForTapDeferral(gesture_event))
|
| - ForwardGestureEventSkipDeferral(gesture_event);
|
| -}
|
| -
|
| -void GestureEventFilter::ForwardGestureEventSkipDeferral(
|
| - const GestureEventWithLatencyInfo& gesture_event) {
|
| - if (ShouldForwardForCoalescing(gesture_event))
|
| - input_router_->SendGestureEventImmediately(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_.event.type, WebInputEvent::GestureTapDown);
|
| - ForwardGestureEventSkipDeferral(deferred_tap_down_event_);
|
| - deferred_tap_down_event_.event.type = WebInputEvent::Undefined;
|
| -}
|
| -
|
| -void GestureEventFilter::SendScrollEndingEventsNow() {
|
| - scrolling_in_progress_ = false;
|
| - for (GestureEventQueue::iterator it =
|
| - debouncing_deferral_queue_.begin();
|
| - it != debouncing_deferral_queue_.end(); it++) {
|
| - if (ShouldForwardForGFCFiltering(*it) &&
|
| - ShouldForwardForTapSuppression(*it) &&
|
| - ShouldForwardForTapDeferral(*it) &&
|
| - ShouldForwardForCoalescing(*it)) {
|
| - input_router_->SendGestureEventImmediately(*it);
|
| - }
|
| - }
|
| - debouncing_deferral_queue_.clear();
|
| -}
|
| -
|
| -void GestureEventFilter::MergeOrInsertScrollAndPinchEvent(
|
| - const GestureEventWithLatencyInfo& gesture_event) {
|
| - if (coalesced_gesture_events_.size() <= 1) {
|
| - coalesced_gesture_events_.push_back(gesture_event);
|
| - return;
|
| - }
|
| - GestureEventWithLatencyInfo* last_event = &coalesced_gesture_events_.back();
|
| - if (gesture_event.event.type == WebInputEvent::GestureScrollUpdate &&
|
| - last_event->event.type == WebInputEvent::GestureScrollUpdate &&
|
| - last_event->event.modifiers == gesture_event.event.modifiers) {
|
| - last_event->event.data.scrollUpdate.deltaX +=
|
| - gesture_event.event.data.scrollUpdate.deltaX;
|
| - last_event->event.data.scrollUpdate.deltaY +=
|
| - gesture_event.event.data.scrollUpdate.deltaY;
|
| - last_event->latency.MergeWith(gesture_event.latency);
|
| - return;
|
| - }
|
| - if (coalesced_gesture_events_.size() == 2 ||
|
| - (coalesced_gesture_events_.size() == 3 && ignore_next_ack_) ||
|
| - !ShouldTryMerging(gesture_event, *last_event)) {
|
| - coalesced_gesture_events_.push_back(gesture_event);
|
| - return;
|
| - }
|
| - GestureEventWithLatencyInfo scroll_event;
|
| - GestureEventWithLatencyInfo pinch_event;
|
| - scroll_event.event.modifiers |= gesture_event.event.modifiers;
|
| - scroll_event.event.timeStampSeconds = gesture_event.event.timeStampSeconds;
|
| - scroll_event.latency = gesture_event.latency;
|
| - scroll_event.latency.MergeWith(last_event->latency);
|
| - pinch_event = scroll_event;
|
| - scroll_event.event.type = WebInputEvent::GestureScrollUpdate;
|
| - pinch_event.event.type = WebInputEvent::GesturePinchUpdate;
|
| - pinch_event.event.x = gesture_event.event.type ==
|
| - WebInputEvent::GesturePinchUpdate ?
|
| - gesture_event.event.x : last_event->event.x;
|
| - pinch_event.event.y = gesture_event.event.type ==
|
| - WebInputEvent::GesturePinchUpdate ?
|
| - gesture_event.event.y : last_event->event.y;
|
| -
|
| - combined_scroll_pinch_.ConcatTransform(GetTransformForEvent(gesture_event));
|
| - GestureEventWithLatencyInfo* second_last_event = &coalesced_gesture_events_
|
| - [coalesced_gesture_events_.size() - 2];
|
| - if (ShouldTryMerging(gesture_event, *second_last_event)) {
|
| - scroll_event.latency.MergeWith(second_last_event->latency);
|
| - pinch_event.latency.MergeWith(second_last_event->latency);
|
| - coalesced_gesture_events_.pop_back();
|
| - } else {
|
| - DCHECK(combined_scroll_pinch_ == GetTransformForEvent(gesture_event));
|
| - combined_scroll_pinch_.
|
| - PreconcatTransform(GetTransformForEvent(*last_event));
|
| - }
|
| - coalesced_gesture_events_.pop_back();
|
| - float combined_scale = combined_scroll_pinch_.matrix().getDouble(0, 0);
|
| - scroll_event.event.data.scrollUpdate.deltaX =
|
| - (combined_scroll_pinch_.matrix().getDouble(0, 3) + pinch_event.event.x)
|
| - / combined_scale - pinch_event.event.x;
|
| - scroll_event.event.data.scrollUpdate.deltaY =
|
| - (combined_scroll_pinch_.matrix().getDouble(1, 3) + pinch_event.event.y)
|
| - / combined_scale - pinch_event.event.y;
|
| - coalesced_gesture_events_.push_back(scroll_event);
|
| - pinch_event.event.data.pinchUpdate.scale = combined_scale;
|
| - coalesced_gesture_events_.push_back(pinch_event);
|
| -}
|
| -
|
| -bool GestureEventFilter::ShouldTryMerging(
|
| - const GestureEventWithLatencyInfo& new_event,
|
| - const GestureEventWithLatencyInfo& event_in_queue) {
|
| - DLOG_IF(WARNING,
|
| - new_event.event.timeStampSeconds <
|
| - event_in_queue.event.timeStampSeconds)
|
| - << "Event time not monotonic?\n";
|
| - return (event_in_queue.event.type == WebInputEvent::GestureScrollUpdate ||
|
| - event_in_queue.event.type == WebInputEvent::GesturePinchUpdate) &&
|
| - event_in_queue.event.modifiers == new_event.event.modifiers;
|
| -}
|
| -
|
| -gfx::Transform GestureEventFilter::GetTransformForEvent(
|
| - const GestureEventWithLatencyInfo& gesture_event) {
|
| - gfx::Transform gesture_transform = gfx::Transform();
|
| - if (gesture_event.event.type == WebInputEvent::GestureScrollUpdate) {
|
| - gesture_transform.Translate(gesture_event.event.data.scrollUpdate.deltaX,
|
| - gesture_event.event.data.scrollUpdate.deltaY);
|
| - } else if (gesture_event.event.type == WebInputEvent::GesturePinchUpdate) {
|
| - float scale = gesture_event.event.data.pinchUpdate.scale;
|
| - gesture_transform.Translate(-gesture_event.event.x, -gesture_event.event.y);
|
| - gesture_transform.Scale(scale,scale);
|
| - gesture_transform.Translate(gesture_event.event.x, gesture_event.event.y);
|
| - }
|
| - return gesture_transform;
|
| -}
|
| -} // namespace content
|
|
|