Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / input / gesture_event_queue.cc
index c71e692..9811e73 100644 (file)
@@ -4,7 +4,6 @@
 
 #include "content/browser/renderer_host/input/gesture_event_queue.h"
 
-#include "base/command_line.h"
 #include "base/debug/trace_event.h"
 #include "base/strings/string_number_conversions.h"
 #include "content/browser/renderer_host/input/input_router.h"
@@ -16,35 +15,27 @@ using blink::WebGestureEvent;
 using blink::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
+GestureEventQueue::Config::Config() {
+}
 
 GestureEventQueue::GestureEventQueue(
     GestureEventQueueClient* 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),
-       debounce_enabled_(true) {
+    TouchpadTapSuppressionControllerClient* touchpad_client,
+    const Config& config)
+    : client_(client),
+      fling_in_progress_(false),
+      scrolling_in_progress_(false),
+      ignore_next_ack_(false),
+      touchpad_tap_suppression_controller_(
+          touchpad_client,
+          config.touchpad_tap_suppression_config),
+      touchscreen_tap_suppression_controller_(
+          this,
+          config.touchscreen_tap_suppression_config),
+      debounce_interval_(config.debounce_interval) {
   DCHECK(client);
-  DCHECK(touchpad_tap_suppression_controller_);
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kDisableGestureDebounce)) {
-    debounce_enabled_ = false;
-  }
+  DCHECK(touchpad_client);
 }
 
 GestureEventQueue::~GestureEventQueue() { }
@@ -67,14 +58,14 @@ bool GestureEventQueue::ShouldDiscardFlingCancelEvent(
 
 bool GestureEventQueue::ShouldForwardForBounceReduction(
     const GestureEventWithLatencyInfo& gesture_event) {
-  if (!debounce_enabled_)
+  if (debounce_interval_ <= base::TimeDelta())
     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_),
+            debounce_interval_,
             this,
             &GestureEventQueue::SendScrollEndingEventsNow);
       } else {
@@ -128,22 +119,21 @@ bool GestureEventQueue::ShouldForwardForTapSuppression(
   switch (gesture_event.event.type) {
     case WebInputEvent::GestureFlingCancel:
       if (gesture_event.event.sourceDevice == WebGestureEvent::Touchscreen)
-        touchscreen_tap_suppression_controller_->GestureFlingCancel();
+        touchscreen_tap_suppression_controller_.GestureFlingCancel();
       else
-        touchpad_tap_suppression_controller_->GestureFlingCancel();
+        touchpad_tap_suppression_controller_.GestureFlingCancel();
       return true;
     case WebInputEvent::GestureTapDown:
-      return !touchscreen_tap_suppression_controller_->
-          ShouldDeferGestureTapDown(gesture_event);
     case WebInputEvent::GestureShowPress:
-      return !touchscreen_tap_suppression_controller_->
-          ShouldDeferGestureShowPress(gesture_event);
+    case WebInputEvent::GestureTapUnconfirmed:
     case WebInputEvent::GestureTapCancel:
     case WebInputEvent::GestureTap:
-    case WebInputEvent::GestureTapUnconfirmed:
     case WebInputEvent::GestureDoubleTap:
-      return !touchscreen_tap_suppression_controller_->
-          ShouldSuppressGestureTapEnd();
+      if (gesture_event.event.sourceDevice == WebGestureEvent::Touchscreen) {
+        return !touchscreen_tap_suppression_controller_.FilterTapEvent(
+            gesture_event);
+      }
+      return true;
     default:
       return true;
   }
@@ -165,7 +155,7 @@ bool GestureEventQueue::ShouldForwardForCoalescing(
     default:
       break;
   }
-  EnqueueEvent(gesture_event);
+  coalesced_gesture_events_.push_back(gesture_event);
   return ShouldHandleEventNow();
 }
 
@@ -179,23 +169,36 @@ void GestureEventQueue::ProcessGestureAck(InputEventAckState ack_result,
     return;
   }
 
-  // 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.
+  // It's possible that the ack for the second event in an in-flight, coalesced
+  // Gesture{Scroll,Pinch}Update pair is received prior to the first event ack.
+  // TODO(jdduke): Unify GSU/GPU pairs into a single event, crbug.com/359115.
+  size_t event_index = 0;
+  if (ignore_next_ack_ &&
+      coalesced_gesture_events_.size() > 1 &&
+      coalesced_gesture_events_[0].event.type != type &&
+      coalesced_gesture_events_[1].event.type == type) {
+    event_index = 1;
+  }
   GestureEventWithLatencyInfo event_with_latency =
-      coalesced_gesture_events_.front();
+      coalesced_gesture_events_[event_index];
   DCHECK_EQ(event_with_latency.event.type, type);
   event_with_latency.latency.AddNewLatencyFrom(latency);
+
+  // 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.
   client_->OnGestureEventAck(event_with_latency, ack_result);
 
   const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result);
   if (type == WebInputEvent::GestureFlingCancel) {
     if (event_with_latency.event.sourceDevice == WebGestureEvent::Touchscreen)
-      touchscreen_tap_suppression_controller_->GestureFlingCancelAck(processed);
+      touchscreen_tap_suppression_controller_.GestureFlingCancelAck(processed);
     else
-      touchpad_tap_suppression_controller_->GestureFlingCancelAck(processed);
+      touchpad_tap_suppression_controller_.GestureFlingCancelAck(processed);
   }
-  coalesced_gesture_events_.pop_front();
+  DCHECK_LT(event_index, coalesced_gesture_events_.size());
+  coalesced_gesture_events_.erase(coalesced_gesture_events_.begin() +
+                                  event_index);
 
   if (ignore_next_ack_) {
     ignore_next_ack_ = false;
@@ -208,8 +211,7 @@ void GestureEventQueue::ProcessGestureAck(InputEventAckState ack_result,
   const GestureEventWithLatencyInfo& first_gesture_event =
       coalesced_gesture_events_.front();
 
-  // TODO(yusufo): Introduce GesturePanScroll so that these can be combined
-  // into one gesture and kept inside the queue that way.
+  // TODO(jdduke): Unify GSU/GPU pairs into a single event, crbug.com/359115.
   // Check for the coupled GesturePinchUpdate before sending either event,
   // handling the case where the first GestureScrollUpdate ack is synchronous.
   GestureEventWithLatencyInfo second_gesture_event;
@@ -228,10 +230,10 @@ void GestureEventQueue::ProcessGestureAck(InputEventAckState ack_result,
 
 TouchpadTapSuppressionController*
     GestureEventQueue::GetTouchpadTapSuppressionController() {
-  return touchpad_tap_suppression_controller_.get();
+  return &touchpad_tap_suppression_controller_;
 }
 
-bool GestureEventQueue::HasQueuedGestureEvents() const {
+bool GestureEventQueue::ExpectingGestureAck() const {
   return !coalesced_gesture_events_.empty();
 }
 
@@ -267,28 +269,28 @@ void GestureEventQueue::SendScrollEndingEventsNow() {
 
 void GestureEventQueue::MergeOrInsertScrollAndPinchEvent(
     const GestureEventWithLatencyInfo& gesture_event) {
-  if (coalesced_gesture_events_.size() <= 1) {
-    EnqueueEvent(gesture_event);
+  const size_t unsent_events_count =
+      coalesced_gesture_events_.size() - EventsInFlightCount();
+  if (!unsent_events_count) {
+    coalesced_gesture_events_.push_back(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);
+
+  if (!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.sourceDevice = gesture_event.event.sourceDevice;
   scroll_event.event.timeStampSeconds = gesture_event.event.timeStampSeconds;
   // Keep the oldest LatencyInfo.
   DCHECK_LE(last_event->latency.trace_id, gesture_event.latency.trace_id);
@@ -303,28 +305,32 @@ void GestureEventQueue::MergeOrInsertScrollAndPinchEvent(
       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)) {
-    // Keep the oldest LatencyInfo.
-    DCHECK_LE(second_last_event->latency.trace_id,
-              scroll_event.latency.trace_id);
-    scroll_event.latency = second_last_event->latency;
-    pinch_event.latency = second_last_event->latency;
-    coalesced_gesture_events_.pop_back();
-  } else {
-    DCHECK(combined_scroll_pinch_ == GetTransformForEvent(gesture_event));
-    combined_scroll_pinch_.
-        PreconcatTransform(GetTransformForEvent(*last_event));
+  gfx::Transform combined_scroll_pinch = GetTransformForEvent(*last_event);
+  // Only include the second-to-last event in the coalesced pair if it exists
+  // and can be combined with the new event.
+  if (unsent_events_count > 1) {
+    const GestureEventWithLatencyInfo& second_last_event =
+        coalesced_gesture_events_[coalesced_gesture_events_.size() - 2];
+    if (ShouldTryMerging(gesture_event, second_last_event)) {
+      // Keep the oldest LatencyInfo.
+      DCHECK_LE(second_last_event.latency.trace_id,
+                scroll_event.latency.trace_id);
+      scroll_event.latency = second_last_event.latency;
+      pinch_event.latency = second_last_event.latency;
+      combined_scroll_pinch.PreconcatTransform(
+          GetTransformForEvent(second_last_event));
+      coalesced_gesture_events_.pop_back();
+    }
   }
+  combined_scroll_pinch.ConcatTransform(GetTransformForEvent(gesture_event));
   coalesced_gesture_events_.pop_back();
+
   float combined_scale =
-      SkMScalarToFloat(combined_scroll_pinch_.matrix().get(0, 0));
+      SkMScalarToFloat(combined_scroll_pinch.matrix().get(0, 0));
   float combined_scroll_pinch_x =
-      SkMScalarToFloat(combined_scroll_pinch_.matrix().get(0, 3));
+      SkMScalarToFloat(combined_scroll_pinch.matrix().get(0, 3));
   float combined_scroll_pinch_y =
-      SkMScalarToFloat(combined_scroll_pinch_.matrix().get(1, 3));
+      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;
@@ -345,12 +351,13 @@ bool GestureEventQueue::ShouldTryMerging(
           << "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;
+      event_in_queue.event.modifiers == new_event.event.modifiers &&
+      event_in_queue.event.sourceDevice == new_event.event.sourceDevice;
 }
 
 gfx::Transform GestureEventQueue::GetTransformForEvent(
     const GestureEventWithLatencyInfo& gesture_event) const {
-  gfx::Transform gesture_transform = gfx::Transform();
+  gfx::Transform gesture_transform;
   if (gesture_event.event.type == WebInputEvent::GestureScrollUpdate) {
     gesture_transform.Translate(gesture_event.event.data.scrollUpdate.deltaX,
                                 gesture_event.event.data.scrollUpdate.deltaY);
@@ -363,12 +370,15 @@ gfx::Transform GestureEventQueue::GetTransformForEvent(
   return gesture_transform;
 }
 
-void GestureEventQueue::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();
+size_t GestureEventQueue::EventsInFlightCount() const {
+  if (coalesced_gesture_events_.empty())
+    return 0;
+
+  if (!ignore_next_ack_)
+    return 1;
+
+  DCHECK_GT(coalesced_gesture_events_.size(), 1U);
+  return 2;
 }
 
 }  // namespace content