gfx/layers/apz/src/AsyncPanZoomController.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     7 #ifndef mozilla_layers_AsyncPanZoomController_h
     8 #define mozilla_layers_AsyncPanZoomController_h
    10 #include "CrossProcessMutex.h"
    11 #include "mozilla/layers/GeckoContentController.h"
    12 #include "mozilla/Attributes.h"
    13 #include "mozilla/EventForwards.h"
    14 #include "mozilla/Monitor.h"
    15 #include "mozilla/ReentrantMonitor.h"
    16 #include "mozilla/RefPtr.h"
    17 #include "mozilla/Atomics.h"
    18 #include "InputData.h"
    19 #include "Axis.h"
    20 #include "TaskThrottler.h"
    21 #include "gfx3DMatrix.h"
    23 #include "base/message_loop.h"
    25 namespace mozilla {
    27 namespace ipc {
    29 class SharedMemoryBasic;
    31 }
    33 namespace layers {
    35 struct ScrollableLayerGuid;
    36 class CompositorParent;
    37 class GestureEventListener;
    38 class ContainerLayer;
    39 class PCompositorParent;
    40 class ViewTransform;
    41 class APZCTreeManager;
    42 class AsyncPanZoomAnimation;
    43 class FlingAnimation;
    45 /**
    46  * Controller for all panning and zooming logic. Any time a user input is
    47  * detected and it must be processed in some way to affect what the user sees,
    48  * it goes through here. Listens for any input event from InputData and can
    49  * optionally handle WidgetGUIEvent-derived touch events, but this must be done
    50  * on the main thread. Note that this class completely cross-platform.
    51  *
    52  * Input events originate on the UI thread of the platform that this runs on,
    53  * and are then sent to this class. This class processes the event in some way;
    54  * for example, a touch move will usually lead to a panning of content (though
    55  * of course there are exceptions, such as if content preventDefaults the event,
    56  * or if the target frame is not scrollable). The compositor interacts with this
    57  * class by locking it and querying it for the current transform matrix based on
    58  * the panning and zooming logic that was invoked on the UI thread.
    59  *
    60  * Currently, each outer DOM window (i.e. a website in a tab, but not any
    61  * subframes) has its own AsyncPanZoomController. In the future, to support
    62  * asynchronously scrolled subframes, we want to have one AsyncPanZoomController
    63  * per frame.
    64  */
    65 class AsyncPanZoomController {
    66   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomController)
    68   typedef mozilla::MonitorAutoLock MonitorAutoLock;
    69   typedef uint32_t TouchBehaviorFlags;
    71 public:
    72   enum GestureBehavior {
    73     // The platform code is responsible for forwarding gesture events here. We
    74     // will not attempt to generate gesture events from MultiTouchInputs.
    75     DEFAULT_GESTURES,
    76     // An instance of GestureEventListener is used to detect gestures. This is
    77     // handled completely internally within this class.
    78     USE_GESTURE_DETECTOR
    79   };
    81   /**
    82    * Constant describing the tolerance in distance we use, multiplied by the
    83    * device DPI, before we start panning the screen. This is to prevent us from
    84    * accidentally processing taps as touch moves, and from very short/accidental
    85    * touches moving the screen.
    86    */
    87   static float GetTouchStartTolerance();
    89   AsyncPanZoomController(uint64_t aLayersId,
    90                          APZCTreeManager* aTreeManager,
    91                          GeckoContentController* aController,
    92                          GestureBehavior aGestures = DEFAULT_GESTURES);
    94   // --------------------------------------------------------------------------
    95   // These methods must only be called on the gecko thread.
    96   //
    98   /**
    99    * Read the various prefs and do any global initialization for all APZC instances.
   100    * This must be run on the gecko thread before any APZC instances are actually
   101    * used for anything meaningful.
   102    */
   103   static void InitializeGlobalState();
   105   // --------------------------------------------------------------------------
   106   // These methods must only be called on the controller/UI thread.
   107   //
   109   /**
   110    * General handler for incoming input events. Manipulates the frame metrics
   111    * based on what type of input it is. For example, a PinchGestureEvent will
   112    * cause scaling. This should only be called externally to this class.
   113    * HandleInputEvent() should be used internally.
   114    */
   115   nsEventStatus ReceiveInputEvent(const InputData& aEvent);
   117   /**
   118    * Kicks an animation to zoom to a rect. This may be either a zoom out or zoom
   119    * in. The actual animation is done on the compositor thread after being set
   120    * up.
   121    */
   122   void ZoomToRect(CSSRect aRect);
   124   /**
   125    * If we have touch listeners, this should always be called when we know
   126    * definitively whether or not content has preventDefaulted any touch events
   127    * that have come in. If |aPreventDefault| is true, any touch events in the
   128    * queue will be discarded.
   129    */
   130   void ContentReceivedTouch(bool aPreventDefault);
   132   /**
   133    * Updates any zoom constraints contained in the <meta name="viewport"> tag.
   134    */
   135   void UpdateZoomConstraints(const ZoomConstraints& aConstraints);
   137   /**
   138    * Return the zoom constraints last set for this APZC (in the constructor
   139    * or in UpdateZoomConstraints()).
   140    */
   141   ZoomConstraints GetZoomConstraints() const;
   143   /**
   144    * Schedules a runnable to run on the controller/UI thread at some time
   145    * in the future.
   146    */
   147   void PostDelayedTask(Task* aTask, int aDelayMs);
   149   // --------------------------------------------------------------------------
   150   // These methods must only be called on the compositor thread.
   151   //
   153   bool UpdateAnimation(const TimeStamp& aSampleTime);
   155   /**
   156    * The compositor calls this when it's about to draw pannable/zoomable content
   157    * and is setting up transforms for compositing the layer tree. This is not
   158    * idempotent. For example, a fling transform can be applied each time this is
   159    * called (though not necessarily). |aSampleTime| is the time that this is
   160    * sampled at; this is used for interpolating animations. Calling this sets a
   161    * new transform in |aNewTransform| which should be multiplied to the transform
   162    * in the shadow layer corresponding to this APZC.
   163    *
   164    * Return value indicates whether or not any currently running animation
   165    * should continue. That is, if true, the compositor should schedule another
   166    * composite.
   167    */
   168   bool SampleContentTransformForFrame(const TimeStamp& aSampleTime,
   169                                       ViewTransform* aNewTransform,
   170                                       ScreenPoint& aScrollOffset);
   172   /**
   173    * A shadow layer update has arrived. |aLayerMetrics| is the new FrameMetrics
   174    * for the container layer corresponding to this APZC.
   175    * |aIsFirstPaint| is a flag passed from the shadow
   176    * layers code indicating that the frame metrics being sent with this call are
   177    * the initial metrics and the initial paint of the frame has just happened.
   178    */
   179   void NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint);
   181   /**
   182    * The platform implementation must set the compositor parent so that we can
   183    * request composites.
   184    */
   185   void SetCompositorParent(CompositorParent* aCompositorParent);
   187   /**
   188    * The platform implementation must set the cross process compositor if
   189    * there is one associated with the layer tree. The cross process compositor
   190    * allows the APZC to share its FrameMetrics with the content process.
   191    * The shared FrameMetrics is used in progressive paint updates.
   192    */
   193   void SetCrossProcessCompositorParent(PCompositorParent* aCrossProcessCompositorParent);
   195   // --------------------------------------------------------------------------
   196   // These methods can be called from any thread.
   197   //
   199   /**
   200    * Shut down the controller/UI thread state and prepare to be
   201    * deleted (which may happen from any thread).
   202    */
   203   void Destroy();
   205   /**
   206    * Returns true if Destroy() has already been called on this APZC instance.
   207    */
   208   bool IsDestroyed();
   210   /**
   211    * Returns the incremental transformation corresponding to the async pan/zoom
   212    * in progress. That is, when this transform is multiplied with the layer's
   213    * existing transform, it will make the layer appear with the desired pan/zoom
   214    * amount.
   215    */
   216   ViewTransform GetCurrentAsyncTransform();
   218   /**
   219    * Returns the part of the async transform that will remain once Gecko does a
   220    * repaint at the desired metrics. That is, in the steady state:
   221    * gfx3DMatrix(GetCurrentAsyncTransform()) === GetNontransientAsyncTransform()
   222    */
   223   gfx3DMatrix GetNontransientAsyncTransform();
   225   /**
   226    * Returns the transform to take something from the coordinate space of the
   227    * last thing we know gecko painted, to the coordinate space of the last thing
   228    * we asked gecko to paint. In cases where that last request has not yet been
   229    * processed, this is needed to transform input events properly into a space
   230    * gecko will understand.
   231    */
   232   gfx3DMatrix GetTransformToLastDispatchedPaint();
   234   /**
   235    * Recalculates the displayport. Ideally, this should paint an area bigger
   236    * than the composite-to dimensions so that when you scroll down, you don't
   237    * checkerboard immediately. This includes a bunch of logic, including
   238    * algorithms to bias painting in the direction of the velocity.
   239    */
   240   static const LayerMargin CalculatePendingDisplayPort(
   241     const FrameMetrics& aFrameMetrics,
   242     const ScreenPoint& aVelocity,
   243     double aEstimatedPaintDuration);
   245   /**
   246    * Send an mozbrowserasyncscroll event.
   247    * *** The monitor must be held while calling this.
   248    */
   249   void SendAsyncScrollEvent();
   251   /**
   252    * Handler for events which should not be intercepted by the touch listener.
   253    * Does the work for ReceiveInputEvent().
   254    */
   255   nsEventStatus HandleInputEvent(const InputData& aEvent);
   257   /**
   258    * Handler for gesture events.
   259    * Currently some gestures are detected in GestureEventListener that calls
   260    * APZC back through this handler in order to avoid recursive calls to
   261    * APZC::HandleInputEvent() which is supposed to do the work for
   262    * ReceiveInputEvent().
   263    */
   264   nsEventStatus HandleGestureEvent(const InputData& aEvent);
   266   /**
   267    * Populates the provided object (if non-null) with the scrollable guid of this apzc.
   268    */
   269   void GetGuid(ScrollableLayerGuid* aGuidOut);
   271   /**
   272    * Returns the scrollable guid of this apzc.
   273    */
   274   ScrollableLayerGuid GetGuid();
   276   /**
   277    * Returns true if this APZC instance is for the layer identified by the guid.
   278    */
   279   bool Matches(const ScrollableLayerGuid& aGuid);
   281   /**
   282    * Sync panning and zooming animation using a fixed frame time.
   283    * This will ensure that we animate the APZC correctly with other external
   284    * animations to the same timestamp.
   285    */
   286   static void SetFrameTime(const TimeStamp& aMilliseconds);
   288   void StartAnimation(AsyncPanZoomAnimation* aAnimation);
   290   /**
   291    * Cancels any currently running animation. Note that all this does is set the
   292    * state of the AsyncPanZoomController back to NOTHING, but it is the
   293    * animation's responsibility to check this before advancing.
   294    */
   295   void CancelAnimation();
   297   /**
   298    * Take over a fling with the given velocity from another APZC. Used for
   299    * during overscroll handoff for a fling.
   300    */
   301   void TakeOverFling(ScreenPoint aVelocity);
   303   /**
   304    * Returns allowed touch behavior for the given point on the scrollable layer.
   305    * Internally performs a kind of hit testing based on the regions constructed
   306    * on the main thread and attached to the current scrollable layer. Each of such regions
   307    * contains info about allowed touch behavior. If regions info isn't enough it returns
   308    * UNKNOWN value and we should switch to the fallback approach - asking content.
   309    * TODO: for now it's only a stub and returns hardcoded magic value. As soon as bug 928833
   310    * is done we should integrate its logic here.
   311    */
   312   TouchBehaviorFlags GetAllowedTouchBehavior(ScreenIntPoint& aPoint);
   314   /**
   315    * Sets allowed touch behavior for current touch session.
   316    * This method is invoked by the APZCTreeManager which in its turn invoked by
   317    * the widget after performing touch-action values retrieving.
   318    * Must be called after receiving the TOUCH_START even that started the
   319    * touch session.
   320    */
   321   void SetAllowedTouchBehavior(const nsTArray<TouchBehaviorFlags>& aBehaviors);
   323   /**
   324    * Returns whether this APZC is for an element marked with the 'scrollgrab'
   325    * attribute.
   326    */
   327   bool HasScrollgrab() const { return mFrameMetrics.mHasScrollgrab; }
   329   /**
   330    * Set an extra offset for testing async scrolling.
   331    */
   332   void SetTestAsyncScrollOffset(const CSSPoint& aPoint)
   333   {
   334     mTestAsyncScrollOffset = aPoint;
   335   }
   337   /**
   338    * Returns whether this APZC has room to be panned (in any direction).
   339    */
   340   bool IsPannable() const;
   342 protected:
   343   // Protected destructor, to discourage deletion outside of Release():
   344   ~AsyncPanZoomController();
   346   /**
   347    * Helper method for touches beginning. Sets everything up for panning and any
   348    * multitouch gestures.
   349    */
   350   nsEventStatus OnTouchStart(const MultiTouchInput& aEvent);
   352   /**
   353    * Helper method for touches moving. Does any transforms needed when panning.
   354    */
   355   nsEventStatus OnTouchMove(const MultiTouchInput& aEvent);
   357   /**
   358    * Helper method for touches ending. Redraws the screen if necessary and does
   359    * any cleanup after a touch has ended.
   360    */
   361   nsEventStatus OnTouchEnd(const MultiTouchInput& aEvent);
   363   /**
   364    * Helper method for touches being cancelled. Treated roughly the same as a
   365    * touch ending (OnTouchEnd()).
   366    */
   367   nsEventStatus OnTouchCancel(const MultiTouchInput& aEvent);
   369   /**
   370    * Helper method for scales beginning. Distinct from the OnTouch* handlers in
   371    * that this implies some outside implementation has determined that the user
   372    * is pinching.
   373    */
   374   nsEventStatus OnScaleBegin(const PinchGestureInput& aEvent);
   376   /**
   377    * Helper method for scaling. As the user moves their fingers when pinching,
   378    * this changes the scale of the page.
   379    */
   380   nsEventStatus OnScale(const PinchGestureInput& aEvent);
   382   /**
   383    * Helper method for scales ending. Redraws the screen if necessary and does
   384    * any cleanup after a scale has ended.
   385    */
   386   nsEventStatus OnScaleEnd(const PinchGestureInput& aEvent);
   388   /**
   389    * Helper methods for long press gestures.
   390    */
   391   nsEventStatus OnLongPress(const TapGestureInput& aEvent);
   392   nsEventStatus OnLongPressUp(const TapGestureInput& aEvent);
   394   /**
   395    * Helper method for single tap gestures.
   396    */
   397   nsEventStatus OnSingleTapUp(const TapGestureInput& aEvent);
   399   /**
   400    * Helper method for a single tap confirmed.
   401    */
   402   nsEventStatus OnSingleTapConfirmed(const TapGestureInput& aEvent);
   404   /**
   405    * Helper method for double taps.
   406    */
   407   nsEventStatus OnDoubleTap(const TapGestureInput& aEvent);
   409   /**
   410    * Helper method to cancel any gesture currently going to Gecko. Used
   411    * primarily when a user taps the screen over some clickable content but then
   412    * pans down instead of letting go (i.e. to cancel a previous touch so that a
   413    * new one can properly take effect.
   414    */
   415   nsEventStatus OnCancelTap(const TapGestureInput& aEvent);
   417   /**
   418    * Scrolls the viewport by an X,Y offset.
   419    */
   420   void ScrollBy(const CSSPoint& aOffset);
   422   /**
   423    * Scales the viewport by an amount (note that it multiplies this scale in to
   424    * the current scale, it doesn't set it to |aScale|). Also considers a focus
   425    * point so that the page zooms inward/outward from that point.
   426    */
   427   void ScaleWithFocus(float aScale,
   428                       const CSSPoint& aFocus);
   430   /**
   431    * Schedules a composite on the compositor thread. Wrapper for
   432    * CompositorParent::ScheduleRenderOnCompositorThread().
   433    */
   434   void ScheduleComposite();
   436   /**
   437    * Gets the displacement of the current touch since it began. That is, it is
   438    * the distance between the current position and the initial position of the
   439    * current touch (this only makes sense if a touch is currently happening and
   440    * OnTouchMove() is being invoked).
   441    */
   442   float PanDistance();
   444   /**
   445    * Gets a vector of the velocities of each axis.
   446    */
   447   const ScreenPoint GetVelocityVector();
   449   /**
   450    * Gets a reference to the first touch point from a MultiTouchInput.  This
   451    * gets only the first one and assumes the rest are either missing or not
   452    * relevant.
   453    */
   454   ScreenIntPoint& GetFirstTouchScreenPoint(const MultiTouchInput& aEvent);
   456   /**
   457    * Sets the panning state basing on the pan direction angle and current touch-action value.
   458    */
   459   void HandlePanningWithTouchAction(double angle, TouchBehaviorFlags value);
   461   /**
   462    * Sets the panning state ignoring the touch action value.
   463    */
   464   void HandlePanning(double angle);
   466   /**
   467    * Sets up anything needed for panning. This takes us out of the "TOUCHING"
   468    * state and starts actually panning us.
   469    */
   470   nsEventStatus StartPanning(const MultiTouchInput& aStartPoint);
   472   /**
   473    * Wrapper for Axis::UpdateWithTouchAtDevicePoint(). Calls this function for
   474    * both axes and factors in the time delta from the last update.
   475    */
   476   void UpdateWithTouchAtDevicePoint(const MultiTouchInput& aEvent);
   478   /**
   479    * Does any panning required due to a new touch event.
   480    */
   481   void TrackTouch(const MultiTouchInput& aEvent);
   483   /**
   484    * Utility function to send updated FrameMetrics to Gecko so that it can paint
   485    * the displayport area. Calls into GeckoContentController to do the actual
   486    * work. Note that only one paint request can be active at a time. If a paint
   487    * request is made while a paint is currently happening, it gets queued up. If
   488    * a new paint request arrives before a paint is completed, the old request
   489    * gets discarded.
   490    */
   491   void RequestContentRepaint();
   493   /**
   494    * Tell the paint throttler to request a content repaint with the given
   495    * metrics.  (Helper function used by RequestContentRepaint.)
   496    */
   497   void RequestContentRepaint(FrameMetrics& aFrameMetrics);
   499   /**
   500    * Actually send the next pending paint request to gecko.
   501    */
   502   void DispatchRepaintRequest(const FrameMetrics& aFrameMetrics);
   504   /**
   505    * Advances a fling by an interpolated amount based on the passed in |aDelta|.
   506    * This should be called whenever sampling the content transform for this
   507    * frame. Returns true if the fling animation should be advanced by one frame,
   508    * or false if there is no fling or the fling has ended.
   509    */
   510   bool DoFling(const TimeDuration& aDelta);
   512   /**
   513    * Gets the current frame metrics. This is *not* the Gecko copy stored in the
   514    * layers code.
   515    */
   516   const FrameMetrics& GetFrameMetrics();
   518   /**
   519    * Sets the timer for content response to a series of touch events, if it
   520    * hasn't been already. This is to prevent us from batching up touch events
   521    * indefinitely in the case that content doesn't respond with whether or not
   522    * it wants to preventDefault. When the timer is fired, the touch event queue
   523    * will be flushed.
   524    */
   525   void SetContentResponseTimer();
   527   /**
   528    * Timeout function for content response. This should be called on a timer
   529    * after we get our first touch event in a batch, under the condition that we
   530    * waiting for response from content. If a notification comes indicating whether or not
   531    * content preventDefaulted a series of touch events and touch behavior values are
   532    * set before the timeout, the timeout should be cancelled.
   533    */
   534   void TimeoutContentResponse();
   536   /**
   537    * Timeout function for mozbrowserasyncscroll event. Because we throttle
   538    * mozbrowserasyncscroll events in some conditions, this function ensures
   539    * that the last mozbrowserasyncscroll event will be fired after a period of
   540    * time.
   541    */
   542   void FireAsyncScrollOnTimeout();
   544 private:
   545   enum PanZoomState {
   546     NOTHING,                  /* no touch-start events received */
   547     FLING,                    /* all touches removed, but we're still scrolling page */
   548     TOUCHING,                 /* one touch-start event received */
   550     PANNING,                  /* panning the frame */
   551     PANNING_LOCKED_X,         /* touch-start followed by move (i.e. panning with axis lock) X axis */
   552     PANNING_LOCKED_Y,         /* as above for Y axis */
   554     CROSS_SLIDING_X,          /* Panning disabled while user does a horizontal gesture
   555                                  on a vertically-scrollable view. This used for the
   556                                  Windows Metro "cross-slide" gesture. */
   557     CROSS_SLIDING_Y,          /* as above for Y axis */
   559     PINCHING,                 /* nth touch-start, where n > 1. this mode allows pan and zoom */
   560     ANIMATING_ZOOM,           /* animated zoom to a new rect */
   561     WAITING_CONTENT_RESPONSE, /* a state halfway between NOTHING and TOUCHING - the user has
   562                                  put a finger down, but we don't yet know if a touch listener has
   563                                  prevented the default actions yet and the allowed touch behavior
   564                                  was not set yet. we still need to abort animations. */
   565   };
   567   // State related to a single touch block. Does not persist across touch blocks.
   568   struct TouchBlockState {
   570     TouchBlockState()
   571       :  mAllowedTouchBehaviorSet(false),
   572          mPreventDefault(false),
   573          mPreventDefaultSet(false),
   574          mSingleTapOccurred(false)
   575     {}
   577     // Values of allowed touch behavior for touch points of this touch block.
   578     // Since there are maybe a few current active touch points per time (multitouch case)
   579     // and each touch point should have its own value of allowed touch behavior- we're
   580     // keeping an array of allowed touch behavior values, not the single value.
   581     nsTArray<TouchBehaviorFlags> mAllowedTouchBehaviors;
   583     // Specifies whether mAllowedTouchBehaviors is set for this touch events block.
   584     bool mAllowedTouchBehaviorSet;
   586     // Flag used to specify that content prevented the default behavior of this
   587     // touch events block.
   588     bool mPreventDefault;
   590     // Specifies whether mPreventDefault property is set for this touch events block.
   591     bool mPreventDefaultSet;
   593     // Specifies whether a single tap event was generated during this touch block.
   594     bool mSingleTapOccurred;
   595   };
   597   /*
   598    * Returns whether current touch behavior values allow pinch-zooming.
   599    */
   600   bool TouchActionAllowPinchZoom();
   602   /*
   603    * Returns whether current touch behavior values allow double-tap-zooming.
   604    */
   605   bool TouchActionAllowDoubleTapZoom();
   607   /*
   608    * Returns allowed touch behavior from the mAllowedTouchBehavior array.
   609    * In case apzc didn't receive touch behavior values within the timeout
   610    * it returns default value.
   611    */
   612   TouchBehaviorFlags GetTouchBehavior(uint32_t touchIndex);
   614   /**
   615    * To move from the WAITING_CONTENT_RESPONSE state to TOUCHING one we need two
   616    * conditions set: get content listeners response (whether they called preventDefault)
   617    * and get allowed touch behaviors.
   618    * This method checks both conditions and changes (or not changes) state
   619    * appropriately.
   620    */
   621   void CheckContentResponse();
   623   /**
   624    * Helper to set the current state. Holds the monitor before actually setting
   625    * it and fires content controller events based on state changes. Always set
   626    * the state using this call, do not set it directly.
   627    */
   628   void SetState(PanZoomState aState);
   630   /**
   631    * Convert ScreenPoint relative to this APZC to CSSPoint relative
   632    * to the parent document. This excludes the transient compositor transform.
   633    * NOTE: This must be converted to CSSPoint relative to the child
   634    * document before sending over IPC.
   635    */
   636   bool ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut);
   638   /**
   639    * Internal helpers for checking general state of this apzc.
   640    */
   641   bool IsTransformingState(PanZoomState aState);
   642   bool IsPanningState(PanZoomState mState);
   644   enum AxisLockMode {
   645     FREE,     /* No locking at all */
   646     STANDARD, /* Default axis locking mode that remains locked until pan ends*/
   647     STICKY,   /* Allow lock to be broken, with hysteresis */
   648   };
   650   static AxisLockMode GetAxisLockMode();
   652   // Convert a point from local screen coordinates to parent layer coordinates.
   653   // This is a common operation as inputs from the tree manager are in screen
   654   // coordinates but the composition bounds is in parent layer coordinates.
   655   ParentLayerPoint ToParentLayerCoords(const ScreenPoint& aPoint);
   657   // Update mFrameMetrics.mTransformScale. This should be called whenever
   658   // our CSS transform or the non-transient part of our async transform
   659   // changes, as it corresponds to the scale portion of those transforms.
   660   void UpdateTransformScale();
   662   // Helper function for OnSingleTapUp() and OnSingleTapConfirmed().
   663   nsEventStatus GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers);
   665   // Common processing at the end of a touch block.
   666   void OnTouchEndOrCancel();
   668   uint64_t mLayersId;
   669   nsRefPtr<CompositorParent> mCompositorParent;
   670   PCompositorParent* mCrossProcessCompositorParent;
   671   TaskThrottler mPaintThrottler;
   673   /* Access to the following two fields is protected by the mRefPtrMonitor,
   674      since they are accessed on the UI thread but can be cleared on the
   675      compositor thread. */
   676   nsRefPtr<GeckoContentController> mGeckoContentController;
   677   nsRefPtr<GestureEventListener> mGestureEventListener;
   678   Monitor mRefPtrMonitor;
   680   /* Utility functions that return a addrefed pointer to the corresponding fields. */
   681   already_AddRefed<GeckoContentController> GetGeckoContentController();
   682   already_AddRefed<GestureEventListener> GetGestureEventListener();
   684 protected:
   685   // Both |mFrameMetrics| and |mLastContentPaintMetrics| are protected by the
   686   // monitor. Do not read from or modify either of them without locking.
   687   FrameMetrics mFrameMetrics;
   689   // Protects |mFrameMetrics|, |mLastContentPaintMetrics|, and |mState|.
   690   // Before manipulating |mFrameMetrics| or |mLastContentPaintMetrics|, the
   691   // monitor should be held. When setting |mState|, either the SetState()
   692   // function can be used, or the monitor can be held and then |mState| updated.
   693   // IMPORTANT: See the note about lock ordering at the top of APZCTreeManager.h.
   694   // This is mutable to allow entering it from 'const' methods; doing otherwise
   695   // would significantly limit what methods could be 'const'.
   696   mutable ReentrantMonitor mMonitor;
   698   // Specifies whether we should use touch-action css property. Initialized from
   699   // the preferences. This property (in comparison with the global one) simplifies
   700   // testing apzc with (and without) touch-action property enabled concurrently
   701   // (e.g. with the gtest framework).
   702   bool mTouchActionPropertyEnabled;
   704 private:
   705   // Metrics of the container layer corresponding to this APZC. This is
   706   // stored here so that it is accessible from the UI/controller thread.
   707   // These are the metrics at last content paint, the most recent
   708   // values we were notified of in NotifyLayersUpdate(). Since it represents
   709   // the Gecko state, it should be used as a basis for untransformation when
   710   // sending messages back to Gecko.
   711   FrameMetrics mLastContentPaintMetrics;
   712   // The last metrics that we requested a paint for. These are used to make sure
   713   // that we're not requesting a paint of the same thing that's already drawn.
   714   // If we don't do this check, we don't get a ShadowLayersUpdated back.
   715   FrameMetrics mLastPaintRequestMetrics;
   716   // The last metrics that we actually sent to Gecko. This allows us to transform
   717   // inputs into a coordinate space that Gecko knows about. This assumes the pipe
   718   // through which input events and repaint requests are sent to Gecko operates
   719   // in a FIFO manner.
   720   FrameMetrics mLastDispatchedPaintMetrics;
   722   nsTArray<MultiTouchInput> mTouchQueue;
   724   CancelableTask* mContentResponseTimeoutTask;
   726   AxisX mX;
   727   AxisY mY;
   729   // This flag is set to true when we are in a axis-locked pan as a result of
   730   // the touch-action CSS property.
   731   bool mPanDirRestricted;
   733   // Most up-to-date constraints on zooming. These should always be reasonable
   734   // values; for example, allowing a min zoom of 0.0 can cause very bad things
   735   // to happen.
   736   ZoomConstraints mZoomConstraints;
   738   // The last time the compositor has sampled the content transform for this
   739   // frame.
   740   TimeStamp mLastSampleTime;
   741   // The last time a touch event came through on the UI thread.
   742   uint32_t mLastEventTime;
   744   // Stores the previous focus point if there is a pinch gesture happening. Used
   745   // to allow panning by moving multiple fingers (thus moving the focus point).
   746   ParentLayerPoint mLastZoomFocus;
   748   // Stores the state of panning and zooming this frame. This is protected by
   749   // |mMonitor|; that is, it should be held whenever this is updated.
   750   PanZoomState mState;
   752   // The last time and offset we fire the mozbrowserasyncscroll event when
   753   // compositor has sampled the content transform for this frame.
   754   TimeStamp mLastAsyncScrollTime;
   755   CSSPoint mLastAsyncScrollOffset;
   757   // The current offset drawn on the screen, it may not be sent since we have
   758   // throttling policy for mozbrowserasyncscroll event.
   759   CSSPoint mCurrentAsyncScrollOffset;
   761   // The delay task triggered by the throttling mozbrowserasyncscroll event
   762   // ensures the last mozbrowserasyncscroll event is always been fired.
   763   CancelableTask* mAsyncScrollTimeoutTask;
   765   // Flag used to determine whether or not we should try to enter the
   766   // WAITING_LISTENERS state. This is used in the case that we are processing a
   767   // queued up event block. If set, this means that we are handling this queue
   768   // and we don't want to queue the events back up again.
   769   bool mHandlingTouchQueue;
   771   // Stores information about the current touch block.
   772   TouchBlockState mTouchBlockState;
   774   // Extra offset to add in SampleContentTransformForFrame for testing
   775   CSSPoint mTestAsyncScrollOffset;
   777   RefPtr<AsyncPanZoomAnimation> mAnimation;
   779   friend class Axis;
   780   friend class FlingAnimation;
   783   /* ===================================================================
   784    * The functions and members in this section are used to build a tree
   785    * structure out of APZC instances. This tree can only be walked or
   786    * manipulated while holding the lock in the associated APZCTreeManager
   787    * instance.
   788    */
   789 public:
   790   void SetLastChild(AsyncPanZoomController* child) {
   791     mLastChild = child;
   792     if (child) {
   793       child->mParent = this;
   794     }
   795   }
   797   void SetPrevSibling(AsyncPanZoomController* sibling) {
   798     mPrevSibling = sibling;
   799     if (sibling) {
   800       sibling->mParent = mParent;
   801     }
   802   }
   804   AsyncPanZoomController* GetLastChild() const { return mLastChild; }
   805   AsyncPanZoomController* GetPrevSibling() const { return mPrevSibling; }
   806   AsyncPanZoomController* GetParent() const { return mParent; }
   808   /* Returns true if there is no APZC higher in the tree with the same
   809    * layers id.
   810    */
   811   bool IsRootForLayersId() const {
   812     return !mParent || (mParent->mLayersId != mLayersId);
   813   }
   815   bool IsRootForLayersId(const uint64_t& aLayersId) const {
   816     return (mLayersId == aLayersId) && IsRootForLayersId();
   817   }
   819 private:
   820   // This is a raw pointer to avoid introducing a reference cycle between
   821   // AsyncPanZoomController and APZCTreeManager. Since these objects don't
   822   // live on the main thread, we can't use the cycle collector with them.
   823   // The APZCTreeManager owns the lifetime of the APZCs, so nulling this
   824   // pointer out in Destroy() will prevent accessing deleted memory.
   825   Atomic<APZCTreeManager*> mTreeManager;
   827   nsRefPtr<AsyncPanZoomController> mLastChild;
   828   nsRefPtr<AsyncPanZoomController> mPrevSibling;
   829   nsRefPtr<AsyncPanZoomController> mParent;
   832   /* ===================================================================
   833    * The functions and members in this section are used in building the
   834    * scroll handoff chain, so that we can have seamless scrolling continue
   835    * across APZC instances.
   836    */
   837 public:
   838   void SetScrollHandoffParentId(FrameMetrics::ViewID aScrollParentId) {
   839     mScrollParentId = aScrollParentId;
   840   }
   842   FrameMetrics::ViewID GetScrollHandoffParentId() const {
   843     return mScrollParentId;
   844   }
   846   /**
   847    * Attempt to scroll in response to a touch-move from |aStartPoint| to
   848    * |aEndPoint|, which are in our (transformed) screen coordinates.
   849    * Due to overscroll handling, there may not actually have been a touch-move
   850    * at these points, but this function will scroll as if there had been.
   851    * If this attempt causes overscroll (i.e. the layer cannot be scrolled
   852    * by the entire amount requested), the overscroll is passed back to the
   853    * tree manager via APZCTreeManager::DispatchScroll().
   854    * |aOverscrollHandoffChainIndex| is used by the tree manager to keep track
   855    * of which APZC to hand off the overscroll to; this function increments it
   856    * and passes it on to APZCTreeManager::DispatchScroll() in the event of
   857    * overscroll.
   858    */
   859   void AttemptScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint,
   860                      uint32_t aOverscrollHandoffChainIndex = 0);
   862   void FlushRepaintForOverscrollHandoff();
   864 private:
   865   FrameMetrics::ViewID mScrollParentId;
   867   /**
   868    * A helper function for calling APZCTreeManager::DispatchScroll().
   869    * Guards against the case where the APZC is being concurrently destroyed
   870    * (and thus mTreeManager is being nulled out).
   871    */
   872   void CallDispatchScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint,
   873                           uint32_t aOverscrollHandoffChainIndex);
   876   /* ===================================================================
   877    * The functions and members in this section are used to maintain the
   878    * area that this APZC instance is responsible for. This is used when
   879    * hit-testing to see which APZC instance should handle touch events.
   880    */
   881 public:
   882   void SetLayerHitTestData(const ParentLayerRect& aRect, const gfx3DMatrix& aTransformToLayer,
   883                            const gfx3DMatrix& aTransformForLayer) {
   884     mVisibleRect = aRect;
   885     mAncestorTransform = aTransformToLayer;
   886     mCSSTransform = aTransformForLayer;
   887     UpdateTransformScale();
   888   }
   890   gfx3DMatrix GetAncestorTransform() const {
   891     return mAncestorTransform;
   892   }
   894   gfx3DMatrix GetCSSTransform() const {
   895     return mCSSTransform;
   896   }
   898   bool VisibleRegionContains(const ParentLayerPoint& aPoint) const {
   899     return mVisibleRect.Contains(aPoint);
   900   }
   902 private:
   903   /* This is the visible region of the layer that this APZC corresponds to, in
   904    * that layer's screen pixels (the same coordinate system in which this APZC
   905    * receives events in ReceiveInputEvent()). */
   906   ParentLayerRect mVisibleRect;
   907   /* This is the cumulative CSS transform for all the layers between the parent
   908    * APZC and this one (not inclusive) */
   909   gfx3DMatrix mAncestorTransform;
   910   /* This is the CSS transform for this APZC's layer. */
   911   gfx3DMatrix mCSSTransform;
   914   /* ===================================================================
   915    * The functions and members in this section are used for sharing the
   916    * FrameMetrics across processes for the progressive tiling code.
   917    */
   918 private:
   919   /* Unique id assigned to each APZC. Used with ViewID to uniquely identify
   920    * shared FrameMeterics used in progressive tile painting. */
   921   const uint32_t mAPZCId;
   923   ipc::SharedMemoryBasic* mSharedFrameMetricsBuffer;
   924   CrossProcessMutex* mSharedLock;
   925   /**
   926    * Called when ever mFrameMetrics is updated so that if it is being
   927    * shared with the content process the shared FrameMetrics may be updated.
   928    */
   929   void UpdateSharedCompositorFrameMetrics();
   930   /**
   931    * Create a shared memory buffer for containing the FrameMetrics and
   932    * a CrossProcessMutex that may be shared with the content process
   933    * for use in progressive tiled update calculations.
   934    */
   935   void ShareCompositorFrameMetrics();
   936 };
   938 class AsyncPanZoomAnimation {
   939   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomAnimation)
   941 public:
   942   AsyncPanZoomAnimation(const TimeDuration& aRepaintInterval =
   943                         TimeDuration::Forever())
   944     : mRepaintInterval(aRepaintInterval)
   945   { }
   947   virtual bool Sample(FrameMetrics& aFrameMetrics,
   948                       const TimeDuration& aDelta) = 0;
   950   /**
   951    * Get the deferred tasks in |mDeferredTasks|. See |mDeferredTasks|
   952    * for more information.
   953    * Clears |mDeferredTasks|.
   954    */
   955   Vector<Task*> TakeDeferredTasks() {
   956     Vector<Task*> result;
   957     mDeferredTasks.swap(result);
   958     return result;
   959   }
   961   /**
   962    * Specifies how frequently (at most) we want to do repaints during the
   963    * animation sequence. TimeDuration::Forever() will cause it to only repaint
   964    * at the end of the animation.
   965    */
   966   TimeDuration mRepaintInterval;
   968 protected:
   969   // Protected destructor, to discourage deletion outside of Release():
   970   virtual ~AsyncPanZoomAnimation()
   971   { }
   973   /**
   974    * Tasks scheduled for execution after the APZC's mMonitor is released.
   975    * Derived classes can add tasks here in Sample(), and the APZC can call
   976    * ExecuteDeferredTasks() to execute them.
   977    */
   978   Vector<Task*> mDeferredTasks;
   979 };
   981 }
   982 }
   984 #endif // mozilla_layers_PanZoomController_h

mercurial