/* -*- 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 #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 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& 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 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 ScrollingDownWillMoveDynamicToolbar( const AsyncPanZoomController* aApzc) const; private: std::vector> 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 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 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 mScrolledApzc; }; } // namespace layers } // namespace mozilla #endif /* mozilla_layers_OverscrollHandoffChain_h */