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 #include "mozilla/layers/APZUtils.h"
8 
9 #include "mozilla/StaticPrefs_apz.h"
10 #include "mozilla/StaticPrefs_layers.h"
11 
12 namespace mozilla {
13 namespace layers {
14 
15 namespace apz {
16 
IsCloseToHorizontal(float aAngle,float aThreshold)17 bool IsCloseToHorizontal(float aAngle, float aThreshold) {
18   return (aAngle < aThreshold || aAngle > (M_PI - aThreshold));
19 }
20 
IsCloseToVertical(float aAngle,float aThreshold)21 bool IsCloseToVertical(float aAngle, float aThreshold) {
22   return (fabs(aAngle - (M_PI / 2)) < aThreshold);
23 }
24 
IsStuckAtBottom(gfxFloat aTranslation,const LayerRectAbsolute & aInnerRange,const LayerRectAbsolute & aOuterRange)25 bool IsStuckAtBottom(gfxFloat aTranslation,
26                      const LayerRectAbsolute& aInnerRange,
27                      const LayerRectAbsolute& aOuterRange) {
28   // The item will be stuck at the bottom if the async scroll delta is in
29   // the range [aOuterRange.Y(), aInnerRange.Y()]. Since the translation
30   // is negated with repect to the async scroll delta (i.e. scrolling down
31   // produces a positive scroll delta and negative translation), we invert it
32   // and check to see if it falls in the specified range.
33   return aOuterRange.Y() <= -aTranslation && -aTranslation <= aInnerRange.Y();
34 }
35 
IsStuckAtTop(gfxFloat aTranslation,const LayerRectAbsolute & aInnerRange,const LayerRectAbsolute & aOuterRange)36 bool IsStuckAtTop(gfxFloat aTranslation, const LayerRectAbsolute& aInnerRange,
37                   const LayerRectAbsolute& aOuterRange) {
38   // Same as IsStuckAtBottom, except we want to check for the range
39   // [aInnerRange.YMost(), aOuterRange.YMost()].
40   return aInnerRange.YMost() <= -aTranslation &&
41          -aTranslation <= aOuterRange.YMost();
42 }
43 
ComputeFixedMarginsOffset(const ScreenMargin & aCompositorFixedLayerMargins,SideBits aFixedSides,const ScreenMargin & aGeckoFixedLayerMargins)44 ScreenPoint ComputeFixedMarginsOffset(
45     const ScreenMargin& aCompositorFixedLayerMargins, SideBits aFixedSides,
46     const ScreenMargin& aGeckoFixedLayerMargins) {
47   // Work out the necessary translation, in screen space.
48   ScreenPoint translation;
49 
50   ScreenMargin effectiveMargin =
51       aCompositorFixedLayerMargins - aGeckoFixedLayerMargins;
52   if ((aFixedSides & SideBits::eLeftRight) == SideBits::eLeftRight) {
53     translation.x += (effectiveMargin.left - effectiveMargin.right) / 2;
54   } else if (aFixedSides & SideBits::eRight) {
55     translation.x -= effectiveMargin.right;
56   } else if (aFixedSides & SideBits::eLeft) {
57     translation.x += effectiveMargin.left;
58   }
59 
60   if ((aFixedSides & SideBits::eTopBottom) == SideBits::eTopBottom) {
61     translation.y += (effectiveMargin.top - effectiveMargin.bottom) / 2;
62   } else if (aFixedSides & SideBits::eBottom) {
63     translation.y -= effectiveMargin.bottom;
64   } else if (aFixedSides & SideBits::eTop) {
65     translation.y += effectiveMargin.top;
66   }
67 
68   return translation;
69 }
70 
AboutToCheckerboard(const FrameMetrics & aPaintedMetrics,const FrameMetrics & aCompositorMetrics)71 bool AboutToCheckerboard(const FrameMetrics& aPaintedMetrics,
72                          const FrameMetrics& aCompositorMetrics) {
73   // The main-thread code to compute the painted area can introduce some
74   // rounding error due to multiple unit conversions, so we inflate the rect by
75   // one app unit to account for that.
76   CSSRect painted = (aPaintedMetrics.GetCriticalDisplayPort().IsEmpty()
77                          ? aPaintedMetrics.GetDisplayPort()
78                          : aPaintedMetrics.GetCriticalDisplayPort()) +
79                     aPaintedMetrics.GetLayoutScrollOffset();
80   painted.Inflate(CSSMargin::FromAppUnits(nsMargin(1, 1, 1, 1)));
81 
82   // Inflate the rect by the danger zone. See the description of the danger zone
83   // prefs in AsyncPanZoomController.cpp for an explanation of this.
84   CSSRect visible =
85       CSSRect(aCompositorMetrics.GetVisualScrollOffset(),
86               aCompositorMetrics.CalculateBoundedCompositedSizeInCssPixels());
87   visible.Inflate(LayerSize(StaticPrefs::apz_danger_zone_x(),
88                             StaticPrefs::apz_danger_zone_y()) /
89                   aCompositorMetrics.LayersPixelsPerCSSPixel());
90 
91   // Clamp both rects to the scrollable rect, because having either of those
92   // exceed the scrollable rect doesn't make sense, and could lead to false
93   // positives.
94   painted = painted.Intersect(aPaintedMetrics.GetScrollableRect());
95   visible = visible.Intersect(aPaintedMetrics.GetScrollableRect());
96 
97   return !painted.Contains(visible);
98 }
99 
ShouldUseProgressivePaint()100 bool ShouldUseProgressivePaint() {
101   // The mutexes required for progressive painting pose a security risk
102   // on sandboxed platforms. Additionally, Android is the only platform
103   // that supports progressive painting, so if on a sandboxed platform
104   // or not on Android, we should not use progressive painting.
105 #if defined(MOZ_SANDBOX) || !defined(MOZ_WIDGET_ANDROID)
106   return false;
107 #else
108   return StaticPrefs::layers_progressive_paint_DoNotUseDirectly();
109 #endif
110 }
111 
GetOverscrollSideBits(const ParentLayerPoint & aOverscrollAmount)112 SideBits GetOverscrollSideBits(const ParentLayerPoint& aOverscrollAmount) {
113   SideBits sides = SideBits::eNone;
114 
115   if (aOverscrollAmount.x < 0) {
116     sides |= SideBits::eLeft;
117   } else if (aOverscrollAmount.x > 0) {
118     sides |= SideBits::eRight;
119   }
120 
121   if (aOverscrollAmount.y < 0) {
122     sides |= SideBits::eTop;
123   } else if (aOverscrollAmount.y > 0) {
124     sides |= SideBits::eBottom;
125   }
126 
127   return sides;
128 }
129 
130 }  // namespace apz
131 }  // namespace layers
132 }  // namespace mozilla
133