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 "FrameMetrics.h" 10 #include "InputData.h" 11 #include "mozilla/EventForwards.h" 12 #include "mozilla/Function.h" 13 #include "mozilla/layers/APZUtils.h" 14 #include "nsIDOMWindowUtils.h" 15 16 class nsIContent; 17 class nsIDocument; 18 class nsIPresShell; 19 class nsIScrollableFrame; 20 class nsIWidget; 21 template<class T> struct already_AddRefed; 22 template<class T> class nsCOMPtr; 23 24 namespace mozilla { 25 namespace layers { 26 27 typedef function<void(uint64_t, const nsTArray<TouchBehaviorFlags>&)> 28 SetAllowedTouchBehaviorCallback; 29 30 /* This class contains some helper methods that facilitate implementing the 31 GeckoContentController callback interface required by the AsyncPanZoomController. 32 Since different platforms need to implement this interface in similar-but- 33 not-quite-the-same ways, this utility class provides some helpful methods 34 to hold code that can be shared across the different platform implementations. 35 */ 36 class APZCCallbackHelper 37 { 38 typedef mozilla::layers::FrameMetrics FrameMetrics; 39 typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid; 40 41 public: 42 /* Applies the scroll and zoom parameters from the given FrameMetrics object 43 to the root frame for the given metrics' scrollId. If tiled thebes layers 44 are enabled, this will align the displayport to tile boundaries. Setting 45 the scroll position can cause some small adjustments to be made to the 46 actual scroll position. aMetrics' display port and scroll position will 47 be updated with any modifications made. */ 48 static void UpdateRootFrame(FrameMetrics& aMetrics); 49 50 /* Applies the scroll parameters from the given FrameMetrics object to the 51 subframe corresponding to given metrics' scrollId. If tiled thebes 52 layers are enabled, this will align the displayport to tile boundaries. 53 Setting the scroll position can cause some small adjustments to be made 54 to the actual scroll position. aMetrics' display port and scroll position 55 will be updated with any modifications made. */ 56 static void UpdateSubFrame(FrameMetrics& aMetrics); 57 58 /* Get the presShellId and view ID for the given content element. 59 * If the view ID does not exist, one is created. 60 * The pres shell ID should generally already exist; if it doesn't for some 61 * reason, false is returned. */ 62 static bool GetOrCreateScrollIdentifiers(nsIContent* aContent, 63 uint32_t* aPresShellIdOut, 64 FrameMetrics::ViewID* aViewIdOut); 65 66 /* Initialize a zero-margin displayport on the root document element of the 67 given presShell. */ 68 static void InitializeRootDisplayport(nsIPresShell* aPresShell); 69 70 /* Get the pres context associated with the document enclosing |aContent|. */ 71 static nsPresContext* GetPresContextForContent(nsIContent* aContent); 72 73 /* Get the pres shell associated with the root content document enclosing |aContent|. */ 74 static nsIPresShell* GetRootContentDocumentPresShellForContent(nsIContent* aContent); 75 76 /* Apply an "input transform" to the given |aInput| and return the transformed value. 77 The input transform applied is the one for the content element corresponding to 78 |aGuid|; this is populated in a previous call to UpdateCallbackTransform. See that 79 method's documentations for details. 80 This method additionally adjusts |aInput| by inversely scaling by the provided 81 pres shell resolution, to cancel out a compositor-side transform (added in 82 bug 1076241) that APZ doesn't unapply. */ 83 static CSSPoint ApplyCallbackTransform(const CSSPoint& aInput, 84 const ScrollableLayerGuid& aGuid); 85 86 /* Same as above, but operates on LayoutDeviceIntPoint. 87 Requires an additonal |aScale| parameter to convert between CSS and 88 LayoutDevice space. */ 89 static mozilla::LayoutDeviceIntPoint 90 ApplyCallbackTransform(const LayoutDeviceIntPoint& aPoint, 91 const ScrollableLayerGuid& aGuid, 92 const CSSToLayoutDeviceScale& aScale); 93 94 /* Convenience function for applying a callback transform to all refpoints 95 * in the input event. */ 96 static void ApplyCallbackTransform(WidgetEvent& aEvent, 97 const ScrollableLayerGuid& aGuid, 98 const CSSToLayoutDeviceScale& aScale); 99 100 /* Dispatch a widget event via the widget stored in the event, if any. 101 * In a child process, allows the TabParent event-capture mechanism to 102 * intercept the event. */ 103 static nsEventStatus DispatchWidgetEvent(WidgetGUIEvent& aEvent); 104 105 /* Synthesize a mouse event with the given parameters, and dispatch it 106 * via the given widget. */ 107 static nsEventStatus DispatchSynthesizedMouseEvent(EventMessage aMsg, 108 uint64_t aTime, 109 const LayoutDevicePoint& aRefPoint, 110 Modifiers aModifiers, 111 int32_t aClickCount, 112 nsIWidget* aWidget); 113 114 /* Dispatch a mouse event with the given parameters. 115 * Return whether or not any listeners have called preventDefault on the event. */ 116 static bool DispatchMouseEvent(const nsCOMPtr<nsIPresShell>& aPresShell, 117 const nsString& aType, 118 const CSSPoint& aPoint, 119 int32_t aButton, 120 int32_t aClickCount, 121 int32_t aModifiers, 122 bool aIgnoreRootScrollFrame, 123 unsigned short aInputSourceArg); 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, 129 int32_t aClickCount, 130 nsIWidget* aWidget); 131 132 /* Perform hit-testing on the touch points of |aEvent| to determine 133 * which scrollable frames they target. If any of these frames don't have 134 * a displayport, set one. 135 * 136 * If any displayports need to be set, the actual notification to APZ is 137 * sent to the compositor, which will then post a message back to APZ's 138 * controller thread. Otherwise, the provided widget's SetConfirmedTargetAPZC 139 * method is invoked immediately. 140 */ 141 static void SendSetTargetAPZCNotification(nsIWidget* aWidget, 142 nsIDocument* aDocument, 143 const WidgetGUIEvent& aEvent, 144 const ScrollableLayerGuid& aGuid, 145 uint64_t aInputBlockId); 146 147 /* Figure out the allowed touch behaviors of each touch point in |aEvent| 148 * and send that information to the provided callback. */ 149 static void SendSetAllowedTouchBehaviorNotification(nsIWidget* aWidget, 150 nsIDocument* aDocument, 151 const WidgetTouchEvent& aEvent, 152 uint64_t aInputBlockId, 153 const SetAllowedTouchBehaviorCallback& aCallback); 154 155 /* Notify content of a mouse scroll testing event. */ 156 static void NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId, const nsString& aEvent); 157 158 /* Notify content that the repaint flush is complete. */ 159 static void NotifyFlushComplete(nsIPresShell* aShell); 160 161 /* Temporarily ignore the Displayport for better paint performance. If at 162 * all possible, pass in a presShell if you have one at the call site, we 163 * use it to trigger a repaint once suppression is disabled. Without that 164 * the displayport may get left at the suppressed size for an extended 165 * period of time and result in unnecessary checkerboarding (see bug 166 * 1255054). */ 167 static void SuppressDisplayport(const bool& aEnabled, 168 const nsCOMPtr<nsIPresShell>& aShell); 169 170 /* Whether or not displayport suppression should be turned on. Note that 171 * this only affects the return value of |IsDisplayportSuppressed()|, and 172 * doesn't change the value of the internal counter. As with 173 * SuppressDisplayport, this function should be passed a presShell to trigger 174 * a repaint if suppression is being turned off. 175 */ 176 static void RespectDisplayPortSuppression(bool aEnabled, 177 const nsCOMPtr<nsIPresShell>& aShell); 178 179 /* Whether or not the displayport is currently suppressed. */ 180 static bool IsDisplayportSuppressed(); 181 182 static void 183 AdjustDisplayPortForScrollDelta(mozilla::layers::FrameMetrics& aFrameMetrics, 184 const CSSPoint& aActualScrollOffset); 185 186 /* 187 * Check if the scrollable frame is currently in the middle of an async 188 * or smooth scroll. We want to discard certain scroll input if this is 189 * true to prevent clobbering higher priority origins. 190 */ 191 static bool 192 IsScrollInProgress(nsIScrollableFrame* aFrame); 193 194 /* Notify content of the progress of a pinch gesture that APZ won't do 195 * zooming for (because the apz.allow_zooming pref is false). This function 196 * will dispatch appropriate WidgetSimpleGestureEvent events to gecko. 197 */ 198 static void NotifyPinchGesture(PinchGestureInput::PinchGestureType aType, 199 LayoutDeviceCoord aSpanChange, 200 Modifiers aModifiers, 201 nsIWidget* aWidget); 202 private: 203 static uint64_t sLastTargetAPZCNotificationInputBlock; 204 }; 205 206 } // namespace layers 207 } // namespace mozilla 208 209 #endif /* mozilla_layers_APZCCallbackHelper_h */ 210