Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1220)

Unified Diff: content/browser/renderer_host/input/gesture_event_filter.cc

Issue 45623005: [NOT FOR REVIEW] Patch demonstrating the changes required for browser side fling. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: patch Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/input/gesture_event_filter.cc
diff --git a/content/browser/renderer_host/input/gesture_event_filter.cc b/content/browser/renderer_host/input/gesture_event_filter.cc
deleted file mode 100644
index 62fcb9c34fc20f2fefd547b4c3eafde17eb7ff14..0000000000000000000000000000000000000000
--- a/content/browser/renderer_host/input/gesture_event_filter.cc
+++ /dev/null
@@ -1,392 +0,0 @@
-// Copyright 2013 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/input/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/input/touchpad_tap_suppression_controller.h"
-#include "content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h"
-#include "content/public/common/content_switches.h"
-
-using WebKit::WebGestureEvent;
-using WebKit::WebInputEvent;
-
-namespace content {
-namespace {
-
-// 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;
-
-} // namespace
-
-GestureEventFilter::GestureEventFilter(
- GestureEventFilterClient* client,
- TouchpadTapSuppressionControllerClient* touchpad_client)
- : client_(client),
- fling_in_progress_(false),
- scrolling_in_progress_(false),
- ignore_next_ack_(false),
- combined_scroll_pinch_(gfx::Transform()),
- touchpad_tap_suppression_controller_(
- new TouchpadTapSuppressionController(touchpad_client)),
- touchscreen_tap_suppression_controller_(
- new TouchscreenTapSuppressionController(this)),
- debounce_interval_time_ms_(kDebouncingIntervalTimeMs) {
- DCHECK(client);
- DCHECK(touchpad_tap_suppression_controller_);
-}
-
-GestureEventFilter::~GestureEventFilter() { }
-
-bool GestureEventFilter::ShouldDiscardFlingCancelEvent(
- const GestureEventWithLatencyInfo& gesture_event) const {
- if (coalesced_gesture_events_.empty() && fling_in_progress_)
- return false;
- GestureEventQueue::const_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) &&
- ShouldForwardForCoalescing(gesture_event);
-}
-
-bool GestureEventFilter::ShouldForwardForZeroVelocityFlingStart(
- const GestureEventWithLatencyInfo& gesture_event) const {
- 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) const {
- 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::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;
- }
- EnqueueEvent(gesture_event);
-
- // Ensure that if the added event ignores its ack, it is fired and
- // removed from |coalesced_gesture_events_|.
- SendEventsIgnoringAck();
- return ShouldHandleEventNow();
-}
-
-void GestureEventFilter::ProcessGestureAck(InputEventAckState ack_result,
- WebInputEvent::Type type,
- const ui::LatencyInfo& latency) {
- if (ShouldIgnoreAckForGestureType(type))
- return;
-
- if (coalesced_gesture_events_.empty()) {
- DLOG(ERROR) << "Received unexpected ACK for event type " << type;
- return;
- }
- DCHECK_EQ(coalesced_gesture_events_.front().event.type, type);
-
- // Ack'ing an event may enqueue additional gesture events. By ack'ing the
- // event before the forwarding of queued events below, such additional events
- // can be coalesced with existing queued events prior to dispatch.
- GestureEventWithLatencyInfo event_with_latency = GetGestureEventAwaitingAck();
- event_with_latency.latency.AddNewLatencyFrom(latency);
- client_->OnGestureEventAck(event_with_latency, ack_result);
-
- const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
- 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 the event which was just ACKed was blocking events ignoring ack, fire
- // those events now.
- SendEventsIgnoringAck();
- if (ignore_next_ack_) {
- ignore_next_ack_ = false;
- } else if (!coalesced_gesture_events_.empty()) {
- const GestureEventWithLatencyInfo& next_gesture_event =
- coalesced_gesture_events_.front();
- client_->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) {
- client_->SendGestureEventImmediately(second_gesture_event);
- ignore_next_ack_ = true;
- }
- }
- }
-}
-
-TouchpadTapSuppressionController*
- GestureEventFilter::GetTouchpadTapSuppressionController() {
- return touchpad_tap_suppression_controller_.get();
-}
-
-bool GestureEventFilter::HasQueuedGestureEvents() const {
- return !coalesced_gesture_events_.empty();
-}
-
-const GestureEventWithLatencyInfo&
-GestureEventFilter::GetGestureEventAwaitingAck() const {
- DCHECK(!coalesced_gesture_events_.empty());
- if (!ignore_next_ack_)
- return coalesced_gesture_events_.front();
- else
- return coalesced_gesture_events_.at(1);
-}
-
-void GestureEventFilter::FlingHasBeenHalted() {
- fling_in_progress_ = false;
-}
-
-bool GestureEventFilter::ShouldHandleEventNow() const {
- return coalesced_gesture_events_.size() == 1;
-}
-
-void GestureEventFilter::ForwardGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) {
- if (ShouldForwardForCoalescing(gesture_event))
- client_->SendGestureEventImmediately(gesture_event);
-}
-
-void GestureEventFilter::SendScrollEndingEventsNow() {
- scrolling_in_progress_ = false;
- for (GestureEventQueue::const_iterator it =
- debouncing_deferral_queue_.begin();
- it != debouncing_deferral_queue_.end(); it++) {
- if (ShouldForwardForGFCFiltering(*it) &&
- ShouldForwardForTapSuppression(*it) &&
- ShouldForwardForCoalescing(*it)) {
- client_->SendGestureEventImmediately(*it);
- }
- }
- debouncing_deferral_queue_.clear();
-}
-
-void GestureEventFilter::MergeOrInsertScrollAndPinchEvent(
- const GestureEventWithLatencyInfo& gesture_event) {
- if (coalesced_gesture_events_.size() <= 1) {
- EnqueueEvent(gesture_event);
- return;
- }
- GestureEventWithLatencyInfo* last_event = &coalesced_gesture_events_.back();
- if (last_event->CanCoalesceWith(gesture_event)) {
- last_event->CoalesceWith(gesture_event);
- if (!combined_scroll_pinch_.IsIdentity()) {
- combined_scroll_pinch_.ConcatTransform(
- GetTransformForEvent(gesture_event));
- }
- return;
- }
- if (coalesced_gesture_events_.size() == 2 ||
- (coalesced_gesture_events_.size() == 3 && ignore_next_ack_) ||
- !ShouldTryMerging(gesture_event, *last_event)) {
- EnqueueEvent(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 =
- SkMScalarToFloat(combined_scroll_pinch_.matrix().get(0, 0));
- float combined_scroll_pinch_x =
- SkMScalarToFloat(combined_scroll_pinch_.matrix().get(0, 3));
- float combined_scroll_pinch_y =
- SkMScalarToFloat(combined_scroll_pinch_.matrix().get(1, 3));
- scroll_event.event.data.scrollUpdate.deltaX =
- (combined_scroll_pinch_x + pinch_event.event.x) / combined_scale -
- pinch_event.event.x;
- scroll_event.event.data.scrollUpdate.deltaY =
- (combined_scroll_pinch_y + 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) const {
- 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) const {
- 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;
-}
-
-void GestureEventFilter::SendEventsIgnoringAck() {
- GestureEventWithLatencyInfo gesture_event;
- while (!coalesced_gesture_events_.empty()) {
- gesture_event = coalesced_gesture_events_.front();
- if (!GestureEventFilter::ShouldIgnoreAckForGestureType(
- gesture_event.event.type)) {
- return;
- }
- coalesced_gesture_events_.pop_front();
- client_->SendGestureEventImmediately(gesture_event);
- }
-}
-
-bool GestureEventFilter::ShouldIgnoreAckForGestureType(
- WebInputEvent::Type type) {
- return type == WebInputEvent::GestureTapDown ||
- type == WebInputEvent::GestureShowPress;
-}
-
-void GestureEventFilter::EnqueueEvent(
- const GestureEventWithLatencyInfo& gesture_event) {
- coalesced_gesture_events_.push_back(gesture_event);
- // Scroll and pinch events contributing to |combined_scroll_pinch_| will be
- // manually added to the queue in |MergeOrInsertScrollAndPinchEvent()|.
- combined_scroll_pinch_ = gfx::Transform();
-}
-
-} // namespace content

Powered by Google App Engine
This is Rietveld 408576698