gfx/layers/apz/src/AsyncPanZoomController.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/layers/apz/src/AsyncPanZoomController.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,984 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim: set sw=2 ts=8 et tw=80 : */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef mozilla_layers_AsyncPanZoomController_h
    1.11 +#define mozilla_layers_AsyncPanZoomController_h
    1.12 +
    1.13 +#include "CrossProcessMutex.h"
    1.14 +#include "mozilla/layers/GeckoContentController.h"
    1.15 +#include "mozilla/Attributes.h"
    1.16 +#include "mozilla/EventForwards.h"
    1.17 +#include "mozilla/Monitor.h"
    1.18 +#include "mozilla/ReentrantMonitor.h"
    1.19 +#include "mozilla/RefPtr.h"
    1.20 +#include "mozilla/Atomics.h"
    1.21 +#include "InputData.h"
    1.22 +#include "Axis.h"
    1.23 +#include "TaskThrottler.h"
    1.24 +#include "gfx3DMatrix.h"
    1.25 +
    1.26 +#include "base/message_loop.h"
    1.27 +
    1.28 +namespace mozilla {
    1.29 +
    1.30 +namespace ipc {
    1.31 +
    1.32 +class SharedMemoryBasic;
    1.33 +
    1.34 +}
    1.35 +
    1.36 +namespace layers {
    1.37 +
    1.38 +struct ScrollableLayerGuid;
    1.39 +class CompositorParent;
    1.40 +class GestureEventListener;
    1.41 +class ContainerLayer;
    1.42 +class PCompositorParent;
    1.43 +class ViewTransform;
    1.44 +class APZCTreeManager;
    1.45 +class AsyncPanZoomAnimation;
    1.46 +class FlingAnimation;
    1.47 +
    1.48 +/**
    1.49 + * Controller for all panning and zooming logic. Any time a user input is
    1.50 + * detected and it must be processed in some way to affect what the user sees,
    1.51 + * it goes through here. Listens for any input event from InputData and can
    1.52 + * optionally handle WidgetGUIEvent-derived touch events, but this must be done
    1.53 + * on the main thread. Note that this class completely cross-platform.
    1.54 + *
    1.55 + * Input events originate on the UI thread of the platform that this runs on,
    1.56 + * and are then sent to this class. This class processes the event in some way;
    1.57 + * for example, a touch move will usually lead to a panning of content (though
    1.58 + * of course there are exceptions, such as if content preventDefaults the event,
    1.59 + * or if the target frame is not scrollable). The compositor interacts with this
    1.60 + * class by locking it and querying it for the current transform matrix based on
    1.61 + * the panning and zooming logic that was invoked on the UI thread.
    1.62 + *
    1.63 + * Currently, each outer DOM window (i.e. a website in a tab, but not any
    1.64 + * subframes) has its own AsyncPanZoomController. In the future, to support
    1.65 + * asynchronously scrolled subframes, we want to have one AsyncPanZoomController
    1.66 + * per frame.
    1.67 + */
    1.68 +class AsyncPanZoomController {
    1.69 +  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomController)
    1.70 +
    1.71 +  typedef mozilla::MonitorAutoLock MonitorAutoLock;
    1.72 +  typedef uint32_t TouchBehaviorFlags;
    1.73 +
    1.74 +public:
    1.75 +  enum GestureBehavior {
    1.76 +    // The platform code is responsible for forwarding gesture events here. We
    1.77 +    // will not attempt to generate gesture events from MultiTouchInputs.
    1.78 +    DEFAULT_GESTURES,
    1.79 +    // An instance of GestureEventListener is used to detect gestures. This is
    1.80 +    // handled completely internally within this class.
    1.81 +    USE_GESTURE_DETECTOR
    1.82 +  };
    1.83 +
    1.84 +  /**
    1.85 +   * Constant describing the tolerance in distance we use, multiplied by the
    1.86 +   * device DPI, before we start panning the screen. This is to prevent us from
    1.87 +   * accidentally processing taps as touch moves, and from very short/accidental
    1.88 +   * touches moving the screen.
    1.89 +   */
    1.90 +  static float GetTouchStartTolerance();
    1.91 +
    1.92 +  AsyncPanZoomController(uint64_t aLayersId,
    1.93 +                         APZCTreeManager* aTreeManager,
    1.94 +                         GeckoContentController* aController,
    1.95 +                         GestureBehavior aGestures = DEFAULT_GESTURES);
    1.96 +
    1.97 +  // --------------------------------------------------------------------------
    1.98 +  // These methods must only be called on the gecko thread.
    1.99 +  //
   1.100 +
   1.101 +  /**
   1.102 +   * Read the various prefs and do any global initialization for all APZC instances.
   1.103 +   * This must be run on the gecko thread before any APZC instances are actually
   1.104 +   * used for anything meaningful.
   1.105 +   */
   1.106 +  static void InitializeGlobalState();
   1.107 +
   1.108 +  // --------------------------------------------------------------------------
   1.109 +  // These methods must only be called on the controller/UI thread.
   1.110 +  //
   1.111 +
   1.112 +  /**
   1.113 +   * General handler for incoming input events. Manipulates the frame metrics
   1.114 +   * based on what type of input it is. For example, a PinchGestureEvent will
   1.115 +   * cause scaling. This should only be called externally to this class.
   1.116 +   * HandleInputEvent() should be used internally.
   1.117 +   */
   1.118 +  nsEventStatus ReceiveInputEvent(const InputData& aEvent);
   1.119 +
   1.120 +  /**
   1.121 +   * Kicks an animation to zoom to a rect. This may be either a zoom out or zoom
   1.122 +   * in. The actual animation is done on the compositor thread after being set
   1.123 +   * up.
   1.124 +   */
   1.125 +  void ZoomToRect(CSSRect aRect);
   1.126 +
   1.127 +  /**
   1.128 +   * If we have touch listeners, this should always be called when we know
   1.129 +   * definitively whether or not content has preventDefaulted any touch events
   1.130 +   * that have come in. If |aPreventDefault| is true, any touch events in the
   1.131 +   * queue will be discarded.
   1.132 +   */
   1.133 +  void ContentReceivedTouch(bool aPreventDefault);
   1.134 +
   1.135 +  /**
   1.136 +   * Updates any zoom constraints contained in the <meta name="viewport"> tag.
   1.137 +   */
   1.138 +  void UpdateZoomConstraints(const ZoomConstraints& aConstraints);
   1.139 +
   1.140 +  /**
   1.141 +   * Return the zoom constraints last set for this APZC (in the constructor
   1.142 +   * or in UpdateZoomConstraints()).
   1.143 +   */
   1.144 +  ZoomConstraints GetZoomConstraints() const;
   1.145 +
   1.146 +  /**
   1.147 +   * Schedules a runnable to run on the controller/UI thread at some time
   1.148 +   * in the future.
   1.149 +   */
   1.150 +  void PostDelayedTask(Task* aTask, int aDelayMs);
   1.151 +
   1.152 +  // --------------------------------------------------------------------------
   1.153 +  // These methods must only be called on the compositor thread.
   1.154 +  //
   1.155 +
   1.156 +  bool UpdateAnimation(const TimeStamp& aSampleTime);
   1.157 +
   1.158 +  /**
   1.159 +   * The compositor calls this when it's about to draw pannable/zoomable content
   1.160 +   * and is setting up transforms for compositing the layer tree. This is not
   1.161 +   * idempotent. For example, a fling transform can be applied each time this is
   1.162 +   * called (though not necessarily). |aSampleTime| is the time that this is
   1.163 +   * sampled at; this is used for interpolating animations. Calling this sets a
   1.164 +   * new transform in |aNewTransform| which should be multiplied to the transform
   1.165 +   * in the shadow layer corresponding to this APZC.
   1.166 +   *
   1.167 +   * Return value indicates whether or not any currently running animation
   1.168 +   * should continue. That is, if true, the compositor should schedule another
   1.169 +   * composite.
   1.170 +   */
   1.171 +  bool SampleContentTransformForFrame(const TimeStamp& aSampleTime,
   1.172 +                                      ViewTransform* aNewTransform,
   1.173 +                                      ScreenPoint& aScrollOffset);
   1.174 +
   1.175 +  /**
   1.176 +   * A shadow layer update has arrived. |aLayerMetrics| is the new FrameMetrics
   1.177 +   * for the container layer corresponding to this APZC.
   1.178 +   * |aIsFirstPaint| is a flag passed from the shadow
   1.179 +   * layers code indicating that the frame metrics being sent with this call are
   1.180 +   * the initial metrics and the initial paint of the frame has just happened.
   1.181 +   */
   1.182 +  void NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint);
   1.183 +
   1.184 +  /**
   1.185 +   * The platform implementation must set the compositor parent so that we can
   1.186 +   * request composites.
   1.187 +   */
   1.188 +  void SetCompositorParent(CompositorParent* aCompositorParent);
   1.189 +
   1.190 +  /**
   1.191 +   * The platform implementation must set the cross process compositor if
   1.192 +   * there is one associated with the layer tree. The cross process compositor
   1.193 +   * allows the APZC to share its FrameMetrics with the content process.
   1.194 +   * The shared FrameMetrics is used in progressive paint updates.
   1.195 +   */
   1.196 +  void SetCrossProcessCompositorParent(PCompositorParent* aCrossProcessCompositorParent);
   1.197 +
   1.198 +  // --------------------------------------------------------------------------
   1.199 +  // These methods can be called from any thread.
   1.200 +  //
   1.201 +
   1.202 +  /**
   1.203 +   * Shut down the controller/UI thread state and prepare to be
   1.204 +   * deleted (which may happen from any thread).
   1.205 +   */
   1.206 +  void Destroy();
   1.207 +
   1.208 +  /**
   1.209 +   * Returns true if Destroy() has already been called on this APZC instance.
   1.210 +   */
   1.211 +  bool IsDestroyed();
   1.212 +
   1.213 +  /**
   1.214 +   * Returns the incremental transformation corresponding to the async pan/zoom
   1.215 +   * in progress. That is, when this transform is multiplied with the layer's
   1.216 +   * existing transform, it will make the layer appear with the desired pan/zoom
   1.217 +   * amount.
   1.218 +   */
   1.219 +  ViewTransform GetCurrentAsyncTransform();
   1.220 +
   1.221 +  /**
   1.222 +   * Returns the part of the async transform that will remain once Gecko does a
   1.223 +   * repaint at the desired metrics. That is, in the steady state:
   1.224 +   * gfx3DMatrix(GetCurrentAsyncTransform()) === GetNontransientAsyncTransform()
   1.225 +   */
   1.226 +  gfx3DMatrix GetNontransientAsyncTransform();
   1.227 +
   1.228 +  /**
   1.229 +   * Returns the transform to take something from the coordinate space of the
   1.230 +   * last thing we know gecko painted, to the coordinate space of the last thing
   1.231 +   * we asked gecko to paint. In cases where that last request has not yet been
   1.232 +   * processed, this is needed to transform input events properly into a space
   1.233 +   * gecko will understand.
   1.234 +   */
   1.235 +  gfx3DMatrix GetTransformToLastDispatchedPaint();
   1.236 +
   1.237 +  /**
   1.238 +   * Recalculates the displayport. Ideally, this should paint an area bigger
   1.239 +   * than the composite-to dimensions so that when you scroll down, you don't
   1.240 +   * checkerboard immediately. This includes a bunch of logic, including
   1.241 +   * algorithms to bias painting in the direction of the velocity.
   1.242 +   */
   1.243 +  static const LayerMargin CalculatePendingDisplayPort(
   1.244 +    const FrameMetrics& aFrameMetrics,
   1.245 +    const ScreenPoint& aVelocity,
   1.246 +    double aEstimatedPaintDuration);
   1.247 +
   1.248 +  /**
   1.249 +   * Send an mozbrowserasyncscroll event.
   1.250 +   * *** The monitor must be held while calling this.
   1.251 +   */
   1.252 +  void SendAsyncScrollEvent();
   1.253 +
   1.254 +  /**
   1.255 +   * Handler for events which should not be intercepted by the touch listener.
   1.256 +   * Does the work for ReceiveInputEvent().
   1.257 +   */
   1.258 +  nsEventStatus HandleInputEvent(const InputData& aEvent);
   1.259 +
   1.260 +  /**
   1.261 +   * Handler for gesture events.
   1.262 +   * Currently some gestures are detected in GestureEventListener that calls
   1.263 +   * APZC back through this handler in order to avoid recursive calls to
   1.264 +   * APZC::HandleInputEvent() which is supposed to do the work for
   1.265 +   * ReceiveInputEvent().
   1.266 +   */
   1.267 +  nsEventStatus HandleGestureEvent(const InputData& aEvent);
   1.268 +
   1.269 +  /**
   1.270 +   * Populates the provided object (if non-null) with the scrollable guid of this apzc.
   1.271 +   */
   1.272 +  void GetGuid(ScrollableLayerGuid* aGuidOut);
   1.273 +
   1.274 +  /**
   1.275 +   * Returns the scrollable guid of this apzc.
   1.276 +   */
   1.277 +  ScrollableLayerGuid GetGuid();
   1.278 +
   1.279 +  /**
   1.280 +   * Returns true if this APZC instance is for the layer identified by the guid.
   1.281 +   */
   1.282 +  bool Matches(const ScrollableLayerGuid& aGuid);
   1.283 +
   1.284 +  /**
   1.285 +   * Sync panning and zooming animation using a fixed frame time.
   1.286 +   * This will ensure that we animate the APZC correctly with other external
   1.287 +   * animations to the same timestamp.
   1.288 +   */
   1.289 +  static void SetFrameTime(const TimeStamp& aMilliseconds);
   1.290 +
   1.291 +  void StartAnimation(AsyncPanZoomAnimation* aAnimation);
   1.292 +
   1.293 +  /**
   1.294 +   * Cancels any currently running animation. Note that all this does is set the
   1.295 +   * state of the AsyncPanZoomController back to NOTHING, but it is the
   1.296 +   * animation's responsibility to check this before advancing.
   1.297 +   */
   1.298 +  void CancelAnimation();
   1.299 +
   1.300 +  /**
   1.301 +   * Take over a fling with the given velocity from another APZC. Used for
   1.302 +   * during overscroll handoff for a fling.
   1.303 +   */
   1.304 +  void TakeOverFling(ScreenPoint aVelocity);
   1.305 +
   1.306 +  /**
   1.307 +   * Returns allowed touch behavior for the given point on the scrollable layer.
   1.308 +   * Internally performs a kind of hit testing based on the regions constructed
   1.309 +   * on the main thread and attached to the current scrollable layer. Each of such regions
   1.310 +   * contains info about allowed touch behavior. If regions info isn't enough it returns
   1.311 +   * UNKNOWN value and we should switch to the fallback approach - asking content.
   1.312 +   * TODO: for now it's only a stub and returns hardcoded magic value. As soon as bug 928833
   1.313 +   * is done we should integrate its logic here.
   1.314 +   */
   1.315 +  TouchBehaviorFlags GetAllowedTouchBehavior(ScreenIntPoint& aPoint);
   1.316 +
   1.317 +  /**
   1.318 +   * Sets allowed touch behavior for current touch session.
   1.319 +   * This method is invoked by the APZCTreeManager which in its turn invoked by
   1.320 +   * the widget after performing touch-action values retrieving.
   1.321 +   * Must be called after receiving the TOUCH_START even that started the
   1.322 +   * touch session.
   1.323 +   */
   1.324 +  void SetAllowedTouchBehavior(const nsTArray<TouchBehaviorFlags>& aBehaviors);
   1.325 +
   1.326 +  /**
   1.327 +   * Returns whether this APZC is for an element marked with the 'scrollgrab'
   1.328 +   * attribute.
   1.329 +   */
   1.330 +  bool HasScrollgrab() const { return mFrameMetrics.mHasScrollgrab; }
   1.331 +
   1.332 +  /**
   1.333 +   * Set an extra offset for testing async scrolling.
   1.334 +   */
   1.335 +  void SetTestAsyncScrollOffset(const CSSPoint& aPoint)
   1.336 +  {
   1.337 +    mTestAsyncScrollOffset = aPoint;
   1.338 +  }
   1.339 +
   1.340 +  /**
   1.341 +   * Returns whether this APZC has room to be panned (in any direction).
   1.342 +   */
   1.343 +  bool IsPannable() const;
   1.344 +
   1.345 +protected:
   1.346 +  // Protected destructor, to discourage deletion outside of Release():
   1.347 +  ~AsyncPanZoomController();
   1.348 +
   1.349 +  /**
   1.350 +   * Helper method for touches beginning. Sets everything up for panning and any
   1.351 +   * multitouch gestures.
   1.352 +   */
   1.353 +  nsEventStatus OnTouchStart(const MultiTouchInput& aEvent);
   1.354 +
   1.355 +  /**
   1.356 +   * Helper method for touches moving. Does any transforms needed when panning.
   1.357 +   */
   1.358 +  nsEventStatus OnTouchMove(const MultiTouchInput& aEvent);
   1.359 +
   1.360 +  /**
   1.361 +   * Helper method for touches ending. Redraws the screen if necessary and does
   1.362 +   * any cleanup after a touch has ended.
   1.363 +   */
   1.364 +  nsEventStatus OnTouchEnd(const MultiTouchInput& aEvent);
   1.365 +
   1.366 +  /**
   1.367 +   * Helper method for touches being cancelled. Treated roughly the same as a
   1.368 +   * touch ending (OnTouchEnd()).
   1.369 +   */
   1.370 +  nsEventStatus OnTouchCancel(const MultiTouchInput& aEvent);
   1.371 +
   1.372 +  /**
   1.373 +   * Helper method for scales beginning. Distinct from the OnTouch* handlers in
   1.374 +   * that this implies some outside implementation has determined that the user
   1.375 +   * is pinching.
   1.376 +   */
   1.377 +  nsEventStatus OnScaleBegin(const PinchGestureInput& aEvent);
   1.378 +
   1.379 +  /**
   1.380 +   * Helper method for scaling. As the user moves their fingers when pinching,
   1.381 +   * this changes the scale of the page.
   1.382 +   */
   1.383 +  nsEventStatus OnScale(const PinchGestureInput& aEvent);
   1.384 +
   1.385 +  /**
   1.386 +   * Helper method for scales ending. Redraws the screen if necessary and does
   1.387 +   * any cleanup after a scale has ended.
   1.388 +   */
   1.389 +  nsEventStatus OnScaleEnd(const PinchGestureInput& aEvent);
   1.390 +
   1.391 +  /**
   1.392 +   * Helper methods for long press gestures.
   1.393 +   */
   1.394 +  nsEventStatus OnLongPress(const TapGestureInput& aEvent);
   1.395 +  nsEventStatus OnLongPressUp(const TapGestureInput& aEvent);
   1.396 +
   1.397 +  /**
   1.398 +   * Helper method for single tap gestures.
   1.399 +   */
   1.400 +  nsEventStatus OnSingleTapUp(const TapGestureInput& aEvent);
   1.401 +
   1.402 +  /**
   1.403 +   * Helper method for a single tap confirmed.
   1.404 +   */
   1.405 +  nsEventStatus OnSingleTapConfirmed(const TapGestureInput& aEvent);
   1.406 +
   1.407 +  /**
   1.408 +   * Helper method for double taps.
   1.409 +   */
   1.410 +  nsEventStatus OnDoubleTap(const TapGestureInput& aEvent);
   1.411 +
   1.412 +  /**
   1.413 +   * Helper method to cancel any gesture currently going to Gecko. Used
   1.414 +   * primarily when a user taps the screen over some clickable content but then
   1.415 +   * pans down instead of letting go (i.e. to cancel a previous touch so that a
   1.416 +   * new one can properly take effect.
   1.417 +   */
   1.418 +  nsEventStatus OnCancelTap(const TapGestureInput& aEvent);
   1.419 +
   1.420 +  /**
   1.421 +   * Scrolls the viewport by an X,Y offset.
   1.422 +   */
   1.423 +  void ScrollBy(const CSSPoint& aOffset);
   1.424 +
   1.425 +  /**
   1.426 +   * Scales the viewport by an amount (note that it multiplies this scale in to
   1.427 +   * the current scale, it doesn't set it to |aScale|). Also considers a focus
   1.428 +   * point so that the page zooms inward/outward from that point.
   1.429 +   */
   1.430 +  void ScaleWithFocus(float aScale,
   1.431 +                      const CSSPoint& aFocus);
   1.432 +
   1.433 +  /**
   1.434 +   * Schedules a composite on the compositor thread. Wrapper for
   1.435 +   * CompositorParent::ScheduleRenderOnCompositorThread().
   1.436 +   */
   1.437 +  void ScheduleComposite();
   1.438 +
   1.439 +  /**
   1.440 +   * Gets the displacement of the current touch since it began. That is, it is
   1.441 +   * the distance between the current position and the initial position of the
   1.442 +   * current touch (this only makes sense if a touch is currently happening and
   1.443 +   * OnTouchMove() is being invoked).
   1.444 +   */
   1.445 +  float PanDistance();
   1.446 +
   1.447 +  /**
   1.448 +   * Gets a vector of the velocities of each axis.
   1.449 +   */
   1.450 +  const ScreenPoint GetVelocityVector();
   1.451 +
   1.452 +  /**
   1.453 +   * Gets a reference to the first touch point from a MultiTouchInput.  This
   1.454 +   * gets only the first one and assumes the rest are either missing or not
   1.455 +   * relevant.
   1.456 +   */
   1.457 +  ScreenIntPoint& GetFirstTouchScreenPoint(const MultiTouchInput& aEvent);
   1.458 +
   1.459 +  /**
   1.460 +   * Sets the panning state basing on the pan direction angle and current touch-action value.
   1.461 +   */
   1.462 +  void HandlePanningWithTouchAction(double angle, TouchBehaviorFlags value);
   1.463 +
   1.464 +  /**
   1.465 +   * Sets the panning state ignoring the touch action value.
   1.466 +   */
   1.467 +  void HandlePanning(double angle);
   1.468 +
   1.469 +  /**
   1.470 +   * Sets up anything needed for panning. This takes us out of the "TOUCHING"
   1.471 +   * state and starts actually panning us.
   1.472 +   */
   1.473 +  nsEventStatus StartPanning(const MultiTouchInput& aStartPoint);
   1.474 +
   1.475 +  /**
   1.476 +   * Wrapper for Axis::UpdateWithTouchAtDevicePoint(). Calls this function for
   1.477 +   * both axes and factors in the time delta from the last update.
   1.478 +   */
   1.479 +  void UpdateWithTouchAtDevicePoint(const MultiTouchInput& aEvent);
   1.480 +
   1.481 +  /**
   1.482 +   * Does any panning required due to a new touch event.
   1.483 +   */
   1.484 +  void TrackTouch(const MultiTouchInput& aEvent);
   1.485 +
   1.486 +  /**
   1.487 +   * Utility function to send updated FrameMetrics to Gecko so that it can paint
   1.488 +   * the displayport area. Calls into GeckoContentController to do the actual
   1.489 +   * work. Note that only one paint request can be active at a time. If a paint
   1.490 +   * request is made while a paint is currently happening, it gets queued up. If
   1.491 +   * a new paint request arrives before a paint is completed, the old request
   1.492 +   * gets discarded.
   1.493 +   */
   1.494 +  void RequestContentRepaint();
   1.495 +
   1.496 +  /**
   1.497 +   * Tell the paint throttler to request a content repaint with the given
   1.498 +   * metrics.  (Helper function used by RequestContentRepaint.)
   1.499 +   */
   1.500 +  void RequestContentRepaint(FrameMetrics& aFrameMetrics);
   1.501 +
   1.502 +  /**
   1.503 +   * Actually send the next pending paint request to gecko.
   1.504 +   */
   1.505 +  void DispatchRepaintRequest(const FrameMetrics& aFrameMetrics);
   1.506 +
   1.507 +  /**
   1.508 +   * Advances a fling by an interpolated amount based on the passed in |aDelta|.
   1.509 +   * This should be called whenever sampling the content transform for this
   1.510 +   * frame. Returns true if the fling animation should be advanced by one frame,
   1.511 +   * or false if there is no fling or the fling has ended.
   1.512 +   */
   1.513 +  bool DoFling(const TimeDuration& aDelta);
   1.514 +
   1.515 +  /**
   1.516 +   * Gets the current frame metrics. This is *not* the Gecko copy stored in the
   1.517 +   * layers code.
   1.518 +   */
   1.519 +  const FrameMetrics& GetFrameMetrics();
   1.520 +
   1.521 +  /**
   1.522 +   * Sets the timer for content response to a series of touch events, if it
   1.523 +   * hasn't been already. This is to prevent us from batching up touch events
   1.524 +   * indefinitely in the case that content doesn't respond with whether or not
   1.525 +   * it wants to preventDefault. When the timer is fired, the touch event queue
   1.526 +   * will be flushed.
   1.527 +   */
   1.528 +  void SetContentResponseTimer();
   1.529 +
   1.530 +  /**
   1.531 +   * Timeout function for content response. This should be called on a timer
   1.532 +   * after we get our first touch event in a batch, under the condition that we
   1.533 +   * waiting for response from content. If a notification comes indicating whether or not
   1.534 +   * content preventDefaulted a series of touch events and touch behavior values are
   1.535 +   * set before the timeout, the timeout should be cancelled.
   1.536 +   */
   1.537 +  void TimeoutContentResponse();
   1.538 +
   1.539 +  /**
   1.540 +   * Timeout function for mozbrowserasyncscroll event. Because we throttle
   1.541 +   * mozbrowserasyncscroll events in some conditions, this function ensures
   1.542 +   * that the last mozbrowserasyncscroll event will be fired after a period of
   1.543 +   * time.
   1.544 +   */
   1.545 +  void FireAsyncScrollOnTimeout();
   1.546 +
   1.547 +private:
   1.548 +  enum PanZoomState {
   1.549 +    NOTHING,                  /* no touch-start events received */
   1.550 +    FLING,                    /* all touches removed, but we're still scrolling page */
   1.551 +    TOUCHING,                 /* one touch-start event received */
   1.552 +
   1.553 +    PANNING,                  /* panning the frame */
   1.554 +    PANNING_LOCKED_X,         /* touch-start followed by move (i.e. panning with axis lock) X axis */
   1.555 +    PANNING_LOCKED_Y,         /* as above for Y axis */
   1.556 +
   1.557 +    CROSS_SLIDING_X,          /* Panning disabled while user does a horizontal gesture
   1.558 +                                 on a vertically-scrollable view. This used for the
   1.559 +                                 Windows Metro "cross-slide" gesture. */
   1.560 +    CROSS_SLIDING_Y,          /* as above for Y axis */
   1.561 +
   1.562 +    PINCHING,                 /* nth touch-start, where n > 1. this mode allows pan and zoom */
   1.563 +    ANIMATING_ZOOM,           /* animated zoom to a new rect */
   1.564 +    WAITING_CONTENT_RESPONSE, /* a state halfway between NOTHING and TOUCHING - the user has
   1.565 +                                 put a finger down, but we don't yet know if a touch listener has
   1.566 +                                 prevented the default actions yet and the allowed touch behavior
   1.567 +                                 was not set yet. we still need to abort animations. */
   1.568 +  };
   1.569 +
   1.570 +  // State related to a single touch block. Does not persist across touch blocks.
   1.571 +  struct TouchBlockState {
   1.572 +
   1.573 +    TouchBlockState()
   1.574 +      :  mAllowedTouchBehaviorSet(false),
   1.575 +         mPreventDefault(false),
   1.576 +         mPreventDefaultSet(false),
   1.577 +         mSingleTapOccurred(false)
   1.578 +    {}
   1.579 +
   1.580 +    // Values of allowed touch behavior for touch points of this touch block.
   1.581 +    // Since there are maybe a few current active touch points per time (multitouch case)
   1.582 +    // and each touch point should have its own value of allowed touch behavior- we're
   1.583 +    // keeping an array of allowed touch behavior values, not the single value.
   1.584 +    nsTArray<TouchBehaviorFlags> mAllowedTouchBehaviors;
   1.585 +
   1.586 +    // Specifies whether mAllowedTouchBehaviors is set for this touch events block.
   1.587 +    bool mAllowedTouchBehaviorSet;
   1.588 +
   1.589 +    // Flag used to specify that content prevented the default behavior of this
   1.590 +    // touch events block.
   1.591 +    bool mPreventDefault;
   1.592 +
   1.593 +    // Specifies whether mPreventDefault property is set for this touch events block.
   1.594 +    bool mPreventDefaultSet;
   1.595 +
   1.596 +    // Specifies whether a single tap event was generated during this touch block.
   1.597 +    bool mSingleTapOccurred;
   1.598 +  };
   1.599 +
   1.600 +  /*
   1.601 +   * Returns whether current touch behavior values allow pinch-zooming.
   1.602 +   */
   1.603 +  bool TouchActionAllowPinchZoom();
   1.604 +
   1.605 +  /*
   1.606 +   * Returns whether current touch behavior values allow double-tap-zooming.
   1.607 +   */
   1.608 +  bool TouchActionAllowDoubleTapZoom();
   1.609 +
   1.610 +  /*
   1.611 +   * Returns allowed touch behavior from the mAllowedTouchBehavior array.
   1.612 +   * In case apzc didn't receive touch behavior values within the timeout
   1.613 +   * it returns default value.
   1.614 +   */
   1.615 +  TouchBehaviorFlags GetTouchBehavior(uint32_t touchIndex);
   1.616 +
   1.617 +  /**
   1.618 +   * To move from the WAITING_CONTENT_RESPONSE state to TOUCHING one we need two
   1.619 +   * conditions set: get content listeners response (whether they called preventDefault)
   1.620 +   * and get allowed touch behaviors.
   1.621 +   * This method checks both conditions and changes (or not changes) state
   1.622 +   * appropriately.
   1.623 +   */
   1.624 +  void CheckContentResponse();
   1.625 +
   1.626 +  /**
   1.627 +   * Helper to set the current state. Holds the monitor before actually setting
   1.628 +   * it and fires content controller events based on state changes. Always set
   1.629 +   * the state using this call, do not set it directly.
   1.630 +   */
   1.631 +  void SetState(PanZoomState aState);
   1.632 +
   1.633 +  /**
   1.634 +   * Convert ScreenPoint relative to this APZC to CSSPoint relative
   1.635 +   * to the parent document. This excludes the transient compositor transform.
   1.636 +   * NOTE: This must be converted to CSSPoint relative to the child
   1.637 +   * document before sending over IPC.
   1.638 +   */
   1.639 +  bool ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut);
   1.640 +
   1.641 +  /**
   1.642 +   * Internal helpers for checking general state of this apzc.
   1.643 +   */
   1.644 +  bool IsTransformingState(PanZoomState aState);
   1.645 +  bool IsPanningState(PanZoomState mState);
   1.646 +
   1.647 +  enum AxisLockMode {
   1.648 +    FREE,     /* No locking at all */
   1.649 +    STANDARD, /* Default axis locking mode that remains locked until pan ends*/
   1.650 +    STICKY,   /* Allow lock to be broken, with hysteresis */
   1.651 +  };
   1.652 +
   1.653 +  static AxisLockMode GetAxisLockMode();
   1.654 +
   1.655 +  // Convert a point from local screen coordinates to parent layer coordinates.
   1.656 +  // This is a common operation as inputs from the tree manager are in screen
   1.657 +  // coordinates but the composition bounds is in parent layer coordinates.
   1.658 +  ParentLayerPoint ToParentLayerCoords(const ScreenPoint& aPoint);
   1.659 +
   1.660 +  // Update mFrameMetrics.mTransformScale. This should be called whenever
   1.661 +  // our CSS transform or the non-transient part of our async transform
   1.662 +  // changes, as it corresponds to the scale portion of those transforms.
   1.663 +  void UpdateTransformScale();
   1.664 +
   1.665 +  // Helper function for OnSingleTapUp() and OnSingleTapConfirmed().
   1.666 +  nsEventStatus GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers);
   1.667 +
   1.668 +  // Common processing at the end of a touch block.
   1.669 +  void OnTouchEndOrCancel();
   1.670 +
   1.671 +  uint64_t mLayersId;
   1.672 +  nsRefPtr<CompositorParent> mCompositorParent;
   1.673 +  PCompositorParent* mCrossProcessCompositorParent;
   1.674 +  TaskThrottler mPaintThrottler;
   1.675 +
   1.676 +  /* Access to the following two fields is protected by the mRefPtrMonitor,
   1.677 +     since they are accessed on the UI thread but can be cleared on the
   1.678 +     compositor thread. */
   1.679 +  nsRefPtr<GeckoContentController> mGeckoContentController;
   1.680 +  nsRefPtr<GestureEventListener> mGestureEventListener;
   1.681 +  Monitor mRefPtrMonitor;
   1.682 +
   1.683 +  /* Utility functions that return a addrefed pointer to the corresponding fields. */
   1.684 +  already_AddRefed<GeckoContentController> GetGeckoContentController();
   1.685 +  already_AddRefed<GestureEventListener> GetGestureEventListener();
   1.686 +
   1.687 +protected:
   1.688 +  // Both |mFrameMetrics| and |mLastContentPaintMetrics| are protected by the
   1.689 +  // monitor. Do not read from or modify either of them without locking.
   1.690 +  FrameMetrics mFrameMetrics;
   1.691 +
   1.692 +  // Protects |mFrameMetrics|, |mLastContentPaintMetrics|, and |mState|.
   1.693 +  // Before manipulating |mFrameMetrics| or |mLastContentPaintMetrics|, the
   1.694 +  // monitor should be held. When setting |mState|, either the SetState()
   1.695 +  // function can be used, or the monitor can be held and then |mState| updated.
   1.696 +  // IMPORTANT: See the note about lock ordering at the top of APZCTreeManager.h.
   1.697 +  // This is mutable to allow entering it from 'const' methods; doing otherwise
   1.698 +  // would significantly limit what methods could be 'const'.
   1.699 +  mutable ReentrantMonitor mMonitor;
   1.700 +
   1.701 +  // Specifies whether we should use touch-action css property. Initialized from
   1.702 +  // the preferences. This property (in comparison with the global one) simplifies
   1.703 +  // testing apzc with (and without) touch-action property enabled concurrently
   1.704 +  // (e.g. with the gtest framework).
   1.705 +  bool mTouchActionPropertyEnabled;
   1.706 +
   1.707 +private:
   1.708 +  // Metrics of the container layer corresponding to this APZC. This is
   1.709 +  // stored here so that it is accessible from the UI/controller thread.
   1.710 +  // These are the metrics at last content paint, the most recent
   1.711 +  // values we were notified of in NotifyLayersUpdate(). Since it represents
   1.712 +  // the Gecko state, it should be used as a basis for untransformation when
   1.713 +  // sending messages back to Gecko.
   1.714 +  FrameMetrics mLastContentPaintMetrics;
   1.715 +  // The last metrics that we requested a paint for. These are used to make sure
   1.716 +  // that we're not requesting a paint of the same thing that's already drawn.
   1.717 +  // If we don't do this check, we don't get a ShadowLayersUpdated back.
   1.718 +  FrameMetrics mLastPaintRequestMetrics;
   1.719 +  // The last metrics that we actually sent to Gecko. This allows us to transform
   1.720 +  // inputs into a coordinate space that Gecko knows about. This assumes the pipe
   1.721 +  // through which input events and repaint requests are sent to Gecko operates
   1.722 +  // in a FIFO manner.
   1.723 +  FrameMetrics mLastDispatchedPaintMetrics;
   1.724 +
   1.725 +  nsTArray<MultiTouchInput> mTouchQueue;
   1.726 +
   1.727 +  CancelableTask* mContentResponseTimeoutTask;
   1.728 +
   1.729 +  AxisX mX;
   1.730 +  AxisY mY;
   1.731 +
   1.732 +  // This flag is set to true when we are in a axis-locked pan as a result of
   1.733 +  // the touch-action CSS property.
   1.734 +  bool mPanDirRestricted;
   1.735 +
   1.736 +  // Most up-to-date constraints on zooming. These should always be reasonable
   1.737 +  // values; for example, allowing a min zoom of 0.0 can cause very bad things
   1.738 +  // to happen.
   1.739 +  ZoomConstraints mZoomConstraints;
   1.740 +
   1.741 +  // The last time the compositor has sampled the content transform for this
   1.742 +  // frame.
   1.743 +  TimeStamp mLastSampleTime;
   1.744 +  // The last time a touch event came through on the UI thread.
   1.745 +  uint32_t mLastEventTime;
   1.746 +
   1.747 +  // Stores the previous focus point if there is a pinch gesture happening. Used
   1.748 +  // to allow panning by moving multiple fingers (thus moving the focus point).
   1.749 +  ParentLayerPoint mLastZoomFocus;
   1.750 +
   1.751 +  // Stores the state of panning and zooming this frame. This is protected by
   1.752 +  // |mMonitor|; that is, it should be held whenever this is updated.
   1.753 +  PanZoomState mState;
   1.754 +
   1.755 +  // The last time and offset we fire the mozbrowserasyncscroll event when
   1.756 +  // compositor has sampled the content transform for this frame.
   1.757 +  TimeStamp mLastAsyncScrollTime;
   1.758 +  CSSPoint mLastAsyncScrollOffset;
   1.759 +
   1.760 +  // The current offset drawn on the screen, it may not be sent since we have
   1.761 +  // throttling policy for mozbrowserasyncscroll event.
   1.762 +  CSSPoint mCurrentAsyncScrollOffset;
   1.763 +
   1.764 +  // The delay task triggered by the throttling mozbrowserasyncscroll event
   1.765 +  // ensures the last mozbrowserasyncscroll event is always been fired.
   1.766 +  CancelableTask* mAsyncScrollTimeoutTask;
   1.767 +
   1.768 +  // Flag used to determine whether or not we should try to enter the
   1.769 +  // WAITING_LISTENERS state. This is used in the case that we are processing a
   1.770 +  // queued up event block. If set, this means that we are handling this queue
   1.771 +  // and we don't want to queue the events back up again.
   1.772 +  bool mHandlingTouchQueue;
   1.773 +
   1.774 +  // Stores information about the current touch block.
   1.775 +  TouchBlockState mTouchBlockState;
   1.776 +
   1.777 +  // Extra offset to add in SampleContentTransformForFrame for testing
   1.778 +  CSSPoint mTestAsyncScrollOffset;
   1.779 +
   1.780 +  RefPtr<AsyncPanZoomAnimation> mAnimation;
   1.781 +
   1.782 +  friend class Axis;
   1.783 +  friend class FlingAnimation;
   1.784 +
   1.785 +
   1.786 +  /* ===================================================================
   1.787 +   * The functions and members in this section are used to build a tree
   1.788 +   * structure out of APZC instances. This tree can only be walked or
   1.789 +   * manipulated while holding the lock in the associated APZCTreeManager
   1.790 +   * instance.
   1.791 +   */
   1.792 +public:
   1.793 +  void SetLastChild(AsyncPanZoomController* child) {
   1.794 +    mLastChild = child;
   1.795 +    if (child) {
   1.796 +      child->mParent = this;
   1.797 +    }
   1.798 +  }
   1.799 +
   1.800 +  void SetPrevSibling(AsyncPanZoomController* sibling) {
   1.801 +    mPrevSibling = sibling;
   1.802 +    if (sibling) {
   1.803 +      sibling->mParent = mParent;
   1.804 +    }
   1.805 +  }
   1.806 +
   1.807 +  AsyncPanZoomController* GetLastChild() const { return mLastChild; }
   1.808 +  AsyncPanZoomController* GetPrevSibling() const { return mPrevSibling; }
   1.809 +  AsyncPanZoomController* GetParent() const { return mParent; }
   1.810 +
   1.811 +  /* Returns true if there is no APZC higher in the tree with the same
   1.812 +   * layers id.
   1.813 +   */
   1.814 +  bool IsRootForLayersId() const {
   1.815 +    return !mParent || (mParent->mLayersId != mLayersId);
   1.816 +  }
   1.817 +
   1.818 +  bool IsRootForLayersId(const uint64_t& aLayersId) const {
   1.819 +    return (mLayersId == aLayersId) && IsRootForLayersId();
   1.820 +  }
   1.821 +
   1.822 +private:
   1.823 +  // This is a raw pointer to avoid introducing a reference cycle between
   1.824 +  // AsyncPanZoomController and APZCTreeManager. Since these objects don't
   1.825 +  // live on the main thread, we can't use the cycle collector with them.
   1.826 +  // The APZCTreeManager owns the lifetime of the APZCs, so nulling this
   1.827 +  // pointer out in Destroy() will prevent accessing deleted memory.
   1.828 +  Atomic<APZCTreeManager*> mTreeManager;
   1.829 +
   1.830 +  nsRefPtr<AsyncPanZoomController> mLastChild;
   1.831 +  nsRefPtr<AsyncPanZoomController> mPrevSibling;
   1.832 +  nsRefPtr<AsyncPanZoomController> mParent;
   1.833 +
   1.834 +
   1.835 +  /* ===================================================================
   1.836 +   * The functions and members in this section are used in building the
   1.837 +   * scroll handoff chain, so that we can have seamless scrolling continue
   1.838 +   * across APZC instances.
   1.839 +   */
   1.840 +public:
   1.841 +  void SetScrollHandoffParentId(FrameMetrics::ViewID aScrollParentId) {
   1.842 +    mScrollParentId = aScrollParentId;
   1.843 +  }
   1.844 +
   1.845 +  FrameMetrics::ViewID GetScrollHandoffParentId() const {
   1.846 +    return mScrollParentId;
   1.847 +  }
   1.848 +
   1.849 +  /**
   1.850 +   * Attempt to scroll in response to a touch-move from |aStartPoint| to
   1.851 +   * |aEndPoint|, which are in our (transformed) screen coordinates.
   1.852 +   * Due to overscroll handling, there may not actually have been a touch-move
   1.853 +   * at these points, but this function will scroll as if there had been.
   1.854 +   * If this attempt causes overscroll (i.e. the layer cannot be scrolled
   1.855 +   * by the entire amount requested), the overscroll is passed back to the
   1.856 +   * tree manager via APZCTreeManager::DispatchScroll().
   1.857 +   * |aOverscrollHandoffChainIndex| is used by the tree manager to keep track
   1.858 +   * of which APZC to hand off the overscroll to; this function increments it
   1.859 +   * and passes it on to APZCTreeManager::DispatchScroll() in the event of
   1.860 +   * overscroll.
   1.861 +   */
   1.862 +  void AttemptScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint,
   1.863 +                     uint32_t aOverscrollHandoffChainIndex = 0);
   1.864 +
   1.865 +  void FlushRepaintForOverscrollHandoff();
   1.866 +
   1.867 +private:
   1.868 +  FrameMetrics::ViewID mScrollParentId;
   1.869 +
   1.870 +  /**
   1.871 +   * A helper function for calling APZCTreeManager::DispatchScroll().
   1.872 +   * Guards against the case where the APZC is being concurrently destroyed
   1.873 +   * (and thus mTreeManager is being nulled out).
   1.874 +   */
   1.875 +  void CallDispatchScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint,
   1.876 +                          uint32_t aOverscrollHandoffChainIndex);
   1.877 +
   1.878 +
   1.879 +  /* ===================================================================
   1.880 +   * The functions and members in this section are used to maintain the
   1.881 +   * area that this APZC instance is responsible for. This is used when
   1.882 +   * hit-testing to see which APZC instance should handle touch events.
   1.883 +   */
   1.884 +public:
   1.885 +  void SetLayerHitTestData(const ParentLayerRect& aRect, const gfx3DMatrix& aTransformToLayer,
   1.886 +                           const gfx3DMatrix& aTransformForLayer) {
   1.887 +    mVisibleRect = aRect;
   1.888 +    mAncestorTransform = aTransformToLayer;
   1.889 +    mCSSTransform = aTransformForLayer;
   1.890 +    UpdateTransformScale();
   1.891 +  }
   1.892 +
   1.893 +  gfx3DMatrix GetAncestorTransform() const {
   1.894 +    return mAncestorTransform;
   1.895 +  }
   1.896 +
   1.897 +  gfx3DMatrix GetCSSTransform() const {
   1.898 +    return mCSSTransform;
   1.899 +  }
   1.900 +
   1.901 +  bool VisibleRegionContains(const ParentLayerPoint& aPoint) const {
   1.902 +    return mVisibleRect.Contains(aPoint);
   1.903 +  }
   1.904 +
   1.905 +private:
   1.906 +  /* This is the visible region of the layer that this APZC corresponds to, in
   1.907 +   * that layer's screen pixels (the same coordinate system in which this APZC
   1.908 +   * receives events in ReceiveInputEvent()). */
   1.909 +  ParentLayerRect mVisibleRect;
   1.910 +  /* This is the cumulative CSS transform for all the layers between the parent
   1.911 +   * APZC and this one (not inclusive) */
   1.912 +  gfx3DMatrix mAncestorTransform;
   1.913 +  /* This is the CSS transform for this APZC's layer. */
   1.914 +  gfx3DMatrix mCSSTransform;
   1.915 +
   1.916 +
   1.917 +  /* ===================================================================
   1.918 +   * The functions and members in this section are used for sharing the
   1.919 +   * FrameMetrics across processes for the progressive tiling code.
   1.920 +   */
   1.921 +private:
   1.922 +  /* Unique id assigned to each APZC. Used with ViewID to uniquely identify
   1.923 +   * shared FrameMeterics used in progressive tile painting. */
   1.924 +  const uint32_t mAPZCId;
   1.925 +
   1.926 +  ipc::SharedMemoryBasic* mSharedFrameMetricsBuffer;
   1.927 +  CrossProcessMutex* mSharedLock;
   1.928 +  /**
   1.929 +   * Called when ever mFrameMetrics is updated so that if it is being
   1.930 +   * shared with the content process the shared FrameMetrics may be updated.
   1.931 +   */
   1.932 +  void UpdateSharedCompositorFrameMetrics();
   1.933 +  /**
   1.934 +   * Create a shared memory buffer for containing the FrameMetrics and
   1.935 +   * a CrossProcessMutex that may be shared with the content process
   1.936 +   * for use in progressive tiled update calculations.
   1.937 +   */
   1.938 +  void ShareCompositorFrameMetrics();
   1.939 +};
   1.940 +
   1.941 +class AsyncPanZoomAnimation {
   1.942 +  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomAnimation)
   1.943 +
   1.944 +public:
   1.945 +  AsyncPanZoomAnimation(const TimeDuration& aRepaintInterval =
   1.946 +                        TimeDuration::Forever())
   1.947 +    : mRepaintInterval(aRepaintInterval)
   1.948 +  { }
   1.949 +
   1.950 +  virtual bool Sample(FrameMetrics& aFrameMetrics,
   1.951 +                      const TimeDuration& aDelta) = 0;
   1.952 +
   1.953 +  /**
   1.954 +   * Get the deferred tasks in |mDeferredTasks|. See |mDeferredTasks|
   1.955 +   * for more information.
   1.956 +   * Clears |mDeferredTasks|.
   1.957 +   */
   1.958 +  Vector<Task*> TakeDeferredTasks() {
   1.959 +    Vector<Task*> result;
   1.960 +    mDeferredTasks.swap(result);
   1.961 +    return result;
   1.962 +  }
   1.963 +
   1.964 +  /**
   1.965 +   * Specifies how frequently (at most) we want to do repaints during the
   1.966 +   * animation sequence. TimeDuration::Forever() will cause it to only repaint
   1.967 +   * at the end of the animation.
   1.968 +   */
   1.969 +  TimeDuration mRepaintInterval;
   1.970 +
   1.971 +protected:
   1.972 +  // Protected destructor, to discourage deletion outside of Release():
   1.973 +  virtual ~AsyncPanZoomAnimation()
   1.974 +  { }
   1.975 +
   1.976 +  /**
   1.977 +   * Tasks scheduled for execution after the APZC's mMonitor is released.
   1.978 +   * Derived classes can add tasks here in Sample(), and the APZC can call
   1.979 +   * ExecuteDeferredTasks() to execute them.
   1.980 +   */
   1.981 +  Vector<Task*> mDeferredTasks;
   1.982 +};
   1.983 +
   1.984 +}
   1.985 +}
   1.986 +
   1.987 +#endif // mozilla_layers_PanZoomController_h

mercurial