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