Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et 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/. */
7 #ifndef mozilla_layers_AsyncPanZoomController_h
8 #define mozilla_layers_AsyncPanZoomController_h
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/ReentrantMonitor.h"
16 #include "mozilla/RefPtr.h"
17 #include "mozilla/Atomics.h"
18 #include "InputData.h"
19 #include "Axis.h"
20 #include "TaskThrottler.h"
21 #include "gfx3DMatrix.h"
23 #include "base/message_loop.h"
25 namespace mozilla {
27 namespace ipc {
29 class SharedMemoryBasic;
31 }
33 namespace layers {
35 struct ScrollableLayerGuid;
36 class CompositorParent;
37 class GestureEventListener;
38 class ContainerLayer;
39 class PCompositorParent;
40 class ViewTransform;
41 class APZCTreeManager;
42 class AsyncPanZoomAnimation;
43 class FlingAnimation;
45 /**
46 * Controller for all panning and zooming logic. Any time a user input is
47 * detected and it must be processed in some way to affect what the user sees,
48 * it goes through here. Listens for any input event from InputData and can
49 * optionally handle WidgetGUIEvent-derived touch events, but this must be done
50 * on the main thread. Note that this class completely cross-platform.
51 *
52 * Input events originate on the UI thread of the platform that this runs on,
53 * and are then sent to this class. This class processes the event in some way;
54 * for example, a touch move will usually lead to a panning of content (though
55 * of course there are exceptions, such as if content preventDefaults the event,
56 * or if the target frame is not scrollable). The compositor interacts with this
57 * class by locking it and querying it for the current transform matrix based on
58 * the panning and zooming logic that was invoked on the UI thread.
59 *
60 * Currently, each outer DOM window (i.e. a website in a tab, but not any
61 * subframes) has its own AsyncPanZoomController. In the future, to support
62 * asynchronously scrolled subframes, we want to have one AsyncPanZoomController
63 * per frame.
64 */
65 class AsyncPanZoomController {
66 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomController)
68 typedef mozilla::MonitorAutoLock MonitorAutoLock;
69 typedef uint32_t TouchBehaviorFlags;
71 public:
72 enum GestureBehavior {
73 // The platform code is responsible for forwarding gesture events here. We
74 // will not attempt to generate gesture events from MultiTouchInputs.
75 DEFAULT_GESTURES,
76 // An instance of GestureEventListener is used to detect gestures. This is
77 // handled completely internally within this class.
78 USE_GESTURE_DETECTOR
79 };
81 /**
82 * Constant describing the tolerance in distance we use, multiplied by the
83 * device DPI, before we start panning the screen. This is to prevent us from
84 * accidentally processing taps as touch moves, and from very short/accidental
85 * touches moving the screen.
86 */
87 static float GetTouchStartTolerance();
89 AsyncPanZoomController(uint64_t aLayersId,
90 APZCTreeManager* aTreeManager,
91 GeckoContentController* aController,
92 GestureBehavior aGestures = DEFAULT_GESTURES);
94 // --------------------------------------------------------------------------
95 // These methods must only be called on the gecko thread.
96 //
98 /**
99 * Read the various prefs and do any global initialization for all APZC instances.
100 * This must be run on the gecko thread before any APZC instances are actually
101 * used for anything meaningful.
102 */
103 static void InitializeGlobalState();
105 // --------------------------------------------------------------------------
106 // These methods must only be called on the controller/UI thread.
107 //
109 /**
110 * General handler for incoming input events. Manipulates the frame metrics
111 * based on what type of input it is. For example, a PinchGestureEvent will
112 * cause scaling. This should only be called externally to this class.
113 * HandleInputEvent() should be used internally.
114 */
115 nsEventStatus ReceiveInputEvent(const InputData& aEvent);
117 /**
118 * Kicks an animation to zoom to a rect. This may be either a zoom out or zoom
119 * in. The actual animation is done on the compositor thread after being set
120 * up.
121 */
122 void ZoomToRect(CSSRect aRect);
124 /**
125 * If we have touch listeners, this should always be called when we know
126 * definitively whether or not content has preventDefaulted any touch events
127 * that have come in. If |aPreventDefault| is true, any touch events in the
128 * queue will be discarded.
129 */
130 void ContentReceivedTouch(bool aPreventDefault);
132 /**
133 * Updates any zoom constraints contained in the <meta name="viewport"> tag.
134 */
135 void UpdateZoomConstraints(const ZoomConstraints& aConstraints);
137 /**
138 * Return the zoom constraints last set for this APZC (in the constructor
139 * or in UpdateZoomConstraints()).
140 */
141 ZoomConstraints GetZoomConstraints() const;
143 /**
144 * Schedules a runnable to run on the controller/UI thread at some time
145 * in the future.
146 */
147 void PostDelayedTask(Task* aTask, int aDelayMs);
149 // --------------------------------------------------------------------------
150 // These methods must only be called on the compositor thread.
151 //
153 bool UpdateAnimation(const TimeStamp& aSampleTime);
155 /**
156 * The compositor calls this when it's about to draw pannable/zoomable content
157 * and is setting up transforms for compositing the layer tree. This is not
158 * idempotent. For example, a fling transform can be applied each time this is
159 * called (though not necessarily). |aSampleTime| is the time that this is
160 * sampled at; this is used for interpolating animations. Calling this sets a
161 * new transform in |aNewTransform| which should be multiplied to the transform
162 * in the shadow layer corresponding to this APZC.
163 *
164 * Return value indicates whether or not any currently running animation
165 * should continue. That is, if true, the compositor should schedule another
166 * composite.
167 */
168 bool SampleContentTransformForFrame(const TimeStamp& aSampleTime,
169 ViewTransform* aNewTransform,
170 ScreenPoint& aScrollOffset);
172 /**
173 * A shadow layer update has arrived. |aLayerMetrics| is the new FrameMetrics
174 * for the container layer corresponding to this APZC.
175 * |aIsFirstPaint| is a flag passed from the shadow
176 * layers code indicating that the frame metrics being sent with this call are
177 * the initial metrics and the initial paint of the frame has just happened.
178 */
179 void NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint);
181 /**
182 * The platform implementation must set the compositor parent so that we can
183 * request composites.
184 */
185 void SetCompositorParent(CompositorParent* aCompositorParent);
187 /**
188 * The platform implementation must set the cross process compositor if
189 * there is one associated with the layer tree. The cross process compositor
190 * allows the APZC to share its FrameMetrics with the content process.
191 * The shared FrameMetrics is used in progressive paint updates.
192 */
193 void SetCrossProcessCompositorParent(PCompositorParent* aCrossProcessCompositorParent);
195 // --------------------------------------------------------------------------
196 // These methods can be called from any thread.
197 //
199 /**
200 * Shut down the controller/UI thread state and prepare to be
201 * deleted (which may happen from any thread).
202 */
203 void Destroy();
205 /**
206 * Returns true if Destroy() has already been called on this APZC instance.
207 */
208 bool IsDestroyed();
210 /**
211 * Returns the incremental transformation corresponding to the async pan/zoom
212 * in progress. That is, when this transform is multiplied with the layer's
213 * existing transform, it will make the layer appear with the desired pan/zoom
214 * amount.
215 */
216 ViewTransform GetCurrentAsyncTransform();
218 /**
219 * Returns the part of the async transform that will remain once Gecko does a
220 * repaint at the desired metrics. That is, in the steady state:
221 * gfx3DMatrix(GetCurrentAsyncTransform()) === GetNontransientAsyncTransform()
222 */
223 gfx3DMatrix GetNontransientAsyncTransform();
225 /**
226 * Returns the transform to take something from the coordinate space of the
227 * last thing we know gecko painted, to the coordinate space of the last thing
228 * we asked gecko to paint. In cases where that last request has not yet been
229 * processed, this is needed to transform input events properly into a space
230 * gecko will understand.
231 */
232 gfx3DMatrix GetTransformToLastDispatchedPaint();
234 /**
235 * Recalculates the displayport. Ideally, this should paint an area bigger
236 * than the composite-to dimensions so that when you scroll down, you don't
237 * checkerboard immediately. This includes a bunch of logic, including
238 * algorithms to bias painting in the direction of the velocity.
239 */
240 static const LayerMargin CalculatePendingDisplayPort(
241 const FrameMetrics& aFrameMetrics,
242 const ScreenPoint& aVelocity,
243 double aEstimatedPaintDuration);
245 /**
246 * Send an mozbrowserasyncscroll event.
247 * *** The monitor must be held while calling this.
248 */
249 void SendAsyncScrollEvent();
251 /**
252 * Handler for events which should not be intercepted by the touch listener.
253 * Does the work for ReceiveInputEvent().
254 */
255 nsEventStatus HandleInputEvent(const InputData& aEvent);
257 /**
258 * Handler for gesture events.
259 * Currently some gestures are detected in GestureEventListener that calls
260 * APZC back through this handler in order to avoid recursive calls to
261 * APZC::HandleInputEvent() which is supposed to do the work for
262 * ReceiveInputEvent().
263 */
264 nsEventStatus HandleGestureEvent(const InputData& aEvent);
266 /**
267 * Populates the provided object (if non-null) with the scrollable guid of this apzc.
268 */
269 void GetGuid(ScrollableLayerGuid* aGuidOut);
271 /**
272 * Returns the scrollable guid of this apzc.
273 */
274 ScrollableLayerGuid GetGuid();
276 /**
277 * Returns true if this APZC instance is for the layer identified by the guid.
278 */
279 bool Matches(const ScrollableLayerGuid& aGuid);
281 /**
282 * Sync panning and zooming animation using a fixed frame time.
283 * This will ensure that we animate the APZC correctly with other external
284 * animations to the same timestamp.
285 */
286 static void SetFrameTime(const TimeStamp& aMilliseconds);
288 void StartAnimation(AsyncPanZoomAnimation* aAnimation);
290 /**
291 * Cancels any currently running animation. Note that all this does is set the
292 * state of the AsyncPanZoomController back to NOTHING, but it is the
293 * animation's responsibility to check this before advancing.
294 */
295 void CancelAnimation();
297 /**
298 * Take over a fling with the given velocity from another APZC. Used for
299 * during overscroll handoff for a fling.
300 */
301 void TakeOverFling(ScreenPoint aVelocity);
303 /**
304 * Returns allowed touch behavior for the given point on the scrollable layer.
305 * Internally performs a kind of hit testing based on the regions constructed
306 * on the main thread and attached to the current scrollable layer. Each of such regions
307 * contains info about allowed touch behavior. If regions info isn't enough it returns
308 * UNKNOWN value and we should switch to the fallback approach - asking content.
309 * TODO: for now it's only a stub and returns hardcoded magic value. As soon as bug 928833
310 * is done we should integrate its logic here.
311 */
312 TouchBehaviorFlags GetAllowedTouchBehavior(ScreenIntPoint& aPoint);
314 /**
315 * Sets allowed touch behavior for current touch session.
316 * This method is invoked by the APZCTreeManager which in its turn invoked by
317 * the widget after performing touch-action values retrieving.
318 * Must be called after receiving the TOUCH_START even that started the
319 * touch session.
320 */
321 void SetAllowedTouchBehavior(const nsTArray<TouchBehaviorFlags>& aBehaviors);
323 /**
324 * Returns whether this APZC is for an element marked with the 'scrollgrab'
325 * attribute.
326 */
327 bool HasScrollgrab() const { return mFrameMetrics.mHasScrollgrab; }
329 /**
330 * Set an extra offset for testing async scrolling.
331 */
332 void SetTestAsyncScrollOffset(const CSSPoint& aPoint)
333 {
334 mTestAsyncScrollOffset = aPoint;
335 }
337 /**
338 * Returns whether this APZC has room to be panned (in any direction).
339 */
340 bool IsPannable() const;
342 protected:
343 // Protected destructor, to discourage deletion outside of Release():
344 ~AsyncPanZoomController();
346 /**
347 * Helper method for touches beginning. Sets everything up for panning and any
348 * multitouch gestures.
349 */
350 nsEventStatus OnTouchStart(const MultiTouchInput& aEvent);
352 /**
353 * Helper method for touches moving. Does any transforms needed when panning.
354 */
355 nsEventStatus OnTouchMove(const MultiTouchInput& aEvent);
357 /**
358 * Helper method for touches ending. Redraws the screen if necessary and does
359 * any cleanup after a touch has ended.
360 */
361 nsEventStatus OnTouchEnd(const MultiTouchInput& aEvent);
363 /**
364 * Helper method for touches being cancelled. Treated roughly the same as a
365 * touch ending (OnTouchEnd()).
366 */
367 nsEventStatus OnTouchCancel(const MultiTouchInput& aEvent);
369 /**
370 * Helper method for scales beginning. Distinct from the OnTouch* handlers in
371 * that this implies some outside implementation has determined that the user
372 * is pinching.
373 */
374 nsEventStatus OnScaleBegin(const PinchGestureInput& aEvent);
376 /**
377 * Helper method for scaling. As the user moves their fingers when pinching,
378 * this changes the scale of the page.
379 */
380 nsEventStatus OnScale(const PinchGestureInput& aEvent);
382 /**
383 * Helper method for scales ending. Redraws the screen if necessary and does
384 * any cleanup after a scale has ended.
385 */
386 nsEventStatus OnScaleEnd(const PinchGestureInput& aEvent);
388 /**
389 * Helper methods for long press gestures.
390 */
391 nsEventStatus OnLongPress(const TapGestureInput& aEvent);
392 nsEventStatus OnLongPressUp(const TapGestureInput& aEvent);
394 /**
395 * Helper method for single tap gestures.
396 */
397 nsEventStatus OnSingleTapUp(const TapGestureInput& aEvent);
399 /**
400 * Helper method for a single tap confirmed.
401 */
402 nsEventStatus OnSingleTapConfirmed(const TapGestureInput& aEvent);
404 /**
405 * Helper method for double taps.
406 */
407 nsEventStatus OnDoubleTap(const TapGestureInput& aEvent);
409 /**
410 * Helper method to cancel any gesture currently going to Gecko. Used
411 * primarily when a user taps the screen over some clickable content but then
412 * pans down instead of letting go (i.e. to cancel a previous touch so that a
413 * new one can properly take effect.
414 */
415 nsEventStatus OnCancelTap(const TapGestureInput& aEvent);
417 /**
418 * Scrolls the viewport by an X,Y offset.
419 */
420 void ScrollBy(const CSSPoint& aOffset);
422 /**
423 * Scales the viewport by an amount (note that it multiplies this scale in to
424 * the current scale, it doesn't set it to |aScale|). Also considers a focus
425 * point so that the page zooms inward/outward from that point.
426 */
427 void ScaleWithFocus(float aScale,
428 const CSSPoint& aFocus);
430 /**
431 * Schedules a composite on the compositor thread. Wrapper for
432 * CompositorParent::ScheduleRenderOnCompositorThread().
433 */
434 void ScheduleComposite();
436 /**
437 * Gets the displacement of the current touch since it began. That is, it is
438 * the distance between the current position and the initial position of the
439 * current touch (this only makes sense if a touch is currently happening and
440 * OnTouchMove() is being invoked).
441 */
442 float PanDistance();
444 /**
445 * Gets a vector of the velocities of each axis.
446 */
447 const ScreenPoint GetVelocityVector();
449 /**
450 * Gets a reference to the first touch point from a MultiTouchInput. This
451 * gets only the first one and assumes the rest are either missing or not
452 * relevant.
453 */
454 ScreenIntPoint& GetFirstTouchScreenPoint(const MultiTouchInput& aEvent);
456 /**
457 * Sets the panning state basing on the pan direction angle and current touch-action value.
458 */
459 void HandlePanningWithTouchAction(double angle, TouchBehaviorFlags value);
461 /**
462 * Sets the panning state ignoring the touch action value.
463 */
464 void HandlePanning(double angle);
466 /**
467 * Sets up anything needed for panning. This takes us out of the "TOUCHING"
468 * state and starts actually panning us.
469 */
470 nsEventStatus StartPanning(const MultiTouchInput& aStartPoint);
472 /**
473 * Wrapper for Axis::UpdateWithTouchAtDevicePoint(). Calls this function for
474 * both axes and factors in the time delta from the last update.
475 */
476 void UpdateWithTouchAtDevicePoint(const MultiTouchInput& aEvent);
478 /**
479 * Does any panning required due to a new touch event.
480 */
481 void TrackTouch(const MultiTouchInput& aEvent);
483 /**
484 * Utility function to send updated FrameMetrics to Gecko so that it can paint
485 * the displayport area. Calls into GeckoContentController to do the actual
486 * work. Note that only one paint request can be active at a time. If a paint
487 * request is made while a paint is currently happening, it gets queued up. If
488 * a new paint request arrives before a paint is completed, the old request
489 * gets discarded.
490 */
491 void RequestContentRepaint();
493 /**
494 * Tell the paint throttler to request a content repaint with the given
495 * metrics. (Helper function used by RequestContentRepaint.)
496 */
497 void RequestContentRepaint(FrameMetrics& aFrameMetrics);
499 /**
500 * Actually send the next pending paint request to gecko.
501 */
502 void DispatchRepaintRequest(const FrameMetrics& aFrameMetrics);
504 /**
505 * Advances a fling by an interpolated amount based on the passed in |aDelta|.
506 * This should be called whenever sampling the content transform for this
507 * frame. Returns true if the fling animation should be advanced by one frame,
508 * or false if there is no fling or the fling has ended.
509 */
510 bool DoFling(const TimeDuration& aDelta);
512 /**
513 * Gets the current frame metrics. This is *not* the Gecko copy stored in the
514 * layers code.
515 */
516 const FrameMetrics& GetFrameMetrics();
518 /**
519 * Sets the timer for content response to a series of touch events, if it
520 * hasn't been already. This is to prevent us from batching up touch events
521 * indefinitely in the case that content doesn't respond with whether or not
522 * it wants to preventDefault. When the timer is fired, the touch event queue
523 * will be flushed.
524 */
525 void SetContentResponseTimer();
527 /**
528 * Timeout function for content response. This should be called on a timer
529 * after we get our first touch event in a batch, under the condition that we
530 * waiting for response from content. If a notification comes indicating whether or not
531 * content preventDefaulted a series of touch events and touch behavior values are
532 * set before the timeout, the timeout should be cancelled.
533 */
534 void TimeoutContentResponse();
536 /**
537 * Timeout function for mozbrowserasyncscroll event. Because we throttle
538 * mozbrowserasyncscroll events in some conditions, this function ensures
539 * that the last mozbrowserasyncscroll event will be fired after a period of
540 * time.
541 */
542 void FireAsyncScrollOnTimeout();
544 private:
545 enum PanZoomState {
546 NOTHING, /* no touch-start events received */
547 FLING, /* all touches removed, but we're still scrolling page */
548 TOUCHING, /* one touch-start event received */
550 PANNING, /* panning the frame */
551 PANNING_LOCKED_X, /* touch-start followed by move (i.e. panning with axis lock) X axis */
552 PANNING_LOCKED_Y, /* as above for Y axis */
554 CROSS_SLIDING_X, /* Panning disabled while user does a horizontal gesture
555 on a vertically-scrollable view. This used for the
556 Windows Metro "cross-slide" gesture. */
557 CROSS_SLIDING_Y, /* as above for Y axis */
559 PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */
560 ANIMATING_ZOOM, /* animated zoom to a new rect */
561 WAITING_CONTENT_RESPONSE, /* a state halfway between NOTHING and TOUCHING - the user has
562 put a finger down, but we don't yet know if a touch listener has
563 prevented the default actions yet and the allowed touch behavior
564 was not set yet. we still need to abort animations. */
565 };
567 // State related to a single touch block. Does not persist across touch blocks.
568 struct TouchBlockState {
570 TouchBlockState()
571 : mAllowedTouchBehaviorSet(false),
572 mPreventDefault(false),
573 mPreventDefaultSet(false),
574 mSingleTapOccurred(false)
575 {}
577 // Values of allowed touch behavior for touch points of this touch block.
578 // Since there are maybe a few current active touch points per time (multitouch case)
579 // and each touch point should have its own value of allowed touch behavior- we're
580 // keeping an array of allowed touch behavior values, not the single value.
581 nsTArray<TouchBehaviorFlags> mAllowedTouchBehaviors;
583 // Specifies whether mAllowedTouchBehaviors is set for this touch events block.
584 bool mAllowedTouchBehaviorSet;
586 // Flag used to specify that content prevented the default behavior of this
587 // touch events block.
588 bool mPreventDefault;
590 // Specifies whether mPreventDefault property is set for this touch events block.
591 bool mPreventDefaultSet;
593 // Specifies whether a single tap event was generated during this touch block.
594 bool mSingleTapOccurred;
595 };
597 /*
598 * Returns whether current touch behavior values allow pinch-zooming.
599 */
600 bool TouchActionAllowPinchZoom();
602 /*
603 * Returns whether current touch behavior values allow double-tap-zooming.
604 */
605 bool TouchActionAllowDoubleTapZoom();
607 /*
608 * Returns allowed touch behavior from the mAllowedTouchBehavior array.
609 * In case apzc didn't receive touch behavior values within the timeout
610 * it returns default value.
611 */
612 TouchBehaviorFlags GetTouchBehavior(uint32_t touchIndex);
614 /**
615 * To move from the WAITING_CONTENT_RESPONSE state to TOUCHING one we need two
616 * conditions set: get content listeners response (whether they called preventDefault)
617 * and get allowed touch behaviors.
618 * This method checks both conditions and changes (or not changes) state
619 * appropriately.
620 */
621 void CheckContentResponse();
623 /**
624 * Helper to set the current state. Holds the monitor before actually setting
625 * it and fires content controller events based on state changes. Always set
626 * the state using this call, do not set it directly.
627 */
628 void SetState(PanZoomState aState);
630 /**
631 * Convert ScreenPoint relative to this APZC to CSSPoint relative
632 * to the parent document. This excludes the transient compositor transform.
633 * NOTE: This must be converted to CSSPoint relative to the child
634 * document before sending over IPC.
635 */
636 bool ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut);
638 /**
639 * Internal helpers for checking general state of this apzc.
640 */
641 bool IsTransformingState(PanZoomState aState);
642 bool IsPanningState(PanZoomState mState);
644 enum AxisLockMode {
645 FREE, /* No locking at all */
646 STANDARD, /* Default axis locking mode that remains locked until pan ends*/
647 STICKY, /* Allow lock to be broken, with hysteresis */
648 };
650 static AxisLockMode GetAxisLockMode();
652 // Convert a point from local screen coordinates to parent layer coordinates.
653 // This is a common operation as inputs from the tree manager are in screen
654 // coordinates but the composition bounds is in parent layer coordinates.
655 ParentLayerPoint ToParentLayerCoords(const ScreenPoint& aPoint);
657 // Update mFrameMetrics.mTransformScale. This should be called whenever
658 // our CSS transform or the non-transient part of our async transform
659 // changes, as it corresponds to the scale portion of those transforms.
660 void UpdateTransformScale();
662 // Helper function for OnSingleTapUp() and OnSingleTapConfirmed().
663 nsEventStatus GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers);
665 // Common processing at the end of a touch block.
666 void OnTouchEndOrCancel();
668 uint64_t mLayersId;
669 nsRefPtr<CompositorParent> mCompositorParent;
670 PCompositorParent* mCrossProcessCompositorParent;
671 TaskThrottler mPaintThrottler;
673 /* Access to the following two fields is protected by the mRefPtrMonitor,
674 since they are accessed on the UI thread but can be cleared on the
675 compositor thread. */
676 nsRefPtr<GeckoContentController> mGeckoContentController;
677 nsRefPtr<GestureEventListener> mGestureEventListener;
678 Monitor mRefPtrMonitor;
680 /* Utility functions that return a addrefed pointer to the corresponding fields. */
681 already_AddRefed<GeckoContentController> GetGeckoContentController();
682 already_AddRefed<GestureEventListener> GetGestureEventListener();
684 protected:
685 // Both |mFrameMetrics| and |mLastContentPaintMetrics| are protected by the
686 // monitor. Do not read from or modify either of them without locking.
687 FrameMetrics mFrameMetrics;
689 // Protects |mFrameMetrics|, |mLastContentPaintMetrics|, and |mState|.
690 // Before manipulating |mFrameMetrics| or |mLastContentPaintMetrics|, the
691 // monitor should be held. When setting |mState|, either the SetState()
692 // function can be used, or the monitor can be held and then |mState| updated.
693 // IMPORTANT: See the note about lock ordering at the top of APZCTreeManager.h.
694 // This is mutable to allow entering it from 'const' methods; doing otherwise
695 // would significantly limit what methods could be 'const'.
696 mutable ReentrantMonitor mMonitor;
698 // Specifies whether we should use touch-action css property. Initialized from
699 // the preferences. This property (in comparison with the global one) simplifies
700 // testing apzc with (and without) touch-action property enabled concurrently
701 // (e.g. with the gtest framework).
702 bool mTouchActionPropertyEnabled;
704 private:
705 // Metrics of the container layer corresponding to this APZC. This is
706 // stored here so that it is accessible from the UI/controller thread.
707 // These are the metrics at last content paint, the most recent
708 // values we were notified of in NotifyLayersUpdate(). Since it represents
709 // the Gecko state, it should be used as a basis for untransformation when
710 // sending messages back to Gecko.
711 FrameMetrics mLastContentPaintMetrics;
712 // The last metrics that we requested a paint for. These are used to make sure
713 // that we're not requesting a paint of the same thing that's already drawn.
714 // If we don't do this check, we don't get a ShadowLayersUpdated back.
715 FrameMetrics mLastPaintRequestMetrics;
716 // The last metrics that we actually sent to Gecko. This allows us to transform
717 // inputs into a coordinate space that Gecko knows about. This assumes the pipe
718 // through which input events and repaint requests are sent to Gecko operates
719 // in a FIFO manner.
720 FrameMetrics mLastDispatchedPaintMetrics;
722 nsTArray<MultiTouchInput> mTouchQueue;
724 CancelableTask* mContentResponseTimeoutTask;
726 AxisX mX;
727 AxisY mY;
729 // This flag is set to true when we are in a axis-locked pan as a result of
730 // the touch-action CSS property.
731 bool mPanDirRestricted;
733 // Most up-to-date constraints on zooming. These should always be reasonable
734 // values; for example, allowing a min zoom of 0.0 can cause very bad things
735 // to happen.
736 ZoomConstraints mZoomConstraints;
738 // The last time the compositor has sampled the content transform for this
739 // frame.
740 TimeStamp mLastSampleTime;
741 // The last time a touch event came through on the UI thread.
742 uint32_t mLastEventTime;
744 // Stores the previous focus point if there is a pinch gesture happening. Used
745 // to allow panning by moving multiple fingers (thus moving the focus point).
746 ParentLayerPoint mLastZoomFocus;
748 // Stores the state of panning and zooming this frame. This is protected by
749 // |mMonitor|; that is, it should be held whenever this is updated.
750 PanZoomState mState;
752 // The last time and offset we fire the mozbrowserasyncscroll event when
753 // compositor has sampled the content transform for this frame.
754 TimeStamp mLastAsyncScrollTime;
755 CSSPoint mLastAsyncScrollOffset;
757 // The current offset drawn on the screen, it may not be sent since we have
758 // throttling policy for mozbrowserasyncscroll event.
759 CSSPoint mCurrentAsyncScrollOffset;
761 // The delay task triggered by the throttling mozbrowserasyncscroll event
762 // ensures the last mozbrowserasyncscroll event is always been fired.
763 CancelableTask* mAsyncScrollTimeoutTask;
765 // Flag used to determine whether or not we should try to enter the
766 // WAITING_LISTENERS state. This is used in the case that we are processing a
767 // queued up event block. If set, this means that we are handling this queue
768 // and we don't want to queue the events back up again.
769 bool mHandlingTouchQueue;
771 // Stores information about the current touch block.
772 TouchBlockState mTouchBlockState;
774 // Extra offset to add in SampleContentTransformForFrame for testing
775 CSSPoint mTestAsyncScrollOffset;
777 RefPtr<AsyncPanZoomAnimation> mAnimation;
779 friend class Axis;
780 friend class FlingAnimation;
783 /* ===================================================================
784 * The functions and members in this section are used to build a tree
785 * structure out of APZC instances. This tree can only be walked or
786 * manipulated while holding the lock in the associated APZCTreeManager
787 * instance.
788 */
789 public:
790 void SetLastChild(AsyncPanZoomController* child) {
791 mLastChild = child;
792 if (child) {
793 child->mParent = this;
794 }
795 }
797 void SetPrevSibling(AsyncPanZoomController* sibling) {
798 mPrevSibling = sibling;
799 if (sibling) {
800 sibling->mParent = mParent;
801 }
802 }
804 AsyncPanZoomController* GetLastChild() const { return mLastChild; }
805 AsyncPanZoomController* GetPrevSibling() const { return mPrevSibling; }
806 AsyncPanZoomController* GetParent() const { return mParent; }
808 /* Returns true if there is no APZC higher in the tree with the same
809 * layers id.
810 */
811 bool IsRootForLayersId() const {
812 return !mParent || (mParent->mLayersId != mLayersId);
813 }
815 bool IsRootForLayersId(const uint64_t& aLayersId) const {
816 return (mLayersId == aLayersId) && IsRootForLayersId();
817 }
819 private:
820 // This is a raw pointer to avoid introducing a reference cycle between
821 // AsyncPanZoomController and APZCTreeManager. Since these objects don't
822 // live on the main thread, we can't use the cycle collector with them.
823 // The APZCTreeManager owns the lifetime of the APZCs, so nulling this
824 // pointer out in Destroy() will prevent accessing deleted memory.
825 Atomic<APZCTreeManager*> mTreeManager;
827 nsRefPtr<AsyncPanZoomController> mLastChild;
828 nsRefPtr<AsyncPanZoomController> mPrevSibling;
829 nsRefPtr<AsyncPanZoomController> mParent;
832 /* ===================================================================
833 * The functions and members in this section are used in building the
834 * scroll handoff chain, so that we can have seamless scrolling continue
835 * across APZC instances.
836 */
837 public:
838 void SetScrollHandoffParentId(FrameMetrics::ViewID aScrollParentId) {
839 mScrollParentId = aScrollParentId;
840 }
842 FrameMetrics::ViewID GetScrollHandoffParentId() const {
843 return mScrollParentId;
844 }
846 /**
847 * Attempt to scroll in response to a touch-move from |aStartPoint| to
848 * |aEndPoint|, which are in our (transformed) screen coordinates.
849 * Due to overscroll handling, there may not actually have been a touch-move
850 * at these points, but this function will scroll as if there had been.
851 * If this attempt causes overscroll (i.e. the layer cannot be scrolled
852 * by the entire amount requested), the overscroll is passed back to the
853 * tree manager via APZCTreeManager::DispatchScroll().
854 * |aOverscrollHandoffChainIndex| is used by the tree manager to keep track
855 * of which APZC to hand off the overscroll to; this function increments it
856 * and passes it on to APZCTreeManager::DispatchScroll() in the event of
857 * overscroll.
858 */
859 void AttemptScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint,
860 uint32_t aOverscrollHandoffChainIndex = 0);
862 void FlushRepaintForOverscrollHandoff();
864 private:
865 FrameMetrics::ViewID mScrollParentId;
867 /**
868 * A helper function for calling APZCTreeManager::DispatchScroll().
869 * Guards against the case where the APZC is being concurrently destroyed
870 * (and thus mTreeManager is being nulled out).
871 */
872 void CallDispatchScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint,
873 uint32_t aOverscrollHandoffChainIndex);
876 /* ===================================================================
877 * The functions and members in this section are used to maintain the
878 * area that this APZC instance is responsible for. This is used when
879 * hit-testing to see which APZC instance should handle touch events.
880 */
881 public:
882 void SetLayerHitTestData(const ParentLayerRect& aRect, const gfx3DMatrix& aTransformToLayer,
883 const gfx3DMatrix& aTransformForLayer) {
884 mVisibleRect = aRect;
885 mAncestorTransform = aTransformToLayer;
886 mCSSTransform = aTransformForLayer;
887 UpdateTransformScale();
888 }
890 gfx3DMatrix GetAncestorTransform() const {
891 return mAncestorTransform;
892 }
894 gfx3DMatrix GetCSSTransform() const {
895 return mCSSTransform;
896 }
898 bool VisibleRegionContains(const ParentLayerPoint& aPoint) const {
899 return mVisibleRect.Contains(aPoint);
900 }
902 private:
903 /* This is the visible region of the layer that this APZC corresponds to, in
904 * that layer's screen pixels (the same coordinate system in which this APZC
905 * receives events in ReceiveInputEvent()). */
906 ParentLayerRect mVisibleRect;
907 /* This is the cumulative CSS transform for all the layers between the parent
908 * APZC and this one (not inclusive) */
909 gfx3DMatrix mAncestorTransform;
910 /* This is the CSS transform for this APZC's layer. */
911 gfx3DMatrix mCSSTransform;
914 /* ===================================================================
915 * The functions and members in this section are used for sharing the
916 * FrameMetrics across processes for the progressive tiling code.
917 */
918 private:
919 /* Unique id assigned to each APZC. Used with ViewID to uniquely identify
920 * shared FrameMeterics used in progressive tile painting. */
921 const uint32_t mAPZCId;
923 ipc::SharedMemoryBasic* mSharedFrameMetricsBuffer;
924 CrossProcessMutex* mSharedLock;
925 /**
926 * Called when ever mFrameMetrics is updated so that if it is being
927 * shared with the content process the shared FrameMetrics may be updated.
928 */
929 void UpdateSharedCompositorFrameMetrics();
930 /**
931 * Create a shared memory buffer for containing the FrameMetrics and
932 * a CrossProcessMutex that may be shared with the content process
933 * for use in progressive tiled update calculations.
934 */
935 void ShareCompositorFrameMetrics();
936 };
938 class AsyncPanZoomAnimation {
939 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomAnimation)
941 public:
942 AsyncPanZoomAnimation(const TimeDuration& aRepaintInterval =
943 TimeDuration::Forever())
944 : mRepaintInterval(aRepaintInterval)
945 { }
947 virtual bool Sample(FrameMetrics& aFrameMetrics,
948 const TimeDuration& aDelta) = 0;
950 /**
951 * Get the deferred tasks in |mDeferredTasks|. See |mDeferredTasks|
952 * for more information.
953 * Clears |mDeferredTasks|.
954 */
955 Vector<Task*> TakeDeferredTasks() {
956 Vector<Task*> result;
957 mDeferredTasks.swap(result);
958 return result;
959 }
961 /**
962 * Specifies how frequently (at most) we want to do repaints during the
963 * animation sequence. TimeDuration::Forever() will cause it to only repaint
964 * at the end of the animation.
965 */
966 TimeDuration mRepaintInterval;
968 protected:
969 // Protected destructor, to discourage deletion outside of Release():
970 virtual ~AsyncPanZoomAnimation()
971 { }
973 /**
974 * Tasks scheduled for execution after the APZC's mMonitor is released.
975 * Derived classes can add tasks here in Sample(), and the APZC can call
976 * ExecuteDeferredTasks() to execute them.
977 */
978 Vector<Task*> mDeferredTasks;
979 };
981 }
982 }
984 #endif // mozilla_layers_PanZoomController_h