LCOV - code coverage report
Current view: top level - gfx/layers/apz/src - GestureEventListener.h (source / functions) Hit Total Coverage
Test: output.info Lines: 1 1 100.0 %
Date: 2017-07-14 16:53:18 Functions: 1 2 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set sw=2 ts=8 et tw=80 : */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef mozilla_layers_GestureEventListener_h
       8             : #define mozilla_layers_GestureEventListener_h
       9             : 
      10             : #include "InputData.h"                  // for MultiTouchInput, etc
      11             : #include "Units.h"
      12             : #include "mozilla/EventForwards.h"      // for nsEventStatus
      13             : #include "mozilla/RefPtr.h"             // for RefPtr
      14             : #include "nsISupportsImpl.h"
      15             : #include "nsTArray.h"                   // for nsTArray
      16             : 
      17             : namespace mozilla {
      18             : 
      19             : class CancelableRunnable;
      20             : 
      21             : namespace layers {
      22             : 
      23             : class AsyncPanZoomController;
      24             : 
      25             : /**
      26             :  * Platform-non-specific, generalized gesture event listener. This class
      27             :  * intercepts all touches events on their way to AsyncPanZoomController and
      28             :  * determines whether or not they are part of a gesture.
      29             :  *
      30             :  * For example, seeing that two fingers are on the screen means that the user
      31             :  * wants to do a pinch gesture, so we don't forward the touches along to
      32             :  * AsyncPanZoomController since it will think that they are just trying to pan
      33             :  * the screen. Instead, we generate a PinchGestureInput and send that. If the
      34             :  * touch event is not part of a gesture, we just return nsEventStatus_eIgnore
      35             :  * and AsyncPanZoomController is expected to handle it.
      36             :  */
      37             : class GestureEventListener final {
      38             : public:
      39           2 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GestureEventListener)
      40             : 
      41             :   explicit GestureEventListener(AsyncPanZoomController* aAsyncPanZoomController);
      42             : 
      43             :   // --------------------------------------------------------------------------
      44             :   // These methods must only be called on the controller/UI thread.
      45             :   //
      46             : 
      47             :   /**
      48             :    * General input handler for a touch event. If the touch event is not a part
      49             :    * of a gesture, then we pass it along to AsyncPanZoomController. Otherwise,
      50             :    * it gets consumed here and never forwarded along.
      51             :    */
      52             :   nsEventStatus HandleInputEvent(const MultiTouchInput& aEvent);
      53             : 
      54             :   /**
      55             :    * Returns the identifier of the touch in the last touch event processed by
      56             :    * this GestureEventListener. This should only be called when the last touch
      57             :    * event contained only one touch.
      58             :    */
      59             :   int32_t GetLastTouchIdentifier() const;
      60             : 
      61             :   /**
      62             :    * Function used to disable long tap gestures.
      63             :    *
      64             :    * On slow running tests, drags and touch events can be misinterpreted
      65             :    * as a long tap. This allows tests to disable long tap gesture detection.
      66             :    */
      67             :   static void SetLongTapEnabled(bool aLongTapEnabled);
      68             : 
      69             : private:
      70             :   // Private destructor, to discourage deletion outside of Release():
      71             :   ~GestureEventListener();
      72             : 
      73             :   /**
      74             :    * States of GEL finite-state machine.
      75             :    */
      76             :   enum GestureState {
      77             :     // This is the initial and final state of any gesture.
      78             :     // In this state there's no gesture going on, and we don't think we're
      79             :     // about to enter one.
      80             :     // Allowed next states: GESTURE_FIRST_SINGLE_TOUCH_DOWN, GESTURE_MULTI_TOUCH_DOWN.
      81             :     GESTURE_NONE,
      82             : 
      83             :     // A touch start with a single touch point has just happened.
      84             :     // After having gotten into this state we start timers for MAX_TAP_TIME and
      85             :     // gfxPrefs::UiClickHoldContextMenusDelay().
      86             :     // Allowed next states: GESTURE_MULTI_TOUCH_DOWN, GESTURE_NONE,
      87             :     //                      GESTURE_FIRST_SINGLE_TOUCH_UP, GESTURE_LONG_TOUCH_DOWN,
      88             :     //                      GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN.
      89             :     GESTURE_FIRST_SINGLE_TOUCH_DOWN,
      90             : 
      91             :     // While in GESTURE_FIRST_SINGLE_TOUCH_DOWN state a MAX_TAP_TIME timer got
      92             :     // triggered. Now we'll trigger either a single tap if a user lifts her
      93             :     // finger or a long tap if gfxPrefs::UiClickHoldContextMenusDelay() happens
      94             :     // first.
      95             :     // Allowed next states: GESTURE_MULTI_TOUCH_DOWN, GESTURE_NONE,
      96             :     //                      GESTURE_LONG_TOUCH_DOWN.
      97             :     GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN,
      98             : 
      99             :     // A user put her finger down and lifted it up quickly enough.
     100             :     // After having gotten into this state we clear the timer for MAX_TAP_TIME.
     101             :     // Allowed next states: GESTURE_SECOND_SINGLE_TOUCH_DOWN, GESTURE_NONE,
     102             :     //                      GESTURE_MULTI_TOUCH_DOWN.
     103             :     GESTURE_FIRST_SINGLE_TOUCH_UP,
     104             : 
     105             :     // A user put down her finger again right after a single tap thus the
     106             :     // gesture can't be a single tap, but rather a double tap. But we're
     107             :     // still not sure about that until the user lifts her finger again.
     108             :     // Allowed next states: GESTURE_MULTI_TOUCH_DOWN, GESTURE_ONE_TOUCH_PINCH,
     109             :     //                      GESTURE_NONE.
     110             :     GESTURE_SECOND_SINGLE_TOUCH_DOWN,
     111             : 
     112             :     // A long touch has happened, but the user still keeps her finger down.
     113             :     // We'll trigger a "long tap up" event when the finger is up.
     114             :     // Allowed next states: GESTURE_NONE, GESTURE_MULTI_TOUCH_DOWN.
     115             :     GESTURE_LONG_TOUCH_DOWN,
     116             : 
     117             :     // We have detected that two or more fingers are on the screen, but there
     118             :     // hasn't been enough movement yet to make us start actually zooming the
     119             :     // screen.
     120             :     // Allowed next states: GESTURE_PINCH, GESTURE_NONE
     121             :     GESTURE_MULTI_TOUCH_DOWN,
     122             : 
     123             :     // There are two or more fingers on the screen, and the user has already
     124             :     // pinched enough for us to start zooming the screen.
     125             :     // Allowed next states: GESTURE_NONE
     126             :     GESTURE_PINCH,
     127             : 
     128             :     // The user has double tapped, but not lifted her finger, and moved her
     129             :     // finger more than PINCH_START_THRESHOLD.
     130             :     // Allowed next states: GESTURE_NONE.
     131             :     GESTURE_ONE_TOUCH_PINCH
     132             :   };
     133             : 
     134             :   /**
     135             :    * These HandleInput* functions comprise input alphabet of the GEL
     136             :    * finite-state machine triggering state transitions.
     137             :    */
     138             :   nsEventStatus HandleInputTouchSingleStart();
     139             :   nsEventStatus HandleInputTouchMultiStart();
     140             :   nsEventStatus HandleInputTouchEnd();
     141             :   nsEventStatus HandleInputTouchMove();
     142             :   nsEventStatus HandleInputTouchCancel();
     143             :   void HandleInputTimeoutLongTap();
     144             :   void HandleInputTimeoutMaxTap(bool aDuringFastFling);
     145             : 
     146             :   void TriggerSingleTapConfirmedEvent();
     147             : 
     148             :   bool MoveDistanceIsLarge();
     149             : 
     150             :   /**
     151             :    * Returns current vertical span, counting from the where the user first put
     152             :    * her finger down.
     153             :    */
     154             :   ParentLayerCoord GetYSpanFromStartPoint();
     155             : 
     156             :   /**
     157             :    * Do actual state transition and reset substates.
     158             :    */
     159             :   void SetState(GestureState aState);
     160             : 
     161             :   RefPtr<AsyncPanZoomController> mAsyncPanZoomController;
     162             : 
     163             :   /**
     164             :    * Array containing all active touches. When a touch happens it, gets added to
     165             :    * this array, even if we choose not to handle it. When it ends, we remove it.
     166             :    * We need to maintain this array in order to detect the end of the
     167             :    * "multitouch" states because touch start events contain all current touches,
     168             :    * but touch end events contain only those touches that have gone.
     169             :    */
     170             :   nsTArray<SingleTouchData> mTouches;
     171             : 
     172             :   /**
     173             :    * Current state we're dealing with.
     174             :    */
     175             :   GestureState mState;
     176             : 
     177             :   /**
     178             :    * Total change in span since we detected a pinch gesture. Only used when we
     179             :    * are in the |GESTURE_WAITING_PINCH| state and need to know how far zoomed
     180             :    * out we are compared to our original pinch span. Note that this does _not_
     181             :    * continue to be updated once we jump into the |GESTURE_PINCH| state.
     182             :    */
     183             :   ParentLayerCoord mSpanChange;
     184             : 
     185             :   /**
     186             :    * Previous span calculated for the purposes of setting inside a
     187             :    * PinchGestureInput.
     188             :    */
     189             :   ParentLayerCoord mPreviousSpan;
     190             : 
     191             :   /* Properties similar to mSpanChange and mPreviousSpan, but for the focus */
     192             :   ParentLayerCoord mFocusChange;
     193             :   ParentLayerPoint mPreviousFocus;
     194             : 
     195             :   /**
     196             :    * Cached copy of the last touch input.
     197             :    */
     198             :   MultiTouchInput mLastTouchInput;
     199             : 
     200             :   /**
     201             :    * Cached copy of the last tap gesture input.
     202             :    * In the situation when we have a tap followed by a pinch we lose info
     203             :    * about tap since we keep only last input and to dispatch it correctly
     204             :    * we save last tap copy into this variable.
     205             :    * For more info see bug 947892.
     206             :    */
     207             :   MultiTouchInput mLastTapInput;
     208             : 
     209             :   /**
     210             :    * Position of the last touch starting. This is only valid during an attempt
     211             :    * to determine if a touch is a tap. If a touch point moves away from
     212             :    * mTouchStartPosition to the distance greater than
     213             :    * AsyncPanZoomController::GetTouchStartTolerance() while in
     214             :    * GESTURE_FIRST_SINGLE_TOUCH_DOWN, GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN
     215             :    * or GESTURE_SECOND_SINGLE_TOUCH_DOWN then we're certain the gesture is
     216             :    * not tap.
     217             :    */
     218             :   ParentLayerPoint mTouchStartPosition;
     219             : 
     220             :   /**
     221             :    * Task used to timeout a long tap. This gets posted to the UI thread such
     222             :    * that it runs a time when a single tap happens. We cache it so that
     223             :    * we can cancel it if any other touch event happens.
     224             :    *
     225             :    * The task is supposed to be non-null if in GESTURE_FIRST_SINGLE_TOUCH_DOWN
     226             :    * and GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN states.
     227             :    *
     228             :    * CancelLongTapTimeoutTask: Cancel the mLongTapTimeoutTask and also set
     229             :    * it to null.
     230             :    */
     231             :   RefPtr<CancelableRunnable> mLongTapTimeoutTask;
     232             :   void CancelLongTapTimeoutTask();
     233             :   void CreateLongTapTimeoutTask();
     234             : 
     235             :   /**
     236             :    * Task used to timeout a single tap or a double tap.
     237             :    *
     238             :    * The task is supposed to be non-null if in GESTURE_FIRST_SINGLE_TOUCH_DOWN,
     239             :    * GESTURE_FIRST_SINGLE_TOUCH_UP and GESTURE_SECOND_SINGLE_TOUCH_DOWN states.
     240             :    *
     241             :    * CancelMaxTapTimeoutTask: Cancel the mMaxTapTimeoutTask and also set
     242             :    * it to null.
     243             :    */
     244             :   RefPtr<CancelableRunnable> mMaxTapTimeoutTask;
     245             :   void CancelMaxTapTimeoutTask();
     246             :   void CreateMaxTapTimeoutTask();
     247             : 
     248             :   /**
     249             :    * Tracks whether the single-tap event was already sent to content. This is
     250             :    * needed because it affects how the double-tap gesture, if detected, is
     251             :    * handled. The value is only valid in states GESTURE_FIRST_SINGLE_TOUCH_UP and
     252             :    * GESTURE_SECOND_SINGLE_TOUCH_DOWN; to more easily catch violations it is
     253             :    * stored in a Maybe which is set to Nothing() at all other times.
     254             :    */
     255             :   Maybe<bool> mSingleTapSent;
     256             : };
     257             : 
     258             : } // namespace layers
     259             : } // namespace mozilla
     260             : 
     261             : #endif

Generated by: LCOV version 1.13