Home | History | Annotate | Download | only in input
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_GESTURE_EVENT_FILTER_H_
      6 #define CONTENT_BROWSER_RENDERER_HOST_INPUT_GESTURE_EVENT_FILTER_H_
      7 
      8 #include <deque>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/timer/timer.h"
     13 #include "content/port/browser/event_with_latency_info.h"
     14 #include "third_party/WebKit/public/web/WebInputEvent.h"
     15 #include "ui/gfx/transform.h"
     16 
     17 namespace content {
     18 class InputRouter;
     19 class MockRenderWidgetHost;
     20 class TouchpadTapSuppressionController;
     21 class TouchscreenTapSuppressionController;
     22 
     23 // Maintains WebGestureEvents in a queue before forwarding them to the renderer
     24 // to apply a sequence of filters on them:
     25 // 1. Zero-velocity fling-starts from touchpad are filtered.
     26 // 2. The sequence is filtered for bounces. A bounce is when the finger lifts
     27 //    from the screen briefly during an in-progress scroll. If this happens,
     28 //    non-GestureScrollUpdate events are queued until the de-bounce interval
     29 //    passes or another GestureScrollUpdate event occurs.
     30 // 3. Unnecessary GestureFlingCancel events are filtered. These are
     31 //    GestureFlingCancels that have no corresponding GestureFlingStart in the
     32 //    queue.
     33 // 4. Taps immediately after a GestureFlingCancel (caused by the same tap) are
     34 //    filtered.
     35 // 5. Whenever possible, events in the queue are coalesced to have as few events
     36 //    as possible and therefore maximize the chance that the event stream can be
     37 //    handled entirely by the compositor thread.
     38 // Events in the queue are forwarded to the renderer one by one; i.e., each
     39 // event is sent after receiving the ACK for previous one. The only exception is
     40 // that if a GestureScrollUpdate is followed by a GesturePinchUpdate, they are
     41 // sent together.
     42 // TODO(rjkroege): Possibly refactor into a filter chain:
     43 // http://crbug.com/148443.
     44 class GestureEventFilter {
     45  public:
     46   // The |input_router| must outlive the GestureEventFilter.
     47   explicit GestureEventFilter(InputRouter* input_router);
     48   ~GestureEventFilter();
     49 
     50   // Returns |true| if the caller should immediately forward the provided
     51   // |GestureEventWithLatencyInfo| argument to the renderer.
     52   bool ShouldForward(const GestureEventWithLatencyInfo&);
     53 
     54   // Indicates that the caller has received an acknowledgement from the renderer
     55   // with state |processed| and event |type|. May send events if the queue is
     56   // not empty.
     57   void ProcessGestureAck(bool processed, int type);
     58 
     59   // Sets the state of the |fling_in_progress_| field to indicate that a fling
     60   // is definitely not in progress.
     61   void FlingHasBeenHalted();
     62 
     63   // Returns the |TouchpadTapSuppressionController| instance.
     64   TouchpadTapSuppressionController* GetTouchpadTapSuppressionController();
     65 
     66   // Returns whether there are any gesture event in the queue.
     67   bool HasQueuedGestureEvents() const;
     68 
     69   // Returns the last gesture event that was sent to the renderer.
     70   const WebKit::WebGestureEvent& GetGestureEventAwaitingAck() const;
     71 
     72   // Tries forwarding the event to the tap deferral sub-filter.
     73   void ForwardGestureEventForDeferral(
     74       const GestureEventWithLatencyInfo& gesture_event);
     75 
     76   // Tries forwarding the event, skipping the tap deferral sub-filter.
     77   void ForwardGestureEventSkipDeferral(
     78       const GestureEventWithLatencyInfo& gesture_event);
     79 
     80  private:
     81   friend class MockRenderWidgetHost;
     82   friend class ImmediateInputRouterTest;
     83 
     84   // TODO(mohsen): There are a bunch of ShouldForward.../ShouldDiscard...
     85   // methods that are getting confusing. This should be somehow fixed. Maybe
     86   // while refactoring GEF: http://crbug.com/148443.
     87 
     88   // Invoked on the expiration of the timer to release a deferred
     89   // GestureTapDown to the renderer.
     90   void SendGestureTapDownNow();
     91 
     92   // Inovked on the expiration of the debounce interval to release
     93   // deferred events.
     94   void SendScrollEndingEventsNow();
     95 
     96   // Returns |true| if the given GestureFlingCancel should be discarded
     97   // as unnecessary.
     98   bool ShouldDiscardFlingCancelEvent(
     99       const GestureEventWithLatencyInfo& gesture_event) const;
    100 
    101   // Returns |true| if the only event in the queue is the current event and
    102   // hence that event should be handled now.
    103   bool ShouldHandleEventNow() const;
    104 
    105   // Merge or append a GestureScrollUpdate or GesturePinchUpdate into
    106   // the coalescing queue.
    107   void MergeOrInsertScrollAndPinchEvent(
    108       const GestureEventWithLatencyInfo& gesture_event);
    109 
    110   // Sub-filter for removing zero-velocity fling-starts from touchpad.
    111   bool ShouldForwardForZeroVelocityFlingStart(
    112       const GestureEventWithLatencyInfo& gesture_event) const;
    113 
    114   // Sub-filter for removing bounces from in-progress scrolls.
    115   bool ShouldForwardForBounceReduction(
    116       const GestureEventWithLatencyInfo& gesture_event);
    117 
    118   // Sub-filter for removing unnecessary GestureFlingCancels.
    119   bool ShouldForwardForGFCFiltering(
    120       const GestureEventWithLatencyInfo& gesture_event) const;
    121 
    122   // Sub-filter for suppressing taps immediately after a GestureFlingCancel.
    123   bool ShouldForwardForTapSuppression(
    124       const GestureEventWithLatencyInfo& gesture_event);
    125 
    126   // Sub-filter for deferring GestureTapDowns.
    127   bool ShouldForwardForTapDeferral(
    128       const GestureEventWithLatencyInfo& gesture_event);
    129 
    130   // Puts the events in a queue to forward them one by one; i.e., forward them
    131   // whenever ACK for previous event is received. This queue also tries to
    132   // coalesce events as much as possible.
    133   bool ShouldForwardForCoalescing(
    134       const GestureEventWithLatencyInfo& gesture_event);
    135 
    136   // Whether the event_in_queue is GesturePinchUpdate or
    137   // GestureScrollUpdate and it has the same modifiers as the
    138   // new event.
    139   bool ShouldTryMerging(
    140       const GestureEventWithLatencyInfo& new_event,
    141       const GestureEventWithLatencyInfo& event_in_queue)const;
    142 
    143   // Returns the transform matrix corresponding to the gesture event.
    144   // Assumes the gesture event sent is either GestureScrollUpdate or
    145   // GesturePinchUpdate. Returns the identity matrix otherwise.
    146   gfx::Transform GetTransformForEvent(
    147       const GestureEventWithLatencyInfo& gesture_event) const;
    148 
    149   // The receiver of all forwarded gesture events.
    150   InputRouter* input_router_;
    151 
    152   // True if a GestureFlingStart is in progress on the renderer or
    153   // queued without a subsequent queued GestureFlingCancel event.
    154   bool fling_in_progress_;
    155 
    156   // True if a GestureScrollUpdate sequence is in progress.
    157   bool scrolling_in_progress_;
    158 
    159   // True if two related gesture events were sent before without waiting
    160   // for an ACK, so the next gesture ACK should be ignored.
    161   bool ignore_next_ack_;
    162 
    163   // Transform that holds the combined transform matrix for the current
    164   // scroll-pinch sequence at the end of the queue.
    165   gfx::Transform combined_scroll_pinch_;
    166 
    167   // Timer to release a previously deferred GestureTapDown event.
    168   base::OneShotTimer<GestureEventFilter> send_gtd_timer_;
    169 
    170   // An object tracking the state of touchpad on the delivery of mouse events to
    171   // the renderer to filter mouse immediately after a touchpad fling canceling
    172   // tap.
    173   // TODO(mohsen): Move touchpad tap suppression out of GestureEventFilter since
    174   // GEF is meant to only be used for touchscreen gesture events.
    175   scoped_ptr<TouchpadTapSuppressionController>
    176       touchpad_tap_suppression_controller_;
    177 
    178   // An object tracking the state of touchscreen on the delivery of gesture tap
    179   // events to the renderer to filter taps immediately after a touchscreen fling
    180   // canceling tap.
    181   scoped_ptr<TouchscreenTapSuppressionController>
    182       touchscreen_tap_suppression_controller_;
    183 
    184   typedef std::deque<GestureEventWithLatencyInfo> GestureEventQueue;
    185 
    186   // Queue of coalesced gesture events not yet sent to the renderer.
    187   GestureEventQueue coalesced_gesture_events_;
    188 
    189   // Tap gesture event currently subject to deferral.
    190   GestureEventWithLatencyInfo deferred_tap_down_event_;
    191 
    192   // Timer to release a previously deferred GestureTapDown event.
    193   base::OneShotTimer<GestureEventFilter> debounce_deferring_timer_;
    194 
    195   // Queue of events that have been deferred for debounce.
    196   GestureEventQueue debouncing_deferral_queue_;
    197 
    198   // Time window in which to defer a GestureTapDown.
    199   int maximum_tap_gap_time_ms_;
    200 
    201   // Time window in which to debounce scroll/fling ends.
    202   // TODO(rjkroege): Make this dynamically configurable.
    203   int debounce_interval_time_ms_;
    204 
    205   DISALLOW_COPY_AND_ASSIGN(GestureEventFilter);
    206 };
    207 
    208 }  // namespace content
    209 
    210 #endif  // CONTENT_BROWSER_RENDERER_HOST_INPUT_GESTURE_EVENT_FILTER_H_
    211