APZUtils.h (9356B)
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_APZUtils_h 8 #define mozilla_layers_APZUtils_h 9 10 // This file is for APZ-related utilities that are used by code in gfx/layers 11 // only. For APZ-related utilities used by the Rest of the World (widget/, 12 // layout/, dom/, IPDL protocols, etc.), use APZPublicUtils.h. 13 // Do not include this header from source files outside of gfx/layers. 14 15 #include <stdint.h> // for uint32_t 16 #include "gfxTypes.h" 17 #include "FrameMetrics.h" 18 #include "LayersTypes.h" 19 #include "UnitTransforms.h" 20 #include "mozilla/gfx/CompositorHitTestInfo.h" 21 #include "mozilla/gfx/Point.h" 22 #include "mozilla/layers/APZPublicUtils.h" // for DispatchToContent 23 #include "mozilla/EnumSet.h" 24 #include "mozilla/FloatingPoint.h" 25 26 namespace mozilla { 27 28 namespace layers { 29 30 enum CancelAnimationFlags : uint32_t { 31 Default = 0, /* Cancel all animations */ 32 ExcludeOverscroll = (1 << 0), /* Don't clear overscroll */ 33 ScrollSnap = (1 << 1), /* Snap to snap points */ 34 TriggeredExternally = (1 << 2), /* Cancellation was not triggered by APZ in 35 response to an input event */ 36 ExcludeAutoscroll = (1 << 3) /* Don't cancel overscroll animations */ 37 }; 38 39 inline CancelAnimationFlags operator|(CancelAnimationFlags a, 40 CancelAnimationFlags b) { 41 return static_cast<CancelAnimationFlags>(static_cast<int>(a) | 42 static_cast<int>(b)); 43 } 44 45 // clang-format off 46 enum class ScrollSource { 47 // Touch-screen. 48 Touchscreen, 49 50 // Touchpad with gesture support. 51 Touchpad, 52 53 // Mouse wheel. 54 Wheel, 55 56 // Keyboard 57 Keyboard, 58 }; 59 // clang-format on 60 61 inline bool ScrollSourceRespectsDisregardedDirections(ScrollSource aSource) { 62 return aSource == ScrollSource::Wheel || aSource == ScrollSource::Touchpad; 63 } 64 65 inline bool ScrollSourceAllowsOverscroll(ScrollSource aSource) { 66 return aSource == ScrollSource::Touchpad || 67 aSource == ScrollSource::Touchscreen; 68 } 69 70 // Epsilon to be used when comparing 'float' coordinate values 71 // with FuzzyEqualsAdditive. The rationale is that 'float' has 7 decimal 72 // digits of precision, and coordinate values should be no larger than in the 73 // ten thousands. Note also that the smallest legitimate difference in page 74 // coordinates is 1 app unit, which is 1/60 of a (CSS pixel), so this epsilon 75 // isn't too large. 76 const CSSCoord COORDINATE_EPSILON = 0.01f; 77 78 inline bool IsZero(const CSSPoint& aPoint) { 79 return FuzzyEqualsAdditive(aPoint.x, CSSCoord(), COORDINATE_EPSILON) && 80 FuzzyEqualsAdditive(aPoint.y, CSSCoord(), COORDINATE_EPSILON); 81 } 82 83 // Represents async transforms consisting of a scale and a translation. 84 struct AsyncTransform { 85 explicit AsyncTransform( 86 LayerToParentLayerScale aScale = LayerToParentLayerScale(), 87 ParentLayerPoint aTranslation = ParentLayerPoint()) 88 : mScale(aScale), mTranslation(aTranslation) {} 89 90 operator AsyncTransformComponentMatrix() const { 91 return AsyncTransformComponentMatrix::Scaling(mScale.scale, mScale.scale, 1) 92 .PostTranslate(mTranslation.x, mTranslation.y, 0); 93 } 94 95 bool operator==(const AsyncTransform& rhs) const { 96 return mTranslation == rhs.mTranslation && mScale == rhs.mScale; 97 } 98 99 bool operator!=(const AsyncTransform& rhs) const { return !(*this == rhs); } 100 101 LayerToParentLayerScale mScale; 102 ParentLayerPoint mTranslation; 103 }; 104 105 // Deem an AsyncTransformComponentMatrix (obtained by multiplying together 106 // one or more AsyncTransformComponentMatrix objects) as constituting a 107 // complete async transform. 108 inline AsyncTransformMatrix CompleteAsyncTransform( 109 const AsyncTransformComponentMatrix& aMatrix) { 110 return ViewAs<AsyncTransformMatrix>( 111 aMatrix, PixelCastJustification::MultipleAsyncTransforms); 112 } 113 114 struct TargetConfirmationFlags final { 115 explicit TargetConfirmationFlags(bool aTargetConfirmed) 116 : mTargetConfirmed(aTargetConfirmed), 117 mRequiresTargetConfirmation(false), 118 mHitScrollbar(false), 119 mHitScrollThumb(false), 120 mDispatchToContent(false) {} 121 122 explicit TargetConfirmationFlags( 123 const gfx::CompositorHitTestInfo& aHitTestInfo) 124 : mTargetConfirmed( 125 (aHitTestInfo != gfx::CompositorHitTestInvisibleToHit) && 126 (aHitTestInfo & gfx::CompositorHitTestDispatchToContent).isEmpty()), 127 mRequiresTargetConfirmation(aHitTestInfo.contains( 128 gfx::CompositorHitTestFlags::eRequiresTargetConfirmation)), 129 mHitScrollbar( 130 aHitTestInfo.contains(gfx::CompositorHitTestFlags::eScrollbar)), 131 mHitScrollThumb(aHitTestInfo.contains( 132 gfx::CompositorHitTestFlags::eScrollbarThumb)), 133 mDispatchToContent( 134 !(aHitTestInfo & gfx::CompositorHitTestDispatchToContent) 135 .isEmpty()) {} 136 137 DispatchToContent NeedDispatchToContent() const { 138 return mDispatchToContent ? DispatchToContent::Yes : DispatchToContent::No; 139 } 140 141 bool mTargetConfirmed : 1; 142 bool mRequiresTargetConfirmation : 1; 143 bool mHitScrollbar : 1; 144 bool mHitScrollThumb : 1; 145 bool mDispatchToContent : 1; 146 }; 147 148 enum class AsyncTransformComponent { eLayout, eVisual }; 149 150 using AsyncTransformComponents = EnumSet<AsyncTransformComponent>; 151 152 constexpr AsyncTransformComponents LayoutAndVisual( 153 AsyncTransformComponent::eLayout, AsyncTransformComponent::eVisual); 154 155 /** 156 * Allows consumers of async transforms to specify for what purpose they are 157 * using the async transform: 158 * 159 * |eForEventHandling| is intended for event handling and other uses that 160 * need the most up-to-date transform, reflecting all 161 * events that have been processed so far, even if the 162 * transform is not yet reflected visually. 163 * |eForCompositing| is intended for the transform that should be reflected 164 * visually. 165 * 166 * For example, if an APZC has metrics with the mForceDisableApz flag set, 167 * then the |eForCompositing| async transform will be empty, while the 168 * |eForEventHandling| async transform will reflect processed input events 169 * regardless of mForceDisableApz. 170 */ 171 enum class AsyncTransformConsumer { 172 eForEventHandling, 173 eForCompositing, 174 }; 175 176 /** 177 * A flag type for use by functions which return information about 178 * handoff, in case they need to differentiate between handoff for 179 * the purpose of scrolling and handoff for the purpose of pull-to-refresh. 180 */ 181 enum class HandoffConsumer { Scrolling, PullToRefresh }; 182 183 namespace apz { 184 185 /** 186 * Is aAngle within the given threshold of the horizontal axis? 187 * @param aAngle an angle in radians in the range [0, pi] 188 * @param aThreshold an angle in radians in the range [0, pi/2] 189 */ 190 bool IsCloseToHorizontal(float aAngle, float aThreshold); 191 192 // As above, but for the vertical axis. 193 bool IsCloseToVertical(float aAngle, float aThreshold); 194 195 // Returns true if a sticky layer with async translation |aTranslation| is 196 // stuck with a bottom margin. The inner/outer ranges are produced by the main 197 // thread at the last paint, and so |aTranslation| only needs to be the 198 // async translation from the last paint. 199 bool IsStuckAtBottom(gfxFloat aTranslation, 200 const LayerRectAbsolute& aInnerRange, 201 const LayerRectAbsolute& aOuterRange); 202 203 // Returns true if a sticky layer with async translation |aTranslation| is 204 // stuck with a top margin. 205 bool IsStuckAtTop(gfxFloat aTranslation, const LayerRectAbsolute& aInnerRange, 206 const LayerRectAbsolute& aOuterRange); 207 208 /** 209 * Takes the visible rect from the compositor metrics, adds a pref-based 210 * margin around it, and checks to see if it is contained inside the painted 211 * rect from the painted metrics. Returns true if it is contained, or false 212 * if not. Returning false means that a (relatively) small amount of async 213 * scrolling/zooming can result in the visible area going outside the painted 214 * area and resulting in visual checkerboarding. 215 * Note that this may return false positives for cases where the scrollframe 216 * in question is nested inside other scrollframes, as the composition bounds 217 * used to determine the visible rect may in fact be clipped by enclosing 218 * scrollframes, but that is not accounted for in this function. 219 */ 220 bool AboutToCheckerboard(const FrameMetrics& aPaintedMetrics, 221 const FrameMetrics& aCompositorMetrics); 222 223 /** 224 * Returns SideBits where the given |aOverscrollAmount| overscrolls. 225 */ 226 SideBits GetOverscrollSideBits(const ParentLayerPoint& aOverscrollAmount); 227 228 // Represents tri-state when a touch-end event received. 229 enum class SingleTapState : uint8_t { 230 NotClick, // The touch-block doesn't trigger a click event 231 WasClick, // The touch-block did trigger a click event 232 NotYetDetermined, // It's not yet determined whether the touch-block trigger 233 // a click event or not since double-tapping might happen 234 }; 235 236 } // namespace apz 237 238 } // namespace layers 239 } // namespace mozilla 240 241 #endif // mozilla_layers_APZUtils_h