Source code

Revision control

Other Tools

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 "gfxPoint.h" // for gfxPoint
14
#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2
15
#include "mozilla/gfx/CompositorHitTestInfo.h"
16
#include "mozilla/gfx/Logging.h" // for gfx::TreeLog
17
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
18
#include "mozilla/layers/APZInputBridge.h" // for APZInputBridge
19
#include "mozilla/layers/APZTestData.h" // for APZTestData
20
#include "mozilla/layers/IAPZCTreeManager.h" // for IAPZCTreeManager
21
#include "mozilla/layers/LayerAttributes.h"
22
#include "mozilla/layers/LayersTypes.h"
23
#include "mozilla/layers/KeyboardMap.h" // for KeyboardMap
24
#include "mozilla/layers/TouchCounter.h" // for TouchCounter
25
#include "mozilla/layers/ZoomConstraints.h" // for ZoomConstraints
26
#include "mozilla/RecursiveMutex.h" // for RecursiveMutex
27
#include "mozilla/RefPtr.h" // for RefPtr
28
#include "mozilla/TimeStamp.h" // for mozilla::TimeStamp
29
#include "mozilla/UniquePtr.h" // for UniquePtr
30
#include "nsCOMPtr.h" // for already_AddRefed
31
32
#if defined(MOZ_WIDGET_ANDROID)
33
# include "mozilla/layers/AndroidDynamicToolbarAnimator.h"
34
#endif // defined(MOZ_WIDGET_ANDROID)
35
36
namespace mozilla {
37
class MultiTouchInput;
38
39
namespace wr {
40
class TransactionWrapper;
41
class WebRenderAPI;
42
struct WrTransformProperty;
43
} // namespace wr
44
45
namespace layers {
46
47
class Layer;
48
class AsyncPanZoomController;
49
class APZCTreeManagerParent;
50
class APZSampler;
51
class APZUpdater;
52
class CompositorBridgeParent;
53
class OverscrollHandoffChain;
54
struct OverscrollHandoffState;
55
class FocusTarget;
56
struct FlingHandoffState;
57
class LayerMetricsWrapper;
58
class InputQueue;
59
class GeckoContentController;
60
class HitTestingTreeNode;
61
class HitTestingTreeNodeAutoLock;
62
class WebRenderScrollDataWrapper;
63
struct AncestorTransform;
64
struct ScrollThumbData;
65
66
/**
67
* ****************** NOTE ON LOCK ORDERING IN APZ **************************
68
*
69
* There are two main kinds of locks used by APZ: APZCTreeManager::mTreeLock
70
* ("the tree lock") and AsyncPanZoomController::mRecursiveMutex ("APZC locks").
71
* There is also the APZCTreeManager::mTestDataLock ("test lock") and
72
* APZCTreeManager::mMapLock ("map lock").
73
*
74
* To avoid deadlock, we impose a lock ordering between these locks, which is:
75
*
76
* tree lock -> map lock -> APZC locks -> test lock
77
*
78
* The interpretation of the lock ordering is that if lock A precedes lock B
79
* in the ordering sequence, then you must NOT wait on A while holding B.
80
*
81
* In addition, the WR hit-testing codepath acquires the tree lock and then
82
* blocks on the render backend thread to do the hit-test. Similar operations
83
* elsewhere mean that we need to be careful with which threads are allowed
84
* to acquire which locks and the order they do so. At the time of this writing,
85
* bug1391318.bmoattachments.org/attachment.cgi?id=8965040">https://bug1391318.bmoattachments.org/attachment.cgi?id=8965040 contains
86
* the most complete description we have of the situation. The total dependency
87
* ordering including both threads and locks is as follows:
88
*
89
* UI main thread
90
* -> GPU main thread // only if GPU enabled
91
* -> Compositor thread
92
* -> SceneBuilder thread // only if WR enabled
93
* -> APZ tree lock
94
* -> RenderBackend thread // only if WR enabled
95
* -> APZC map lock
96
* -> APZC instance lock
97
* -> APZC test lock
98
*
99
* where the -> annotation means the same as described above.
100
* **************************************************************************
101
*/
102
103
/**
104
* This class manages the tree of AsyncPanZoomController instances. There is one
105
* instance of this class owned by each CompositorBridgeParent, and it contains
106
* as many AsyncPanZoomController instances as there are scrollable container
107
* layers. This class generally lives on the updater thread, although some
108
* functions may be called from other threads as noted; thread safety is ensured
109
* internally.
110
*
111
* The bulk of the work of this class happens as part of the
112
* UpdateHitTestingTree function, which is when a layer tree update is received
113
* by the compositor. This function walks through the layer tree and creates a
114
* tree of HitTestingTreeNode instances to match the layer tree and for use in
115
* hit-testing on the controller thread. APZC instances may be preserved across
116
* calls to this function if the corresponding layers are still present in the
117
* layer tree.
118
*
119
* The other functions on this class are used by various pieces of client code
120
* to notify the APZC instances of events relevant to them. This includes, for
121
* example, user input events that drive panning and zooming, changes to the
122
* scroll viewport area, and changes to pan/zoom constraints.
123
*
124
* Note that the ClearTree function MUST be called when this class is no longer
125
* needed; see the method documentation for details.
126
*
127
* Behaviour of APZ is controlled by a number of preferences shown
128
* \ref APZCPrefs "here".
129
*/
130
class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
131
typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior;
132
typedef mozilla::layers::AsyncDragMetrics AsyncDragMetrics;
133
134
// Helper struct to hold some state while we build the hit-testing tree. The
135
// sole purpose of this struct is to shorten the argument list to
136
// UpdateHitTestingTree. All the state that we don't need to
137
// push on the stack during recursion and pop on unwind is stored here.
138
struct TreeBuildingState;
139
140
public:
141
explicit APZCTreeManager(LayersId aRootLayersId);
142
143
void SetSampler(APZSampler* aSampler);
144
void SetUpdater(APZUpdater* aUpdater);
145
146
/**
147
* Notifies this APZCTreeManager that the associated compositor is now
148
* responsible for managing another layers id, which got moved over from
149
* some other compositor. That other compositor's APZCTreeManager is also
150
* provided. This allows APZCTreeManager to transfer any necessary state
151
* from the old APZCTreeManager related to that layers id.
152
* This function must be called on the updater thread.
153
*/
154
void NotifyLayerTreeAdopted(LayersId aLayersId,
155
const RefPtr<APZCTreeManager>& aOldTreeManager);
156
157
/**
158
* Notifies this APZCTreeManager that a layer tree being managed by the
159
* associated compositor has been removed/destroyed. Note that this does
160
* NOT get called during shutdown situations, when the root layer tree is
161
* also getting destroyed.
162
* This function must be called on the updater thread.
163
*/
164
void NotifyLayerTreeRemoved(LayersId aLayersId);
165
166
/**
167
* Rebuild the focus state based on the focus target from the layer tree
168
* update that just occurred. This must be called on the updater thread.
169
*
170
* @param aRootLayerTreeId The layer tree ID of the root layer corresponding
171
* to this APZCTreeManager
172
* @param aOriginatingLayersId The layer tree ID of the layer corresponding to
173
* this layer tree update.
174
*/
175
void UpdateFocusState(LayersId aRootLayerTreeId,
176
LayersId aOriginatingLayersId,
177
const FocusTarget& aFocusTarget);
178
179
/**
180
* Rebuild the hit-testing tree based on the layer update that just came up.
181
* Preserve nodes and APZC instances where possible, but retire those whose
182
* layers are no longer in the layer tree.
183
*
184
* This must be called on the updater thread as it walks the layer tree.
185
*
186
* @param aRoot The root of the (full) layer tree
187
* @param aOriginatingLayersId The layers id of the subtree that triggered
188
* this repaint, and to which aIsFirstPaint
189
* applies.
190
* @param aIsFirstPaint True if the layers update that this is called in
191
* response to included a first-paint. If this is true,
192
* the part of the tree that is affected by the
193
* first-paint flag is indicated by the
194
* aFirstPaintLayersId parameter.
195
* @param aPaintSequenceNumber The sequence number of the paint that triggered
196
* this layer update. Note that every layer child
197
* process' layer subtree has its own sequence
198
* numbers.
199
*/
200
void UpdateHitTestingTree(Layer* aRoot, bool aIsFirstPaint,
201
LayersId aOriginatingLayersId,
202
uint32_t aPaintSequenceNumber);
203
204
/**
205
* Same as the above UpdateHitTestingTree, except slightly modified to take
206
* the scrolling data passed over PWebRenderBridge instead of the raw layer
207
* tree. This version is used when WebRender is enabled because we don't have
208
* shadow layers in that scenario.
209
*/
210
void UpdateHitTestingTree(const WebRenderScrollDataWrapper& aScrollWrapper,
211
bool aIsFirstPaint, WRRootId aOriginatingWrRootId,
212
uint32_t aPaintSequenceNumber);
213
214
/**
215
* Called when webrender is enabled, from the sampler thread. This function
216
* populates the provided transaction with any async scroll offsets needed.
217
* It also advances APZ animations to the specified sample time, and requests
218
* another composite if there are still active animations.
219
* In effect it is the webrender equivalent of (part of) the code in
220
* AsyncCompositionManager.
221
* In the WebRender world a single "layer tree" might get split into multiple
222
* render roots; the aRenderRoot argument indicates which render root we are
223
* sampling in this call. The transaction should only be updated with samples
224
* from APZC instances in that render root.
225
*/
226
void SampleForWebRender(wr::TransactionWrapper& aTxn,
227
const TimeStamp& aSampleTime,
228
wr::RenderRoot aRenderRoot);
229
230
/**
231
* General handler for incoming input events. Manipulates the frame metrics
232
* based on what type of input it is. For example, a PinchGestureEvent will
233
* cause scaling. This should only be called externally to this class, and
234
* must be called on the controller thread.
235
*
236
* This function transforms |aEvent| to have its coordinates in DOM space.
237
* This is so that the event can be passed through the DOM and content can
238
* handle them. The event may need to be converted to a WidgetInputEvent
239
* by the caller if it wants to do this.
240
*
241
* The following values may be returned by this function:
242
* nsEventStatus_eConsumeNoDefault is returned to indicate the
243
* APZ is consuming this event and the caller should discard the event with
244
* extreme prejudice. The exact scenarios under which this is returned is
245
* implementation-dependent and may vary.
246
* nsEventStatus_eIgnore is returned to indicate that the APZ code didn't
247
* use this event. This might be because it was directed at a point on
248
* the screen where there was no APZ, or because the thing the user was
249
* trying to do was not allowed. (For example, attempting to pan a
250
* non-pannable document).
251
* nsEventStatus_eConsumeDoDefault is returned to indicate that the APZ
252
* code may have used this event to do some user-visible thing. Note that
253
* in some cases CONSUMED is returned even if the event was NOT used. This
254
* is because we cannot always know at the time of event delivery whether
255
* the event will be used or not. So we err on the side of sending
256
* CONSUMED when we are uncertain.
257
*
258
* @param aEvent input event object; is modified in-place
259
* @param aOutTargetGuid returns the guid of the apzc this event was
260
* delivered to. May be null.
261
* @param aOutInputBlockId returns the id of the input block that this event
262
* was added to, if that was the case. May be null.
263
*/
264
nsEventStatus ReceiveInputEvent(InputData& aEvent,
265
ScrollableLayerGuid* aOutTargetGuid,
266
uint64_t* aOutInputBlockId) override;
267
268
/**
269
* Set the keyboard shortcuts to use for translating keyboard events.
270
*/
271
void SetKeyboardMap(const KeyboardMap& aKeyboardMap) override;
272
273
/**
274
* Kicks an animation to zoom to a rect. This may be either a zoom out or zoom
275
* in. The actual animation is done on the sampler thread after being set
276
* up. |aRect| must be given in CSS pixels, relative to the document.
277
* |aFlags| is a combination of the ZoomToRectBehavior enum values.
278
*/
279
void ZoomToRect(const SLGuidAndRenderRoot& aGuid, const CSSRect& aRect,
280
const uint32_t aFlags = DEFAULT_BEHAVIOR) override;
281
282
/**
283
* If we have touch listeners, this should always be called when we know
284
* definitively whether or not content has preventDefaulted any touch events
285
* that have come in. If |aPreventDefault| is true, any touch events in the
286
* queue will be discarded. This function must be called on the controller
287
* thread.
288
*/
289
void ContentReceivedInputBlock(uint64_t aInputBlockId,
290
bool aPreventDefault) override;
291
292
/**
293
* When the event regions code is enabled, this function should be invoked to
294
* to confirm the target of the input block. This is only needed in cases
295
* where the initial input event of the block hit a dispatch-to-content region
296
* but is safe to call for all input blocks. This function should always be
297
* invoked on the controller thread.
298
* The different elements in the array of targets correspond to the targets
299
* for the different touch points. In the case where the touch point has no
300
* target, or the target is not a scrollable frame, the target's |mScrollId|
301
* should be set to ScrollableLayerGuid::NULL_SCROLL_ID.
302
* Note: For mouse events that start a scrollbar drag, both SetTargetAPZC()
303
* and StartScrollbarDrag() will be called, and the calls may happen
304
* in either order. That's fine - whichever arrives first will confirm
305
* the block, and StartScrollbarDrag() will fill in the drag metrics.
306
* If the block is confirmed before we have drag metrics, some events
307
* in the drag block may be handled as no-ops until the drag metrics
308
* arrive.
309
*/
310
void SetTargetAPZC(uint64_t aInputBlockId,
311
const nsTArray<SLGuidAndRenderRoot>& aTargets) override;
312
313
/**
314
* Updates any zoom constraints contained in the <meta name="viewport"> tag.
315
* If the |aConstraints| is Nothing() then previously-provided constraints for
316
* the given |aGuid| are cleared.
317
*/
318
void UpdateZoomConstraints(
319
const SLGuidAndRenderRoot& aGuid,
320
const Maybe<ZoomConstraints>& aConstraints) override;
321
322
/**
323
* Adjusts the root APZC to compensate for a shift in the surface. See the
324
* documentation on AsyncPanZoomController::AdjustScrollForSurfaceShift for
325
* some more details. This is only currently needed due to surface shifts
326
* caused by the dynamic toolbar on Android.
327
*/
328
void AdjustScrollForSurfaceShift(const ScreenPoint& aShift);
329
330
/**
331
* Calls Destroy() on all APZC instances attached to the tree, and resets the
332
* tree back to empty. This function must be called exactly once during the
333
* lifetime of this APZCTreeManager, when this APZCTreeManager is no longer
334
* needed. Failing to call this function may prevent objects from being freed
335
* properly.
336
* This must be called on the updater thread.
337
*/
338
void ClearTree();
339
340
/**
341
* Tests if a screen point intersect an apz in the tree.
342
*/
343
bool HitTestAPZC(const ScreenIntPoint& aPoint);
344
345
/**
346
* Sets the dpi value used by all AsyncPanZoomControllers attached to this
347
* tree manager.
348
* DPI defaults to 160 if not set using SetDPI() at any point.
349
*/
350
void SetDPI(float aDpiValue) override;
351
352
/**
353
* Returns the current dpi value in use.
354
*/
355
float GetDPI() const;
356
357
/**
358
* Find the hit testing node for the scrollbar thumb that matches these
359
* drag metrics. Initializes aOutThumbNode with the node, if there is one.
360
*/
361
void FindScrollThumbNode(const AsyncDragMetrics& aDragMetrics,
362
HitTestingTreeNodeAutoLock& aOutThumbNode);
363
364
/**
365
* Sets allowed touch behavior values for current touch-session for specific
366
* input block (determined by aInputBlock).
367
* Should be invoked by the widget. Each value of the aValues arrays
368
* corresponds to the different touch point that is currently active.
369
* Must be called after receiving the TOUCH_START event that starts the
370
* touch-session.
371
* This must be called on the controller thread.
372
*/
373
void SetAllowedTouchBehavior(
374
uint64_t aInputBlockId,
375
const nsTArray<TouchBehaviorFlags>& aValues) override;
376
377
/**
378
* This is a callback for AsyncPanZoomController to call when it wants to
379
* scroll in response to a touch-move event, or when it needs to hand off
380
* overscroll to the next APZC. Note that because of scroll grabbing, the
381
* first APZC to scroll may not be the one that is receiving the touch events.
382
*
383
* |aAPZC| is the APZC that received the touch events triggering the scroll
384
* (in the case of an initial scroll), or the last APZC to scroll (in the
385
* case of overscroll)
386
* |aStartPoint| and |aEndPoint| are in |aAPZC|'s transformed screen
387
* coordinates (i.e. the same coordinates in which touch points are given to
388
* APZCs). The amount of (over)scroll is represented by two points rather
389
* than a displacement because with certain 3D transforms, the same
390
* displacement between different points in transformed coordinates can
391
* represent different displacements in untransformed coordinates.
392
* |aOverscrollHandoffChain| is the overscroll handoff chain used for
393
* determining the order in which scroll should be handed off between
394
* APZCs
395
* |aOverscrollHandoffChainIndex| is the next position in the overscroll
396
* handoff chain that should be scrolled.
397
*
398
* aStartPoint and aEndPoint will be modified depending on how much of the
399
* scroll each APZC consumes. This is to allow the sending APZC to go into
400
* an overscrolled state if no APZC further up in the handoff chain accepted
401
* the entire scroll.
402
*
403
* The way this method works is best illustrated with an example.
404
* Consider three nested APZCs, A, B, and C, with C being the innermost one.
405
* Say B is scroll-grabbing.
406
* The touch events go to C because it's the innermost one (so e.g. taps
407
* should go through C), but the overscroll handoff chain is B -> C -> A
408
* because B is scroll-grabbing.
409
* For convenience I'll refer to the three APZC objects as A, B, and C, and
410
* to the tree manager object as TM.
411
* Here's what happens when C receives a touch-move event:
412
* - C.TrackTouch() calls TM.DispatchScroll() with index = 0.
413
* - TM.DispatchScroll() calls B.AttemptScroll() (since B is at index 0 in
414
* the chain).
415
* - B.AttemptScroll() scrolls B. If there is overscroll, it calls
416
* TM.DispatchScroll() with index = 1.
417
* - TM.DispatchScroll() calls C.AttemptScroll() (since C is at index 1 in
418
* the chain)
419
* - C.AttemptScroll() scrolls C. If there is overscroll, it calls
420
* TM.DispatchScroll() with index = 2.
421
* - TM.DispatchScroll() calls A.AttemptScroll() (since A is at index 2 in
422
* the chain)
423
* - A.AttemptScroll() scrolls A. If there is overscroll, it calls
424
* TM.DispatchScroll() with index = 3.
425
* - TM.DispatchScroll() discards the rest of the scroll as there are no
426
* more elements in the chain.
427
*
428
* Note: this should be used for panning only. For handing off overscroll for
429
* a fling, use DispatchFling().
430
*/
431
void DispatchScroll(AsyncPanZoomController* aApzc,
432
ParentLayerPoint& aStartPoint,
433
ParentLayerPoint& aEndPoint,
434
OverscrollHandoffState& aOverscrollHandoffState);
435
436
/**
437
* This is a callback for AsyncPanZoomController to call when it wants to
438
* start a fling in response to a touch-end event, or when it needs to hand
439
* off a fling to the next APZC. Note that because of scroll grabbing, the
440
* first APZC to fling may not be the one that is receiving the touch events.
441
*
442
* @param aApzc the APZC that wants to start or hand off the fling
443
* @param aHandoffState a collection of state about the operation,
444
* which contains the following:
445
*
446
* mVelocity the current velocity of the fling, in |aApzc|'s screen
447
* pixels per millisecond
448
* mChain the chain of APZCs along which the fling
449
* should be handed off
450
* mIsHandoff is true if |aApzc| is handing off an existing fling (in
451
* this case the fling is given to the next APZC in the
452
* handoff chain after |aApzc|), and false is |aApzc| wants
453
* start a fling (in this case the fling is given to the
454
* first APZC in the chain)
455
*
456
* The return value is the "residual velocity", the portion of
457
* |aHandoffState.mVelocity| that was not consumed by APZCs in the
458
* handoff chain doing flings.
459
* The caller can use this value to determine whether it should consume
460
* the excess velocity by going into overscroll.
461
*/
462
ParentLayerPoint DispatchFling(AsyncPanZoomController* aApzc,
463
const FlingHandoffState& aHandoffState);
464
465
void StartScrollbarDrag(const SLGuidAndRenderRoot& aGuid,
466
const AsyncDragMetrics& aDragMetrics) override;
467
468
bool StartAutoscroll(const SLGuidAndRenderRoot& aGuid,
469
const ScreenPoint& aAnchorLocation) override;
470
471
void StopAutoscroll(const SLGuidAndRenderRoot& aGuid) override;
472
473
/*
474
* Build the chain of APZCs that will handle overscroll for a pan starting at
475
* |aInitialTarget|.
476
*/
477
RefPtr<const OverscrollHandoffChain> BuildOverscrollHandoffChain(
478
const RefPtr<AsyncPanZoomController>& aInitialTarget);
479
480
/**
481
* Function used to disable LongTap gestures.
482
*
483
* On slow running tests, drags and touch events can be misinterpreted
484
* as a long tap. This allows tests to disable long tap gesture detection.
485
*/
486
void SetLongTapEnabled(bool aTapGestureEnabled) override;
487
488
APZInputBridge* InputBridge() override { return this; }
489
490
// Methods to help process WidgetInputEvents (or manage conversion to/from
491
// InputData)
492
493
void ProcessUnhandledEvent(LayoutDeviceIntPoint* aRefPoint,
494
ScrollableLayerGuid* aOutTargetGuid,
495
uint64_t* aOutFocusSequenceNumber,
496
LayersId* aOutLayersId) override;
497
498
void UpdateWheelTransaction(LayoutDeviceIntPoint aRefPoint,
499
EventMessage aEventMessage) override;
500
501
bool GetAPZTestData(LayersId aLayersId, APZTestData* aOutData);
502
503
/**
504
* Iterates over the hit testing tree, collects LayersIds and associated
505
* transforms from layer coordinate space to root coordinate space, and
506
* sends these over to the main thread of the chrome process. If the provided
507
* |aAncestor| argument is non-null, then only the transforms for layer
508
* subtrees scrolled by the aAncestor (i.e. descendants of aAncestor) will be
509
* sent.
510
*/
511
void SendSubtreeTransformsToChromeMainThread(
512
const AsyncPanZoomController* aAncestor);
513
514
/**
515
* Compute the updated shadow transform for a scroll thumb layer that
516
* reflects async scrolling of the associated scroll frame.
517
*
518
* @param aCurrentTransform The current shadow transform on the scroll thumb
519
* layer, as returned by Layer::GetLocalTransform() or similar.
520
* @param aScrollableContentTransform The current content transform on the
521
* scrollable content, as returned by Layer::GetTransform().
522
* @param aApzc The APZC that scrolls the scroll frame.
523
* @param aMetrics The metrics associated with the scroll frame, reflecting
524
* the last paint of the associated content. Note: this metrics should
525
* NOT reflect async scrolling, i.e. they should be the layer tree's
526
* copy of the metrics, or APZC's last-content-paint metrics.
527
* @param aScrollbarData The scrollbar data for the the scroll thumb layer.
528
* @param aScrollbarIsDescendant True iff. the scroll thumb layer is a
529
* descendant of the layer bearing the scroll frame's metrics.
530
* @param aOutClipTransform If not null, and |aScrollbarIsDescendant| is true,
531
* this will be populated with a transform that should be applied to the
532
* clip rects of all layers between the scroll thumb layer and the ancestor
533
* layer for the scrollable content.
534
* @return The new shadow transform for the scroll thumb layer, including
535
* any pre- or post-scales.
536
*/
537
static LayerToParentLayerMatrix4x4 ComputeTransformForScrollThumb(
538
const LayerToParentLayerMatrix4x4& aCurrentTransform,
539
const gfx::Matrix4x4& aScrollableContentTransform,
540
AsyncPanZoomController* aApzc, const FrameMetrics& aMetrics,
541
const ScrollbarData& aScrollbarData, bool aScrollbarIsDescendant,
542
AsyncTransformComponentMatrix* aOutClipTransform);
543
544
/**
545
* Dispatch a flush complete notification from the repaint thread of the
546
* content controller for the given layers id.
547
*/
548
static void FlushApzRepaints(LayersId aLayersId);
549
550
// Assert that the current thread is the sampler thread for this APZCTM.
551
void AssertOnSamplerThread();
552
// Assert that the current thread is the updater thread for this APZCTM.
553
void AssertOnUpdaterThread();
554
555
// Returns a pointer to the WebRenderAPI this APZCTreeManager is for, for
556
// the provided RenderRoot (since an APZCTreeManager can cover multiple
557
// RenderRoots). This might be null (for example, if WebRender is not
558
// enabled).
559
already_AddRefed<wr::WebRenderAPI> GetWebRenderAPI(
560
wr::RenderRoot aRenderRoot) const;
561
562
// Returns a pointer to the root WebRenderAPI for the RenderRoot that owns
563
// the given point. For example, if aPoint is in the content area and
564
// RenderRoot splitting is enabled, this will return the WebRenderAPI for
565
// the Content RenderRoot.
566
// This might be null (for example, if WebRender is not enabled).
567
already_AddRefed<wr::WebRenderAPI> GetWebRenderAPIAtPoint(
568
const ScreenPoint& aPoint) const;
569
570
protected:
571
// Protected destructor, to discourage deletion outside of Release():
572
virtual ~APZCTreeManager();
573
574
APZSampler* GetSampler() const;
575
APZUpdater* GetUpdater() const;
576
577
// We need to allow APZUpdater to lock and unlock this tree during a WR
578
// scene swap. We do this using private helpers to avoid exposing these
579
// functions to the world.
580
private:
581
friend class APZUpdater;
582
void LockTree();
583
void UnlockTree();
584
585
// Protected hooks for gtests subclass
586
virtual AsyncPanZoomController* NewAPZCInstance(
587
LayersId aLayersId, GeckoContentController* aController,
588
wr::RenderRoot aRenderRoot);
589
590
public:
591
// Public hook for gtests subclass
592
virtual TimeStamp GetFrameTime();
593
594
// Also used for controlling time during tests
595
void SetTestSampleTime(const Maybe<TimeStamp>& aTime);
596
597
private:
598
Maybe<TimeStamp> mTestSampleTime;
599
600
public:
601
/* Some helper functions to find an APZC given some identifying input. These
602
functions lock the tree of APZCs while they find the right one, and then
603
return an addref'd pointer to it. This allows caller code to just use the
604
target APZC without worrying about it going away. These are public for
605
testing code and generally should not be used by other production code.
606
*/
607
RefPtr<HitTestingTreeNode> GetRootNode() const;
608
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(
609
const ScreenPoint& aPoint, gfx::CompositorHitTestInfo* aOutHitResult,
610
LayersId* aOutLayersId,
611
HitTestingTreeNodeAutoLock* aOutScrollbarNode = nullptr);
612
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(
613
const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId);
614
ScreenToParentLayerMatrix4x4 GetScreenToApzcTransform(
615
const AsyncPanZoomController* aApzc) const;
616
ParentLayerToScreenMatrix4x4 GetApzcToGeckoTransform(
617
const AsyncPanZoomController* aApzc) const;
618
ScreenPoint GetCurrentMousePosition() const;
619
620
/**
621
* Process a movement of the dynamic toolbar by |aDeltaY| over the time
622
* period from |aStartTimestampMs| to |aEndTimestampMs|.
623
* This is used to track velocities accurately in the presence of movement
624
* of the dynamic toolbar, since in such cases the finger can be moving
625
* relative to the screen even though no scrolling is occurring.
626
* Note that this function expects "spatial coordinates" (i.e. toolbar
627
* moves up --> negative delta).
628
*/
629
void ProcessDynamicToolbarMovement(uint32_t aStartTimestampMs,
630
uint32_t aEndTimestampMs,
631
ScreenCoord aDeltaY);
632
633
/**
634
* Find the zoomable APZC in the same layer subtree (i.e. with the same
635
* layers id) as the given APZC.
636
*/
637
already_AddRefed<AsyncPanZoomController> FindZoomableApzc(
638
AsyncPanZoomController* aStart) const;
639
640
private:
641
typedef bool (*GuidComparator)(const ScrollableLayerGuid&,
642
const ScrollableLayerGuid&);
643
644
/* Helpers */
645
template <class ScrollNode>
646
void UpdateHitTestingTreeImpl(const ScrollNode& aRoot, bool aIsFirstPaint,
647
WRRootId aOriginatingWrRootId,
648
uint32_t aPaintSequenceNumber);
649
650
void AttachNodeToTree(HitTestingTreeNode* aNode, HitTestingTreeNode* aParent,
651
HitTestingTreeNode* aNextSibling);
652
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(
653
const ScrollableLayerGuid& aGuid);
654
already_AddRefed<HitTestingTreeNode> GetTargetNode(
655
const ScrollableLayerGuid& aGuid, GuidComparator aComparator) const;
656
HitTestingTreeNode* FindTargetNode(HitTestingTreeNode* aNode,
657
const ScrollableLayerGuid& aGuid,
658
GuidComparator aComparator);
659
AsyncPanZoomController* GetTargetApzcForNode(HitTestingTreeNode* aNode);
660
AsyncPanZoomController* GetAPZCAtPoint(
661
HitTestingTreeNode* aNode, const ScreenPoint& aHitTestPoint,
662
gfx::CompositorHitTestInfo* aOutHitResult, LayersId* aOutLayersId,
663
HitTestingTreeNode** aOutScrollbarNode);
664
already_AddRefed<AsyncPanZoomController> GetAPZCAtPointWR(
665
const ScreenPoint& aHitTestPoint,
666
gfx::CompositorHitTestInfo* aOutHitResult, LayersId* aOutLayersId,
667
HitTestingTreeNode** aOutScrollbarNode);
668
AsyncPanZoomController* FindRootApzcForLayersId(LayersId aLayersId) const;
669
AsyncPanZoomController* FindRootContentApzcForLayersId(
670
LayersId aLayersId) const;
671
AsyncPanZoomController* FindRootContentOrRootApzc() const;
672
already_AddRefed<AsyncPanZoomController> GetZoomableTarget(
673
AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const;
674
already_AddRefed<AsyncPanZoomController> CommonAncestor(
675
AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const;
676
/**
677
* Perform hit testing for a touch-start event.
678
*
679
* @param aEvent The touch-start event.
680
*
681
* The remaining parameters are out-parameter used to communicate additional
682
* return values:
683
*
684
* @param aOutTouchBehaviors
685
* The touch behaviours that should be allowed for this touch block.
686
* @param aOutHitResult The hit test result.
687
* @param aOutHitScrollbarNode
688
* If the touch event contains a single touch point (so that it may
689
* potentially start a scrollbar drag), and a scrollbar node was hit,
690
* that scrollbar node, otherwise nullptr.
691
*
692
* @return The APZC that was hit.
693
*/
694
already_AddRefed<AsyncPanZoomController> GetTouchInputBlockAPZC(
695
const MultiTouchInput& aEvent,
696
nsTArray<TouchBehaviorFlags>* aOutTouchBehaviors,
697
gfx::CompositorHitTestInfo* aOutHitResult, LayersId* aOutLayersId,
698
HitTestingTreeNodeAutoLock* aOutHitScrollbarNode);
699
nsEventStatus ProcessTouchInput(MultiTouchInput& aInput,
700
ScrollableLayerGuid* aOutTargetGuid,
701
uint64_t* aOutInputBlockId);
702
/**
703
* Given a mouse-down event that hit a scroll thumb node, set up APZ
704
* dragging of the scroll thumb.
705
*
706
* Must be called after the mouse event has been sent to InputQueue.
707
*
708
* @param aMouseInput The mouse-down event.
709
* @param aScrollThumbNode Tthe scroll thumb node that was hit.
710
* @param aApzc
711
* The APZC for the scroll frame scrolled by the scroll thumb, if that
712
* scroll frame is layerized. (A thumb can be layerized without its
713
* target scroll frame being layerized.) Otherwise, an enclosing APZC.
714
*/
715
void SetupScrollbarDrag(MouseInput& aMouseInput,
716
const HitTestingTreeNodeAutoLock& aScrollThumbNode,
717
AsyncPanZoomController* aApzc);
718
/**
719
* Process a touch event that's part of a scrollbar touch-drag gesture.
720
*
721
* @param aInput The touch event.
722
* @param aScrollThumbNode
723
* If this is the touch-start event, the node representing the scroll
724
* thumb we are starting to drag. Otherwise nullptr.
725
* @param aOutTargetGuid
726
* The guid of the APZC for the scroll frame whose scroll thumb is
727
* being dragged.
728
* @param aOutInputBlockId
729
* The ID of the input block for the touch-drag gesture.
730
* @return See ReceiveInputEvent() for what the return value means.
731
*/
732
nsEventStatus ProcessTouchInputForScrollbarDrag(
733
MultiTouchInput& aInput,
734
const HitTestingTreeNodeAutoLock& aScrollThumbNode,
735
ScrollableLayerGuid* aOutTargetGuid, uint64_t* aOutInputBlockId);
736
void FlushRepaintsToClearScreenToGeckoTransform();
737
738
void SynthesizePinchGestureFromMouseWheel(
739
const ScrollWheelInput& aWheelInput,
740
const RefPtr<AsyncPanZoomController>& aTarget);
741
742
already_AddRefed<HitTestingTreeNode> RecycleOrCreateNode(
743
const RecursiveMutexAutoLock& aProofOfTreeLock, TreeBuildingState& aState,
744
AsyncPanZoomController* aApzc, LayersId aLayersId);
745
template <class ScrollNode>
746
HitTestingTreeNode* PrepareNodeForLayer(
747
const RecursiveMutexAutoLock& aProofOfTreeLock, const ScrollNode& aLayer,
748
const FrameMetrics& aMetrics, LayersId aLayersId,
749
const AncestorTransform& aAncestorTransform, HitTestingTreeNode* aParent,
750
HitTestingTreeNode* aNextSibling, TreeBuildingState& aState,
751
wr::RenderRoot aRenderRoot);
752
template <class ScrollNode>
753
Maybe<ParentLayerIntRegion> ComputeClipRegion(const ScrollNode& aLayer);
754
755
template <class ScrollNode>
756
void PrintAPZCInfo(const ScrollNode& aLayer,
757
const AsyncPanZoomController* apzc);
758
759
void NotifyScrollbarDragInitiated(uint64_t aDragBlockId,
760
const ScrollableLayerGuid& aGuid,
761
ScrollDirection aDirection) const;
762
void NotifyScrollbarDragRejected(const ScrollableLayerGuid& aGuid) const;
763
void NotifyAutoscrollRejected(const ScrollableLayerGuid& aGuid) const;
764
765
// Requires the caller to hold mTreeLock.
766
LayerToParentLayerMatrix4x4 ComputeTransformForNode(
767
const HitTestingTreeNode* aNode) const;
768
769
// Look up the GeckoContentController for the given layers id.
770
static already_AddRefed<GeckoContentController> GetContentController(
771
LayersId aLayersId);
772
773
protected:
774
/* The input queue where input events are held until we know enough to
775
* figure out where they're going. Protected so gtests can access it.
776
*/
777
RefPtr<InputQueue> mInputQueue;
778
779
private:
780
/* Layers id for the root CompositorBridgeParent that owns this
781
* APZCTreeManager. */
782
LayersId mRootLayersId;
783
784
/* Pointer to the APZSampler instance that is bound to this APZCTreeManager.
785
* The sampler has a RefPtr to this class, and this non-owning raw pointer
786
* back to the APZSampler is nulled out in the sampler's destructor, so this
787
* pointer should always be valid.
788
*/
789
APZSampler* MOZ_NON_OWNING_REF mSampler;
790
/* Pointer to the APZUpdater instance that is bound to this APZCTreeManager.
791
* The updater has a RefPtr to this class, and this non-owning raw pointer
792
* back to the APZUpdater is nulled out in the updater's destructor, so this
793
* pointer should always be valid.
794
*/
795
APZUpdater* MOZ_NON_OWNING_REF mUpdater;
796
797
/* Whenever walking or mutating the tree rooted at mRootNode, mTreeLock must
798
* be held. This lock does not need to be held while manipulating a single
799
* APZC instance in isolation (that is, if its tree pointers are not being
800
* accessed or mutated). The lock also needs to be held when accessing the
801
* mRootNode instance variable, as that is considered part of the APZC tree
802
* management state.
803
* IMPORTANT: See the note about lock ordering at the top of this file. */
804
mutable mozilla::RecursiveMutex mTreeLock;
805
RefPtr<HitTestingTreeNode> mRootNode;
806
807
/* True if the current hit-testing tree contains an async zoom container
808
* node.
809
*/
810
bool mUsingAsyncZoomContainer;
811
812
/** A lock that protects mApzcMap and mScrollThumbInfo. */
813
mutable mozilla::Mutex mMapLock;
814
/**
815
* A map for quick access to get APZC instances by guid, without having to
816
* acquire the tree lock. mMapLock must be acquired while accessing or
817
* modifying mApzcMap.
818
*/
819
std::unordered_map<ScrollableLayerGuid, RefPtr<AsyncPanZoomController>,
820
ScrollableLayerGuid::HashIgnoringPresShellFn,
821
ScrollableLayerGuid::EqualIgnoringPresShellFn>
822
mApzcMap;
823
/**
824
* A helper structure to store all the information needed to compute the
825
* async transform for a scrollthumb on the sampler thread.
826
*/
827
struct ScrollThumbInfo {
828
uint64_t mThumbAnimationId;
829
CSSTransformMatrix mThumbTransform;
830
ScrollbarData mThumbData;
831
ScrollableLayerGuid mTargetGuid;
832
CSSTransformMatrix mTargetTransform;
833
bool mTargetIsAncestor;
834
835
ScrollThumbInfo(const uint64_t& aThumbAnimationId,
836
const CSSTransformMatrix& aThumbTransform,
837
const ScrollbarData& aThumbData,
838
const ScrollableLayerGuid& aTargetGuid,
839
const CSSTransformMatrix& aTargetTransform,
840
bool aTargetIsAncestor)
841
: mThumbAnimationId(aThumbAnimationId),
842
mThumbTransform(aThumbTransform),
843
mThumbData(aThumbData),
844
mTargetGuid(aTargetGuid),
845
mTargetTransform(aTargetTransform),
846
mTargetIsAncestor(aTargetIsAncestor) {
847
MOZ_ASSERT(mTargetGuid.mScrollId == mThumbData.mTargetViewId);
848
}
849
};
850
/**
851
* If this APZCTreeManager is being used with WebRender, this vector gets
852
* populated during a layers update. It holds a package of information needed
853
* to compute and set the async transforms on scroll thumbs. This information
854
* is extracted from the HitTestingTreeNodes for the WebRender case because
855
* accessing the HitTestingTreeNodes requires holding the tree lock which
856
* we cannot do on the WR sampler thread. mScrollThumbInfo, however, can
857
* be accessed while just holding the mMapLock which is safe to do on the
858
* sampler thread.
859
* mMapLock must be acquired while accessing or modifying mScrollThumbInfo.
860
*/
861
std::vector<ScrollThumbInfo> mScrollThumbInfo;
862
863
/* Holds the zoom constraints for scrollable layers, as determined by the
864
* the main-thread gecko code. This can only be accessed on the updater
865
* thread. */
866
std::unordered_map<ScrollableLayerGuid, ZoomConstraints,
867
ScrollableLayerGuid::HashFn>
868
mZoomConstraints;
869
/* A list of keyboard shortcuts to use for translating keyboard inputs into
870
* keyboard actions. This is gathered on the main thread from XBL bindings.
871
* This must only be accessed on the controller thread.
872
*/
873
KeyboardMap mKeyboardMap;
874
/* This tracks the focus targets of chrome and content and whether we have
875
* a current focus target or whether we are waiting for a new confirmation.
876
*/
877
FocusState mFocusState;
878
/* This tracks the APZC that should receive all inputs for the current input
879
* event block. This allows touch points to move outside the thing they
880
* started on, but still have the touch events delivered to the same initial
881
* APZC. This will only ever be touched on the input delivery thread, and so
882
* does not require locking.
883
*/
884
RefPtr<AsyncPanZoomController> mApzcForInputBlock;
885
/* The hit result for the current input event block; this should always be in
886
* sync with mApzcForInputBlock.
887
*/
888
gfx::CompositorHitTestInfo mHitResultForInputBlock;
889
/* Sometimes we want to ignore all touches except one. In such cases, this
890
* is set to the identifier of the touch we are not ignoring; in other cases,
891
* this is set to -1.
892
*/
893
int32_t mRetainedTouchIdentifier;
894
/* This tracks whether the current input block represents a touch-drag of
895
* a scrollbar. In this state, touch events are forwarded to content as touch
896
* events, but converted to mouse events before going into InputQueue and
897
* being handled by an APZC (to reuse the APZ code for scrollbar dragging
898
* with a mouse).
899
*/
900
bool mInScrollbarTouchDrag;
901
/* Tracks the number of touch points we are tracking that are currently on
902
* the screen. */
903
TouchCounter mTouchCounter;
904
/* Stores the current mouse position in screen coordinates.
905
*/
906
ScreenPoint mCurrentMousePosition;
907
/* For logging the APZC tree for debugging (enabled by the apz.printtree
908
* pref). */
909
gfx::TreeLog<gfx::LOG_DEFAULT> mApzcTreeLog;
910
911
class CheckerboardFlushObserver;
912
friend class CheckerboardFlushObserver;
913
RefPtr<CheckerboardFlushObserver> mFlushObserver;
914
915
// Map from layers id to APZTestData. Accesses and mutations must be
916
// protected by the mTestDataLock.
917
std::unordered_map<LayersId, UniquePtr<APZTestData>, LayersId::HashFn>
918
mTestData;
919
mutable mozilla::Mutex mTestDataLock;
920
921
// This must only be touched on the controller thread.
922
float mDPI;
923
924
#if defined(MOZ_WIDGET_ANDROID)
925
public:
926
AndroidDynamicToolbarAnimator* GetAndroidDynamicToolbarAnimator();
927
928
private:
929
RefPtr<AndroidDynamicToolbarAnimator> mToolbarAnimator;
930
#endif // defined(MOZ_WIDGET_ANDROID)
931
};
932
933
} // namespace layers
934
} // namespace mozilla
935
936
#endif // mozilla_layers_PanZoomController_h