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