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 #include <stdint.h>  // for uint32_t
11 #include <type_traits>
12 #include "gfxTypes.h"
13 #include "FrameMetrics.h"
14 #include "LayersTypes.h"
15 #include "UnitTransforms.h"
16 #include "mozilla/gfx/CompositorHitTestInfo.h"
17 #include "mozilla/gfx/Point.h"
18 #include "mozilla/DefineEnum.h"
19 #include "mozilla/EnumSet.h"
20 #include "mozilla/FloatingPoint.h"
21 
22 namespace mozilla {
23 
24 struct ExternalPixel;
25 
26 template <>
27 struct IsPixel<ExternalPixel> : std::true_type {};
28 
29 typedef gfx::CoordTyped<ExternalPixel> ExternalCoord;
30 typedef gfx::IntCoordTyped<ExternalPixel> ExternalIntCoord;
31 typedef gfx::PointTyped<ExternalPixel> ExternalPoint;
32 typedef gfx::IntPointTyped<ExternalPixel> ExternalIntPoint;
33 typedef gfx::SizeTyped<ExternalPixel> ExternalSize;
34 typedef gfx::IntSizeTyped<ExternalPixel> ExternalIntSize;
35 typedef gfx::RectTyped<ExternalPixel> ExternalRect;
36 typedef gfx::IntRectTyped<ExternalPixel> ExternalIntRect;
37 typedef gfx::MarginTyped<ExternalPixel> ExternalMargin;
38 typedef gfx::IntMarginTyped<ExternalPixel> ExternalIntMargin;
39 typedef gfx::IntRegionTyped<ExternalPixel> ExternalIntRegion;
40 
41 typedef gfx::Matrix4x4Typed<ExternalPixel, ParentLayerPixel>
42     ExternalToParentLayerMatrix4x4;
43 
44 struct ExternalPixel {};
45 
46 namespace layers {
47 
48 class AsyncPanZoomController;
49 
50 enum CancelAnimationFlags : uint32_t {
51   Default = 0x0,             /* Cancel all animations */
52   ExcludeOverscroll = 0x1,   /* Don't clear overscroll */
53   ScrollSnap = 0x2,          /* Snap to snap points */
54   ExcludeWheel = 0x4,        /* Don't stop wheel smooth-scroll animations */
55   TriggeredExternally = 0x8, /* Cancellation was not triggered by APZ in
56                                 response to an input event */
57 };
58 
59 inline CancelAnimationFlags operator|(CancelAnimationFlags a,
60                                       CancelAnimationFlags b) {
61   return static_cast<CancelAnimationFlags>(static_cast<int>(a) |
62                                            static_cast<int>(b));
63 }
64 
65 typedef EnumSet<ScrollDirection> ScrollDirections;
66 
67 // clang-format off
68 enum class ScrollSource {
69   // scrollTo() or something similar.
70   DOM,
71 
72   // Touch-screen or trackpad with gesture support.
73   Touch,
74 
75   // Mouse wheel.
76   Wheel,
77 
78   // Keyboard
79   Keyboard,
80 };
81 
82 MOZ_DEFINE_ENUM_CLASS_WITH_BASE(APZWheelAction, uint8_t, (
83     Scroll,
84     PinchZoom
85 ))
86 // clang-format on
87 
88 // Epsilon to be used when comparing 'float' coordinate values
89 // with FuzzyEqualsAdditive. The rationale is that 'float' has 7 decimal
90 // digits of precision, and coordinate values should be no larger than in the
91 // ten thousands. Note also that the smallest legitimate difference in page
92 // coordinates is 1 app unit, which is 1/60 of a (CSS pixel), so this epsilon
93 // isn't too large.
94 const float COORDINATE_EPSILON = 0.01f;
95 
96 template <typename Units>
97 static bool IsZero(const gfx::PointTyped<Units>& aPoint) {
98   return FuzzyEqualsAdditive(aPoint.x, 0.0f, COORDINATE_EPSILON) &&
99          FuzzyEqualsAdditive(aPoint.y, 0.0f, COORDINATE_EPSILON);
100 }
101 
102 // Deem an AsyncTransformComponentMatrix (obtained by multiplying together
103 // one or more AsyncTransformComponentMatrix objects) as constituting a
104 // complete async transform.
105 inline AsyncTransformMatrix CompleteAsyncTransform(
106     const AsyncTransformComponentMatrix& aMatrix) {
107   return ViewAs<AsyncTransformMatrix>(
108       aMatrix, PixelCastJustification::MultipleAsyncTransforms);
109 }
110 
111 struct TargetConfirmationFlags final {
112   explicit TargetConfirmationFlags(bool aTargetConfirmed)
113       : mTargetConfirmed(aTargetConfirmed),
114         mRequiresTargetConfirmation(false) {}
115 
116   explicit TargetConfirmationFlags(
117       const gfx::CompositorHitTestInfo& aHitTestInfo)
118       : mTargetConfirmed(
119             (aHitTestInfo != gfx::CompositorHitTestInvisibleToHit) &&
120             (aHitTestInfo & gfx::CompositorHitTestDispatchToContent).isEmpty()),
121         mRequiresTargetConfirmation(aHitTestInfo.contains(
122             gfx::CompositorHitTestFlags::eRequiresTargetConfirmation)) {}
123 
124   bool mTargetConfirmed : 1;
125   bool mRequiresTargetConfirmation : 1;
126 };
127 
128 enum class AsyncTransformComponent { eLayout, eVisual };
129 
130 using AsyncTransformComponents = EnumSet<AsyncTransformComponent>;
131 
132 constexpr AsyncTransformComponents LayoutAndVisual(
133     AsyncTransformComponent::eLayout, AsyncTransformComponent::eVisual);
134 
135 namespace apz {
136 
137 /**
138  * Initializes the global state used in AsyncPanZoomController.
139  * This is normally called when it is first needed in the constructor
140  * of APZCTreeManager, but can be called manually to force it to be
141  * initialized earlier.
142  */
143 void InitializeGlobalState();
144 
145 /**
146  * See AsyncPanZoomController::CalculatePendingDisplayPort. This
147  * function simply delegates to that one, so that non-layers code
148  * never needs to include AsyncPanZoomController.h
149  */
150 const ScreenMargin CalculatePendingDisplayPort(
151     const FrameMetrics& aFrameMetrics, const ParentLayerPoint& aVelocity);
152 
153 /**
154  * Is aAngle within the given threshold of the horizontal axis?
155  * @param aAngle an angle in radians in the range [0, pi]
156  * @param aThreshold an angle in radians in the range [0, pi/2]
157  */
158 bool IsCloseToHorizontal(float aAngle, float aThreshold);
159 
160 // As above, but for the vertical axis.
161 bool IsCloseToVertical(float aAngle, float aThreshold);
162 
163 // Determine the amount of overlap between the 1D vector |aTranslation|
164 // and the interval [aMin, aMax].
165 gfxFloat IntervalOverlap(gfxFloat aTranslation, gfxFloat aMin, gfxFloat aMax);
166 
167 // Returns true if a sticky layer with async translation |aTranslation| is
168 // stuck with a bottom margin. The inner/outer ranges are produced by the main
169 // thread at the last paint, and so |aTranslation| only needs to be the
170 // async translation from the last paint.
171 bool IsStuckAtBottom(gfxFloat aTranslation,
172                      const LayerRectAbsolute& aInnerRange,
173                      const LayerRectAbsolute& aOuterRange);
174 
175 // Returns true if a sticky layer with async translation |aTranslation| is
176 // stuck with a top margin.
177 bool IsStuckAtTop(gfxFloat aTranslation, const LayerRectAbsolute& aInnerRange,
178                   const LayerRectAbsolute& aOuterRange);
179 
180 }  // namespace apz
181 
182 }  // namespace layers
183 }  // namespace mozilla
184 
185 #endif  // mozilla_layers_APZUtils_h
186