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