LCOV - code coverage report
Current view: top level - gfx/layers/apz/src - GestureEventListener.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 3 302 1.0 %
Date: 2017-07-14 16:53:18 Functions: 1 23 4.3 %
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             : #include "GestureEventListener.h"
       8             : #include <math.h>                       // for fabsf
       9             : #include <stddef.h>                     // for size_t
      10             : #include "AsyncPanZoomController.h"     // for AsyncPanZoomController
      11             : #include "InputBlockState.h"            // for TouchBlockState
      12             : #include "base/task.h"                  // for CancelableTask, etc
      13             : #include "gfxPrefs.h"                   // for gfxPrefs
      14             : #include "InputBlockState.h"            // for TouchBlockState
      15             : #include "mozilla/SizePrintfMacros.h"   // for PRIuSIZE
      16             : #include "nsDebug.h"                    // for NS_WARNING
      17             : #include "nsMathUtils.h"                // for NS_hypot
      18             : 
      19             : #define GEL_LOG(...)
      20             : // #define GEL_LOG(...) printf_stderr("GEL: " __VA_ARGS__)
      21             : 
      22             : namespace mozilla {
      23             : namespace layers {
      24             : 
      25             : /**
      26             :  * Maximum time for a touch on the screen and corresponding lift of the finger
      27             :  * to be considered a tap. This also applies to double taps, except that it is
      28             :  * used twice.
      29             :  */
      30             : static const uint32_t MAX_TAP_TIME = 300;
      31             : 
      32             : /**
      33             :  * Amount of span or focus change needed to take us from the GESTURE_WAITING_PINCH
      34             :  * state to the GESTURE_PINCH state. This is measured as either a change in distance
      35             :  * between the fingers used to compute the span ratio, or the a change in
      36             :  * position of the focus point between the two fingers.
      37             :  */
      38             : static const float PINCH_START_THRESHOLD = 35.0f;
      39             : 
      40             : /**
      41             :  * Determines how fast a one touch pinch zooms in and out. The greater the
      42             :  * value, the faster it zooms.
      43             :  */
      44             : static const float ONE_TOUCH_PINCH_SPEED = 0.005f;
      45             : 
      46             : static bool sLongTapEnabled = true;
      47             : 
      48           0 : ParentLayerPoint GetCurrentFocus(const MultiTouchInput& aEvent)
      49             : {
      50           0 :   const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint;
      51           0 :   const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint;
      52           0 :   return (firstTouch + secondTouch) / 2;
      53             : }
      54             : 
      55           0 : ParentLayerCoord GetCurrentSpan(const MultiTouchInput& aEvent)
      56             : {
      57           0 :   const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint;
      58           0 :   const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint;
      59           0 :   ParentLayerPoint delta = secondTouch - firstTouch;
      60           0 :   return delta.Length();
      61             : }
      62             : 
      63           0 : ParentLayerCoord GestureEventListener::GetYSpanFromStartPoint()
      64             : {
      65           0 :   const ParentLayerPoint start = mTouchStartPosition;
      66           0 :   const ParentLayerPoint& current = mTouches[0].mLocalScreenPoint;
      67           0 :   return current.y - start.y;
      68             : }
      69             : 
      70           0 : TapGestureInput CreateTapEvent(const MultiTouchInput& aTouch, TapGestureInput::TapGestureType aType)
      71             : {
      72             :   return TapGestureInput(aType,
      73           0 :                          aTouch.mTime,
      74             :                          aTouch.mTimeStamp,
      75           0 :                          aTouch.mTouches[0].mScreenPoint,
      76           0 :                          aTouch.modifiers);
      77             : }
      78             : 
      79           2 : GestureEventListener::GestureEventListener(AsyncPanZoomController* aAsyncPanZoomController)
      80             :   : mAsyncPanZoomController(aAsyncPanZoomController),
      81             :     mState(GESTURE_NONE),
      82             :     mSpanChange(0.0f),
      83             :     mPreviousSpan(0.0f),
      84             :     mFocusChange(0.0f),
      85             :     mLastTouchInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0),
      86             :     mLastTapInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0),
      87             :     mLongTapTimeoutTask(nullptr),
      88           2 :     mMaxTapTimeoutTask(nullptr)
      89             : {
      90           2 : }
      91             : 
      92           0 : GestureEventListener::~GestureEventListener()
      93             : {
      94           0 : }
      95             : 
      96           0 : nsEventStatus GestureEventListener::HandleInputEvent(const MultiTouchInput& aEvent)
      97             : {
      98             :   GEL_LOG("Receiving event type %d with %" PRIuSIZE " touches in state %d\n", aEvent.mType, aEvent.mTouches.Length(), mState);
      99             : 
     100           0 :   nsEventStatus rv = nsEventStatus_eIgnore;
     101             : 
     102             :   // Cache the current event since it may become the single or long tap that we
     103             :   // send.
     104           0 :   mLastTouchInput = aEvent;
     105             : 
     106           0 :   switch (aEvent.mType) {
     107             :   case MultiTouchInput::MULTITOUCH_START:
     108           0 :     mTouches.Clear();
     109             :     // Cache every touch.
     110           0 :     for (size_t i = 0; i < aEvent.mTouches.Length(); i++) {
     111           0 :       mTouches.AppendElement(aEvent.mTouches[i]);
     112             :     }
     113             : 
     114           0 :     if (aEvent.mTouches.Length() == 1) {
     115           0 :       rv = HandleInputTouchSingleStart();
     116             :     } else {
     117           0 :       rv = HandleInputTouchMultiStart();
     118             :     }
     119           0 :     break;
     120             :   case MultiTouchInput::MULTITOUCH_MOVE:
     121             :     // Update the screen points of the cached touches.
     122           0 :     for (size_t i = 0; i < aEvent.mTouches.Length(); i++) {
     123           0 :       for (size_t j = 0; j < mTouches.Length(); j++) {
     124           0 :         if (aEvent.mTouches[i].mIdentifier == mTouches[j].mIdentifier) {
     125           0 :           mTouches[j].mScreenPoint = aEvent.mTouches[i].mScreenPoint;
     126           0 :           mTouches[j].mLocalScreenPoint = aEvent.mTouches[i].mLocalScreenPoint;
     127             :         }
     128             :       }
     129             :     }
     130           0 :     rv = HandleInputTouchMove();
     131           0 :     break;
     132             :   case MultiTouchInput::MULTITOUCH_END:
     133             :     // Remove the cache of the touch that ended.
     134           0 :     for (size_t i = 0; i < aEvent.mTouches.Length(); i++) {
     135           0 :       for (size_t j = 0; j < mTouches.Length(); j++) {
     136           0 :         if (aEvent.mTouches[i].mIdentifier == mTouches[j].mIdentifier) {
     137           0 :           mTouches.RemoveElementAt(j);
     138           0 :           break;
     139             :         }
     140             :       }
     141             :     }
     142             : 
     143           0 :     rv = HandleInputTouchEnd();
     144           0 :     break;
     145             :   case MultiTouchInput::MULTITOUCH_CANCEL:
     146           0 :     mTouches.Clear();
     147           0 :     rv = HandleInputTouchCancel();
     148           0 :     break;
     149             :   }
     150             : 
     151           0 :   return rv;
     152             : }
     153             : 
     154           0 : int32_t GestureEventListener::GetLastTouchIdentifier() const
     155             : {
     156           0 :   if (mTouches.Length() != 1) {
     157             :     NS_WARNING("GetLastTouchIdentifier() called when last touch event "
     158           0 :                "did not have one touch");
     159             :   }
     160           0 :   return mTouches.IsEmpty() ? -1 : mTouches[0].mIdentifier;
     161             : }
     162             : 
     163             : /* static */
     164           0 : void GestureEventListener::SetLongTapEnabled(bool aLongTapEnabled)
     165             : {
     166           0 :   sLongTapEnabled = aLongTapEnabled;
     167           0 : }
     168             : 
     169           0 : nsEventStatus GestureEventListener::HandleInputTouchSingleStart()
     170             : {
     171           0 :   switch (mState) {
     172             :   case GESTURE_NONE:
     173           0 :     SetState(GESTURE_FIRST_SINGLE_TOUCH_DOWN);
     174           0 :     mTouchStartPosition = mLastTouchInput.mTouches[0].mLocalScreenPoint;
     175             : 
     176           0 :     if (sLongTapEnabled) {
     177           0 :       CreateLongTapTimeoutTask();
     178             :     }
     179           0 :     CreateMaxTapTimeoutTask();
     180           0 :     break;
     181             :   case GESTURE_FIRST_SINGLE_TOUCH_UP:
     182           0 :     SetState(GESTURE_SECOND_SINGLE_TOUCH_DOWN);
     183           0 :     break;
     184             :   default:
     185           0 :     NS_WARNING("Unhandled state upon single touch start");
     186           0 :     SetState(GESTURE_NONE);
     187           0 :     break;
     188             :   }
     189             : 
     190           0 :   return nsEventStatus_eIgnore;
     191             : }
     192             : 
     193           0 : nsEventStatus GestureEventListener::HandleInputTouchMultiStart()
     194             : {
     195           0 :   nsEventStatus rv = nsEventStatus_eIgnore;
     196             : 
     197           0 :   switch (mState) {
     198             :   case GESTURE_NONE:
     199           0 :     SetState(GESTURE_MULTI_TOUCH_DOWN);
     200           0 :     break;
     201             :   case GESTURE_FIRST_SINGLE_TOUCH_DOWN:
     202           0 :     CancelLongTapTimeoutTask();
     203           0 :     CancelMaxTapTimeoutTask();
     204           0 :     SetState(GESTURE_MULTI_TOUCH_DOWN);
     205             :     // Prevent APZC::OnTouchStart() from handling MULTITOUCH_START event
     206           0 :     rv = nsEventStatus_eConsumeNoDefault;
     207           0 :     break;
     208             :   case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN:
     209           0 :     CancelLongTapTimeoutTask();
     210           0 :     SetState(GESTURE_MULTI_TOUCH_DOWN);
     211             :     // Prevent APZC::OnTouchStart() from handling MULTITOUCH_START event
     212           0 :     rv = nsEventStatus_eConsumeNoDefault;
     213           0 :     break;
     214             :   case GESTURE_FIRST_SINGLE_TOUCH_UP:
     215             :   case GESTURE_SECOND_SINGLE_TOUCH_DOWN:
     216             :     // Cancel wait for double tap
     217           0 :     CancelMaxTapTimeoutTask();
     218           0 :     MOZ_ASSERT(mSingleTapSent.isSome());
     219           0 :     if (!mSingleTapSent.value()) {
     220           0 :       TriggerSingleTapConfirmedEvent();
     221             :     }
     222           0 :     mSingleTapSent = Nothing();
     223           0 :     SetState(GESTURE_MULTI_TOUCH_DOWN);
     224             :     // Prevent APZC::OnTouchStart() from handling MULTITOUCH_START event
     225           0 :     rv = nsEventStatus_eConsumeNoDefault;
     226           0 :     break;
     227             :   case GESTURE_LONG_TOUCH_DOWN:
     228           0 :     SetState(GESTURE_MULTI_TOUCH_DOWN);
     229           0 :     break;
     230             :   case GESTURE_MULTI_TOUCH_DOWN:
     231             :   case GESTURE_PINCH:
     232             :     // Prevent APZC::OnTouchStart() from handling MULTITOUCH_START event
     233           0 :     rv = nsEventStatus_eConsumeNoDefault;
     234           0 :     break;
     235             :   default:
     236           0 :     NS_WARNING("Unhandled state upon multitouch start");
     237           0 :     SetState(GESTURE_NONE);
     238           0 :     break;
     239             :   }
     240             : 
     241           0 :   return rv;
     242             : }
     243             : 
     244           0 : bool GestureEventListener::MoveDistanceIsLarge()
     245             : {
     246           0 :   const ParentLayerPoint start = mLastTouchInput.mTouches[0].mLocalScreenPoint;
     247           0 :   ParentLayerPoint delta = start - mTouchStartPosition;
     248           0 :   ScreenPoint screenDelta = mAsyncPanZoomController->ToScreenCoordinates(delta, start);
     249           0 :   return (screenDelta.Length() > AsyncPanZoomController::GetTouchStartTolerance());
     250             : }
     251             : 
     252           0 : nsEventStatus GestureEventListener::HandleInputTouchMove()
     253             : {
     254           0 :   nsEventStatus rv = nsEventStatus_eIgnore;
     255             : 
     256           0 :   switch (mState) {
     257             :   case GESTURE_NONE:
     258             :     // Ignore this input signal as the corresponding events get handled by APZC
     259           0 :     break;
     260             : 
     261             :   case GESTURE_LONG_TOUCH_DOWN:
     262           0 :     if (MoveDistanceIsLarge()) {
     263             :       // So that we don't fire a long-tap-up if the user moves around after a
     264             :       // long-tap
     265           0 :       SetState(GESTURE_NONE);
     266             :     }
     267           0 :     break;
     268             : 
     269             :   case GESTURE_FIRST_SINGLE_TOUCH_DOWN:
     270             :   case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN: {
     271             :     // If we move too much, bail out of the tap.
     272           0 :     if (MoveDistanceIsLarge()) {
     273           0 :       CancelLongTapTimeoutTask();
     274           0 :       CancelMaxTapTimeoutTask();
     275           0 :       mSingleTapSent = Nothing();
     276           0 :       SetState(GESTURE_NONE);
     277             :     }
     278           0 :     break;
     279             :   }
     280             : 
     281             :   // The user has performed a double tap, but not lifted her finger.
     282             :   case GESTURE_SECOND_SINGLE_TOUCH_DOWN: {
     283             :     // If touch has moved noticeably (within MAX_TAP_TIME), change state.
     284           0 :     if (MoveDistanceIsLarge()) {
     285           0 :       CancelLongTapTimeoutTask();
     286           0 :       CancelMaxTapTimeoutTask();
     287           0 :       mSingleTapSent = Nothing();
     288           0 :       if (!gfxPrefs::APZOneTouchPinchEnabled()) {
     289             :         // If the one-touch-pinch feature is disabled, bail out of the double-
     290             :         // tap gesture instead.
     291           0 :         SetState(GESTURE_NONE);
     292           0 :         break;
     293             :       }
     294             : 
     295           0 :       SetState(GESTURE_ONE_TOUCH_PINCH);
     296             : 
     297           0 :       ParentLayerCoord currentSpan = 1.0f;
     298           0 :       ParentLayerPoint currentFocus = mTouchStartPosition;
     299             : 
     300             :       PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_START,
     301             :                                    mLastTouchInput.mTime,
     302             :                                    mLastTouchInput.mTimeStamp,
     303             :                                    currentFocus,
     304             :                                    currentSpan,
     305             :                                    currentSpan,
     306           0 :                                    mLastTouchInput.modifiers);
     307             : 
     308           0 :       rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
     309             : 
     310           0 :       mPreviousSpan = currentSpan;
     311           0 :       mPreviousFocus = currentFocus;
     312             :     }
     313           0 :     break;
     314             :   }
     315             : 
     316             :   case GESTURE_MULTI_TOUCH_DOWN: {
     317           0 :     if (mLastTouchInput.mTouches.Length() < 2) {
     318           0 :       NS_WARNING("Wrong input: less than 2 moving points in GESTURE_MULTI_TOUCH_DOWN state");
     319           0 :       break;
     320             :     }
     321             : 
     322           0 :     ParentLayerCoord currentSpan = GetCurrentSpan(mLastTouchInput);
     323           0 :     ParentLayerPoint currentFocus = GetCurrentFocus(mLastTouchInput);
     324             : 
     325           0 :     mSpanChange += fabsf(currentSpan - mPreviousSpan);
     326           0 :     mFocusChange += (currentFocus - mPreviousFocus).Length();
     327           0 :     if (mSpanChange > PINCH_START_THRESHOLD ||
     328           0 :         mFocusChange > PINCH_START_THRESHOLD) {
     329           0 :       SetState(GESTURE_PINCH);
     330             :       PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_START,
     331             :                                    mLastTouchInput.mTime,
     332             :                                    mLastTouchInput.mTimeStamp,
     333             :                                    currentFocus,
     334             :                                    currentSpan,
     335             :                                    currentSpan,
     336           0 :                                    mLastTouchInput.modifiers);
     337             : 
     338           0 :       rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
     339             :     } else {
     340             :       // Prevent APZC::OnTouchMove from processing a move event when two
     341             :       // touches are active
     342           0 :       rv = nsEventStatus_eConsumeNoDefault;
     343             :     }
     344             : 
     345           0 :     mPreviousSpan = currentSpan;
     346           0 :     mPreviousFocus = currentFocus;
     347           0 :     break;
     348             :   }
     349             : 
     350             :   case GESTURE_PINCH: {
     351           0 :     if (mLastTouchInput.mTouches.Length() < 2) {
     352           0 :       NS_WARNING("Wrong input: less than 2 moving points in GESTURE_PINCH state");
     353             :       // Prevent APZC::OnTouchMove() from handling this wrong input
     354           0 :       rv = nsEventStatus_eConsumeNoDefault;
     355           0 :       break;
     356             :     }
     357             : 
     358           0 :     ParentLayerCoord currentSpan = GetCurrentSpan(mLastTouchInput);
     359             : 
     360             :     PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_SCALE,
     361             :                                  mLastTouchInput.mTime,
     362             :                                  mLastTouchInput.mTimeStamp,
     363           0 :                                  GetCurrentFocus(mLastTouchInput),
     364             :                                  currentSpan,
     365             :                                  mPreviousSpan,
     366           0 :                                  mLastTouchInput.modifiers);
     367             : 
     368           0 :     rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
     369           0 :     mPreviousSpan = currentSpan;
     370             : 
     371           0 :     break;
     372             :   }
     373             : 
     374             :   case GESTURE_ONE_TOUCH_PINCH: {
     375           0 :     ParentLayerCoord currentSpan = GetYSpanFromStartPoint();
     376           0 :     float effectiveSpan = 1.0f + (fabsf(currentSpan.value) * ONE_TOUCH_PINCH_SPEED);
     377           0 :     ParentLayerPoint currentFocus = mTouchStartPosition;
     378             : 
     379             :     // Invert zoom.
     380           0 :     if (currentSpan.value < 0) {
     381           0 :       effectiveSpan = 1.0f / effectiveSpan;
     382             :     }
     383             : 
     384             :     PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_SCALE,
     385             :                                  mLastTouchInput.mTime,
     386             :                                  mLastTouchInput.mTimeStamp,
     387             :                                  currentFocus,
     388             :                                  effectiveSpan,
     389             :                                  mPreviousSpan,
     390           0 :                                  mLastTouchInput.modifiers);
     391             : 
     392           0 :     rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
     393           0 :     mPreviousSpan = effectiveSpan;
     394             : 
     395           0 :     break;
     396             :   }
     397             : 
     398             :   default:
     399           0 :     NS_WARNING("Unhandled state upon touch move");
     400           0 :     SetState(GESTURE_NONE);
     401           0 :     break;
     402             :   }
     403             : 
     404           0 :   return rv;
     405             : }
     406             : 
     407           0 : nsEventStatus GestureEventListener::HandleInputTouchEnd()
     408             : {
     409             :   // We intentionally do not pass apzc return statuses up since
     410             :   // it may cause apzc stay in the touching state even after
     411             :   // gestures are completed (please see Bug 1013378 for reference).
     412             : 
     413           0 :   nsEventStatus rv = nsEventStatus_eIgnore;
     414             : 
     415           0 :   switch (mState) {
     416             :   case GESTURE_NONE:
     417             :     // GEL doesn't have a dedicated state for PANNING handled in APZC thus ignore.
     418           0 :     break;
     419             : 
     420             :   case GESTURE_FIRST_SINGLE_TOUCH_DOWN: {
     421           0 :     CancelLongTapTimeoutTask();
     422           0 :     CancelMaxTapTimeoutTask();
     423           0 :     nsEventStatus tapupStatus = mAsyncPanZoomController->HandleGestureEvent(
     424           0 :         CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_UP));
     425           0 :     mSingleTapSent = Some(tapupStatus != nsEventStatus_eIgnore);
     426           0 :     SetState(GESTURE_FIRST_SINGLE_TOUCH_UP);
     427           0 :     CreateMaxTapTimeoutTask();
     428           0 :     break;
     429             :   }
     430             : 
     431             :   case GESTURE_SECOND_SINGLE_TOUCH_DOWN: {
     432           0 :     CancelMaxTapTimeoutTask();
     433           0 :     MOZ_ASSERT(mSingleTapSent.isSome());
     434           0 :     mAsyncPanZoomController->HandleGestureEvent(
     435           0 :         CreateTapEvent(mLastTouchInput,
     436           0 :             mSingleTapSent.value() ? TapGestureInput::TAPGESTURE_SECOND
     437           0 :                                    : TapGestureInput::TAPGESTURE_DOUBLE));
     438           0 :     mSingleTapSent = Nothing();
     439           0 :     SetState(GESTURE_NONE);
     440           0 :     break;
     441             :   }
     442             : 
     443             :   case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN:
     444           0 :     CancelLongTapTimeoutTask();
     445           0 :     SetState(GESTURE_NONE);
     446           0 :     TriggerSingleTapConfirmedEvent();
     447           0 :     break;
     448             : 
     449             :   case GESTURE_LONG_TOUCH_DOWN: {
     450           0 :     SetState(GESTURE_NONE);
     451           0 :     mAsyncPanZoomController->HandleGestureEvent(
     452           0 :         CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_LONG_UP));
     453           0 :     break;
     454             :   }
     455             : 
     456             :   case GESTURE_MULTI_TOUCH_DOWN:
     457           0 :     if (mTouches.Length() < 2) {
     458           0 :       SetState(GESTURE_NONE);
     459             :     }
     460           0 :     break;
     461             : 
     462             :   case GESTURE_PINCH:
     463           0 :     if (mTouches.Length() < 2) {
     464           0 :       SetState(GESTURE_NONE);
     465           0 :       ParentLayerPoint point(-1, -1);
     466           0 :       if (mTouches.Length() == 1) {
     467             :         // As user still keeps one finger down the event's focus point should
     468             :         // contain meaningful data.
     469           0 :         point = mTouches[0].mLocalScreenPoint;
     470             :       }
     471             :       PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END,
     472             :                                    mLastTouchInput.mTime,
     473             :                                    mLastTouchInput.mTimeStamp,
     474             :                                    point,
     475             :                                    1.0f,
     476             :                                    1.0f,
     477           0 :                                    mLastTouchInput.modifiers);
     478           0 :       mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
     479             :     }
     480             : 
     481           0 :     rv = nsEventStatus_eConsumeNoDefault;
     482             : 
     483           0 :     break;
     484             : 
     485             :   case GESTURE_ONE_TOUCH_PINCH: {
     486           0 :     SetState(GESTURE_NONE);
     487           0 :     ParentLayerPoint point(-1, -1);
     488             :     PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END,
     489             :                                  mLastTouchInput.mTime,
     490             :                                  mLastTouchInput.mTimeStamp,
     491             :                                  point,
     492             :                                  1.0f,
     493             :                                  1.0f,
     494           0 :                                  mLastTouchInput.modifiers);
     495           0 :     mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
     496             : 
     497           0 :     rv = nsEventStatus_eConsumeNoDefault;
     498             : 
     499           0 :     break;
     500             :   }
     501             : 
     502             :   default:
     503           0 :     NS_WARNING("Unhandled state upon touch end");
     504           0 :     SetState(GESTURE_NONE);
     505           0 :     break;
     506             :   }
     507             : 
     508           0 :   return rv;
     509             : }
     510             : 
     511           0 : nsEventStatus GestureEventListener::HandleInputTouchCancel()
     512             : {
     513           0 :   mSingleTapSent = Nothing();
     514           0 :   SetState(GESTURE_NONE);
     515           0 :   CancelMaxTapTimeoutTask();
     516           0 :   CancelLongTapTimeoutTask();
     517           0 :   return nsEventStatus_eIgnore;
     518             : }
     519             : 
     520           0 : void GestureEventListener::HandleInputTimeoutLongTap()
     521             : {
     522             :   GEL_LOG("Running long-tap timeout task in state %d\n", mState);
     523             : 
     524           0 :   mLongTapTimeoutTask = nullptr;
     525             : 
     526           0 :   switch (mState) {
     527             :   case GESTURE_FIRST_SINGLE_TOUCH_DOWN:
     528             :     // just in case MAX_TAP_TIME > ContextMenuDelay cancel MAX_TAP timer
     529             :     // and fall through
     530           0 :     CancelMaxTapTimeoutTask();
     531             :     MOZ_FALLTHROUGH;
     532             :   case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN: {
     533           0 :     SetState(GESTURE_LONG_TOUCH_DOWN);
     534           0 :     mAsyncPanZoomController->HandleGestureEvent(
     535           0 :         CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_LONG));
     536           0 :     break;
     537             :   }
     538             :   default:
     539           0 :     NS_WARNING("Unhandled state upon long tap timeout");
     540           0 :     SetState(GESTURE_NONE);
     541           0 :     break;
     542             :   }
     543           0 : }
     544             : 
     545           0 : void GestureEventListener::HandleInputTimeoutMaxTap(bool aDuringFastFling)
     546             : {
     547             :   GEL_LOG("Running max-tap timeout task in state %d\n", mState);
     548             : 
     549           0 :   mMaxTapTimeoutTask = nullptr;
     550             : 
     551           0 :   if (mState == GESTURE_FIRST_SINGLE_TOUCH_DOWN) {
     552           0 :     SetState(GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN);
     553           0 :   } else if (mState == GESTURE_FIRST_SINGLE_TOUCH_UP ||
     554           0 :              mState == GESTURE_SECOND_SINGLE_TOUCH_DOWN) {
     555           0 :     MOZ_ASSERT(mSingleTapSent.isSome());
     556           0 :     if (!aDuringFastFling && !mSingleTapSent.value()) {
     557           0 :       TriggerSingleTapConfirmedEvent();
     558             :     }
     559           0 :     mSingleTapSent = Nothing();
     560           0 :     SetState(GESTURE_NONE);
     561             :   } else {
     562           0 :     NS_WARNING("Unhandled state upon MAX_TAP timeout");
     563           0 :     SetState(GESTURE_NONE);
     564             :   }
     565           0 : }
     566             : 
     567           0 : void GestureEventListener::TriggerSingleTapConfirmedEvent()
     568             : {
     569           0 :   mAsyncPanZoomController->HandleGestureEvent(
     570           0 :       CreateTapEvent(mLastTapInput, TapGestureInput::TAPGESTURE_CONFIRMED));
     571           0 : }
     572             : 
     573           0 : void GestureEventListener::SetState(GestureState aState)
     574             : {
     575           0 :   mState = aState;
     576             : 
     577           0 :   if (mState == GESTURE_NONE) {
     578           0 :     mSpanChange = 0.0f;
     579           0 :     mPreviousSpan = 0.0f;
     580           0 :     mFocusChange = 0.0f;
     581           0 :   } else if (mState == GESTURE_MULTI_TOUCH_DOWN) {
     582           0 :     mPreviousSpan = GetCurrentSpan(mLastTouchInput);
     583           0 :     mPreviousFocus = GetCurrentFocus(mLastTouchInput);
     584             :   }
     585           0 : }
     586             : 
     587           0 : void GestureEventListener::CancelLongTapTimeoutTask()
     588             : {
     589           0 :   if (mState == GESTURE_SECOND_SINGLE_TOUCH_DOWN) {
     590             :     // being in this state means the task has been canceled already
     591           0 :     return;
     592             :   }
     593             : 
     594           0 :   if (mLongTapTimeoutTask) {
     595           0 :     mLongTapTimeoutTask->Cancel();
     596           0 :     mLongTapTimeoutTask = nullptr;
     597             :   }
     598             : }
     599             : 
     600           0 : void GestureEventListener::CreateLongTapTimeoutTask()
     601             : {
     602           0 :   RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod(
     603             :     "layers::GestureEventListener::HandleInputTimeoutLongTap",
     604             :     this,
     605           0 :     &GestureEventListener::HandleInputTimeoutLongTap);
     606             : 
     607           0 :   mLongTapTimeoutTask = task;
     608           0 :   mAsyncPanZoomController->PostDelayedTask(
     609           0 :     task.forget(),
     610           0 :     gfxPrefs::UiClickHoldContextMenusDelay());
     611           0 : }
     612             : 
     613           0 : void GestureEventListener::CancelMaxTapTimeoutTask()
     614             : {
     615           0 :   if (mState == GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN) {
     616             :     // being in this state means the timer has just been triggered
     617           0 :     return;
     618             :   }
     619             : 
     620           0 :   if (mMaxTapTimeoutTask) {
     621           0 :     mMaxTapTimeoutTask->Cancel();
     622           0 :     mMaxTapTimeoutTask = nullptr;
     623             :   }
     624             : }
     625             : 
     626           0 : void GestureEventListener::CreateMaxTapTimeoutTask()
     627             : {
     628           0 :   mLastTapInput = mLastTouchInput;
     629             : 
     630           0 :   TouchBlockState* block = mAsyncPanZoomController->GetInputQueue()->GetCurrentTouchBlock();
     631           0 :   MOZ_ASSERT(block);
     632           0 :   RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod<bool>(
     633             :     "layers::GestureEventListener::HandleInputTimeoutMaxTap",
     634             :     this,
     635             :     &GestureEventListener::HandleInputTimeoutMaxTap,
     636           0 :     block->IsDuringFastFling());
     637             : 
     638           0 :   mMaxTapTimeoutTask = task;
     639           0 :   mAsyncPanZoomController->PostDelayedTask(
     640           0 :     task.forget(),
     641           0 :     MAX_TAP_TIME);
     642           0 : }
     643             : 
     644             : } // namespace layers
     645             : } // namespace mozilla

Generated by: LCOV version 1.13