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