1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_layers_AsyncPanZoomController_h
8 #define mozilla_layers_AsyncPanZoomController_h
9 
10 #include "CrossProcessMutex.h"
11 #include "mozilla/layers/GeckoContentController.h"
12 #include "mozilla/layers/RepaintRequest.h"
13 #include "mozilla/layers/ZoomConstraints.h"
14 #include "mozilla/Atomics.h"
15 #include "mozilla/Attributes.h"
16 #include "mozilla/EventForwards.h"
17 #include "mozilla/Monitor.h"
18 #include "mozilla/RecursiveMutex.h"
19 #include "mozilla/RefPtr.h"
20 #include "mozilla/ScrollTypes.h"
21 #include "mozilla/StaticPrefs_apz.h"
22 #include "mozilla/UniquePtr.h"
23 #include "InputData.h"
24 #include "Axis.h"  // for Axis, Side, etc.
25 #include "InputQueue.h"
26 #include "APZUtils.h"
27 #include "Layers.h"  // for Layer::ScrollDirection
28 #include "LayersTypes.h"
29 #include "mozilla/gfx/Matrix.h"
30 #include "nsRegion.h"
31 #include "nsTArray.h"
32 #include "PotentialCheckerboardDurationTracker.h"
33 #include "RecentEventsBuffer.h"  // for RecentEventsBuffer
34 #include "SampledAPZCState.h"
35 
36 namespace mozilla {
37 
38 namespace ipc {
39 
40 class SharedMemoryBasic;
41 
42 }  // namespace ipc
43 
44 namespace layers {
45 
46 class AsyncDragMetrics;
47 class APZCTreeManager;
48 struct ScrollableLayerGuid;
49 class CompositorController;
50 class MetricsSharingController;
51 class GestureEventListener;
52 struct AsyncTransform;
53 class AsyncPanZoomAnimation;
54 class StackScrollerFlingAnimation;
55 template <typename FlingPhysics>
56 class GenericFlingAnimation;
57 class AndroidFlingPhysics;
58 class DesktopFlingPhysics;
59 class InputBlockState;
60 struct FlingHandoffState;
61 class TouchBlockState;
62 class PanGestureBlockState;
63 class OverscrollHandoffChain;
64 struct OverscrollHandoffState;
65 class StateChangeNotificationBlocker;
66 class CheckerboardEvent;
67 class OverscrollEffectBase;
68 class WidgetOverscrollEffect;
69 class GenericOverscrollEffect;
70 class AndroidSpecificState;
71 struct KeyboardScrollAction;
72 
73 // Base class for grouping platform-specific APZC state variables.
74 class PlatformSpecificStateBase {
75  public:
76   virtual ~PlatformSpecificStateBase() = default;
AsAndroidSpecificState()77   virtual AndroidSpecificState* AsAndroidSpecificState() { return nullptr; }
78   // PLPPI = "ParentLayer pixels per (Screen) inch"
79   virtual AsyncPanZoomAnimation* CreateFlingAnimation(
80       AsyncPanZoomController& aApzc, const FlingHandoffState& aHandoffState,
81       float aPLPPI);
82   virtual UniquePtr<VelocityTracker> CreateVelocityTracker(Axis* aAxis);
83 
InitializeGlobalState()84   static void InitializeGlobalState() {}
85 };
86 
87 /*
88  * Represents a transform from the ParentLayer coordinate space of an APZC
89  * to the ParentLayer coordinate space of its parent APZC.
90  * Each layer along the way contributes to the transform. We track
91  * contributions that are perspective transforms separately, as sometimes
92  * these require special handling.
93  */
94 struct AncestorTransform {
95   gfx::Matrix4x4 mTransform;
96   gfx::Matrix4x4 mPerspectiveTransform;
97 
98   AncestorTransform() = default;
99 
AncestorTransformAncestorTransform100   AncestorTransform(const gfx::Matrix4x4& aTransform,
101                     bool aTransformIsPerspective) {
102     (aTransformIsPerspective ? mPerspectiveTransform : mTransform) = aTransform;
103   }
104 
AncestorTransformAncestorTransform105   AncestorTransform(const gfx::Matrix4x4& aTransform,
106                     const gfx::Matrix4x4& aPerspectiveTransform)
107       : mTransform(aTransform), mPerspectiveTransform(aPerspectiveTransform) {}
108 
CombinedTransformAncestorTransform109   gfx::Matrix4x4 CombinedTransform() const {
110     return mTransform * mPerspectiveTransform;
111   }
112 
ContainsPerspectiveTransformAncestorTransform113   bool ContainsPerspectiveTransform() const {
114     return !mPerspectiveTransform.IsIdentity();
115   }
116 
GetPerspectiveTransformAncestorTransform117   gfx::Matrix4x4 GetPerspectiveTransform() const {
118     return mPerspectiveTransform;
119   }
120 
121   friend AncestorTransform operator*(const AncestorTransform& aA,
122                                      const AncestorTransform& aB) {
123     return AncestorTransform{
124         aA.mTransform * aB.mTransform,
125         aA.mPerspectiveTransform * aB.mPerspectiveTransform};
126   }
127 };
128 
129 /**
130  * Controller for all panning and zooming logic. Any time a user input is
131  * detected and it must be processed in some way to affect what the user sees,
132  * it goes through here. Listens for any input event from InputData and can
133  * optionally handle WidgetGUIEvent-derived touch events, but this must be done
134  * on the main thread. Note that this class completely cross-platform.
135  *
136  * Input events originate on the UI thread of the platform that this runs on,
137  * and are then sent to this class. This class processes the event in some way;
138  * for example, a touch move will usually lead to a panning of content (though
139  * of course there are exceptions, such as if content preventDefaults the event,
140  * or if the target frame is not scrollable). The compositor interacts with this
141  * class by locking it and querying it for the current transform matrix based on
142  * the panning and zooming logic that was invoked on the UI thread.
143  *
144  * Currently, each outer DOM window (i.e. a website in a tab, but not any
145  * subframes) has its own AsyncPanZoomController. In the future, to support
146  * asynchronously scrolled subframes, we want to have one AsyncPanZoomController
147  * per frame.
148  */
149 class AsyncPanZoomController {
150   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomController)
151 
152   typedef mozilla::MonitorAutoLock MonitorAutoLock;
153   typedef mozilla::gfx::Matrix4x4 Matrix4x4;
154   typedef mozilla::layers::RepaintRequest::ScrollOffsetUpdateType
155       RepaintUpdateType;
156 
157  public:
158   enum GestureBehavior {
159     // The platform code is responsible for forwarding gesture events here. We
160     // will not attempt to generate gesture events from MultiTouchInputs.
161     DEFAULT_GESTURES,
162     // An instance of GestureEventListener is used to detect gestures. This is
163     // handled completely internally within this class.
164     USE_GESTURE_DETECTOR
165   };
166 
167   /**
168    * Gets the DPI from the tree manager.
169    */
170   float GetDPI() const;
171 
172   /**
173    * Constant describing the tolerance in distance we use, multiplied by the
174    * device DPI, before we start panning the screen. This is to prevent us from
175    * accidentally processing taps as touch moves, and from very short/accidental
176    * touches moving the screen.
177    * Note: It's an abuse of the 'Coord' class to use it to represent a 2D
178    *       distance, but it's the closest thing we currently have.
179    */
180   ScreenCoord GetTouchStartTolerance() const;
181   /**
182    * Same as GetTouchStartTolerance, but the tolerance for how far the touch
183    * has to move before it starts allowing touchmove events to be dispatched
184    * to content, for non-scrollable content.
185    */
186   ScreenCoord GetTouchMoveTolerance() const;
187   /**
188    * Same as GetTouchStartTolerance, but the tolerance for how close the second
189    * tap has to be to the first tap in order to be counted as part of a
190    * multi-tap gesture (double-tap or one-touch-pinch).
191    */
192   ScreenCoord GetSecondTapTolerance() const;
193 
194   AsyncPanZoomController(LayersId aLayersId, APZCTreeManager* aTreeManager,
195                          const RefPtr<InputQueue>& aInputQueue,
196                          GeckoContentController* aController,
197                          GestureBehavior aGestures = DEFAULT_GESTURES);
198 
199   // --------------------------------------------------------------------------
200   // These methods must only be called on the gecko thread.
201   //
202 
203   /**
204    * Read the various prefs and do any global initialization for all APZC
205    * instances. This must be run on the gecko thread before any APZC instances
206    * are actually used for anything meaningful.
207    */
208   static void InitializeGlobalState();
209 
210   // --------------------------------------------------------------------------
211   // These methods must only be called on the controller/UI thread.
212   //
213 
214   /**
215    * Kicks an animation to zoom to a rect. This may be either a zoom out or zoom
216    * in. The actual animation is done on the sampler thread after being set
217    * up.
218    */
219   void ZoomToRect(CSSRect aRect, const uint32_t aFlags);
220 
221   /**
222    * Updates any zoom constraints contained in the <meta name="viewport"> tag.
223    */
224   void UpdateZoomConstraints(const ZoomConstraints& aConstraints);
225 
226   /**
227    * Return the zoom constraints last set for this APZC (in the constructor
228    * or in UpdateZoomConstraints()).
229    */
230   ZoomConstraints GetZoomConstraints() const;
231 
232   /**
233    * Schedules a runnable to run on the controller/UI thread at some time
234    * in the future.
235    */
236   void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs);
237 
238   // --------------------------------------------------------------------------
239   // These methods must only be called on the sampler thread.
240   //
241 
242   /**
243    * Advances any animations currently running to the given timestamp.
244    * This may be called multiple times with the same timestamp.
245    *
246    * The return value indicates whether or not any currently running animation
247    * should continue. If true, the compositor should schedule another composite.
248    */
249   bool AdvanceAnimations(const TimeStamp& aSampleTime);
250 
251   bool UpdateAnimation(const RecursiveMutexAutoLock& aProofOfLock,
252                        const TimeStamp& aSampleTime,
253                        nsTArray<RefPtr<Runnable>>* aOutDeferredTasks);
254 
255   // --------------------------------------------------------------------------
256   // These methods must only be called on the updater thread.
257   //
258 
259   /**
260    * A shadow layer update has arrived. |aScrollMetdata| is the new
261    * ScrollMetadata for the container layer corresponding to this APZC.
262    * |aIsFirstPaint| is a flag passed from the shadow
263    * layers code indicating that the scroll metadata being sent with this call
264    * are the initial metadata and the initial paint of the frame has just
265    * happened.
266    */
267   void NotifyLayersUpdated(const ScrollMetadata& aScrollMetadata,
268                            bool aIsFirstPaint, bool aThisLayerTreeUpdated);
269 
270   /**
271    * The platform implementation must set the compositor controller so that we
272    * can request composites.
273    */
274   void SetCompositorController(CompositorController* aCompositorController);
275 
276   /**
277    * If we need to share the frame metrics with some other thread, this
278    * controller needs to be set and provides relevant information/APIs.
279    */
280   void SetMetricsSharingController(
281       MetricsSharingController* aMetricsSharingController);
282 
283   // --------------------------------------------------------------------------
284   // These methods can be called from any thread.
285   //
286 
287   /**
288    * Shut down the controller/UI thread state and prepare to be
289    * deleted (which may happen from any thread).
290    */
291   void Destroy();
292 
293   /**
294    * Returns true if Destroy() has already been called on this APZC instance.
295    */
296   bool IsDestroyed() const;
297 
298   /**
299    * Returns the transform to take something from the coordinate space of the
300    * last thing we know gecko painted, to the coordinate space of the last thing
301    * we asked gecko to paint. In cases where that last request has not yet been
302    * processed, this is needed to transform input events properly into a space
303    * gecko will understand.
304    */
305   Matrix4x4 GetTransformToLastDispatchedPaint() const;
306 
307   /**
308    * Returns the number of CSS pixels of checkerboard according to the metrics
309    * in this APZC. The argument provided by the caller is the composition bounds
310    * of this APZC, additionally clipped by the composition bounds of any
311    * ancestor APZCs, accounting for all the async transforms.
312    */
313   uint32_t GetCheckerboardMagnitude(
314       const ParentLayerRect& aClippedCompositionBounds) const;
315 
316   /**
317    * Report the number of CSSPixel-milliseconds of checkerboard to telemetry.
318    * See GetCheckerboardMagnitude for documentation of the
319    * aClippedCompositionBounds argument that needs to be provided by the caller.
320    */
321   void ReportCheckerboard(const TimeStamp& aSampleTime,
322                           const ParentLayerRect& aClippedCompositionBounds);
323 
324   /**
325    * Flush any active checkerboard report that's in progress. This basically
326    * pretends like any in-progress checkerboard event has terminated, and pushes
327    * out the report to the checkerboard reporting service and telemetry. If the
328    * checkerboard event has not really finished, it will start a new event
329    * on the next composite.
330    */
331   void FlushActiveCheckerboardReport();
332 
333   /**
334    * Recalculates the displayport. Ideally, this should paint an area bigger
335    * than the composite-to dimensions so that when you scroll down, you don't
336    * checkerboard immediately. This includes a bunch of logic, including
337    * algorithms to bias painting in the direction of the velocity.
338    */
339   static const ScreenMargin CalculatePendingDisplayPort(
340       const FrameMetrics& aFrameMetrics, const ParentLayerPoint& aVelocity);
341 
342   nsEventStatus HandleDragEvent(const MouseInput& aEvent,
343                                 const AsyncDragMetrics& aDragMetrics,
344                                 CSSCoord aInitialThumbPos);
345 
346   /**
347    * Handler for events which should not be intercepted by the touch listener.
348    */
349   nsEventStatus HandleInputEvent(
350       const InputData& aEvent,
351       const ScreenToParentLayerMatrix4x4& aTransformToApzc);
352 
353   /**
354    * Handler for gesture events.
355    * Currently some gestures are detected in GestureEventListener that calls
356    * APZC back through this handler in order to avoid recursive calls to
357    * APZC::HandleInputEvent() which is supposed to do the work for
358    * ReceiveInputEvent().
359    */
360   nsEventStatus HandleGestureEvent(const InputData& aEvent);
361 
362   /**
363    * Start autoscrolling this APZC, anchored at the provided location.
364    */
365   void StartAutoscroll(const ScreenPoint& aAnchorLocation);
366 
367   /**
368    * Stop autoscrolling this APZC.
369    */
370   void StopAutoscroll();
371 
372   /**
373    * Populates the provided object (if non-null) with the scrollable guid of
374    * this apzc.
375    */
376   void GetGuid(ScrollableLayerGuid* aGuidOut) const;
377 
378   /**
379    * Returns the scrollable guid of this apzc.
380    */
381   ScrollableLayerGuid GetGuid() const;
382 
383   /**
384    * Returns true if this APZC instance is for the layer identified by the guid.
385    */
386   bool Matches(const ScrollableLayerGuid& aGuid);
387 
388   /**
389    * Returns true if the tree manager of this APZC is the same as the one
390    * passed in.
391    */
392   bool HasTreeManager(const APZCTreeManager* aTreeManager) const;
393 
394   void StartAnimation(AsyncPanZoomAnimation* aAnimation);
395 
396   /**
397    * Cancels any currently running animation.
398    * aFlags is a bit-field to provide specifics of how to cancel the animation.
399    * See CancelAnimationFlags.
400    */
401   void CancelAnimation(CancelAnimationFlags aFlags = Default);
402 
403   /**
404    * Clear any overscroll on this APZC.
405    */
406   void ClearOverscroll();
407 
408   /**
409    * Returns whether this APZC is for an element marked with the 'scrollgrab'
410    * attribute.
411    */
HasScrollgrab()412   bool HasScrollgrab() const { return mScrollMetadata.GetHasScrollgrab(); }
413 
414   /**
415    * Returns whether this APZC has scroll snap points.
416    */
HasScrollSnapping()417   bool HasScrollSnapping() const {
418     return mScrollMetadata.GetSnapInfo().HasScrollSnapping();
419   }
420 
421   /**
422    * Returns whether this APZC has room to be panned (in any direction).
423    */
424   bool IsPannable() const;
425 
426   /**
427    * Returns whether this APZC represents a scroll info layer.
428    */
429   bool IsScrollInfoLayer() const;
430 
431   /**
432    * Returns true if the APZC has been flung with a velocity greater than the
433    * stop-on-tap fling velocity threshold (which is pref-controlled).
434    */
435   bool IsFlingingFast() const;
436 
437   /**
438    * Returns the identifier of the touch in the last touch event processed by
439    * this APZC. This should only be called when the last touch event contained
440    * only one touch.
441    */
442   int32_t GetLastTouchIdentifier() const;
443 
444   /**
445    * Returns the matrix that transforms points from global screen space into
446    * this APZC's ParentLayer space.
447    * To respect the lock ordering, mRecursiveMutex must NOT be held when calling
448    * this function (since this function acquires the tree lock).
449    */
450   ScreenToParentLayerMatrix4x4 GetTransformToThis() const;
451 
452   /**
453    * Convert the vector |aVector|, rooted at the point |aAnchor|, from
454    * this APZC's ParentLayer coordinates into screen coordinates.
455    * The anchor is necessary because with 3D tranforms, the location of the
456    * vector can affect the result of the transform.
457    * To respect the lock ordering, mRecursiveMutex must NOT be held when calling
458    * this function (since this function acquires the tree lock).
459    */
460   ScreenPoint ToScreenCoordinates(const ParentLayerPoint& aVector,
461                                   const ParentLayerPoint& aAnchor) const;
462 
463   /**
464    * Convert the vector |aVector|, rooted at the point |aAnchor|, from
465    * screen coordinates into this APZC's ParentLayer coordinates.
466    * The anchor is necessary because with 3D tranforms, the location of the
467    * vector can affect the result of the transform.
468    * To respect the lock ordering, mRecursiveMutex must NOT be held when calling
469    * this function (since this function acquires the tree lock).
470    */
471   ParentLayerPoint ToParentLayerCoordinates(const ScreenPoint& aVector,
472                                             const ScreenPoint& aAnchor) const;
473 
474   /**
475    * Same as above, but uses an ExternalPoint as the anchor.
476    */
477   ParentLayerPoint ToParentLayerCoordinates(const ScreenPoint& aVector,
478                                             const ExternalPoint& aAnchor) const;
479 
480   /**
481    * Combines an offset defined as an external point, with a window-relative
482    * offset to give an absolute external point.
483    */
484   static ExternalPoint ToExternalPoint(const ExternalPoint& aScreenOffset,
485                                        const ScreenPoint& aScreenPoint);
486 
487   /**
488    * Gets a vector where the head is the given point, and the tail is
489    * the touch start position.
490    */
491   ScreenPoint PanVector(const ExternalPoint& aPos) const;
492 
493   // Return whether or not a wheel event will be able to scroll in either
494   // direction.
495   bool CanScroll(const InputData& aEvent) const;
496 
497   // Return the directions in which this APZC allows handoff (as governed by
498   // overscroll-behavior).
499   ScrollDirections GetAllowedHandoffDirections() const;
500 
501   // Return whether or not a scroll delta will be able to scroll in either
502   // direction.
503   bool CanScroll(const ParentLayerPoint& aDelta) const;
504 
505   // Return whether or not a scroll delta will be able to scroll in either
506   // direction with wheel.
507   bool CanScrollWithWheel(const ParentLayerPoint& aDelta) const;
508 
509   // Return whether or not there is room to scroll this APZC
510   // in the given direction.
511   bool CanScroll(ScrollDirection aDirection) const;
512 
513   /**
514    * Convert a point on the scrollbar from this APZC's ParentLayer coordinates
515    * to CSS coordinates relative to the beginning of the scroll track.
516    * Only the component in the direction of scrolling is returned.
517    */
518   CSSCoord ConvertScrollbarPoint(const ParentLayerPoint& aScrollbarPoint,
519                                  const ScrollbarData& aThumbData) const;
520 
521   void NotifyMozMouseScrollEvent(const nsString& aString) const;
522 
523   bool OverscrollBehaviorAllowsSwipe() const;
524 
525   //|Metrics()| and |Metrics() const| are getter functions that both return
526   // mScrollMetadata.mMetrics
527 
528   const FrameMetrics& Metrics() const;
529   FrameMetrics& Metrics();
530 
531   // Helper function to compare root frame metrics and update them
532   // Returns true when the metrics have changed and were updated.
533   bool UpdateRootFrameMetricsIfChanged(FrameMetrics& metrics);
534 
535  private:
536   // Get whether the horizontal content of the honoured target of auto-dir
537   // scrolling starts from right to left. If you don't know of auto-dir
538   // scrolling or what a honoured target means,
539   // @see mozilla::WheelDeltaAdjustmentStrategy
540   bool IsContentOfHonouredTargetRightToLeft(bool aHonoursRoot) const;
541 
542  protected:
543   // Protected destructor, to discourage deletion outside of Release():
544   virtual ~AsyncPanZoomController();
545 
546   // Returns the cached current frame time.
547   TimeStamp GetFrameTime() const;
548 
549   /**
550    * Helper method for touches beginning. Sets everything up for panning and any
551    * multitouch gestures.
552    */
553   nsEventStatus OnTouchStart(const MultiTouchInput& aEvent);
554 
555   /**
556    * Helper method for touches moving. Does any transforms needed when panning.
557    */
558   nsEventStatus OnTouchMove(const MultiTouchInput& aEvent);
559 
560   /**
561    * Helper method for touches ending. Redraws the screen if necessary and does
562    * any cleanup after a touch has ended.
563    */
564   nsEventStatus OnTouchEnd(const MultiTouchInput& aEvent);
565 
566   /**
567    * Helper method for touches being cancelled. Treated roughly the same as a
568    * touch ending (OnTouchEnd()).
569    */
570   nsEventStatus OnTouchCancel(const MultiTouchInput& aEvent);
571 
572   /**
573    * Helper method for scales beginning. Distinct from the OnTouch* handlers in
574    * that this implies some outside implementation has determined that the user
575    * is pinching.
576    */
577   nsEventStatus OnScaleBegin(const PinchGestureInput& aEvent);
578 
579   /**
580    * Helper method for scaling. As the user moves their fingers when pinching,
581    * this changes the scale of the page.
582    */
583   nsEventStatus OnScale(const PinchGestureInput& aEvent);
584 
585   /**
586    * Helper method for scales ending. Redraws the screen if necessary and does
587    * any cleanup after a scale has ended.
588    */
589   nsEventStatus OnScaleEnd(const PinchGestureInput& aEvent);
590 
591   /**
592    * Helper methods for handling pan events.
593    */
594   nsEventStatus OnPanMayBegin(const PanGestureInput& aEvent);
595   nsEventStatus OnPanCancelled(const PanGestureInput& aEvent);
596   nsEventStatus OnPanBegin(const PanGestureInput& aEvent);
597   nsEventStatus OnPan(const PanGestureInput& aEvent, bool aFingersOnTouchpad);
598   nsEventStatus OnPanEnd(const PanGestureInput& aEvent);
599   nsEventStatus OnPanMomentumStart(const PanGestureInput& aEvent);
600   nsEventStatus OnPanMomentumEnd(const PanGestureInput& aEvent);
601   nsEventStatus HandleEndOfPan();
602 
603   /**
604    * Helper methods for handling scroll wheel events.
605    */
606   nsEventStatus OnScrollWheel(const ScrollWheelInput& aEvent);
607 
608   /**
609    * Gets the scroll wheel delta's values in parent-layer pixels from the
610    * original delta's values of a wheel input.
611    */
612   ParentLayerPoint GetScrollWheelDelta(const ScrollWheelInput& aEvent) const;
613 
614   /**
615    * This function is like GetScrollWheelDelta(aEvent).
616    * The difference is the four added parameters provide values as alternatives
617    * to the original wheel input's delta values, so |aEvent|'s delta values are
618    * ignored in this function, we only use some other member variables and
619    * functions of |aEvent|.
620    */
621   ParentLayerPoint GetScrollWheelDelta(const ScrollWheelInput& aEvent,
622                                        double aDeltaX, double aDeltaY,
623                                        double aMultiplierX,
624                                        double aMultiplierY) const;
625 
626   /**
627    * This deleted function is used for:
628    * 1. avoiding accidental implicit value type conversions of input delta
629    *    values when callers intend to call the above function;
630    * 2. decoupling the manual relationship between the delta value type and the
631    *    above function. If by any chance the defined delta value type in
632    *    ScrollWheelInput has changed, this will automatically result in build
633    *    time failure, so we can learn of it the first time and accordingly
634    *    redefine those parameters' value types in the above function.
635    */
636   template <typename T>
637   ParentLayerPoint GetScrollWheelDelta(ScrollWheelInput&, T, T, T, T) = delete;
638 
639   /**
640    * Helper methods for handling keyboard events.
641    */
642   nsEventStatus OnKeyboard(const KeyboardInput& aEvent);
643 
644   CSSPoint GetKeyboardDestination(const KeyboardScrollAction& aAction) const;
645 
646   /**
647    * Helper methods for long press gestures.
648    */
649   MOZ_CAN_RUN_SCRIPT_BOUNDARY
650   nsEventStatus OnLongPress(const TapGestureInput& aEvent);
651   nsEventStatus OnLongPressUp(const TapGestureInput& aEvent);
652 
653   /**
654    * Helper method for single tap gestures.
655    */
656   nsEventStatus OnSingleTapUp(const TapGestureInput& aEvent);
657 
658   /**
659    * Helper method for a single tap confirmed.
660    */
661   nsEventStatus OnSingleTapConfirmed(const TapGestureInput& aEvent);
662 
663   /**
664    * Helper method for double taps.
665    */
666   MOZ_CAN_RUN_SCRIPT_BOUNDARY
667   nsEventStatus OnDoubleTap(const TapGestureInput& aEvent);
668 
669   /**
670    * Helper method for double taps where the double-tap gesture is disabled.
671    */
672   nsEventStatus OnSecondTap(const TapGestureInput& aEvent);
673 
674   /**
675    * Helper method to cancel any gesture currently going to Gecko. Used
676    * primarily when a user taps the screen over some clickable content but then
677    * pans down instead of letting go (i.e. to cancel a previous touch so that a
678    * new one can properly take effect.
679    */
680   nsEventStatus OnCancelTap(const TapGestureInput& aEvent);
681 
682   /**
683    * The following five methods modify the scroll offset. For the APZC
684    * representing the RCD-RSF, they also recalculate the offset of the layout
685    * viewport.
686    */
687 
688   /**
689    * Scroll the scroll frame to an X,Y offset.
690    */
691   void SetScrollOffset(const CSSPoint& aOffset);
692 
693   /**
694    * Scroll the scroll frame to an X,Y offset, clamping the resulting scroll
695    * offset to the scroll range.
696    */
697   void ClampAndSetScrollOffset(const CSSPoint& aOffset);
698 
699   /**
700    * Scroll the scroll frame by an X,Y offset.
701    * The resulting scroll offset is not clamped to the scrollable rect;
702    * the caller must ensure it stays within range.
703    */
704   void ScrollBy(const CSSPoint& aOffset);
705 
706   /**
707    * Scroll the scroll frame by an X,Y offset, clamping the resulting
708    * scroll offset to the scroll range.
709    */
710   void ScrollByAndClamp(const CSSPoint& aOffset);
711 
712   /**
713    * Scales the viewport by an amount (note that it multiplies this scale in to
714    * the current scale, it doesn't set it to |aScale|). Also considers a focus
715    * point so that the page zooms inward/outward from that point.
716    */
717   void ScaleWithFocus(float aScale, const CSSPoint& aFocus);
718 
719   /**
720    * Schedules a composite on the compositor thread.
721    */
722   void ScheduleComposite();
723 
724   /**
725    * Schedules a composite, and if enough time has elapsed since the last
726    * paint, a paint.
727    */
728   void ScheduleCompositeAndMaybeRepaint();
729 
730   /**
731    * Gets the start point of the current touch.
732    * This only makes sense if a touch is currently happening and OnTouchMove()
733    * or the equivalent for pan gestures is being invoked.
734    */
735   ParentLayerPoint PanStart() const;
736 
737   /**
738    * Gets a vector of the velocities of each axis.
739    */
740   const ParentLayerPoint GetVelocityVector() const;
741 
742   /**
743    * Sets the velocities of each axis.
744    */
745   void SetVelocityVector(const ParentLayerPoint& aVelocityVector);
746 
747   /**
748    * Gets the first touch point from a MultiTouchInput.  This gets only
749    * the first one and assumes the rest are either missing or not relevant.
750    */
751   ParentLayerPoint GetFirstTouchPoint(const MultiTouchInput& aEvent);
752 
753   /**
754    * Gets the relevant point in the event
755    * (eg. first touch, or pinch focus point) of the given InputData.
756    */
757   ExternalPoint GetExternalPoint(const InputData& aEvent);
758 
759   /**
760    * Gets the relevant point in the event, in external screen coordinates.
761    */
762   ExternalPoint GetFirstExternalTouchPoint(const MultiTouchInput& aEvent);
763 
764   /**
765    * Sets the panning state basing on the pan direction angle and current
766    * touch-action value.
767    */
768   void HandlePanningWithTouchAction(double angle);
769 
770   /**
771    * Sets the panning state ignoring the touch action value.
772    */
773   void HandlePanning(double angle);
774 
775   /**
776    * Update the panning state and axis locks.
777    */
778   void HandlePanningUpdate(const ScreenPoint& aDelta);
779 
780   /**
781    * Set and update the pinch lock
782    */
783   void HandlePinchLocking();
784 
785   /**
786    * Sets up anything needed for panning. This takes us out of the "TOUCHING"
787    * state and starts actually panning us. We provide the physical pixel
788    * position of the start point so that the pan gesture is calculated
789    * regardless of if the window/GeckoView moved during the pan.
790    */
791   nsEventStatus StartPanning(const ExternalPoint& aStartPoint);
792 
793   /**
794    * Wrapper for Axis::UpdateWithTouchAtDevicePoint(). Calls this function for
795    * both axes and factors in the time delta from the last update.
796    */
797   void UpdateWithTouchAtDevicePoint(const MultiTouchInput& aEvent);
798 
799   /**
800    * Does any panning required due to a new touch event.
801    */
802   void TrackTouch(const MultiTouchInput& aEvent);
803 
804   /**
805    * Register the start of a touch or pan gesture at the given position and
806    * time.
807    */
808   void StartTouch(const ParentLayerPoint& aPoint, uint32_t aTimestampMs);
809 
810   /**
811    * Register the end of a touch or pan gesture at the given time.
812    */
813   void EndTouch(uint32_t aTimestampMs);
814 
815   /**
816    * Utility function to send updated FrameMetrics to Gecko so that it can paint
817    * the displayport area. Calls into GeckoContentController to do the actual
818    * work. This call will use the current metrics. If this function is called
819    * from a non-main thread, it will redispatch itself to the main thread, and
820    * use the latest metrics during the redispatch.
821    */
822   void RequestContentRepaint(
823       RepaintUpdateType aUpdateType = RepaintUpdateType::eUserAction);
824 
825   /**
826    * Send the provided metrics to Gecko to trigger a repaint. This function
827    * may filter duplicate calls with the same metrics. This function must be
828    * called on the main thread.
829    */
830   void RequestContentRepaint(const FrameMetrics& aFrameMetrics,
831                              const ParentLayerPoint& aVelocity,
832                              RepaintUpdateType aUpdateType);
833 
834   /**
835    * Gets the current frame metrics. This is *not* the Gecko copy stored in the
836    * layers code.
837    */
838   const FrameMetrics& GetFrameMetrics() const;
839 
840   /**
841    * Gets the current scroll metadata. This is *not* the Gecko copy stored in
842    * the layers code/
843    */
844   const ScrollMetadata& GetScrollMetadata() const;
845 
846   /**
847    * Gets the pointer to the apzc tree manager. All the access to tree manager
848    * should be made via this method and not via private variable since this
849    * method ensures that no lock is set.
850    */
851   APZCTreeManager* GetApzcTreeManager() const;
852 
853   void AssertOnSamplerThread() const;
854   void AssertOnUpdaterThread() const;
855 
856   /**
857    * Convert ScreenPoint relative to the screen to LayoutDevicePoint relative
858    * to the parent document. This excludes the transient compositor transform.
859    * NOTE: This must be converted to LayoutDevicePoint relative to the child
860    * document before sending over IPC to a child process.
861    */
862   Maybe<LayoutDevicePoint> ConvertToGecko(const ScreenIntPoint& aPoint);
863 
864   enum AxisLockMode {
865     FREE,     /* No locking at all */
866     STANDARD, /* Default axis locking mode that remains locked until pan ends*/
867     STICKY,   /* Allow lock to be broken, with hysteresis */
868   };
869 
870   static AxisLockMode GetAxisLockMode();
871 
872   enum PinchLockMode {
873     PINCH_FREE,     /* No locking at all */
874     PINCH_STANDARD, /* Default pinch locking mode that remains locked until
875                        pinch gesture ends*/
876     PINCH_STICKY,   /* Allow lock to be broken, with hysteresis */
877   };
878 
879   static PinchLockMode GetPinchLockMode();
880 
881   // Helper function for OnSingleTapUp(), OnSingleTapConfirmed(), and
882   // OnLongPressUp().
883   nsEventStatus GenerateSingleTap(GeckoContentController::TapType aType,
884                                   const ScreenIntPoint& aPoint,
885                                   mozilla::Modifiers aModifiers);
886 
887   // Common processing at the end of a touch block.
888   void OnTouchEndOrCancel();
889 
890   LayersId mLayersId;
891   RefPtr<CompositorController> mCompositorController;
892   RefPtr<MetricsSharingController> mMetricsSharingController;
893 
894   /* Access to the following two fields is protected by the mRefPtrMonitor,
895      since they are accessed on the UI thread but can be cleared on the
896      updater thread. */
897   RefPtr<GeckoContentController> mGeckoContentController;
898   RefPtr<GestureEventListener> mGestureEventListener;
899   mutable Monitor mRefPtrMonitor;
900 
901   // This is a raw pointer to avoid introducing a reference cycle between
902   // AsyncPanZoomController and APZCTreeManager. Since these objects don't
903   // live on the main thread, we can't use the cycle collector with them.
904   // The APZCTreeManager owns the lifetime of the APZCs, so nulling this
905   // pointer out in Destroy() will prevent accessing deleted memory.
906   Atomic<APZCTreeManager*> mTreeManager;
907 
908   /* Utility functions that return a addrefed pointer to the corresponding
909    * fields. */
910   already_AddRefed<GeckoContentController> GetGeckoContentController() const;
911   already_AddRefed<GestureEventListener> GetGestureEventListener() const;
912 
913   PlatformSpecificStateBase* GetPlatformSpecificState();
914 
915  protected:
916   // Both |mScrollMetadata| and |mLastContentPaintMetrics| are protected by the
917   // monitor. Do not read from or modify them without locking.
918   ScrollMetadata mScrollMetadata;
919 
920   // Protects |mScrollMetadata|, |mLastContentPaintMetrics| and |mState|.
921   // Before manipulating |mScrollMetadata| or |mLastContentPaintMetrics| the
922   // monitor should be held. When setting |mState|, either the SetState()
923   // function can be used, or the monitor can be held and then |mState| updated.
924   // IMPORTANT: See the note about lock ordering at the top of
925   // APZCTreeManager.h. This is mutable to allow entering it from 'const'
926   // methods; doing otherwise would significantly limit what methods could be
927   // 'const'.
928   // FIXME: Please keep in mind that due to some existing coupled relationships
929   // among the class members, we should be aware of indirect usage of the
930   // monitor-protected members. That is, although this monitor isn't required to
931   // be held before manipulating non-protected class members, some functions on
932   // those members might indirectly manipulate the protected members; in such
933   // cases, the monitor should still be held. Let's take mX.CanScroll for
934   // example:
935   // Axis::CanScroll(ParentLayerCoord) calls Axis::CanScroll() which calls
936   // Axis::GetPageLength() which calls Axis::GetFrameMetrics() which calls
937   // AsyncPanZoomController::GetFrameMetrics(), therefore, this monitor should
938   // be held before calling the CanScroll function of |mX| and |mY|. These
939   // coupled relationships bring us the burden of taking care of when the
940   // monitor should be held, so they should be decoupled in the future.
941   mutable RecursiveMutex mRecursiveMutex;
942 
943  private:
944   // Metadata of the container layer corresponding to this APZC. This is
945   // stored here so that it is accessible from the UI/controller thread.
946   // These are the metrics at last content paint, the most recent
947   // values we were notified of in NotifyLayersUpdate(). Since it represents
948   // the Gecko state, it should be used as a basis for untransformation when
949   // sending messages back to Gecko.
950   ScrollMetadata mLastContentPaintMetadata;
951   FrameMetrics& mLastContentPaintMetrics;  // for convenience, refers to
952                                            // mLastContentPaintMetadata.mMetrics
953   // The last content repaint request.
954   RepaintRequest mLastPaintRequestMetrics;
955   // The metrics that we expect content to have. This is updated when we
956   // request a content repaint, and when we receive a shadow layers update.
957   // This allows us to transform events into Gecko's coordinate space.
958   FrameMetrics mExpectedGeckoMetrics;
959 
960   // This holds important state from the Metrics() at previous times
961   // SampleCompositedAsyncTransform() was called. This will always have at least
962   // one item. mRecursiveMutex must be held when using or modifying this member.
963   // Samples should be inserted to the "back" of the deque and extracted from
964   // the "front".
965   std::deque<SampledAPZCState> mSampledState;
966 
967   // Groups state variables that are specific to a platform.
968   // Initialized on first use.
969   UniquePtr<PlatformSpecificStateBase> mPlatformSpecificState;
970 
971   AxisX mX;
972   AxisY mY;
973 
974   // This flag is set to true when we are in a axis-locked pan as a result of
975   // the touch-action CSS property.
976   bool mPanDirRestricted;
977 
978   // This flag is set to true when we are in a pinch-locked state. ie: user
979   // is performing a two-finger pan rather than a pinch gesture
980   bool mPinchLocked;
981 
982   // Stores the pinch events that occured within a given timeframe. Used to
983   // calculate the focusChange and spanDistance within a fixed timeframe.
984   // RecentEventsBuffer is not threadsafe. Should only be accessed on the
985   // controller thread.
986   RecentEventsBuffer<PinchGestureInput> mPinchEventBuffer;
987 
988   // Most up-to-date constraints on zooming. These should always be reasonable
989   // values; for example, allowing a min zoom of 0.0 can cause very bad things
990   // to happen.
991   ZoomConstraints mZoomConstraints;
992 
993   // The last time the compositor has sampled the content transform for this
994   // frame.
995   TimeStamp mLastSampleTime;
996 
997   // The last sample time at which we submitted a checkerboarding report.
998   TimeStamp mLastCheckerboardReport;
999 
1000   // Stores the previous focus point if there is a pinch gesture happening. Used
1001   // to allow panning by moving multiple fingers (thus moving the focus point).
1002   ParentLayerPoint mLastZoomFocus;
1003 
1004   RefPtr<AsyncPanZoomAnimation> mAnimation;
1005 
1006   UniquePtr<OverscrollEffectBase> mOverscrollEffect;
1007 
1008   // Zoom animation id, used for zooming in WebRender. This should only be
1009   // set on the APZC instance for the root content document (i.e. the one we
1010   // support zooming on), and is only used if WebRender is enabled. The
1011   // animation id itself refers to the transform animation id that was set on
1012   // the stacking context in the WR display list. By changing the transform
1013   // associated with this id, we can adjust the scaling that WebRender applies,
1014   // thereby controlling the zoom.
1015   Maybe<uint64_t> mZoomAnimationId;
1016 
1017   // Position on screen where user first put their finger down.
1018   ExternalPoint mStartTouch;
1019 
1020   // Accessing mScrollPayload needs to be protected by mRecursiveMutex
1021   Maybe<CompositionPayload> mScrollPayload;
1022 
1023   friend class Axis;
1024 
1025  public:
1026   Maybe<CompositionPayload> NotifyScrollSampling();
1027 
1028   /**
1029    * Invoke |callable|, passing |mLastContentPaintMetrics| as argument,
1030    * while holding the APZC lock required to access |mLastContentPaintMetrics|.
1031    * This allows code outside of an AsyncPanZoomController method implementation
1032    * to access |mLastContentPaintMetrics| without having to make a copy of it.
1033    * Passes through the return value of |callable|.
1034    */
1035   template <typename Callable>
1036   auto CallWithLastContentPaintMetrics(const Callable& callable) const
1037       -> decltype(callable(mLastContentPaintMetrics)) {
1038     RecursiveMutexAutoLock lock(mRecursiveMutex);
1039     return callable(mLastContentPaintMetrics);
1040   }
1041 
1042   void SetZoomAnimationId(const Maybe<uint64_t>& aZoomAnimationId);
1043   Maybe<uint64_t> GetZoomAnimationId() const;
1044 
1045   /* ===================================================================
1046    * The functions and members in this section are used to expose
1047    * the current async transform state to callers.
1048    */
1049  public:
1050   /**
1051    * Allows consumers of async transforms to specify for what purpose they are
1052    * using the async transform:
1053    *
1054    *   |eForHitTesting| is intended for hit-testing and other uses that need
1055    *                    the most up-to-date transform, reflecting all events
1056    *                    that have been processed so far, even if the transform
1057    *                    is not yet reflected visually.
1058    *   |eForCompositing| is intended for the transform that should be reflected
1059    *                     visually.
1060    *
1061    * For example, if an APZC has metrics with the mForceDisableApz flag set,
1062    * then the |eForCompositing| async transform will be empty, while the
1063    * |eForHitTesting| async transform will reflect processed input events
1064    * regardless of mForceDisableApz.
1065    */
1066   enum AsyncTransformConsumer {
1067     eForHitTesting,
1068     eForCompositing,
1069   };
1070 
1071   /**
1072    * Get the current layout viewport of the scrollable frame corresponding to
1073    * this APZC.
1074    */
1075   CSSRect GetCurrentAsyncLayoutViewport(AsyncTransformConsumer aMode) const;
1076 
1077   /**
1078    * Get the current scroll offset of the scrollable frame corresponding
1079    * to this APZC, including the effects of any asynchronous panning and
1080    * zooming, in ParentLayer pixels.
1081    */
1082   ParentLayerPoint GetCurrentAsyncScrollOffset(
1083       AsyncTransformConsumer aMode) const;
1084 
1085   /**
1086    * Get the current scroll offset of the scrollable frame corresponding
1087    * to this APZC, including the effects of any asynchronous panning, in
1088    * CSS pixels.
1089    */
1090   CSSPoint GetCurrentAsyncScrollOffsetInCssPixels(
1091       AsyncTransformConsumer aMode) const;
1092 
1093   /**
1094    * Return a visual effect that reflects this apzc's
1095    * overscrolled state, if any.
1096    */
1097   AsyncTransformComponentMatrix GetOverscrollTransform(
1098       AsyncTransformConsumer aMode) const;
1099 
1100   /**
1101    * Returns the incremental transformation corresponding to the async pan/zoom
1102    * in progress. That is, when this transform is multiplied with the layer's
1103    * existing transform, it will make the layer appear with the desired pan/zoom
1104    * amount.
1105    * The transform can have both scroll and zoom components; the caller can
1106    * request just one or the other, or both, via the |aComponents| parameter.
1107    * When only the eLayout component is requested, the returned translation
1108    * should really be a LayerPoint, rather than a ParentLayerPoint, as it will
1109    * not be scaled by the asynchronous zoom.
1110    */
1111   AsyncTransform GetCurrentAsyncTransform(
1112       AsyncTransformConsumer aMode,
1113       AsyncTransformComponents aComponents = LayoutAndVisual) const;
1114 
1115   /**
1116    * Returns the same transform as GetCurrentAsyncTransform(), but includes
1117    * any transform due to axis over-scroll.
1118    */
1119   AsyncTransformComponentMatrix GetCurrentAsyncTransformWithOverscroll(
1120       AsyncTransformConsumer aMode,
1121       AsyncTransformComponents aComponents = LayoutAndVisual) const;
1122 
1123   /**
1124    * Returns the "zoom" bits of the transform. This includes both the rasterized
1125    * (layout device to layer scale) and async (layer scale to parent layer
1126    * scale) components of the zoom.
1127    */
1128   LayoutDeviceToParentLayerScale GetCurrentPinchZoomScale(
1129       AsyncTransformConsumer aMode) const;
1130 
GetCompositionBounds()1131   ParentLayerRect GetCompositionBounds() const {
1132     RecursiveMutexAutoLock lock(mRecursiveMutex);
1133     return mScrollMetadata.GetMetrics().GetCompositionBounds();
1134   }
1135 
GetCumulativeResolution()1136   LayoutDeviceToLayerScale2D GetCumulativeResolution() const {
1137     RecursiveMutexAutoLock lock(mRecursiveMutex);
1138     return mScrollMetadata.GetMetrics().GetCumulativeResolution();
1139   }
1140 
1141  private:
1142   /**
1143    * Advances to the next sample, if there is one, the list of sampled states
1144    * stored in mSampledState. This will make the result of
1145    * |GetCurrentAsyncTransform(eForCompositing)| and similar functions reflect
1146    * the async scroll offset and zoom of the next sample. See also
1147    * SampleCompositedAsyncTransform which creates the samples.
1148    */
1149   void AdvanceToNextSample();
1150 
1151   /**
1152    * Samples the composited async transform, storing the result into
1153    * mSampledState. This will make the result of
1154    * |GetCurrentAsyncTransform(eForCompositing)| and similar functions reflect
1155    * the async scroll offset and zoom stored in |Metrics()| when the sample
1156    * is activated via some future call to |AdvanceToNextSample|.
1157    *
1158    * Returns true if the newly sampled value is different from the last
1159    * sampled value.
1160    */
1161   bool SampleCompositedAsyncTransform(
1162       const RecursiveMutexAutoLock& aProofOfLock);
1163 
1164   /**
1165    * Updates the sample at the front of mSampledState with the latest
1166    * metrics. This makes the result of
1167    * |GetCurrentAsyncTransform(eForCompositing)| reflect the current Metrics().
1168    */
1169   void ResampleCompositedAsyncTransform(
1170       const RecursiveMutexAutoLock& aProofOfLock);
1171 
1172   /*
1173    * Helper functions to query the async layout viewport, scroll offset, and
1174    * zoom either directly from |Metrics()|, or from cached variables that
1175    * store the required value from the last time it was sampled by calling
1176    * SampleCompositedAsyncTransform(), depending on who is asking.
1177    */
1178   CSSRect GetEffectiveLayoutViewport(
1179       AsyncTransformConsumer aMode,
1180       const RecursiveMutexAutoLock& aProofOfLock) const;
1181   CSSPoint GetEffectiveScrollOffset(
1182       AsyncTransformConsumer aMode,
1183       const RecursiveMutexAutoLock& aProofOfLock) const;
1184   CSSToParentLayerScale2D GetEffectiveZoom(
1185       AsyncTransformConsumer aMode,
1186       const RecursiveMutexAutoLock& aProofOfLock) const;
1187 
1188   /**
1189    * Returns the visible portion of the content scrolled by this APZC, in
1190    * CSS pixels. The caller must have acquired the mRecursiveMutex lock.
1191    */
1192   CSSRect GetVisibleRect(const RecursiveMutexAutoLock& aProofOfLock) const;
1193 
1194  private:
1195   friend class AutoApplyAsyncTestAttributes;
1196 
1197   /**
1198    * Applies |mTestAsyncScrollOffset| and |mTestAsyncZoom| to this
1199    * AsyncPanZoomController. Calls |SampleCompositedAsyncTransform| to ensure
1200    * that the GetCurrentAsync* functions consider the test offset and zoom in
1201    * their computations.
1202    */
1203   void ApplyAsyncTestAttributes(const RecursiveMutexAutoLock& aProofOfLock);
1204 
1205   /**
1206    * Sets this AsyncPanZoomController's FrameMetrics to |aPrevFrameMetrics| and
1207    * calls |SampleCompositedAsyncTransform| to unapply any test values applied
1208    * by |ApplyAsyncTestAttributes|.
1209    */
1210   void UnapplyAsyncTestAttributes(const RecursiveMutexAutoLock& aProofOfLock,
1211                                   const FrameMetrics& aPrevFrameMetrics);
1212 
1213   /* ===================================================================
1214    * The functions and members in this section are used to manage
1215    * the state that tracks what this APZC is doing with the input events.
1216    */
1217  protected:
1218   enum PanZoomState {
1219     NOTHING,  /* no touch-start events received */
1220     FLING,    /* all touches removed, but we're still scrolling page */
1221     TOUCHING, /* one touch-start event received */
1222 
1223     PANNING,          /* panning the frame */
1224     PANNING_LOCKED_X, /* touch-start followed by move (i.e. panning with axis
1225                          lock) X axis */
1226     PANNING_LOCKED_Y, /* as above for Y axis */
1227 
1228     PAN_MOMENTUM, /* like PANNING, but controlled by momentum PanGestureInput
1229                      events */
1230 
1231     PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */
1232     ANIMATING_ZOOM,       /* animated zoom to a new rect */
1233     OVERSCROLL_ANIMATION, /* Spring-based animation used to relieve overscroll
1234                              once the finger is lifted. */
1235     SMOOTH_SCROLL,        /* Smooth scrolling to destination. Used by
1236                              CSSOM-View smooth scroll-behavior */
1237     WHEEL_SCROLL,    /* Smooth scrolling to a destination for a wheel event. */
1238     KEYBOARD_SCROLL, /* Smooth scrolling to a destination for a keyboard event.
1239                       */
1240     AUTOSCROLL,      /* Autoscroll animation. */
1241     SCROLLBAR_DRAG   /* Async scrollbar drag. */
1242   };
1243   // This is in theory protected by |mRecursiveMutex|; that is, it should be
1244   // held whenever this is updated. In practice though... see bug 897017.
1245   PanZoomState mState;
1246 
1247   static bool IsPanningState(PanZoomState aState);
1248 
1249   /**
1250    * Returns whether the specified PanZoomState does not need to be reset when
1251    * a scroll offset update is processed.
1252    */
1253   static bool CanHandleScrollOffsetUpdate(PanZoomState aState);
1254 
1255   /**
1256    * Determine whether a main-thread scroll offset update should result in
1257    * a call to CancelAnimation() (which interrupts in-progress animations and
1258    * gestures).
1259    *
1260    * If the update is a relative update, |aRelativeDelta| contains its amount.
1261    * If the update is not a relative update, GetMetrics() should already reflect
1262    * the new offset at the time of the call.
1263    */
1264   bool ShouldCancelAnimationForScrollUpdate(
1265       const Maybe<CSSPoint>& aRelativeDelta);
1266 
1267  private:
1268   friend class StateChangeNotificationBlocker;
1269   /**
1270    * A counter of how many StateChangeNotificationBlockers are active.
1271    * A non-zero count will prevent state change notifications from
1272    * being dispatched. Only code that holds mRecursiveMutex should touch this.
1273    */
1274   int mNotificationBlockers;
1275 
1276   /**
1277    * Helper to set the current state. Holds the monitor before actually setting
1278    * it and fires content controller events based on state changes. Always set
1279    * the state using this call, do not set it directly.
1280    */
1281   void SetState(PanZoomState aState);
1282   /**
1283    * Fire content controller notifications about state changes, assuming no
1284    * StateChangeNotificationBlocker has been activated.
1285    */
1286   void DispatchStateChangeNotification(PanZoomState aOldState,
1287                                        PanZoomState aNewState);
1288   /**
1289    * Internal helpers for checking general state of this apzc.
1290    */
1291   bool IsInTransformingState() const;
1292   static bool IsTransformingState(PanZoomState aState);
1293 
1294   /* ===================================================================
1295    * The functions and members in this section are used to manage
1296    * blocks of touch events and the state needed to deal with content
1297    * listeners.
1298    */
1299  public:
1300   /**
1301    * Flush a repaint request if one is needed, without throttling it with the
1302    * paint throttler.
1303    */
1304   void FlushRepaintForNewInputBlock();
1305 
1306   /**
1307    * Given an input event and the touch block it belongs to, check if the
1308    * event can lead to a panning/zooming behavior.
1309    * This is primarily used to figure out when to dispatch the pointercancel
1310    * event for the pointer events spec.
1311    */
1312   bool ArePointerEventsConsumable(TouchBlockState* aBlock,
1313                                   const MultiTouchInput& aInput);
1314 
1315   /**
1316    * Clear internal state relating to touch input handling.
1317    */
1318   void ResetTouchInputState();
1319 
1320   /**
1321    * Gets a ref to the input queue that is shared across the entire tree
1322    * manager.
1323    */
1324   const RefPtr<InputQueue>& GetInputQueue() const;
1325 
1326  private:
1327   void CancelAnimationAndGestureState();
1328 
1329   RefPtr<InputQueue> mInputQueue;
1330   InputBlockState* GetCurrentInputBlock() const;
1331   TouchBlockState* GetCurrentTouchBlock() const;
1332   bool HasReadyTouchBlock() const;
1333 
1334   PanGestureBlockState* GetCurrentPanGestureBlock() const;
1335   PinchGestureBlockState* GetCurrentPinchGestureBlock() const;
1336 
1337  private:
1338   /* ===================================================================
1339    * The functions and members in this section are used to manage
1340    * fling animations, smooth scroll animations, and overscroll
1341    * during a fling or smooth scroll.
1342    */
1343  public:
1344   /**
1345    * Attempt a fling with the velocity specified in |aHandoffState|.
1346    * |aHandoffState.mIsHandoff| should be true iff. the fling was handed off
1347    * from a previous APZC, and determines whether acceleration is applied
1348    * to the fling.
1349    * We only accept the fling in the direction(s) in which we are pannable.
1350    * Returns the "residual velocity", i.e. the portion of
1351    * |aHandoffState.mVelocity| that this APZC did not consume.
1352    */
1353   ParentLayerPoint AttemptFling(const FlingHandoffState& aHandoffState);
1354 
1355   ParentLayerPoint AdjustHandoffVelocityForOverscrollBehavior(
1356       ParentLayerPoint& aHandoffVelocity) const;
1357 
1358  private:
1359   friend class StackScrollerFlingAnimation;
1360   friend class AutoscrollAnimation;
1361   template <typename FlingPhysics>
1362   friend class GenericFlingAnimation;
1363   friend class AndroidFlingPhysics;
1364   friend class DesktopFlingPhysics;
1365   friend class OverscrollAnimation;
1366   friend class SmoothScrollAnimation;
1367   friend class GenericScrollAnimation;
1368   friend class WheelScrollAnimation;
1369   friend class KeyboardScrollAnimation;
1370   friend class ZoomAnimation;
1371 
1372   friend class GenericOverscrollEffect;
1373   friend class WidgetOverscrollEffect;
1374 
1375   // The initial velocity of the most recent fling.
1376   ParentLayerPoint mLastFlingVelocity;
1377   // The time at which the most recent fling started.
1378   TimeStamp mLastFlingTime;
1379   // Indicates if the repaint-during-pinch timer is currently set
1380   bool mPinchPaintTimerSet;
1381 
1382   // Deal with overscroll resulting from a fling animation. This is only ever
1383   // called on APZC instances that were actually performing a fling.
1384   // The overscroll is handled by trying to hand the fling off to an APZC
1385   // later in the handoff chain, or if there are no takers, continuing the
1386   // fling and entering an overscrolled state.
1387   void HandleFlingOverscroll(
1388       const ParentLayerPoint& aVelocity,
1389       const RefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
1390       const RefPtr<const AsyncPanZoomController>& aScrolledApzc);
1391 
1392   void HandleSmoothScrollOverscroll(const ParentLayerPoint& aVelocity);
1393 
1394   // Start an overscroll animation with the given initial velocity.
1395   void StartOverscrollAnimation(const ParentLayerPoint& aVelocity);
1396 
1397   void SmoothScrollTo(const CSSPoint& aDestination);
1398 
1399   // Returns whether overscroll is allowed during an event.
1400   bool AllowScrollHandoffInCurrentBlock() const;
1401 
1402   // Invoked by the pinch repaint timer.
1403   void DoDelayedRequestContentRepaint();
1404 
1405   // Compute the number of ParentLayer pixels per (Screen) inch at the given
1406   // point and in the given direction.
1407   float ComputePLPPI(ParentLayerPoint aPoint,
1408                      ParentLayerPoint aDirection) const;
1409 
1410   /* ===================================================================
1411    * The functions and members in this section are used to make ancestor chains
1412    * out of APZC instances. These chains can only be walked or manipulated
1413    * while holding the lock in the associated APZCTreeManager instance.
1414    */
1415  public:
SetParent(AsyncPanZoomController * aParent)1416   void SetParent(AsyncPanZoomController* aParent) { mParent = aParent; }
1417 
GetParent()1418   AsyncPanZoomController* GetParent() const { return mParent; }
1419 
1420   /* Returns true if there is no APZC higher in the tree with the same
1421    * layers id.
1422    */
HasNoParentWithSameLayersId()1423   bool HasNoParentWithSameLayersId() const {
1424     return !mParent || (mParent->mLayersId != mLayersId);
1425   }
1426 
IsRootForLayersId()1427   bool IsRootForLayersId() const {
1428     RecursiveMutexAutoLock lock(mRecursiveMutex);
1429     return mScrollMetadata.IsLayersIdRoot();
1430   }
1431 
IsRootContent()1432   bool IsRootContent() const {
1433     RecursiveMutexAutoLock lock(mRecursiveMutex);
1434     return Metrics().IsRootContent();
1435   }
1436 
1437  private:
1438   // |mTreeManager| belongs in this section but it's declaration is a bit
1439   // further above due to initialization-order constraints.
1440 
1441   RefPtr<AsyncPanZoomController> mParent;
1442 
1443   /* ===================================================================
1444    * The functions and members in this section are used for scrolling,
1445    * including handing off scroll to another APZC, and overscrolling.
1446    */
1447 
GetScrollId()1448   ScrollableLayerGuid::ViewID GetScrollId() const {
1449     RecursiveMutexAutoLock lock(mRecursiveMutex);
1450     return Metrics().GetScrollId();
1451   }
1452 
1453  public:
GetScrollHandoffParentId()1454   ScrollableLayerGuid::ViewID GetScrollHandoffParentId() const {
1455     return mScrollMetadata.GetScrollParentId();
1456   }
1457 
1458   /**
1459    * Attempt to scroll in response to a touch-move from |aStartPoint| to
1460    * |aEndPoint|, which are in our (transformed) screen coordinates.
1461    * Due to overscroll handling, there may not actually have been a touch-move
1462    * at these points, but this function will scroll as if there had been.
1463    * If this attempt causes overscroll (i.e. the layer cannot be scrolled
1464    * by the entire amount requested), the overscroll is passed back to the
1465    * tree manager via APZCTreeManager::DispatchScroll(). If the tree manager
1466    * does not find an APZC further in the handoff chain to accept the
1467    * overscroll, and this APZC is pannable, this APZC enters an overscrolled
1468    * state.
1469    * |aOverscrollHandoffChain| and |aOverscrollHandoffChainIndex| are used by
1470    * the tree manager to keep track of which APZC to hand off the overscroll
1471    * to; this function increments the chain and the index and passes it on to
1472    * APZCTreeManager::DispatchScroll() in the event of overscroll.
1473    * Returns true iff. this APZC, or an APZC further down the
1474    * handoff chain, accepted the scroll (possibly entering an overscrolled
1475    * state). If this returns false, the caller APZC knows that it should enter
1476    * an overscrolled state itself if it can.
1477    * aStartPoint and aEndPoint are modified depending on how much of the
1478    * scroll gesture was consumed by APZCs in the handoff chain.
1479    */
1480   bool AttemptScroll(ParentLayerPoint& aStartPoint, ParentLayerPoint& aEndPoint,
1481                      OverscrollHandoffState& aOverscrollHandoffState);
1482 
1483   void FlushRepaintForOverscrollHandoff();
1484 
1485   /**
1486    * If overscrolled, start a snap-back animation and return true.
1487    * Otherwise return false.
1488    */
1489   bool SnapBackIfOverscrolled();
1490 
1491   /**
1492    * Build the chain of APZCs along which scroll will be handed off when
1493    * this APZC receives input events.
1494    *
1495    * Notes on lifetime and const-correctness:
1496    *   - The returned handoff chain is |const|, to indicate that it cannot be
1497    *     changed after being built.
1498    *   - When passing the chain to a function that uses it without storing it,
1499    *     pass it by reference-to-const (as in |const OverscrollHandoffChain&|).
1500    *   - When storing the chain, store it by RefPtr-to-const (as in
1501    *     |RefPtr<const OverscrollHandoffChain>|). This ensures the chain is
1502    *     kept alive. Note that queueing a task that uses the chain as an
1503    *     argument constitutes storing, as the task may outlive its queuer.
1504    *   - When passing the chain to a function that will store it, pass it as
1505    *     |const RefPtr<const OverscrollHandoffChain>&|. This allows the
1506    *     function to copy it into the |RefPtr<const OverscrollHandoffChain>|
1507    *     that will store it, while avoiding an unnecessary copy (and thus
1508    *     AddRef() and Release()) when passing it.
1509    */
1510   RefPtr<const OverscrollHandoffChain> BuildOverscrollHandoffChain();
1511 
1512  private:
1513   /**
1514    * A helper function for calling APZCTreeManager::DispatchScroll().
1515    * Guards against the case where the APZC is being concurrently destroyed
1516    * (and thus mTreeManager is being nulled out).
1517    */
1518   bool CallDispatchScroll(ParentLayerPoint& aStartPoint,
1519                           ParentLayerPoint& aEndPoint,
1520                           OverscrollHandoffState& aOverscrollHandoffState);
1521 
1522   void RecordScrollPayload(const TimeStamp& aTimeStamp);
1523 
1524   /**
1525    * A helper function for overscrolling during panning. This is a wrapper
1526    * around OverscrollBy() that also implements restrictions on entering
1527    * overscroll based on the pan angle.
1528    */
1529   void OverscrollForPanning(ParentLayerPoint& aOverscroll,
1530                             const ScreenPoint& aPanDistance);
1531 
1532   /**
1533    * Try to overscroll by 'aOverscroll'.
1534    * If we are pannable on a particular axis, that component of 'aOverscroll'
1535    * is transferred to any existing overscroll.
1536    */
1537   void OverscrollBy(ParentLayerPoint& aOverscroll);
1538 
1539   // Helper function for CanScroll().
1540   ParentLayerPoint GetDeltaForEvent(const InputData& aEvent) const;
1541 
1542   /* ===================================================================
1543    * The functions and members in this section are used to maintain the
1544    * area that this APZC instance is responsible for. This is used when
1545    * hit-testing to see which APZC instance should handle touch events.
1546    */
1547  public:
SetAncestorTransform(const AncestorTransform & aAncestorTransform)1548   void SetAncestorTransform(const AncestorTransform& aAncestorTransform) {
1549     mAncestorTransform = aAncestorTransform;
1550   }
1551 
GetAncestorTransform()1552   Matrix4x4 GetAncestorTransform() const {
1553     return mAncestorTransform.CombinedTransform();
1554   }
1555 
AncestorTransformContainsPerspective()1556   bool AncestorTransformContainsPerspective() const {
1557     return mAncestorTransform.ContainsPerspectiveTransform();
1558   }
1559 
1560   // Return the perspective transform component of the ancestor transform.
GetAncestorTransformPerspective()1561   Matrix4x4 GetAncestorTransformPerspective() const {
1562     return mAncestorTransform.GetPerspectiveTransform();
1563   }
1564 
1565   // Returns whether or not this apzc contains the given screen point within
1566   // its composition bounds.
1567   bool Contains(const ScreenIntPoint& aPoint) const;
1568 
IsOverscrolled()1569   bool IsOverscrolled() const {
1570     return mX.IsOverscrolled() || mY.IsOverscrolled();
1571   }
1572 
1573   bool IsInPanningState() const;
1574 
1575  private:
1576   /* This is the cumulative CSS transform for all the layers from (and
1577    * including) the parent APZC down to (but excluding) this one, and excluding
1578    * any perspective transforms. */
1579   AncestorTransform mAncestorTransform;
1580 
1581   /* ===================================================================
1582    * The functions and members in this section are used for sharing the
1583    * FrameMetrics across processes for the progressive tiling code.
1584    */
1585  private:
1586   /* Unique id assigned to each APZC. Used with ViewID to uniquely identify
1587    * shared FrameMeterics used in progressive tile painting. */
1588   const uint32_t mAPZCId;
1589 
1590   RefPtr<ipc::SharedMemoryBasic> mSharedFrameMetricsBuffer;
1591   CrossProcessMutex* mSharedLock;
1592   /**
1593    * Called when ever Metrics() is updated so that if it is being
1594    * shared with the content process the shared FrameMetrics may be updated.
1595    */
1596   void UpdateSharedCompositorFrameMetrics();
1597   /**
1598    * Create a shared memory buffer for containing the FrameMetrics and
1599    * a CrossProcessMutex that may be shared with the content process
1600    * for use in progressive tiled update calculations.
1601    */
1602   void ShareCompositorFrameMetrics();
1603 
1604   /* ===================================================================
1605    * The functions and members in this section are used for testing
1606    * and assertion purposes only.
1607    */
1608  public:
1609   /**
1610    * Gets whether this APZC has performed async key scrolling.
1611    */
TestHasAsyncKeyScrolled()1612   bool TestHasAsyncKeyScrolled() const { return mTestHasAsyncKeyScrolled; }
1613 
1614   /**
1615    * Set an extra offset for testing async scrolling.
1616    */
1617   void SetTestAsyncScrollOffset(const CSSPoint& aPoint);
1618   /**
1619    * Set an extra offset for testing async scrolling.
1620    */
1621   void SetTestAsyncZoom(const LayerToParentLayerScale& aZoom);
1622 
MarkAsyncTransformAppliedToContent()1623   void MarkAsyncTransformAppliedToContent() {
1624     mAsyncTransformAppliedToContent = true;
1625   }
1626 
GetAsyncTransformAppliedToContent()1627   bool GetAsyncTransformAppliedToContent() const {
1628     return mAsyncTransformAppliedToContent;
1629   }
1630 
GetLayersId()1631   LayersId GetLayersId() const { return mLayersId; }
1632 
IsAsyncZooming()1633   bool IsAsyncZooming() const {
1634     return mState == PINCHING || mState == ANIMATING_ZOOM;
1635   }
1636 
1637  private:
1638   // Extra offset to add to the async scroll position for testing
1639   CSSPoint mTestAsyncScrollOffset;
1640   // Extra zoom to include in the aync zoom for testing
1641   LayerToParentLayerScale mTestAsyncZoom;
1642   uint8_t mTestAttributeAppliers;
1643   // Flag to track whether or not the APZ transform is not used. This
1644   // flag is recomputed for every composition frame.
1645   bool mAsyncTransformAppliedToContent;
1646   // Flag to track whether or not this APZC has ever async key scrolled.
1647   bool mTestHasAsyncKeyScrolled;
1648 
1649   /* ===================================================================
1650    * The functions and members in this section are used for checkerboard
1651    * recording.
1652    */
1653  private:
1654   // Helper function to update the in-progress checkerboard event, if any.
1655   void UpdateCheckerboardEvent(const MutexAutoLock& aProofOfLock,
1656                                uint32_t aMagnitude);
1657 
1658   // Mutex protecting mCheckerboardEvent
1659   Mutex mCheckerboardEventLock;
1660   // This is created when this APZC instance is first included as part of a
1661   // composite. If a checkerboard event takes place, this is destroyed at the
1662   // end of the event, and a new one is created on the next composite.
1663   UniquePtr<CheckerboardEvent> mCheckerboardEvent;
1664   // This is used to track the total amount of time that we could reasonably
1665   // be checkerboarding. Combined with other info, this allows us to
1666   // meaningfully say how frequently users actually encounter checkerboarding.
1667   PotentialCheckerboardDurationTracker mPotentialCheckerboardTracker;
1668 
1669   /* ===================================================================
1670    * The functions in this section are used for CSS scroll snapping.
1671    */
1672 
1673   // If moving |aStartPosition| by |aDelta| should trigger scroll snapping,
1674   // adjust |aDelta| to reflect the snapping (that is, make it a delta that will
1675   // take us to the desired snap point). The delta is interpreted as being
1676   // relative to |aStartPosition|, and if a target snap point is found,
1677   // |aStartPosition| is also updated, to the value of the snap point.
1678   // |aUnit| affects the snapping behaviour (see ScrollSnapUtils::
1679   // GetSnapPointForDestination).
1680   // Returns true iff. a target snap point was found.
1681   bool MaybeAdjustDeltaForScrollSnapping(ScrollUnit aUnit,
1682                                          ParentLayerPoint& aDelta,
1683                                          CSSPoint& aStartPosition);
1684 
1685   // A wrapper function of MaybeAdjustDeltaForScrollSnapping for
1686   // ScrollWheelInput.
1687   bool MaybeAdjustDeltaForScrollSnappingOnWheelInput(
1688       const ScrollWheelInput& aEvent, ParentLayerPoint& aDelta,
1689       CSSPoint& aStartPosition);
1690 
1691   bool MaybeAdjustDestinationForScrollSnapping(const KeyboardInput& aEvent,
1692                                                CSSPoint& aDestination);
1693 
1694   // Snap to a snap position nearby the current scroll position, if appropriate.
1695   void ScrollSnap();
1696 
1697   // Snap to a snap position nearby the destination predicted based on the
1698   // current velocity, if appropriate.
1699   void ScrollSnapToDestination();
1700 
1701   // Snap to a snap position nearby the provided destination, if appropriate.
1702   void ScrollSnapNear(const CSSPoint& aDestination);
1703 
1704   // Find a snap point near |aDestination| that we should snap to.
1705   // Returns the snap point if one was found, or an empty Maybe otherwise.
1706   // |aUnit| affects the snapping behaviour (see ScrollSnapUtils::
1707   // GetSnapPointForDestination). It should generally be determined by the
1708   // type of event that's triggering the scroll.
1709   Maybe<CSSPoint> FindSnapPointNear(const CSSPoint& aDestination,
1710                                     ScrollUnit aUnit);
1711 };
1712 
1713 }  // namespace layers
1714 }  // namespace mozilla
1715 
1716 #endif  // mozilla_layers_PanZoomController_h
1717