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_APZCTreeManager_h 8 #define mozilla_layers_APZCTreeManager_h 9 10 #include <unordered_map> // for std::unordered_map 11 12 #include "FocusState.h" // for FocusState 13 #include "HitTestingTreeNode.h" // for HitTestingTreeNodeAutoLock 14 #include "gfxPoint.h" // for gfxPoint 15 #include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2 16 #include "mozilla/DataMutex.h" // for DataMutex 17 #include "mozilla/gfx/CompositorHitTestInfo.h" 18 #include "mozilla/gfx/Logging.h" // for gfx::TreeLog 19 #include "mozilla/gfx/Matrix.h" // for Matrix4x4 20 #include "mozilla/layers/APZInputBridge.h" // for APZInputBridge 21 #include "mozilla/layers/APZTestData.h" // for APZTestData 22 #include "mozilla/layers/APZUtils.h" // for GeckoViewMetrics 23 #include "mozilla/layers/IAPZCTreeManager.h" // for IAPZCTreeManager 24 #include "mozilla/layers/LayerAttributes.h" 25 #include "mozilla/layers/LayersTypes.h" 26 #include "mozilla/layers/KeyboardMap.h" // for KeyboardMap 27 #include "mozilla/layers/TouchCounter.h" // for TouchCounter 28 #include "mozilla/layers/ZoomConstraints.h" // for ZoomConstraints 29 #include "mozilla/webrender/webrender_ffi.h" 30 #include "mozilla/RecursiveMutex.h" // for RecursiveMutex 31 #include "mozilla/RefPtr.h" // for RefPtr 32 #include "mozilla/TimeStamp.h" // for mozilla::TimeStamp 33 #include "mozilla/UniquePtr.h" // for UniquePtr 34 #include "nsCOMPtr.h" // for already_AddRefed 35 36 namespace mozilla { 37 class MultiTouchInput; 38 39 namespace wr { 40 class TransactionWrapper; 41 class WebRenderAPI; 42 } // namespace wr 43 44 namespace layers { 45 46 class Layer; 47 class AsyncPanZoomController; 48 class APZCTreeManagerParent; 49 class APZSampler; 50 class APZUpdater; 51 class CompositorBridgeParent; 52 class OverscrollHandoffChain; 53 struct OverscrollHandoffState; 54 class FocusTarget; 55 struct FlingHandoffState; 56 class InputQueue; 57 class GeckoContentController; 58 class HitTestingTreeNode; 59 class HitTestingTreeNodeAutoLock; 60 class LayerMetricsWrapper; 61 class SampleTime; 62 class WebRenderScrollDataWrapper; 63 struct AncestorTransform; 64 struct ScrollThumbData; 65 struct ZoomTarget; 66 67 /** 68 * ****************** NOTE ON LOCK ORDERING IN APZ ************************** 69 * 70 * To avoid deadlock, APZ imposes and respects a global ordering on threads 71 * and locks relevant to APZ. 72 * 73 * Please see the "Threading / Locking Overview" section of 74 * gfx/docs/AsyncPanZoom.rst (hosted in rendered form at 75 * https://firefox-source-docs.mozilla.org/gfx/gfx/AsyncPanZoom.html#threading-locking-overview) 76 * for what the ordering is, and what are the rules for respecting it. 77 * ************************************************************************** 78 */ 79 80 /** 81 * This class manages the tree of AsyncPanZoomController instances. There is one 82 * instance of this class owned by each CompositorBridgeParent, and it contains 83 * as many AsyncPanZoomController instances as there are scrollable container 84 * layers. This class generally lives on the updater thread, although some 85 * functions may be called from other threads as noted; thread safety is ensured 86 * internally. 87 * 88 * The bulk of the work of this class happens as part of the 89 * UpdateHitTestingTree function, which is when a layer tree update is received 90 * by the compositor. This function walks through the layer tree and creates a 91 * tree of HitTestingTreeNode instances to match the layer tree and for use in 92 * hit-testing on the controller thread. APZC instances may be preserved across 93 * calls to this function if the corresponding layers are still present in the 94 * layer tree. 95 * 96 * The other functions on this class are used by various pieces of client code 97 * to notify the APZC instances of events relevant to them. This includes, for 98 * example, user input events that drive panning and zooming, changes to the 99 * scroll viewport area, and changes to pan/zoom constraints. 100 * 101 * Note that the ClearTree function MUST be called when this class is no longer 102 * needed; see the method documentation for details. 103 * 104 * Behaviour of APZ is controlled by a number of preferences shown 105 * \ref APZCPrefs "here". 106 */ 107 class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge { 108 typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior; 109 typedef mozilla::layers::AsyncDragMetrics AsyncDragMetrics; 110 111 // Helper struct to hold some state while we build the hit-testing tree. The 112 // sole purpose of this struct is to shorten the argument list to 113 // UpdateHitTestingTree. All the state that we don't need to 114 // push on the stack during recursion and pop on unwind is stored here. 115 struct TreeBuildingState; 116 117 public: 118 APZCTreeManager(LayersId aRootLayersId, bool aIsUsingWebRender); 119 120 void SetSampler(APZSampler* aSampler); 121 void SetUpdater(APZUpdater* aUpdater); 122 123 /** 124 * Notifies this APZCTreeManager that the associated compositor is now 125 * responsible for managing another layers id, which got moved over from 126 * some other compositor. That other compositor's APZCTreeManager is also 127 * provided. This allows APZCTreeManager to transfer any necessary state 128 * from the old APZCTreeManager related to that layers id. 129 * This function must be called on the updater thread. 130 */ 131 void NotifyLayerTreeAdopted(LayersId aLayersId, 132 const RefPtr<APZCTreeManager>& aOldTreeManager); 133 134 /** 135 * Notifies this APZCTreeManager that a layer tree being managed by the 136 * associated compositor has been removed/destroyed. Note that this does 137 * NOT get called during shutdown situations, when the root layer tree is 138 * also getting destroyed. 139 * This function must be called on the updater thread. 140 */ 141 void NotifyLayerTreeRemoved(LayersId aLayersId); 142 143 /** 144 * Rebuild the focus state based on the focus target from the layer tree 145 * update that just occurred. This must be called on the updater thread. 146 * 147 * @param aRootLayerTreeId The layer tree ID of the root layer corresponding 148 * to this APZCTreeManager 149 * @param aOriginatingLayersId The layer tree ID of the layer corresponding to 150 * this layer tree update. 151 */ 152 void UpdateFocusState(LayersId aRootLayerTreeId, 153 LayersId aOriginatingLayersId, 154 const FocusTarget& aFocusTarget); 155 156 /** 157 * Rebuild the hit-testing tree based on the layer update that just came up. 158 * Preserve nodes and APZC instances where possible, but retire those whose 159 * layers are no longer in the layer tree. 160 * 161 * This must be called on the updater thread as it walks the layer tree. 162 * 163 * @param aRoot The root of the (full) layer tree 164 * @param aOriginatingLayersId The layers id of the subtree that triggered 165 * this repaint, and to which aIsFirstPaint 166 * applies. 167 * @param aIsFirstPaint True if the layers update that this is called in 168 * response to included a first-paint. If this is true, 169 * the part of the tree that is affected by the 170 * first-paint flag is indicated by the 171 * aFirstPaintLayersId parameter. 172 * @param aPaintSequenceNumber The sequence number of the paint that triggered 173 * this layer update. Note that every layer child 174 * process' layer subtree has its own sequence 175 * numbers. 176 */ 177 void UpdateHitTestingTree(Layer* aRoot, bool aIsFirstPaint, 178 LayersId aOriginatingLayersId, 179 uint32_t aPaintSequenceNumber); 180 181 /** 182 * Same as the above UpdateHitTestingTree, except slightly modified to take 183 * the scrolling data passed over PWebRenderBridge instead of the raw layer 184 * tree. This version is used when WebRender is enabled because we don't have 185 * shadow layers in that scenario. 186 */ 187 void UpdateHitTestingTree(const WebRenderScrollDataWrapper& aScrollWrapper, 188 bool aIsFirstPaint, LayersId aOriginatingLayersId, 189 uint32_t aPaintSequenceNumber); 190 191 /** 192 * Called when webrender is enabled, from the sampler thread. This function 193 * populates the provided transaction with any async scroll offsets needed. 194 * It also advances APZ animations to the specified sample time, and requests 195 * another composite if there are still active animations. 196 * In effect it is the webrender equivalent of (part of) the code in 197 * AsyncCompositionManager. 198 */ 199 void SampleForWebRender(const Maybe<VsyncId>& aVsyncId, 200 wr::TransactionWrapper& aTxn, 201 const SampleTime& aSampleTime); 202 203 /** 204 * Walk through all the APZCs and do the sampling steps needed when 205 * advancing to the next frame. The APZCs walked can be restricted to a 206 * specific render root by providing that as the first argument. 207 */ 208 bool AdvanceAnimations(const SampleTime& aSampleTime); 209 210 /** 211 * Refer to the documentation of APZInputBridge::ReceiveInputEvent() and 212 * APZEventResult. 213 */ 214 APZEventResult ReceiveInputEvent(InputData& aEvent) override; 215 216 /** 217 * Set the keyboard shortcuts to use for translating keyboard events. 218 */ 219 void SetKeyboardMap(const KeyboardMap& aKeyboardMap) override; 220 221 /** 222 * Kicks an animation to zoom to a rect. This may be either a zoom out or zoom 223 * in. The actual animation is done on the sampler thread after being set 224 * up. |aRect| must be given in CSS pixels, relative to the document. 225 * |aFlags| is a combination of the ZoomToRectBehavior enum values. 226 */ 227 void ZoomToRect(const ScrollableLayerGuid& aGuid, 228 const ZoomTarget& aZoomTarget, 229 const uint32_t aFlags = DEFAULT_BEHAVIOR) override; 230 231 /** 232 * If we have touch listeners, this should always be called when we know 233 * definitively whether or not content has preventDefaulted any touch events 234 * that have come in. If |aPreventDefault| is true, any touch events in the 235 * queue will be discarded. This function must be called on the controller 236 * thread. 237 */ 238 void ContentReceivedInputBlock(uint64_t aInputBlockId, 239 bool aPreventDefault) override; 240 241 /** 242 * When the event regions code is enabled, this function should be invoked to 243 * to confirm the target of the input block. This is only needed in cases 244 * where the initial input event of the block hit a dispatch-to-content region 245 * but is safe to call for all input blocks. This function should always be 246 * invoked on the controller thread. 247 * The different elements in the array of targets correspond to the targets 248 * for the different touch points. In the case where the touch point has no 249 * target, or the target is not a scrollable frame, the target's |mScrollId| 250 * should be set to ScrollableLayerGuid::NULL_SCROLL_ID. 251 * Note: For mouse events that start a scrollbar drag, both SetTargetAPZC() 252 * and StartScrollbarDrag() will be called, and the calls may happen 253 * in either order. That's fine - whichever arrives first will confirm 254 * the block, and StartScrollbarDrag() will fill in the drag metrics. 255 * If the block is confirmed before we have drag metrics, some events 256 * in the drag block may be handled as no-ops until the drag metrics 257 * arrive. 258 */ 259 void SetTargetAPZC(uint64_t aInputBlockId, 260 const nsTArray<ScrollableLayerGuid>& aTargets) override; 261 262 /** 263 * Updates any zoom constraints contained in the <meta name="viewport"> tag. 264 * If the |aConstraints| is Nothing() then previously-provided constraints for 265 * the given |aGuid| are cleared. 266 */ 267 void UpdateZoomConstraints( 268 const ScrollableLayerGuid& aGuid, 269 const Maybe<ZoomConstraints>& aConstraints) override; 270 271 /** 272 * Calls Destroy() on all APZC instances attached to the tree, and resets the 273 * tree back to empty. This function must be called exactly once during the 274 * lifetime of this APZCTreeManager, when this APZCTreeManager is no longer 275 * needed. Failing to call this function may prevent objects from being freed 276 * properly. 277 * This must be called on the updater thread. 278 */ 279 void ClearTree(); 280 281 /** 282 * Sets the dpi value used by all AsyncPanZoomControllers attached to this 283 * tree manager. 284 * DPI defaults to 160 if not set using SetDPI() at any point. 285 */ 286 void SetDPI(float aDpiValue) override; 287 288 /** 289 * Returns the current dpi value in use. 290 */ 291 float GetDPI() const; 292 293 /** 294 * Find the hit testing node for the scrollbar thumb that matches these 295 * drag metrics. Initializes aOutThumbNode with the node, if there is one. 296 */ 297 void FindScrollThumbNode(const AsyncDragMetrics& aDragMetrics, 298 LayersId aLayersId, 299 HitTestingTreeNodeAutoLock& aOutThumbNode); 300 301 /** 302 * Sets allowed touch behavior values for current touch-session for specific 303 * input block (determined by aInputBlock). 304 * Should be invoked by the widget. Each value of the aValues arrays 305 * corresponds to the different touch point that is currently active. 306 * Must be called after receiving the TOUCH_START event that starts the 307 * touch-session. 308 * This must be called on the controller thread. 309 */ 310 void SetAllowedTouchBehavior( 311 uint64_t aInputBlockId, 312 const nsTArray<TouchBehaviorFlags>& aValues) override; 313 314 /** 315 * This is a callback for AsyncPanZoomController to call when it wants to 316 * scroll in response to a touch-move event, or when it needs to hand off 317 * overscroll to the next APZC. Note that because of scroll grabbing, the 318 * first APZC to scroll may not be the one that is receiving the touch events. 319 * 320 * |aPrev| is the APZC that received the touch events triggering the scroll 321 * (in the case of an initial scroll), or the last APZC to scroll (in the 322 * case of overscroll) 323 * |aStartPoint| and |aEndPoint| are in |aPrev|'s transformed screen 324 * coordinates (i.e. the same coordinates in which touch points are given to 325 * APZCs). The amount of (over)scroll is represented by two points rather 326 * than a displacement because with certain 3D transforms, the same 327 * displacement between different points in transformed coordinates can 328 * represent different displacements in untransformed coordinates. 329 * |aOverscrollHandoffChain| is the overscroll handoff chain used for 330 * determining the order in which scroll should be handed off between 331 * APZCs 332 * |aOverscrollHandoffChainIndex| is the next position in the overscroll 333 * handoff chain that should be scrolled. 334 * 335 * aStartPoint and aEndPoint will be modified depending on how much of the 336 * scroll each APZC consumes. This is to allow the sending APZC to go into 337 * an overscrolled state if no APZC further up in the handoff chain accepted 338 * the entire scroll. 339 * 340 * The function will return true if the entire scroll was consumed, and 341 * false otherwise. As this function also modifies aStartPoint and aEndPoint, 342 * when scroll is consumed, it should always the case that this function 343 * returns true if and only if IsZero(aStartPoint - aEndPoint), using the 344 * modified aStartPoint and aEndPoint after the function returns. 345 * 346 * The way this method works is best illustrated with an example. 347 * Consider three nested APZCs, A, B, and C, with C being the innermost one. 348 * Say B is scroll-grabbing. 349 * The touch events go to C because it's the innermost one (so e.g. taps 350 * should go through C), but the overscroll handoff chain is B -> C -> A 351 * because B is scroll-grabbing. 352 * For convenience I'll refer to the three APZC objects as A, B, and C, and 353 * to the tree manager object as TM. 354 * Here's what happens when C receives a touch-move event: 355 * - C.TrackTouch() calls TM.DispatchScroll() with index = 0. 356 * - TM.DispatchScroll() calls B.AttemptScroll() (since B is at index 0 in 357 * the chain). 358 * - B.AttemptScroll() scrolls B. If there is overscroll, it calls 359 * TM.DispatchScroll() with index = 1. 360 * - TM.DispatchScroll() calls C.AttemptScroll() (since C is at index 1 in 361 * the chain) 362 * - C.AttemptScroll() scrolls C. If there is overscroll, it calls 363 * TM.DispatchScroll() with index = 2. 364 * - TM.DispatchScroll() calls A.AttemptScroll() (since A is at index 2 in 365 * the chain) 366 * - A.AttemptScroll() scrolls A. If there is overscroll, it calls 367 * TM.DispatchScroll() with index = 3. 368 * - TM.DispatchScroll() discards the rest of the scroll as there are no 369 * more elements in the chain. 370 * 371 * Note: this should be used for panning only. For handing off overscroll for 372 * a fling, use DispatchFling(). 373 */ 374 bool DispatchScroll(AsyncPanZoomController* aPrev, 375 ParentLayerPoint& aStartPoint, 376 ParentLayerPoint& aEndPoint, 377 OverscrollHandoffState& aOverscrollHandoffState); 378 379 /** 380 * This is a callback for AsyncPanZoomController to call when it wants to 381 * start a fling in response to a touch-end event, or when it needs to hand 382 * off a fling to the next APZC. Note that because of scroll grabbing, the 383 * first APZC to fling may not be the one that is receiving the touch events. 384 * 385 * @param aApzc the APZC that wants to start or hand off the fling 386 * @param aHandoffState a collection of state about the operation, 387 * which contains the following: 388 * 389 * mVelocity the current velocity of the fling, in |aApzc|'s screen 390 * pixels per millisecond 391 * mChain the chain of APZCs along which the fling 392 * should be handed off 393 * mIsHandoff is true if |aApzc| is handing off an existing fling (in 394 * this case the fling is given to the next APZC in the 395 * handoff chain after |aApzc|), and false is |aApzc| wants 396 * start a fling (in this case the fling is given to the 397 * first APZC in the chain) 398 * 399 * The return value is the "residual velocity", the portion of 400 * |aHandoffState.mVelocity| that was not consumed by APZCs in the 401 * handoff chain doing flings. 402 * The caller can use this value to determine whether it should consume 403 * the excess velocity by going into overscroll. 404 */ 405 ParentLayerPoint DispatchFling(AsyncPanZoomController* aApzc, 406 const FlingHandoffState& aHandoffState); 407 408 void StartScrollbarDrag(const ScrollableLayerGuid& aGuid, 409 const AsyncDragMetrics& aDragMetrics) override; 410 411 bool StartAutoscroll(const ScrollableLayerGuid& aGuid, 412 const ScreenPoint& aAnchorLocation) override; 413 414 void StopAutoscroll(const ScrollableLayerGuid& aGuid) override; 415 416 /* 417 * Build the chain of APZCs that will handle overscroll for a pan starting at 418 * |aInitialTarget|. 419 */ 420 RefPtr<const OverscrollHandoffChain> BuildOverscrollHandoffChain( 421 const RefPtr<AsyncPanZoomController>& aInitialTarget); 422 423 /** 424 * Function used to disable LongTap gestures. 425 * 426 * On slow running tests, drags and touch events can be misinterpreted 427 * as a long tap. This allows tests to disable long tap gesture detection. 428 */ 429 void SetLongTapEnabled(bool aTapGestureEnabled) override; 430 InputBridge()431 APZInputBridge* InputBridge() override { return this; } 432 433 void AddInputBlockCallback(uint64_t aInputBlockId, 434 InputBlockCallback&& aCallback) override; 435 436 // Methods to help process WidgetInputEvents (or manage conversion to/from 437 // InputData) 438 439 void ProcessUnhandledEvent(LayoutDeviceIntPoint* aRefPoint, 440 ScrollableLayerGuid* aOutTargetGuid, 441 uint64_t* aOutFocusSequenceNumber, 442 LayersId* aOutLayersId) override; 443 444 void UpdateWheelTransaction(LayoutDeviceIntPoint aRefPoint, 445 EventMessage aEventMessage) override; 446 447 bool GetAPZTestData(LayersId aLayersId, APZTestData* aOutData); 448 449 /** 450 * Iterates over the hit testing tree, collects LayersIds and associated 451 * transforms from layer coordinate space to root coordinate space, and 452 * sends these over to the main thread of the chrome process. If the provided 453 * |aAncestor| argument is non-null, then only the transforms for layer 454 * subtrees scrolled by the aAncestor (i.e. descendants of aAncestor) will be 455 * sent. 456 */ 457 void SendSubtreeTransformsToChromeMainThread( 458 const AsyncPanZoomController* aAncestor); 459 460 /** 461 * Set fixed layer margins for dynamic toolbar. 462 */ 463 void SetFixedLayerMargins(ScreenIntCoord aTop, ScreenIntCoord aBottom); 464 465 /** 466 * Refer to apz::ComputeTransformForScrollThumb() for a description 467 * of the parameters. 468 */ 469 static LayerToParentLayerMatrix4x4 ComputeTransformForScrollThumb( 470 const LayerToParentLayerMatrix4x4& aCurrentTransform, 471 const gfx::Matrix4x4& aScrollableContentTransform, 472 AsyncPanZoomController* aApzc, const FrameMetrics& aMetrics, 473 const ScrollbarData& aScrollbarData, bool aScrollbarIsDescendant, 474 AsyncTransformComponentMatrix* aOutClipTransform); 475 476 /** 477 * Dispatch a flush complete notification from the repaint thread of the 478 * content controller for the given layers id. 479 */ 480 static void FlushApzRepaints(LayersId aLayersId); 481 482 /** 483 * Mark |aLayersId| as having been moved from the compositor that owns this 484 * tree manager to a compositor that doesn't use APZ. 485 * See |mDetachedLayersIds| for more details. 486 */ 487 void MarkAsDetached(LayersId aLayersId); 488 489 // Assert that the current thread is the sampler thread for this APZCTM. 490 void AssertOnSamplerThread(); 491 // Assert that the current thread is the updater thread for this APZCTM. 492 void AssertOnUpdaterThread(); 493 494 // Returns a pointer to the WebRenderAPI this APZCTreeManager is for. 495 // This might be null (for example, if WebRender is not enabled). 496 already_AddRefed<wr::WebRenderAPI> GetWebRenderAPI() const; 497 498 protected: 499 // Protected destructor, to discourage deletion outside of Release(): 500 virtual ~APZCTreeManager(); 501 502 APZSampler* GetSampler() const; 503 APZUpdater* GetUpdater() const; 504 505 // We need to allow APZUpdater to lock and unlock this tree during a WR 506 // scene swap. We do this using private helpers to avoid exposing these 507 // functions to the world. 508 private: 509 friend class APZUpdater; 510 void LockTree(); 511 void UnlockTree(); 512 513 // Protected hooks for gtests subclass 514 virtual AsyncPanZoomController* NewAPZCInstance( 515 LayersId aLayersId, GeckoContentController* aController); 516 517 public: 518 // Public hook for gtests subclass 519 virtual SampleTime GetFrameTime(); 520 521 // Also used for controlling time during tests 522 void SetTestSampleTime(const Maybe<TimeStamp>& aTime); 523 524 private: 525 mutable DataMutex<Maybe<TimeStamp>> mTestSampleTime; 526 527 public: 528 // Represents the results of an APZ hit test. 529 struct HitTestResult { 530 // The APZC targeted by the hit test. 531 RefPtr<AsyncPanZoomController> mTargetApzc; 532 // The applicable hit test flags. 533 gfx::CompositorHitTestInfo mHitResult; 534 // The layers id of the content that was hit. 535 // This effectively identifiers the process that was hit for 536 // Fission purposes. 537 LayersId mLayersId; 538 // If a scrollbar was hit, this will be populated with the 539 // scrollbar node. The AutoLock allows accessing the scrollbar 540 // node without having to hold the tree lock. 541 HitTestingTreeNodeAutoLock mScrollbarNode; 542 // If content that is fixed to the root-content APZC was hit, 543 // the sides of the viewport to which the content is fixed. 544 SideBits mFixedPosSides = SideBits::eNone; 545 // This is set to true If mTargetApzc is overscrolled and the 546 // event targeted the gap space ("gutter") created by the overscroll. 547 bool mHitOverscrollGutter = false; 548 549 HitTestResult() = default; 550 // Make it move-only. 551 HitTestResult(HitTestResult&&) = default; 552 HitTestResult& operator=(HitTestResult&&) = default; 553 554 // Make a copy of all the fields except mScrollbarNode (the field 555 // that makes this move-only). 556 HitTestResult CopyWithoutScrollbarNode() const; 557 }; 558 559 /* Some helper functions to find an APZC given some identifying input. These 560 functions lock the tree of APZCs while they find the right one, and then 561 return an addref'd pointer to it. This allows caller code to just use the 562 target APZC without worrying about it going away. These are public for 563 testing code and generally should not be used by other production code. 564 */ 565 RefPtr<HitTestingTreeNode> GetRootNode() const; 566 HitTestResult GetTargetAPZC(const ScreenPoint& aPoint); 567 already_AddRefed<AsyncPanZoomController> GetTargetAPZC( 568 const LayersId& aLayersId, 569 const ScrollableLayerGuid::ViewID& aScrollId) const; 570 ScreenToParentLayerMatrix4x4 GetScreenToApzcTransform( 571 const AsyncPanZoomController* aApzc) const; 572 ParentLayerToScreenMatrix4x4 GetApzcToGeckoTransform( 573 const AsyncPanZoomController* aApzc) const; 574 ScreenPoint GetCurrentMousePosition() const; 575 void SetCurrentMousePosition(const ScreenPoint& aNewPos); 576 577 /** 578 * Convert a screen point of an event targeting |aApzc| to Gecko 579 * coordinates. 580 */ 581 Maybe<ScreenIntPoint> ConvertToGecko(const ScreenIntPoint& aPoint, 582 AsyncPanZoomController* aApzc); 583 584 /** 585 * Find the zoomable APZC in the same layer subtree (i.e. with the same 586 * layers id) as the given APZC. 587 */ 588 already_AddRefed<AsyncPanZoomController> FindZoomableApzc( 589 AsyncPanZoomController* aStart) const; 590 591 ScreenMargin GetGeckoFixedLayerMargins() const; 592 593 ScreenMargin GetCompositorFixedLayerMargins() const; 594 595 private: 596 typedef bool (*GuidComparator)(const ScrollableLayerGuid&, 597 const ScrollableLayerGuid&); 598 599 /* Helpers */ 600 template <class ScrollNode> 601 void UpdateHitTestingTreeImpl(const ScrollNode& aRoot, bool aIsFirstPaint, 602 LayersId aOriginatingLayersId, 603 uint32_t aPaintSequenceNumber); 604 605 void AttachNodeToTree(HitTestingTreeNode* aNode, HitTestingTreeNode* aParent, 606 HitTestingTreeNode* aNextSibling); 607 already_AddRefed<AsyncPanZoomController> GetTargetAPZC( 608 const ScrollableLayerGuid& aGuid); 609 already_AddRefed<HitTestingTreeNode> GetTargetNode( 610 const ScrollableLayerGuid& aGuid, GuidComparator aComparator) const; 611 HitTestingTreeNode* FindTargetNode(HitTestingTreeNode* aNode, 612 const ScrollableLayerGuid& aGuid, 613 GuidComparator aComparator); 614 AsyncPanZoomController* GetTargetApzcForNode(HitTestingTreeNode* aNode); 615 AsyncPanZoomController* FindHandoffParent( 616 const AsyncPanZoomController* aApzc); 617 HitTestResult GetAPZCAtPoint(const ScreenPoint& aHitTestPoint, 618 const RecursiveMutexAutoLock& aProofOfTreeLock); 619 HitTestResult GetAPZCAtPointWR( 620 const ScreenPoint& aHitTestPoint, 621 const RecursiveMutexAutoLock& aProofOfTreeLock); 622 HitTestingTreeNode* FindRootNodeForLayersId(LayersId aLayersId) const; 623 AsyncPanZoomController* FindRootApzcForLayersId(LayersId aLayersId) const; 624 AsyncPanZoomController* FindRootContentApzcForLayersId( 625 LayersId aLayersId) const; 626 already_AddRefed<AsyncPanZoomController> GetZoomableTarget( 627 AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const; 628 already_AddRefed<AsyncPanZoomController> CommonAncestor( 629 AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const; 630 631 struct FixedPositionInfo; 632 struct StickyPositionInfo; 633 634 // Returns true if |aNode| is a fixed layer that is fixed to the root content 635 // APZC. 636 // The map lock is required within these functions; if the map lock is already 637 // being held by the caller, the second overload should be used. If the map 638 // lock is not being held at the call site, the first overload should be used. 639 bool IsFixedToRootContent(const HitTestingTreeNode* aNode) const; 640 bool IsFixedToRootContent(const FixedPositionInfo& aFixedInfo, 641 const MutexAutoLock& aProofOfMapLock) const; 642 643 // Returns the vertical sides of |aNode| that are stuck to the root content. 644 // The map lock is required within these functions; if the map lock is already 645 // being held by the caller, the second overload should be used. If the map 646 // lock is not being held at the call site, the first overload should be used. 647 SideBits SidesStuckToRootContent(const HitTestingTreeNode* aNode) const; 648 SideBits SidesStuckToRootContent(const StickyPositionInfo& aStickyInfo, 649 const MutexAutoLock& aProofOfMapLock) const; 650 651 /** 652 * Perform hit testing for a touch-start event. 653 * 654 * @param aEvent The touch-start event. 655 * 656 * The remaining parameters are out-parameter used to communicate additional 657 * return values: 658 * 659 * @param aOutTouchBehaviors 660 * The touch behaviours that should be allowed for this touch block. 661 662 * @return The results of the hit test, including the APZC that was hit. 663 */ 664 HitTestResult GetTouchInputBlockAPZC( 665 const MultiTouchInput& aEvent, 666 nsTArray<TouchBehaviorFlags>* aOutTouchBehaviors); 667 668 /** 669 * A helper structure for use by ReceiveInputEvent() and its helpers. 670 */ 671 struct InputHandlingState { 672 // A reference to the event being handled. 673 InputData& mEvent; 674 675 // The value that will be returned by ReceiveInputEvent(). 676 APZEventResult mResult; 677 678 // If we performed a hit-test while handling this input event, or 679 // reused the result of a previous hit-test in the input block, 680 // this is populated with the result of the hit test. 681 HitTestResult mHit; 682 683 // Called at the end of ReceiveInputEvent() to perform any final 684 // computations, and then return mResult. 685 APZEventResult Finish(); 686 }; 687 688 void ProcessTouchInput(InputHandlingState& aState, MultiTouchInput& aInput); 689 /** 690 * Given a mouse-down event that hit a scroll thumb node, set up APZ 691 * dragging of the scroll thumb. 692 * 693 * Must be called after the mouse event has been sent to InputQueue. 694 * 695 * @param aMouseInput The mouse-down event. 696 * @param aScrollThumbNode Tthe scroll thumb node that was hit. 697 * @param aApzc 698 * The APZC for the scroll frame scrolled by the scroll thumb, if that 699 * scroll frame is layerized. (A thumb can be layerized without its 700 * target scroll frame being layerized.) Otherwise, an enclosing APZC. 701 */ 702 void SetupScrollbarDrag(MouseInput& aMouseInput, 703 const HitTestingTreeNodeAutoLock& aScrollThumbNode, 704 AsyncPanZoomController* aApzc); 705 /** 706 * Process a touch event that's part of a scrollbar touch-drag gesture. 707 * 708 * @param aInput The touch event. 709 * @param aScrollThumbNode 710 * If this is the touch-start event, the node representing the scroll 711 * thumb we are starting to drag. Otherwise nullptr. 712 * @param aHitInfo 713 * The hit-test flags for the touch input. 714 * @return See ReceiveInputEvent() for what the return value means. 715 */ 716 APZEventResult ProcessTouchInputForScrollbarDrag( 717 MultiTouchInput& aInput, 718 const HitTestingTreeNodeAutoLock& aScrollThumbNode, 719 const gfx::CompositorHitTestInfo& aHitInfo); 720 void FlushRepaintsToClearScreenToGeckoTransform(); 721 722 void SynthesizePinchGestureFromMouseWheel( 723 const ScrollWheelInput& aWheelInput, 724 const RefPtr<AsyncPanZoomController>& aTarget); 725 726 already_AddRefed<HitTestingTreeNode> RecycleOrCreateNode( 727 const RecursiveMutexAutoLock& aProofOfTreeLock, TreeBuildingState& aState, 728 AsyncPanZoomController* aApzc, LayersId aLayersId); 729 template <class ScrollNode> 730 HitTestingTreeNode* PrepareNodeForLayer( 731 const RecursiveMutexAutoLock& aProofOfTreeLock, const ScrollNode& aLayer, 732 const FrameMetrics& aMetrics, LayersId aLayersId, 733 const Maybe<ZoomConstraints>& aZoomConstraints, 734 const AncestorTransform& aAncestorTransform, HitTestingTreeNode* aParent, 735 HitTestingTreeNode* aNextSibling, TreeBuildingState& aState); 736 template <class ScrollNode> 737 Maybe<ParentLayerIntRegion> ComputeClipRegion(const LayersId& aLayersId, 738 const ScrollNode& aLayer); 739 740 template <class ScrollNode> 741 void PrintAPZCInfo(const ScrollNode& aLayer, 742 const AsyncPanZoomController* apzc); 743 744 void NotifyScrollbarDragInitiated(uint64_t aDragBlockId, 745 const ScrollableLayerGuid& aGuid, 746 ScrollDirection aDirection) const; 747 void NotifyScrollbarDragRejected(const ScrollableLayerGuid& aGuid) const; 748 void NotifyAutoscrollRejected(const ScrollableLayerGuid& aGuid) const; 749 750 // Returns the transform that converts from |aNode|'s coordinates to 751 // the coordinates of |aNode|'s parent in the hit-testing tree. 752 // If the returned transform includes an overscroll transform, 753 // |aOutSourceOfOverscrollTransform| (if not nullptr) is populated 754 // with the APZC which is the source of that overscroll transform. 755 // Requires the caller to hold mTreeLock. 756 LayerToParentLayerMatrix4x4 ComputeTransformForNode( 757 const HitTestingTreeNode* aNode, 758 const AsyncPanZoomController** aOutSourceOfOverscrollTransform = 759 nullptr) const; 760 761 // Look up the GeckoContentController for the given layers id. 762 static already_AddRefed<GeckoContentController> GetContentController( 763 LayersId aLayersId); 764 765 bool AdvanceAnimationsInternal(const MutexAutoLock& aProofOfMapLock, 766 const SampleTime& aSampleTime); 767 768 using ClippedCompositionBoundsMap = 769 std::unordered_map<ScrollableLayerGuid, ParentLayerRect, 770 ScrollableLayerGuid::HashIgnoringPresShellFn, 771 ScrollableLayerGuid::EqualIgnoringPresShellFn>; 772 // This is a recursive function that populates `aDestMap` with the clipped 773 // composition bounds for the APZC corresponding to `aGuid` and returns those 774 // bounds as a convenience. It recurses to also populate `aDestMap` with that 775 // APZC's ancestors. In order to do this it needs to access mApzcMap 776 // and therefore requires the caller to hold the map lock. 777 ParentLayerRect ComputeClippedCompositionBounds( 778 const MutexAutoLock& aProofOfMapLock, 779 ClippedCompositionBoundsMap& aDestMap, ScrollableLayerGuid aGuid); 780 781 ScreenMargin GetCompositorFixedLayerMargins( 782 const MutexAutoLock& aProofOfMapLock) const; 783 784 protected: 785 /* The input queue where input events are held until we know enough to 786 * figure out where they're going. Protected so gtests can access it. 787 */ 788 RefPtr<InputQueue> mInputQueue; 789 790 private: 791 /* Layers id for the root CompositorBridgeParent that owns this 792 * APZCTreeManager. */ 793 LayersId mRootLayersId; 794 795 /* Pointer to the APZSampler instance that is bound to this APZCTreeManager. 796 * The sampler has a RefPtr to this class, and this non-owning raw pointer 797 * back to the APZSampler is nulled out in the sampler's destructor, so this 798 * pointer should always be valid. 799 */ 800 APZSampler* MOZ_NON_OWNING_REF mSampler; 801 /* Pointer to the APZUpdater instance that is bound to this APZCTreeManager. 802 * The updater has a RefPtr to this class, and this non-owning raw pointer 803 * back to the APZUpdater is nulled out in the updater's destructor, so this 804 * pointer should always be valid. 805 */ 806 APZUpdater* MOZ_NON_OWNING_REF mUpdater; 807 808 /* Whenever walking or mutating the tree rooted at mRootNode, mTreeLock must 809 * be held. This lock does not need to be held while manipulating a single 810 * APZC instance in isolation (that is, if its tree pointers are not being 811 * accessed or mutated). The lock also needs to be held when accessing the 812 * mRootNode instance variable, as that is considered part of the APZC tree 813 * management state. 814 * IMPORTANT: See the note about lock ordering at the top of this file. */ 815 mutable mozilla::RecursiveMutex mTreeLock; 816 RefPtr<HitTestingTreeNode> mRootNode; 817 818 /* 819 * A set of LayersIds for which APZCTM should only send empty 820 * MatrixMessages via NotifyLayerTransform(). 821 * This is used in cases where a tab has been transferred to a non-APZ 822 * compositor (and thus will not receive MatrixMessages reflecting its new 823 * transforms) and we need to make sure it doesn't get stuck with transforms 824 * from its old tree manager (us). 825 * Acquire mTreeLock before accessing this. 826 */ 827 std::unordered_set<LayersId, LayersId::HashFn> mDetachedLayersIds; 828 829 /* If the current hit-testing tree contains an async zoom container 830 * node, this is set to the layers id of subtree that has the node. 831 */ 832 Maybe<LayersId> mAsyncZoomContainerSubtree; 833 834 /** A lock that protects mApzcMap, mScrollThumbInfo, mRootScrollbarInfo, 835 * mFixedPositionInfo, and mStickyPositionInfo. 836 */ 837 mutable mozilla::Mutex mMapLock; 838 839 /** 840 * Helper structure to store a bunch of things in mApzcMap so that they can 841 * be used from the sampler thread. 842 */ 843 struct ApzcMapData { 844 // A pointer to the APZC itself 845 RefPtr<AsyncPanZoomController> apzc; 846 // The parent APZC's guid, or Nothing() if there is no parent 847 Maybe<ScrollableLayerGuid> parent; 848 }; 849 850 /** 851 * A map for quick access to get some APZC data by guid, without having to 852 * acquire the tree lock. mMapLock must be acquired while accessing or 853 * modifying mApzcMap. 854 */ 855 std::unordered_map<ScrollableLayerGuid, ApzcMapData, 856 ScrollableLayerGuid::HashIgnoringPresShellFn, 857 ScrollableLayerGuid::EqualIgnoringPresShellFn> 858 mApzcMap; 859 /** 860 * A helper structure to store all the information needed to compute the 861 * async transform for a scrollthumb on the sampler thread. 862 */ 863 struct ScrollThumbInfo { 864 uint64_t mThumbAnimationId; 865 CSSTransformMatrix mThumbTransform; 866 ScrollbarData mThumbData; 867 ScrollableLayerGuid mTargetGuid; 868 CSSTransformMatrix mTargetTransform; 869 bool mTargetIsAncestor; 870 ScrollThumbInfoScrollThumbInfo871 ScrollThumbInfo(const uint64_t& aThumbAnimationId, 872 const CSSTransformMatrix& aThumbTransform, 873 const ScrollbarData& aThumbData, 874 const ScrollableLayerGuid& aTargetGuid, 875 const CSSTransformMatrix& aTargetTransform, 876 bool aTargetIsAncestor) 877 : mThumbAnimationId(aThumbAnimationId), 878 mThumbTransform(aThumbTransform), 879 mThumbData(aThumbData), 880 mTargetGuid(aTargetGuid), 881 mTargetTransform(aTargetTransform), 882 mTargetIsAncestor(aTargetIsAncestor) { 883 MOZ_ASSERT(mTargetGuid.mScrollId == mThumbData.mTargetViewId); 884 } 885 }; 886 /** 887 * If this APZCTreeManager is being used with WebRender, this vector gets 888 * populated during a layers update. It holds a package of information needed 889 * to compute and set the async transforms on scroll thumbs. This information 890 * is extracted from the HitTestingTreeNodes for the WebRender case because 891 * accessing the HitTestingTreeNodes requires holding the tree lock which 892 * we cannot do on the WR sampler thread. mScrollThumbInfo, however, can 893 * be accessed while just holding the mMapLock which is safe to do on the 894 * sampler thread. 895 * mMapLock must be acquired while accessing or modifying mScrollThumbInfo. 896 */ 897 std::vector<ScrollThumbInfo> mScrollThumbInfo; 898 899 /** 900 * A helper structure to store all the information needed to compute the 901 * async transform for a scrollthumb on the sampler thread. 902 */ 903 struct RootScrollbarInfo { 904 uint64_t mScrollbarAnimationId; 905 ScrollDirection mScrollDirection; 906 RootScrollbarInfoRootScrollbarInfo907 RootScrollbarInfo(const uint64_t& aScrollbarAnimationId, 908 const ScrollDirection aScrollDirection) 909 : mScrollbarAnimationId(aScrollbarAnimationId), 910 mScrollDirection(aScrollDirection) {} 911 }; 912 /** 913 * If this APZCTreeManager is being used with WebRender, this vector gets 914 * populated during a layers update. It holds a package of information needed 915 * to compute and set the async transforms on root scrollbars. This 916 * information is extracted from the HitTestingTreeNodes for the WebRender 917 * case because accessing the HitTestingTreeNodes requires holding the tree 918 * lock which we cannot do on the WR sampler thread. mRootScrollbarInfo, 919 * however, can be accessed while just holding the mMapLock which is safe to 920 * do on the sampler thread. 921 * mMapLock must be acquired while accessing or modifying mRootScrollbarInfo. 922 */ 923 std::vector<RootScrollbarInfo> mRootScrollbarInfo; 924 925 /** 926 * A helper structure to store all the information needed to compute the 927 * async transform for a fixed position element on the sampler thread. 928 */ 929 struct FixedPositionInfo { 930 Maybe<uint64_t> mFixedPositionAnimationId; 931 SideBits mFixedPosSides; 932 ScrollableLayerGuid::ViewID mFixedPosTarget; 933 LayersId mLayersId; 934 935 explicit FixedPositionInfo(const HitTestingTreeNode* aNode); 936 }; 937 /** 938 * If this APZCTreeManager is being used with WebRender, this vector gets 939 * populated during a layers update. It holds a package of information needed 940 * to compute and set the async transforms on fixed position content. This 941 * information is extracted from the HitTestingTreeNodes for the WebRender 942 * case because accessing the HitTestingTreeNodes requires holding the tree 943 * lock which we cannot do on the WR sampler thread. mFixedPositionInfo, 944 * however, can be accessed while just holding the mMapLock which is safe to 945 * do on the sampler thread. mMapLock must be acquired while accessing or 946 * modifying mFixedPositionInfo. 947 */ 948 std::vector<FixedPositionInfo> mFixedPositionInfo; 949 950 /** 951 * A helper structure to store all the information needed to compute the 952 * async transform for a sticky position element on the sampler thread. 953 */ 954 struct StickyPositionInfo { 955 Maybe<uint64_t> mStickyPositionAnimationId; 956 SideBits mFixedPosSides; 957 ScrollableLayerGuid::ViewID mStickyPosTarget; 958 LayersId mLayersId; 959 LayerRectAbsolute mStickyScrollRangeInner; 960 LayerRectAbsolute mStickyScrollRangeOuter; 961 962 explicit StickyPositionInfo(const HitTestingTreeNode* aNode); 963 }; 964 /** 965 * If this APZCTreeManager is being used with WebRender, this vector gets 966 * populated during a layers update. It holds a package of information needed 967 * to compute and set the async transforms on sticky position content. This 968 * information is extracted from the HitTestingTreeNodes for the WebRender 969 * case because accessing the HitTestingTreeNodes requires holding the tree 970 * lock which we cannot do on the WR sampler thread. mStickyPositionInfo, 971 * however, can be accessed while just holding the mMapLock which is safe to 972 * do on the sampler thread. mMapLock must be acquired while accessing or 973 * modifying mStickyPositionInfo. 974 */ 975 std::vector<StickyPositionInfo> mStickyPositionInfo; 976 977 /* Holds the zoom constraints for scrollable layers, as determined by the 978 * the main-thread gecko code. This can only be accessed on the updater 979 * thread. */ 980 std::unordered_map<ScrollableLayerGuid, ZoomConstraints, 981 ScrollableLayerGuid::HashIgnoringPresShellFn, 982 ScrollableLayerGuid::EqualIgnoringPresShellFn> 983 mZoomConstraints; 984 /* A list of keyboard shortcuts to use for translating keyboard inputs into 985 * keyboard actions. This is gathered on the main thread from XBL bindings. 986 * This must only be accessed on the controller thread. 987 */ 988 KeyboardMap mKeyboardMap; 989 /* This tracks the focus targets of chrome and content and whether we have 990 * a current focus target or whether we are waiting for a new confirmation. 991 */ 992 FocusState mFocusState; 993 /* This tracks the hit test result info for the current touch input block. 994 * In particular, it tracks the target APZC, the hit test flags, and the 995 * fixed pos sides. This is populated at the start of a touch block based 996 * on the hit-test result, and used for subsequent touch events in the block. 997 * This allows touch points to move outside the thing they started on, but 998 * still have the touch events delivered to the same initial APZC. This will 999 * only ever be touched on the input delivery thread, and so does not require 1000 * locking. 1001 */ 1002 HitTestResult mTouchBlockHitResult; 1003 /* Sometimes we want to ignore all touches except one. In such cases, this 1004 * is set to the identifier of the touch we are not ignoring; in other cases, 1005 * this is set to -1. 1006 */ 1007 int32_t mRetainedTouchIdentifier; 1008 /* This tracks whether the current input block represents a touch-drag of 1009 * a scrollbar. In this state, touch events are forwarded to content as touch 1010 * events, but converted to mouse events before going into InputQueue and 1011 * being handled by an APZC (to reuse the APZ code for scrollbar dragging 1012 * with a mouse). 1013 */ 1014 bool mInScrollbarTouchDrag; 1015 /* Tracks the number of touch points we are tracking that are currently on 1016 * the screen. */ 1017 TouchCounter mTouchCounter; 1018 /* Stores the current mouse position in screen coordinates. 1019 */ 1020 mutable DataMutex<ScreenPoint> mCurrentMousePosition; 1021 /* Extra margins that should be applied to content that fixed wrt. the 1022 * RCD-RSF, to account for the dynamic toolbar. 1023 * Acquire mMapLock before accessing this. 1024 */ 1025 ScreenMargin mCompositorFixedLayerMargins; 1026 /* Similar to above |mCompositorFixedLayerMargins|. But this value is the 1027 * margins on the main-thread at the last time position:fixed elements were 1028 * updated during the dynamic toolbar transitions. 1029 * Acquire mMapLock before accessing this. 1030 */ 1031 ScreenMargin mGeckoFixedLayerMargins; 1032 /* For logging the APZC tree for debugging (enabled by the apz.printtree 1033 * pref). */ 1034 gfx::TreeLog<gfx::LOG_DEFAULT> mApzcTreeLog; 1035 1036 class CheckerboardFlushObserver; 1037 friend class CheckerboardFlushObserver; 1038 RefPtr<CheckerboardFlushObserver> mFlushObserver; 1039 1040 // Map from layers id to APZTestData. Accesses and mutations must be 1041 // protected by the mTestDataLock. 1042 std::unordered_map<LayersId, UniquePtr<APZTestData>, LayersId::HashFn> 1043 mTestData; 1044 mutable mozilla::Mutex mTestDataLock; 1045 1046 // This must only be touched on the controller thread. 1047 float mDPI; 1048 1049 bool mIsUsingWebRender; 1050 1051 #if defined(MOZ_WIDGET_ANDROID) 1052 private: 1053 // Last Frame metrics sent to java through UIController. 1054 GeckoViewMetrics mLastRootMetrics; 1055 #endif // defined(MOZ_WIDGET_ANDROID) 1056 }; 1057 1058 } // namespace layers 1059 } // namespace mozilla 1060 1061 #endif // mozilla_layers_PanZoomController_h 1062