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