1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef mozilla_layers_APZCCallbackHelper_h
7 #define mozilla_layers_APZCCallbackHelper_h
8 
9 #include "InputData.h"
10 #include "LayersTypes.h"
11 #include "Units.h"
12 #include "mozilla/EventForwards.h"
13 #include "mozilla/layers/MatrixMessage.h"
14 #include "nsRefreshObservers.h"
15 
16 #include <functional>
17 
18 class nsIContent;
19 class nsIScrollableFrame;
20 class nsIWidget;
21 class nsPresContext;
22 template <class T>
23 struct already_AddRefed;
24 template <class T>
25 class nsCOMPtr;
26 
27 namespace mozilla {
28 
29 class PresShell;
30 enum class PreventDefaultResult : uint8_t;
31 
32 namespace layers {
33 
34 struct RepaintRequest;
35 
36 typedef std::function<void(uint64_t, const nsTArray<TouchBehaviorFlags>&)>
37     SetAllowedTouchBehaviorCallback;
38 
39 /* Refer to documentation on SendSetTargetAPZCNotification for this class */
40 class DisplayportSetListener : public ManagedPostRefreshObserver {
41  public:
42   DisplayportSetListener(nsIWidget* aWidget, nsPresContext*,
43                          const uint64_t& aInputBlockId,
44                          nsTArray<ScrollableLayerGuid>&& aTargets);
45   virtual ~DisplayportSetListener();
46   void Register();
47 
48  private:
49   RefPtr<nsIWidget> mWidget;
50   uint64_t mInputBlockId;
51   nsTArray<ScrollableLayerGuid> mTargets;
52 
53   void OnPostRefresh();
54 };
55 
56 /* This class contains some helper methods that facilitate implementing the
57    GeckoContentController callback interface required by the
58    AsyncPanZoomController. Since different platforms need to implement this
59    interface in similar-but- not-quite-the-same ways, this utility class
60    provides some helpful methods to hold code that can be shared across the
61    different platform implementations.
62  */
63 class APZCCallbackHelper {
64   typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;
65 
66  public:
67   static void NotifyLayerTransforms(const nsTArray<MatrixMessage>& aTransforms);
68 
69   /* Applies the scroll and zoom parameters from the given RepaintRequest object
70      to the root frame for the given metrics' scrollId. If tiled thebes layers
71      are enabled, this will align the displayport to tile boundaries. Setting
72      the scroll position can cause some small adjustments to be made to the
73      actual scroll position. */
74   static void UpdateRootFrame(const RepaintRequest& aRequest);
75 
76   /* Applies the scroll parameters from the given RepaintRequest object to the
77      subframe corresponding to given metrics' scrollId. If tiled thebes
78      layers are enabled, this will align the displayport to tile boundaries.
79      Setting the scroll position can cause some small adjustments to be made
80      to the actual scroll position. */
81   static void UpdateSubFrame(const RepaintRequest& aRequest);
82 
83   /* Get the presShellId and view ID for the given content element.
84    * If the view ID does not exist, one is created.
85    * The pres shell ID should generally already exist; if it doesn't for some
86    * reason, false is returned. */
87   static bool GetOrCreateScrollIdentifiers(
88       nsIContent* aContent, uint32_t* aPresShellIdOut,
89       ScrollableLayerGuid::ViewID* aViewIdOut);
90 
91   /* Initialize a zero-margin displayport on the root document element of the
92      given presShell. */
93   static void InitializeRootDisplayport(PresShell* aPresShell);
94 
95   /* Get the pres context associated with the document enclosing |aContent|. */
96   static nsPresContext* GetPresContextForContent(nsIContent* aContent);
97 
98   /* Get the pres shell associated with the root content document enclosing
99    * |aContent|. */
100   static PresShell* GetRootContentDocumentPresShellForContent(
101       nsIContent* aContent);
102 
103   /* Dispatch a widget event via the widget stored in the event, if any.
104    * In a child process, allows the BrowserParent event-capture mechanism to
105    * intercept the event. */
106   static nsEventStatus DispatchWidgetEvent(WidgetGUIEvent& aEvent);
107 
108   /* Synthesize a mouse event with the given parameters, and dispatch it
109    * via the given widget. */
110   static nsEventStatus DispatchSynthesizedMouseEvent(
111       EventMessage aMsg, uint64_t aTime, const LayoutDevicePoint& aRefPoint,
112       Modifiers aModifiers, int32_t aClickCount, nsIWidget* aWidget);
113 
114   /* Dispatch a mouse event with the given parameters.
115    * Return whether or not any listeners have called preventDefault on the
116    * event.
117    * This is a lightweight wrapper around nsContentUtils::SendMouseEvent()
118    * and as such expects |aPoint| to be in layout coordinates. */
119   MOZ_CAN_RUN_SCRIPT
120   static PreventDefaultResult DispatchMouseEvent(
121       PresShell* aPresShell, const nsString& aType, const CSSPoint& aPoint,
122       int32_t aButton, int32_t aClickCount, int32_t aModifiers,
123       unsigned short aInputSourceArg, uint32_t aPointerId);
124 
125   /* Fire a single-tap event at the given point. The event is dispatched
126    * via the given widget. */
127   static void FireSingleTapEvent(const LayoutDevicePoint& aPoint,
128                                  Modifiers aModifiers, int32_t aClickCount,
129                                  nsIWidget* aWidget);
130 
131   /* Perform hit-testing on the touch points of |aEvent| to determine
132    * which scrollable frames they target. If any of these frames don't have
133    * a displayport, set one.
134    *
135    * If any displayports need to be set, this function returns a heap-allocated
136    * object. The caller is responsible for calling Register() on that object.
137    *
138    * The object registers itself as a post-refresh observer on the presShell
139    * and ensures that notifications get sent to APZ correctly after the
140    * refresh.
141    *
142    * Having the caller manage this object is desirable in case they want to
143    * (a) know about the fact that a displayport needs to be set, and
144    * (b) register a post-refresh observer of their own that will run in
145    *     a defined ordering relative to the APZ messages.
146    */
147   static already_AddRefed<DisplayportSetListener> SendSetTargetAPZCNotification(
148       nsIWidget* aWidget, mozilla::dom::Document* aDocument,
149       const WidgetGUIEvent& aEvent, const LayersId& aLayersId,
150       uint64_t aInputBlockId);
151 
152   /* Figure out the allowed touch behaviors of each touch point in |aEvent|
153    * and send that information to the provided callback. Also returns the
154    * allowed touch behaviors. */
155   static nsTArray<TouchBehaviorFlags> SendSetAllowedTouchBehaviorNotification(
156       nsIWidget* aWidget, mozilla::dom::Document* aDocument,
157       const WidgetTouchEvent& aEvent, uint64_t aInputBlockId,
158       const SetAllowedTouchBehaviorCallback& aCallback);
159 
160   /* Notify content of a mouse scroll testing event. */
161   static void NotifyMozMouseScrollEvent(
162       const ScrollableLayerGuid::ViewID& aScrollId, const nsString& aEvent);
163 
164   /* Notify content that the repaint flush is complete. */
165   static void NotifyFlushComplete(PresShell* aPresShell);
166 
167   static void NotifyAsyncScrollbarDragInitiated(
168       uint64_t aDragBlockId, const ScrollableLayerGuid::ViewID& aScrollId,
169       ScrollDirection aDirection);
170   static void NotifyAsyncScrollbarDragRejected(
171       const ScrollableLayerGuid::ViewID& aScrollId);
172   static void NotifyAsyncAutoscrollRejected(
173       const ScrollableLayerGuid::ViewID& aScrollId);
174 
175   static void CancelAutoscroll(const ScrollableLayerGuid::ViewID& aScrollId);
176 
177   /*
178    * Check if the scrollable frame is currently in the middle of a main thread
179    * async or smooth scroll, or has already requested some other apz scroll that
180    * hasn't been acknowledged by apz.
181    *
182    * We want to discard apz updates to the main-thread scroll offset if this is
183    * true to prevent clobbering higher priority origins.
184    */
185   static bool IsScrollInProgress(nsIScrollableFrame* aFrame);
186 
187   /* Notify content of the progress of a pinch gesture that APZ won't do
188    * zooming for (because the apz.allow_zooming pref is false). This function
189    * will dispatch appropriate WidgetSimpleGestureEvent events to gecko.
190    */
191   static void NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
192                                  const LayoutDevicePoint& aFocusPoint,
193                                  LayoutDeviceCoord aSpanChange,
194                                  Modifiers aModifiers,
195                                  const nsCOMPtr<nsIWidget>& aWidget);
196 
197  private:
198   static uint64_t sLastTargetAPZCNotificationInputBlock;
199 };
200 
201 }  // namespace layers
202 }  // namespace mozilla
203 
204 #endif /* mozilla_layers_APZCCallbackHelper_h */
205