LCOV - code coverage report
Current view: top level - gfx/layers/apz/src - InputBlockState.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 360 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 74 0.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             : #include "InputBlockState.h"
       8             : #include "AsyncPanZoomController.h"         // for AsyncPanZoomController
       9             : #include "AsyncScrollBase.h"                // for kScrollSeriesTimeoutMs
      10             : #include "gfxPrefs.h"                       // for gfxPrefs
      11             : #include "mozilla/MouseEvents.h"
      12             : #include "mozilla/SizePrintfMacros.h"       // for PRIuSIZE
      13             : #include "mozilla/Telemetry.h"              // for Telemetry
      14             : #include "mozilla/layers/APZCTreeManager.h" // for AllowedTouchBehavior
      15             : #include "OverscrollHandoffState.h"
      16             : #include "QueuedInput.h"
      17             : 
      18             : #define TBS_LOG(...)
      19             : // #define TBS_LOG(...) printf_stderr("TBS: " __VA_ARGS__)
      20             : 
      21             : namespace mozilla {
      22             : namespace layers {
      23             : 
      24             : static uint64_t sBlockCounter = InputBlockState::NO_BLOCK_ID + 1;
      25             : 
      26           0 : InputBlockState::InputBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
      27           0 :                                  bool aTargetConfirmed)
      28             :   : mTargetApzc(aTargetApzc)
      29           0 :   , mTargetConfirmed(aTargetConfirmed ? TargetConfirmationState::eConfirmed
      30             :                                       : TargetConfirmationState::eUnconfirmed)
      31           0 :   , mBlockId(sBlockCounter++)
      32           0 :   , mTransformToApzc(aTargetApzc->GetTransformToThis())
      33             : {
      34             :   // We should never be constructed with a nullptr target.
      35           0 :   MOZ_ASSERT(mTargetApzc);
      36           0 :   mOverscrollHandoffChain = mTargetApzc->BuildOverscrollHandoffChain();
      37           0 : }
      38             : 
      39             : bool
      40           0 : InputBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
      41             :                                         TargetConfirmationState aState,
      42             :                                         InputData* aFirstInput)
      43             : {
      44           0 :   MOZ_ASSERT(aState == TargetConfirmationState::eConfirmed
      45             :           || aState == TargetConfirmationState::eTimedOut);
      46             : 
      47           0 :   if (mTargetConfirmed == TargetConfirmationState::eTimedOut &&
      48             :       aState == TargetConfirmationState::eConfirmed) {
      49             :     // The main thread finally responded. We had already timed out the
      50             :     // confirmation, but we want to update the state internally so that we
      51             :     // can record the time for telemetry purposes.
      52           0 :     mTargetConfirmed = TargetConfirmationState::eTimedOutAndMainThreadResponded;
      53             :   }
      54           0 :   if (mTargetConfirmed != TargetConfirmationState::eUnconfirmed) {
      55           0 :     return false;
      56             :   }
      57           0 :   mTargetConfirmed = aState;
      58             : 
      59             :   TBS_LOG("%p got confirmed target APZC %p\n", this, mTargetApzc.get());
      60           0 :   if (mTargetApzc == aTargetApzc) {
      61             :     // The confirmed target is the same as the tentative one, so we're done.
      62           0 :     return true;
      63             :   }
      64             : 
      65             :   TBS_LOG("%p replacing unconfirmed target %p with real target %p\n",
      66             :       this, mTargetApzc.get(), aTargetApzc.get());
      67             : 
      68           0 :   UpdateTargetApzc(aTargetApzc);
      69           0 :   return true;
      70             : }
      71             : 
      72             : void
      73           0 : InputBlockState::UpdateTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc)
      74             : {
      75             :   // note that aTargetApzc MAY be null here.
      76           0 :   mTargetApzc = aTargetApzc;
      77           0 :   mTransformToApzc = aTargetApzc ? aTargetApzc->GetTransformToThis() : ScreenToParentLayerMatrix4x4();
      78           0 :   mOverscrollHandoffChain = (mTargetApzc ? mTargetApzc->BuildOverscrollHandoffChain() : nullptr);
      79           0 : }
      80             : 
      81             : const RefPtr<AsyncPanZoomController>&
      82           0 : InputBlockState::GetTargetApzc() const
      83             : {
      84           0 :   return mTargetApzc;
      85             : }
      86             : 
      87             : const RefPtr<const OverscrollHandoffChain>&
      88           0 : InputBlockState::GetOverscrollHandoffChain() const
      89             : {
      90           0 :   return mOverscrollHandoffChain;
      91             : }
      92             : 
      93             : uint64_t
      94           0 : InputBlockState::GetBlockId() const
      95             : {
      96           0 :   return mBlockId;
      97             : }
      98             : 
      99             : bool
     100           0 : InputBlockState::IsTargetConfirmed() const
     101             : {
     102           0 :   return mTargetConfirmed != TargetConfirmationState::eUnconfirmed;
     103             : }
     104             : 
     105             : bool
     106           0 : InputBlockState::HasReceivedRealConfirmedTarget() const
     107             : {
     108           0 :   return mTargetConfirmed == TargetConfirmationState::eConfirmed ||
     109           0 :          mTargetConfirmed == TargetConfirmationState::eTimedOutAndMainThreadResponded;
     110             : }
     111             : 
     112             : bool
     113           0 : InputBlockState::IsDownchainOf(AsyncPanZoomController* aA, AsyncPanZoomController* aB) const
     114             : {
     115           0 :   if (aA == aB) {
     116           0 :     return true;
     117             :   }
     118             : 
     119           0 :   bool seenA = false;
     120           0 :   for (size_t i = 0; i < mOverscrollHandoffChain->Length(); ++i) {
     121           0 :     AsyncPanZoomController* apzc = mOverscrollHandoffChain->GetApzcAtIndex(i);
     122           0 :     if (apzc == aB) {
     123           0 :       return seenA;
     124             :     }
     125           0 :     if (apzc == aA) {
     126           0 :       seenA = true;
     127             :     }
     128             :   }
     129           0 :   return false;
     130             : }
     131             : 
     132             : 
     133             : void
     134           0 : InputBlockState::SetScrolledApzc(AsyncPanZoomController* aApzc)
     135             : {
     136             :   // An input block should only have one scrolled APZC.
     137           0 :   MOZ_ASSERT(!mScrolledApzc || (gfxPrefs::APZAllowImmediateHandoff() ? IsDownchainOf(mScrolledApzc, aApzc) : mScrolledApzc == aApzc));
     138             : 
     139           0 :   mScrolledApzc = aApzc;
     140           0 : }
     141             : 
     142             : AsyncPanZoomController*
     143           0 : InputBlockState::GetScrolledApzc() const
     144             : {
     145           0 :   return mScrolledApzc;
     146             : }
     147             : 
     148             : bool
     149           0 : InputBlockState::IsDownchainOfScrolledApzc(AsyncPanZoomController* aApzc) const
     150             : {
     151           0 :   MOZ_ASSERT(aApzc && mScrolledApzc);
     152             : 
     153           0 :   return IsDownchainOf(mScrolledApzc, aApzc);
     154             : }
     155             : 
     156             : void
     157           0 : InputBlockState::DispatchEvent(const InputData& aEvent) const
     158             : {
     159           0 :   GetTargetApzc()->HandleInputEvent(aEvent, mTransformToApzc);
     160           0 : }
     161             : 
     162           0 : CancelableBlockState::CancelableBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
     163           0 :                                            bool aTargetConfirmed)
     164             :   : InputBlockState(aTargetApzc, aTargetConfirmed)
     165             :   , mPreventDefault(false)
     166             :   , mContentResponded(false)
     167           0 :   , mContentResponseTimerExpired(false)
     168             : {
     169           0 : }
     170             : 
     171             : bool
     172           0 : CancelableBlockState::SetContentResponse(bool aPreventDefault)
     173             : {
     174           0 :   if (mContentResponded) {
     175           0 :     return false;
     176             :   }
     177             :   TBS_LOG("%p got content response %d with timer expired %d\n",
     178             :     this, aPreventDefault, mContentResponseTimerExpired);
     179           0 :   mPreventDefault = aPreventDefault;
     180           0 :   mContentResponded = true;
     181           0 :   return true;
     182             : }
     183             : 
     184             : void
     185           0 : CancelableBlockState::StartContentResponseTimer()
     186             : {
     187           0 :   MOZ_ASSERT(mContentResponseTimer.IsNull());
     188           0 :   mContentResponseTimer = TimeStamp::Now();
     189           0 : }
     190             : 
     191             : bool
     192           0 : CancelableBlockState::TimeoutContentResponse()
     193             : {
     194           0 :   if (mContentResponseTimerExpired) {
     195           0 :     return false;
     196             :   }
     197             :   TBS_LOG("%p got content timer expired with response received %d\n",
     198             :     this, mContentResponded);
     199           0 :   if (!mContentResponded) {
     200           0 :     mPreventDefault = false;
     201             :   }
     202           0 :   mContentResponseTimerExpired = true;
     203           0 :   return true;
     204             : }
     205             : 
     206             : bool
     207           0 : CancelableBlockState::IsContentResponseTimerExpired() const
     208             : {
     209           0 :   return mContentResponseTimerExpired;
     210             : }
     211             : 
     212             : bool
     213           0 : CancelableBlockState::IsDefaultPrevented() const
     214             : {
     215           0 :   MOZ_ASSERT(mContentResponded || mContentResponseTimerExpired);
     216           0 :   return mPreventDefault;
     217             : }
     218             : 
     219             : bool
     220           0 : CancelableBlockState::HasReceivedAllContentNotifications() const
     221             : {
     222           0 :   return HasReceivedRealConfirmedTarget() && mContentResponded;
     223             : }
     224             : 
     225             : bool
     226           0 : CancelableBlockState::IsReadyForHandling() const
     227             : {
     228           0 :   if (!IsTargetConfirmed()) {
     229           0 :     return false;
     230             :   }
     231           0 :   return mContentResponded || mContentResponseTimerExpired;
     232             : }
     233             : 
     234             : void
     235           0 : CancelableBlockState::RecordContentResponseTime()
     236             : {
     237           0 :   if (!mContentResponseTimer) {
     238             :     // We might get responses from content even though we didn't wait for them.
     239             :     // In that case, ignore the time on them, because they're not relevant for
     240             :     // tuning our timeout value. Also this function might get called multiple
     241             :     // times on the same input block, so we should only record the time from the
     242             :     // first successful call.
     243           0 :     return;
     244             :   }
     245           0 :   if (!HasReceivedAllContentNotifications()) {
     246             :     // Not done yet, we'll get called again
     247           0 :     return;
     248             :   }
     249           0 :   mozilla::Telemetry::Accumulate(mozilla::Telemetry::CONTENT_RESPONSE_DURATION,
     250           0 :     (uint32_t)(TimeStamp::Now() - mContentResponseTimer).ToMilliseconds());
     251           0 :   mContentResponseTimer = TimeStamp();
     252             : }
     253             : 
     254           0 : DragBlockState::DragBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
     255             :                                bool aTargetConfirmed,
     256           0 :                                const MouseInput& aInitialEvent)
     257             :   : CancelableBlockState(aTargetApzc, aTargetConfirmed)
     258           0 :   , mReceivedMouseUp(false)
     259             : {
     260           0 : }
     261             : 
     262             : bool
     263           0 : DragBlockState::HasReceivedMouseUp()
     264             : {
     265           0 :   return mReceivedMouseUp;
     266             : }
     267             : 
     268             : void
     269           0 : DragBlockState::MarkMouseUpReceived()
     270             : {
     271           0 :   mReceivedMouseUp = true;
     272           0 : }
     273             : 
     274             : void
     275           0 : DragBlockState::SetInitialThumbPos(CSSCoord aThumbPos)
     276             : {
     277           0 :   mInitialThumbPos = aThumbPos;
     278           0 : }
     279             : 
     280             : void
     281           0 : DragBlockState::SetDragMetrics(const AsyncDragMetrics& aDragMetrics)
     282             : {
     283           0 :   mDragMetrics = aDragMetrics;
     284           0 : }
     285             : 
     286             : void
     287           0 : DragBlockState::DispatchEvent(const InputData& aEvent) const
     288             : {
     289           0 :   MouseInput mouseInput = aEvent.AsMouseInput();
     290           0 :   if (!mouseInput.TransformToLocal(mTransformToApzc)) {
     291           0 :     return;
     292             :   }
     293             : 
     294           0 :   GetTargetApzc()->HandleDragEvent(mouseInput, mDragMetrics, mInitialThumbPos);
     295             : }
     296             : 
     297             : bool
     298           0 : DragBlockState::MustStayActive()
     299             : {
     300           0 :   return !mReceivedMouseUp;
     301             : }
     302             : 
     303             : const char*
     304           0 : DragBlockState::Type()
     305             : {
     306           0 :   return "drag";
     307             : }
     308             : // This is used to track the current wheel transaction.
     309             : static uint64_t sLastWheelBlockId = InputBlockState::NO_BLOCK_ID;
     310             : 
     311           0 : WheelBlockState::WheelBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
     312             :                                  bool aTargetConfirmed,
     313           0 :                                  const ScrollWheelInput& aInitialEvent)
     314             :   : CancelableBlockState(aTargetApzc, aTargetConfirmed)
     315             :   , mScrollSeriesCounter(0)
     316           0 :   , mTransactionEnded(false)
     317             : {
     318           0 :   sLastWheelBlockId = GetBlockId();
     319             : 
     320           0 :   if (aTargetConfirmed) {
     321             :     // Find the nearest APZC in the overscroll handoff chain that is scrollable.
     322             :     // If we get a content confirmation later that the apzc is different, then
     323             :     // content should have found a scrollable apzc, so we don't need to handle
     324             :     // that case.
     325             :     RefPtr<AsyncPanZoomController> apzc =
     326           0 :       mOverscrollHandoffChain->FindFirstScrollable(aInitialEvent);
     327             : 
     328             :     // If nothing is scrollable, we don't consider this block as starting a
     329             :     // transaction.
     330           0 :     if (!apzc) {
     331           0 :       EndTransaction();
     332           0 :       return;
     333             :     }
     334             : 
     335           0 :     if (apzc != GetTargetApzc()) {
     336           0 :       UpdateTargetApzc(apzc);
     337             :     }
     338             :   }
     339             : }
     340             : 
     341             : bool
     342           0 : WheelBlockState::SetContentResponse(bool aPreventDefault)
     343             : {
     344           0 :   if (aPreventDefault) {
     345           0 :     EndTransaction();
     346             :   }
     347           0 :   return CancelableBlockState::SetContentResponse(aPreventDefault);
     348             : }
     349             : 
     350             : bool
     351           0 : WheelBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
     352             :                                         TargetConfirmationState aState,
     353             :                                         InputData* aFirstInput)
     354             : {
     355             :   // The APZC that we find via APZCCallbackHelpers may not be the same APZC
     356             :   // ESM or OverscrollHandoff would have computed. Make sure we get the right
     357             :   // one by looking for the first apzc the next pending event can scroll.
     358           0 :   RefPtr<AsyncPanZoomController> apzc = aTargetApzc;
     359           0 :   if (apzc && aFirstInput) {
     360           0 :     apzc = apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(*aFirstInput);
     361             :   }
     362             : 
     363           0 :   InputBlockState::SetConfirmedTargetApzc(apzc, aState, aFirstInput);
     364           0 :   return true;
     365             : }
     366             : 
     367             : void
     368           0 : WheelBlockState::Update(ScrollWheelInput& aEvent)
     369             : {
     370             :   // We might not be in a transaction if the block never started in a
     371             :   // transaction - for example, if nothing was scrollable.
     372           0 :   if (!InTransaction()) {
     373           0 :     return;
     374             :   }
     375             : 
     376             :   // The current "scroll series" is a like a sub-transaction. It has a separate
     377             :   // timeout of 80ms. Since we need to compute wheel deltas at different phases
     378             :   // of a transaction (for example, when it is updated, and later when the
     379             :   // event action is taken), we affix the scroll series counter to the event.
     380             :   // This makes GetScrollWheelDelta() consistent.
     381           0 :   if (!mLastEventTime.IsNull() &&
     382           0 :       (aEvent.mTimeStamp - mLastEventTime).ToMilliseconds() > kScrollSeriesTimeoutMs)
     383             :   {
     384           0 :     mScrollSeriesCounter = 0;
     385             :   }
     386           0 :   aEvent.mScrollSeriesNumber = ++mScrollSeriesCounter;
     387             : 
     388             :   // If we can't scroll in the direction of the wheel event, we don't update
     389             :   // the last move time. This allows us to timeout a transaction even if the
     390             :   // mouse isn't moving.
     391             :   //
     392             :   // We skip this check if the target is not yet confirmed, so that when it is
     393             :   // confirmed, we don't timeout the transaction.
     394           0 :   RefPtr<AsyncPanZoomController> apzc = GetTargetApzc();
     395           0 :   if (IsTargetConfirmed() && !apzc->CanScroll(aEvent)) {
     396           0 :     return;
     397             :   }
     398             : 
     399             :   // Update the time of the last known good event, and reset the mouse move
     400             :   // time to null. This will reset the delays on both the general transaction
     401             :   // timeout and the mouse-move-in-frame timeout.
     402           0 :   mLastEventTime = aEvent.mTimeStamp;
     403           0 :   mLastMouseMove = TimeStamp();
     404             : }
     405             : 
     406             : bool
     407           0 : WheelBlockState::MustStayActive()
     408             : {
     409           0 :   return !mTransactionEnded;
     410             : }
     411             : 
     412             : const char*
     413           0 : WheelBlockState::Type()
     414             : {
     415           0 :   return "scroll wheel";
     416             : }
     417             : 
     418             : bool
     419           0 : WheelBlockState::ShouldAcceptNewEvent() const
     420             : {
     421           0 :   if (!InTransaction()) {
     422             :     // If we're not in a transaction, start a new one.
     423           0 :     return false;
     424             :   }
     425             : 
     426           0 :   RefPtr<AsyncPanZoomController> apzc = GetTargetApzc();
     427           0 :   if (apzc->IsDestroyed()) {
     428           0 :     return false;
     429             :   }
     430             : 
     431           0 :   return true;
     432             : }
     433             : 
     434             : bool
     435           0 : WheelBlockState::MaybeTimeout(const ScrollWheelInput& aEvent)
     436             : {
     437           0 :   MOZ_ASSERT(InTransaction());
     438             : 
     439           0 :   if (MaybeTimeout(aEvent.mTimeStamp)) {
     440           0 :     return true;
     441             :   }
     442             : 
     443           0 :   if (!mLastMouseMove.IsNull()) {
     444             :     // If there's a recent mouse movement, we can time out the transaction early.
     445           0 :     TimeDuration duration = TimeStamp::Now() - mLastMouseMove;
     446           0 :     if (duration.ToMilliseconds() >= gfxPrefs::MouseWheelIgnoreMoveDelayMs()) {
     447             :       TBS_LOG("%p wheel transaction timed out after mouse move\n", this);
     448           0 :       EndTransaction();
     449           0 :       return true;
     450             :     }
     451             :   }
     452             : 
     453           0 :   return false;
     454             : }
     455             : 
     456             : bool
     457           0 : WheelBlockState::MaybeTimeout(const TimeStamp& aTimeStamp)
     458             : {
     459           0 :   MOZ_ASSERT(InTransaction());
     460             : 
     461             :   // End the transaction if the event occurred > 1.5s after the most recently
     462             :   // seen wheel event.
     463           0 :   TimeDuration duration = aTimeStamp - mLastEventTime;
     464           0 :   if (duration.ToMilliseconds() < gfxPrefs::MouseWheelTransactionTimeoutMs()) {
     465           0 :     return false;
     466             :   }
     467             : 
     468             :   TBS_LOG("%p wheel transaction timed out\n", this);
     469             : 
     470           0 :   if (gfxPrefs::MouseScrollTestingEnabled()) {
     471           0 :     RefPtr<AsyncPanZoomController> apzc = GetTargetApzc();
     472           0 :     apzc->NotifyMozMouseScrollEvent(NS_LITERAL_STRING("MozMouseScrollTransactionTimeout"));
     473             :   }
     474             : 
     475           0 :   EndTransaction();
     476           0 :   return true;
     477             : }
     478             : 
     479             : void
     480           0 : WheelBlockState::OnMouseMove(const ScreenIntPoint& aPoint)
     481             : {
     482           0 :   MOZ_ASSERT(InTransaction());
     483             : 
     484           0 :   if (!GetTargetApzc()->Contains(aPoint)) {
     485           0 :     EndTransaction();
     486           0 :     return;
     487             :   }
     488             : 
     489           0 :   if (mLastMouseMove.IsNull()) {
     490             :     // If the cursor is moving inside the frame, and it is more than the
     491             :     // ignoremovedelay time since the last scroll operation, we record
     492             :     // this as the most recent mouse movement.
     493           0 :     TimeStamp now = TimeStamp::Now();
     494           0 :     TimeDuration duration = now - mLastEventTime;
     495           0 :     if (duration.ToMilliseconds() >= gfxPrefs::MouseWheelIgnoreMoveDelayMs()) {
     496           0 :       mLastMouseMove = now;
     497             :     }
     498             :   }
     499             : }
     500             : 
     501             : void
     502           0 : WheelBlockState::UpdateTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc)
     503             : {
     504           0 :   InputBlockState::UpdateTargetApzc(aTargetApzc);
     505             : 
     506             :   // If we found there was no target apzc, then we end the transaction.
     507           0 :   if (!GetTargetApzc()) {
     508           0 :     EndTransaction();
     509             :   }
     510           0 : }
     511             : 
     512             : bool
     513           0 : WheelBlockState::InTransaction() const
     514             : {
     515             :   // We consider a wheel block to be in a transaction if it has a confirmed
     516             :   // target and is the most recent wheel input block to be created.
     517           0 :   if (GetBlockId() != sLastWheelBlockId) {
     518           0 :     return false;
     519             :   }
     520             : 
     521           0 :   if (mTransactionEnded) {
     522           0 :     return false;
     523             :   }
     524             : 
     525           0 :   MOZ_ASSERT(GetTargetApzc());
     526           0 :   return true;
     527             : }
     528             : 
     529             : bool
     530           0 : WheelBlockState::AllowScrollHandoff() const
     531             : {
     532             :   // If we're in a wheel transaction, we do not allow overscroll handoff until
     533             :   // a new event ends the wheel transaction.
     534           0 :   return !IsTargetConfirmed() || !InTransaction();
     535             : }
     536             : 
     537             : void
     538           0 : WheelBlockState::EndTransaction()
     539             : {
     540             :   TBS_LOG("%p ending wheel transaction\n", this);
     541           0 :   mTransactionEnded = true;
     542           0 : }
     543             : 
     544           0 : PanGestureBlockState::PanGestureBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
     545             :                                            bool aTargetConfirmed,
     546           0 :                                            const PanGestureInput& aInitialEvent)
     547             :   : CancelableBlockState(aTargetApzc, aTargetConfirmed)
     548             :   , mInterrupted(false)
     549           0 :   , mWaitingForContentResponse(false)
     550             : {
     551           0 :   if (aTargetConfirmed) {
     552             :     // Find the nearest APZC in the overscroll handoff chain that is scrollable.
     553             :     // If we get a content confirmation later that the apzc is different, then
     554             :     // content should have found a scrollable apzc, so we don't need to handle
     555             :     // that case.
     556             :     RefPtr<AsyncPanZoomController> apzc =
     557           0 :       mOverscrollHandoffChain->FindFirstScrollable(aInitialEvent);
     558             : 
     559           0 :     if (apzc && apzc != GetTargetApzc()) {
     560           0 :       UpdateTargetApzc(apzc);
     561             :     }
     562             :   }
     563           0 : }
     564             : 
     565             : bool
     566           0 : PanGestureBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
     567             :                                              TargetConfirmationState aState,
     568             :                                              InputData* aFirstInput)
     569             : {
     570             :   // The APZC that we find via APZCCallbackHelpers may not be the same APZC
     571             :   // ESM or OverscrollHandoff would have computed. Make sure we get the right
     572             :   // one by looking for the first apzc the next pending event can scroll.
     573           0 :   RefPtr<AsyncPanZoomController> apzc = aTargetApzc;
     574           0 :   if (apzc && aFirstInput) {
     575             :     RefPtr<AsyncPanZoomController> scrollableApzc =
     576           0 :       apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(*aFirstInput);
     577           0 :     if (scrollableApzc) {
     578           0 :       apzc = scrollableApzc;
     579             :     }
     580             :   }
     581             : 
     582           0 :   InputBlockState::SetConfirmedTargetApzc(apzc, aState, aFirstInput);
     583           0 :   return true;
     584             : }
     585             : 
     586             : bool
     587           0 : PanGestureBlockState::MustStayActive()
     588             : {
     589           0 :   return !mInterrupted;
     590             : }
     591             : 
     592             : const char*
     593           0 : PanGestureBlockState::Type()
     594             : {
     595           0 :   return "pan gesture";
     596             : }
     597             : 
     598             : bool
     599           0 : PanGestureBlockState::SetContentResponse(bool aPreventDefault)
     600             : {
     601           0 :   if (aPreventDefault) {
     602             :     TBS_LOG("%p setting interrupted flag\n", this);
     603           0 :     mInterrupted = true;
     604             :   }
     605           0 :   bool stateChanged = CancelableBlockState::SetContentResponse(aPreventDefault);
     606           0 :   if (mWaitingForContentResponse) {
     607           0 :     mWaitingForContentResponse = false;
     608           0 :     stateChanged = true;
     609             :   }
     610           0 :   return stateChanged;
     611             : }
     612             : 
     613             : bool
     614           0 : PanGestureBlockState::HasReceivedAllContentNotifications() const
     615             : {
     616           0 :   return CancelableBlockState::HasReceivedAllContentNotifications()
     617           0 :       && !mWaitingForContentResponse;
     618             : }
     619             : 
     620             : bool
     621           0 : PanGestureBlockState::IsReadyForHandling() const
     622             : {
     623           0 :   if (!CancelableBlockState::IsReadyForHandling()) {
     624           0 :     return false;
     625             :   }
     626           0 :   return !mWaitingForContentResponse ||
     627           0 :          IsContentResponseTimerExpired();
     628             : }
     629             : 
     630             : bool
     631           0 : PanGestureBlockState::AllowScrollHandoff() const
     632             : {
     633           0 :   return false;
     634             : }
     635             : 
     636             : void
     637           0 : PanGestureBlockState::SetNeedsToWaitForContentResponse(bool aWaitForContentResponse)
     638             : {
     639           0 :   mWaitingForContentResponse = aWaitForContentResponse;
     640           0 : }
     641             : 
     642           0 : TouchBlockState::TouchBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
     643           0 :                                  bool aTargetConfirmed, TouchCounter& aCounter)
     644             :   : CancelableBlockState(aTargetApzc, aTargetConfirmed)
     645             :   , mAllowedTouchBehaviorSet(false)
     646             :   , mDuringFastFling(false)
     647             :   , mSingleTapOccurred(false)
     648             :   , mInSlop(false)
     649           0 :   , mTouchCounter(aCounter)
     650             : {
     651             :   TBS_LOG("Creating %p\n", this);
     652           0 :   if (!gfxPrefs::TouchActionEnabled()) {
     653           0 :     mAllowedTouchBehaviorSet = true;
     654             :   }
     655           0 : }
     656             : 
     657             : bool
     658           0 : TouchBlockState::SetAllowedTouchBehaviors(const nsTArray<TouchBehaviorFlags>& aBehaviors)
     659             : {
     660           0 :   if (mAllowedTouchBehaviorSet) {
     661           0 :     return false;
     662             :   }
     663             :   TBS_LOG("%p got allowed touch behaviours for %" PRIuSIZE " points\n", this, aBehaviors.Length());
     664           0 :   mAllowedTouchBehaviors.AppendElements(aBehaviors);
     665           0 :   mAllowedTouchBehaviorSet = true;
     666           0 :   return true;
     667             : }
     668             : 
     669             : bool
     670           0 : TouchBlockState::GetAllowedTouchBehaviors(nsTArray<TouchBehaviorFlags>& aOutBehaviors) const
     671             : {
     672           0 :   if (!mAllowedTouchBehaviorSet) {
     673           0 :     return false;
     674             :   }
     675           0 :   aOutBehaviors.AppendElements(mAllowedTouchBehaviors);
     676           0 :   return true;
     677             : }
     678             : 
     679             : void
     680           0 : TouchBlockState::CopyPropertiesFrom(const TouchBlockState& aOther)
     681             : {
     682             :   TBS_LOG("%p copying properties from %p\n", this, &aOther);
     683           0 :   if (gfxPrefs::TouchActionEnabled()) {
     684           0 :     MOZ_ASSERT(aOther.mAllowedTouchBehaviorSet || aOther.IsContentResponseTimerExpired());
     685           0 :     SetAllowedTouchBehaviors(aOther.mAllowedTouchBehaviors);
     686             :   }
     687           0 :   mTransformToApzc = aOther.mTransformToApzc;
     688           0 : }
     689             : 
     690             : bool
     691           0 : TouchBlockState::HasReceivedAllContentNotifications() const
     692             : {
     693           0 :   return CancelableBlockState::HasReceivedAllContentNotifications()
     694             :       // See comment in TouchBlockState::IsReadyforHandling()
     695           0 :       && (!gfxPrefs::TouchActionEnabled() || mAllowedTouchBehaviorSet);
     696             : }
     697             : 
     698             : bool
     699           0 : TouchBlockState::IsReadyForHandling() const
     700             : {
     701           0 :   if (!CancelableBlockState::IsReadyForHandling()) {
     702           0 :     return false;
     703             :   }
     704             : 
     705           0 :   if (!gfxPrefs::TouchActionEnabled()) {
     706             :     // If TouchActionEnabled() was false when this block was created, then
     707             :     // mAllowedTouchBehaviorSet is guaranteed to the true. However, the pref
     708             :     // may have been flipped to false after the block was created. In that case,
     709             :     // we should eventually get the touch-behaviour notification, or expire the
     710             :     // content response timeout, but we don't really need to wait for those,
     711             :     // since we don't care about the touch-behaviour values any more.
     712           0 :     return true;
     713             :   }
     714             : 
     715           0 :   return mAllowedTouchBehaviorSet || IsContentResponseTimerExpired();
     716             : }
     717             : 
     718             : void
     719           0 : TouchBlockState::SetDuringFastFling()
     720             : {
     721             :   TBS_LOG("%p setting fast-motion flag\n", this);
     722           0 :   mDuringFastFling = true;
     723           0 : }
     724             : 
     725             : bool
     726           0 : TouchBlockState::IsDuringFastFling() const
     727             : {
     728           0 :   return mDuringFastFling;
     729             : }
     730             : 
     731             : void
     732           0 : TouchBlockState::SetSingleTapOccurred()
     733             : {
     734             :   TBS_LOG("%p setting single-tap-occurred flag\n", this);
     735           0 :   mSingleTapOccurred = true;
     736           0 : }
     737             : 
     738             : bool
     739           0 : TouchBlockState::SingleTapOccurred() const
     740             : {
     741           0 :   return mSingleTapOccurred;
     742             : }
     743             : 
     744             : bool
     745           0 : TouchBlockState::MustStayActive()
     746             : {
     747           0 :   return true;
     748             : }
     749             : 
     750             : const char*
     751           0 : TouchBlockState::Type()
     752             : {
     753           0 :   return "touch";
     754             : }
     755             : 
     756             : void
     757           0 : TouchBlockState::DispatchEvent(const InputData& aEvent) const
     758             : {
     759           0 :   MOZ_ASSERT(aEvent.mInputType == MULTITOUCH_INPUT);
     760           0 :   mTouchCounter.Update(aEvent.AsMultiTouchInput());
     761           0 :   CancelableBlockState::DispatchEvent(aEvent);
     762           0 : }
     763             : 
     764             : bool
     765           0 : TouchBlockState::TouchActionAllowsPinchZoom() const
     766             : {
     767           0 :   if (!gfxPrefs::TouchActionEnabled()) {
     768           0 :     return true;
     769             :   }
     770             :   // Pointer events specification requires that all touch points allow zoom.
     771           0 :   for (size_t i = 0; i < mAllowedTouchBehaviors.Length(); i++) {
     772           0 :     if (!(mAllowedTouchBehaviors[i] & AllowedTouchBehavior::PINCH_ZOOM)) {
     773           0 :       return false;
     774             :     }
     775             :   }
     776           0 :   return true;
     777             : }
     778             : 
     779             : bool
     780           0 : TouchBlockState::TouchActionAllowsDoubleTapZoom() const
     781             : {
     782           0 :   if (!gfxPrefs::TouchActionEnabled()) {
     783           0 :     return true;
     784             :   }
     785           0 :   for (size_t i = 0; i < mAllowedTouchBehaviors.Length(); i++) {
     786           0 :     if (!(mAllowedTouchBehaviors[i] & AllowedTouchBehavior::DOUBLE_TAP_ZOOM)) {
     787           0 :       return false;
     788             :     }
     789             :   }
     790           0 :   return true;
     791             : }
     792             : 
     793             : bool
     794           0 : TouchBlockState::TouchActionAllowsPanningX() const
     795             : {
     796           0 :   if (!gfxPrefs::TouchActionEnabled()) {
     797           0 :     return true;
     798             :   }
     799           0 :   if (mAllowedTouchBehaviors.IsEmpty()) {
     800             :     // Default to allowed
     801           0 :     return true;
     802             :   }
     803           0 :   TouchBehaviorFlags flags = mAllowedTouchBehaviors[0];
     804           0 :   return (flags & AllowedTouchBehavior::HORIZONTAL_PAN);
     805             : }
     806             : 
     807             : bool
     808           0 : TouchBlockState::TouchActionAllowsPanningY() const
     809             : {
     810           0 :   if (!gfxPrefs::TouchActionEnabled()) {
     811           0 :     return true;
     812             :   }
     813           0 :   if (mAllowedTouchBehaviors.IsEmpty()) {
     814             :     // Default to allowed
     815           0 :     return true;
     816             :   }
     817           0 :   TouchBehaviorFlags flags = mAllowedTouchBehaviors[0];
     818           0 :   return (flags & AllowedTouchBehavior::VERTICAL_PAN);
     819             : }
     820             : 
     821             : bool
     822           0 : TouchBlockState::TouchActionAllowsPanningXY() const
     823             : {
     824           0 :   if (!gfxPrefs::TouchActionEnabled()) {
     825           0 :     return true;
     826             :   }
     827           0 :   if (mAllowedTouchBehaviors.IsEmpty()) {
     828             :     // Default to allowed
     829           0 :     return true;
     830             :   }
     831           0 :   TouchBehaviorFlags flags = mAllowedTouchBehaviors[0];
     832           0 :   return (flags & AllowedTouchBehavior::HORIZONTAL_PAN)
     833           0 :       && (flags & AllowedTouchBehavior::VERTICAL_PAN);
     834             : }
     835             : 
     836             : bool
     837           0 : TouchBlockState::UpdateSlopState(const MultiTouchInput& aInput,
     838             :                                  bool aApzcCanConsumeEvents)
     839             : {
     840           0 :   if (aInput.mType == MultiTouchInput::MULTITOUCH_START) {
     841             :     // this is by definition the first event in this block. If it's the first
     842             :     // touch, then we enter a slop state.
     843           0 :     mInSlop = (aInput.mTouches.Length() == 1);
     844           0 :     if (mInSlop) {
     845           0 :       mSlopOrigin = aInput.mTouches[0].mScreenPoint;
     846             :       TBS_LOG("%p entering slop with origin %s\n", this, Stringify(mSlopOrigin).c_str());
     847             :     }
     848           0 :     return false;
     849             :   }
     850           0 :   if (mInSlop) {
     851             :     ScreenCoord threshold = aApzcCanConsumeEvents
     852             :         ? AsyncPanZoomController::GetTouchStartTolerance()
     853           0 :         : ScreenCoord(gfxPrefs::APZTouchMoveTolerance() * APZCTreeManager::GetDPI());
     854           0 :     bool stayInSlop = (aInput.mType == MultiTouchInput::MULTITOUCH_MOVE) &&
     855           0 :         (aInput.mTouches.Length() == 1) &&
     856           0 :         ((aInput.mTouches[0].mScreenPoint - mSlopOrigin).Length() < threshold);
     857           0 :     if (!stayInSlop) {
     858             :       // we're out of the slop zone, and will stay out for the remainder of
     859             :       // this block
     860             :       TBS_LOG("%p exiting slop\n", this);
     861           0 :       mInSlop = false;
     862             :     }
     863             :   }
     864           0 :   return mInSlop;
     865             : }
     866             : 
     867             : uint32_t
     868           0 : TouchBlockState::GetActiveTouchCount() const
     869             : {
     870           0 :   return mTouchCounter.GetActiveTouchCount();
     871             : }
     872             : 
     873           0 : KeyboardBlockState::KeyboardBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc)
     874           0 :   : InputBlockState(aTargetApzc, true)
     875             : {
     876           0 : }
     877             : 
     878             : } // namespace layers
     879             : } // namespace mozilla

Generated by: LCOV version 1.13