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