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