diff options
Diffstat (limited to 'gfx/layers/apz/src/OverscrollHandoffState.h')
-rw-r--r-- | gfx/layers/apz/src/OverscrollHandoffState.h | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/gfx/layers/apz/src/OverscrollHandoffState.h b/gfx/layers/apz/src/OverscrollHandoffState.h new file mode 100644 index 0000000000..28c89edd74 --- /dev/null +++ b/gfx/layers/apz/src/OverscrollHandoffState.h @@ -0,0 +1,206 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_layers_OverscrollHandoffChain_h +#define mozilla_layers_OverscrollHandoffChain_h + +#include <vector> +#include "mozilla/RefPtr.h" // for RefPtr +#include "nsISupportsImpl.h" // for NS_INLINE_DECL_THREADSAFE_REFCOUNTING +#include "APZUtils.h" // for CancelAnimationFlags +#include "mozilla/layers/LayersTypes.h" // for Layer::ScrollDirection +#include "Units.h" // for ScreenPoint + +namespace mozilla { + +class InputData; + +namespace layers { + +class AsyncPanZoomController; + +/** + * This class represents the chain of APZCs along which overscroll is handed + * off. It is created by APZCTreeManager by starting from an initial APZC which + * is the target for input events, and following the scroll parent ID links + * (often but not always corresponding to parent pointers in the APZC tree), + * then adjusting for scrollgrab. + */ +class OverscrollHandoffChain { + protected: + // Reference-counted classes cannot have public destructors. + ~OverscrollHandoffChain(); + + public: + // Threadsafe so that the controller and sampler threads can both maintain + // nsRefPtrs to the same handoff chain. + // Mutable so that we can pass around the class by + // RefPtr<const OverscrollHandoffChain> and thus enforce that, once built, + // the chain is not modified. + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OverscrollHandoffChain) + + /* + * Methods for building the handoff chain. + * These should be used only by + * AsyncPanZoomController::BuildOverscrollHandoffChain(). + */ + void Add(AsyncPanZoomController* aApzc); + void SortByScrollPriority(); + + /* + * Methods for accessing the handoff chain. + */ + uint32_t Length() const { return mChain.size(); } + const RefPtr<AsyncPanZoomController>& GetApzcAtIndex(uint32_t aIndex) const; + // Returns Length() if |aApzc| is not on this chain. + uint32_t IndexOf(const AsyncPanZoomController* aApzc) const; + + /* + * Convenience methods for performing operations on APZCs in the chain. + */ + + // Flush repaints all the way up the chain. + void FlushRepaints() const; + + // Cancel animations all the way up the chain. + void CancelAnimations(CancelAnimationFlags aFlags = Default) const; + + // Clear overscroll all the way up the chain. + void ClearOverscroll() const; + + // Snap back the APZC that is overscrolled on the subset of the chain from + // |aStart| onwards, if any. + void SnapBackOverscrolledApzc(const AsyncPanZoomController* aStart) const; + + // Similar to above SnapbackOverscrolledApzc but for pan gestures with + // momentum events, this function doesn't end up calling each APZC's + // ScrollSnap. + // |aVelocity| is the initial velocity of |aStart|. + void SnapBackOverscrolledApzcForMomentum( + const AsyncPanZoomController* aStart, + const ParentLayerPoint& aVelocity) const; + + // Determine whether the given APZC, or any APZC further in the chain, + // has room to be panned. + bool CanBePanned(const AsyncPanZoomController* aApzc) const; + + // Determine whether the given APZC, or any APZC further in the chain, + // can scroll in the given direction. + bool CanScrollInDirection(const AsyncPanZoomController* aApzc, + ScrollDirection aDirection) const; + + // Determine whether any APZC along this handoff chain is overscrolled. + bool HasOverscrolledApzc() const; + + // Determine whether any APZC along this handoff chain has been flung fast. + bool HasFastFlungApzc() const; + + // Determine whether any APZC along this handoff chain is autoscroll. + bool HasAutoscrollApzc() const; + + // Find the first APZC in this handoff chain that can be scrolled by |aInput|. + // Since overscroll-behavior can restrict handoff in some directions, + // |aOutAllowedScrollDirections| is populated with the scroll directions + // in which scrolling of the returned APZC is allowed. + // |aIncludeOverscroll| is an optional flag whether to consider overscrollable + // as scrollable or not. + enum class IncludeOverscroll : bool { No, Yes }; + RefPtr<AsyncPanZoomController> FindFirstScrollable( + const InputData& aInput, ScrollDirections* aOutAllowedScrollDirections, + IncludeOverscroll aIncludeOverscroll = IncludeOverscroll::Yes) const; + + // Return a pair of true and the root content APZC if all non-root APZCs in + // this handoff chain starting from |aApzc| are not able to scroll downwards + // (i.e. there is no room to scroll downwards in each APZC respectively) and + // there is any contents covered by the dynamic toolbar, otherwise return a + // pair of false and nullptr. + std::tuple<bool, const AsyncPanZoomController*> + ScrollingDownWillMoveDynamicToolbar( + const AsyncPanZoomController* aApzc) const; + + bool ScrollingUpWillTriggerPullToRefresh( + const AsyncPanZoomController* aApzc) const; + + private: + std::vector<RefPtr<AsyncPanZoomController>> mChain; + + typedef void (AsyncPanZoomController::*APZCMethod)(); + typedef bool (AsyncPanZoomController::*APZCPredicate)() const; + void ForEachApzc(APZCMethod aMethod) const; + bool AnyApzc(APZCPredicate aPredicate) const; +}; + +/** + * This class groups the state maintained during overscroll handoff. + */ +struct OverscrollHandoffState { + OverscrollHandoffState(const OverscrollHandoffChain& aChain, + const ScreenPoint& aPanDistance, + ScrollSource aScrollSource) + : mChain(aChain), + mChainIndex(0), + mPanDistance(aPanDistance), + mScrollSource(aScrollSource) {} + + // The chain of APZCs along which we hand off scroll. + // This is const to indicate that the chain does not change over the + // course of handoff. + const OverscrollHandoffChain& mChain; + + // The index of the APZC in the chain that we are currently giving scroll to. + // This is non-const to indicate that this changes over the course of handoff. + uint32_t mChainIndex; + + // The total distance since touch-start of the pan that triggered the + // handoff. This is const to indicate that it does not change over the + // course of handoff. + // The x/y components of this are non-negative. + const ScreenPoint mPanDistance; + + ScrollSource mScrollSource; + + // The total amount of actual movement that this scroll caused, including + // scrolling and changes to overscroll. This starts at zero and is accumulated + // over the course of the handoff. + ScreenPoint mTotalMovement; +}; + +/* + * This class groups the state maintained during fling handoff. + */ +struct FlingHandoffState { + // The velocity of the fling being handed off. + ParentLayerPoint mVelocity; + + // The chain of APZCs along which we hand off the fling. + // Unlike in OverscrollHandoffState, this is stored by RefPtr because + // otherwise it may not stay alive for the entire handoff. + RefPtr<const OverscrollHandoffChain> mChain; + + // The time duration between the touch start and the touch move that started + // the pan gesture which triggered this fling. In other words, the time it + // took for the finger to move enough to cross the touch slop threshold. + // Nothing if this fling was not immediately caused by a touch pan. + Maybe<TimeDuration> mTouchStartRestingTime; + + // The slowest panning velocity encountered during the pan that triggered this + // fling. + ParentLayerCoord mMinPanVelocity; + + // Whether handoff has happened by this point, or we're still process + // the original fling. + bool mIsHandoff; + + // The single APZC that was scrolled by the pan that started this fling. + // The fling is only allowed to scroll this APZC, too. + // Used only if immediate scroll handoff is disallowed. + RefPtr<const AsyncPanZoomController> mScrolledApzc; +}; + +} // namespace layers +} // namespace mozilla + +#endif /* mozilla_layers_OverscrollHandoffChain_h */ |