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