summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/src/APZUtils.cpp
blob: 843046c34a1d6f35c519f8e90a4b6b94e916c148 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozilla/layers/APZUtils.h"

#include "mozilla/StaticPrefs_apz.h"
#include "mozilla/StaticPrefs_layers.h"

namespace mozilla {
namespace layers {

namespace apz {

bool IsCloseToHorizontal(float aAngle, float aThreshold) {
  return (aAngle < aThreshold || aAngle > (M_PI - aThreshold));
}

bool IsCloseToVertical(float aAngle, float aThreshold) {
  return (fabs(aAngle - (M_PI / 2)) < aThreshold);
}

bool IsStuckAtBottom(gfxFloat aTranslation,
                     const LayerRectAbsolute& aInnerRange,
                     const LayerRectAbsolute& aOuterRange) {
  // The item will be stuck at the bottom if the async scroll delta is in
  // the range [aOuterRange.Y(), aInnerRange.Y()]. Since the translation
  // is negated with repect to the async scroll delta (i.e. scrolling down
  // produces a positive scroll delta and negative translation), we invert it
  // and check to see if it falls in the specified range.
  return aOuterRange.Y() <= -aTranslation && -aTranslation <= aInnerRange.Y();
}

bool IsStuckAtTop(gfxFloat aTranslation, const LayerRectAbsolute& aInnerRange,
                  const LayerRectAbsolute& aOuterRange) {
  // Same as IsStuckAtBottom, except we want to check for the range
  // [aInnerRange.YMost(), aOuterRange.YMost()].
  return aInnerRange.YMost() <= -aTranslation &&
         -aTranslation <= aOuterRange.YMost();
}

ScreenPoint ComputeFixedMarginsOffset(
    const ScreenMargin& aCompositorFixedLayerMargins, SideBits aFixedSides,
    const ScreenMargin& aGeckoFixedLayerMargins) {
  // Work out the necessary translation, in screen space.
  ScreenPoint translation;

  ScreenMargin effectiveMargin =
      aCompositorFixedLayerMargins - aGeckoFixedLayerMargins;
  if ((aFixedSides & SideBits::eLeftRight) == SideBits::eLeftRight) {
    translation.x += (effectiveMargin.left - effectiveMargin.right) / 2;
  } else if (aFixedSides & SideBits::eRight) {
    translation.x -= effectiveMargin.right;
  } else if (aFixedSides & SideBits::eLeft) {
    translation.x += effectiveMargin.left;
  }

  if ((aFixedSides & SideBits::eTopBottom) == SideBits::eTopBottom) {
    translation.y += (effectiveMargin.top - effectiveMargin.bottom) / 2;
  } else if (aFixedSides & SideBits::eBottom) {
    translation.y -= effectiveMargin.bottom;
  } else if (aFixedSides & SideBits::eTop) {
    translation.y += effectiveMargin.top;
  }

  return translation;
}

bool AboutToCheckerboard(const FrameMetrics& aPaintedMetrics,
                         const FrameMetrics& aCompositorMetrics) {
  // The main-thread code to compute the painted area can introduce some
  // rounding error due to multiple unit conversions, so we inflate the rect by
  // one app unit to account for that.
  CSSRect painted = aPaintedMetrics.GetDisplayPort() +
                    aPaintedMetrics.GetLayoutScrollOffset();
  painted.Inflate(CSSMargin::FromAppUnits(nsMargin(1, 1, 1, 1)));

  // Inflate the rect by the danger zone. See the description of the danger zone
  // prefs in AsyncPanZoomController.cpp for an explanation of this.
  CSSRect visible =
      CSSRect(aCompositorMetrics.GetVisualScrollOffset(),
              aCompositorMetrics.CalculateBoundedCompositedSizeInCssPixels());
  visible.Inflate(ScreenSize(StaticPrefs::apz_danger_zone_x(),
                             StaticPrefs::apz_danger_zone_y()) /
                  aCompositorMetrics.DisplayportPixelsPerCSSPixel());

  // Clamp both rects to the scrollable rect, because having either of those
  // exceed the scrollable rect doesn't make sense, and could lead to false
  // positives.
  painted = painted.Intersect(aPaintedMetrics.GetScrollableRect());
  visible = visible.Intersect(aPaintedMetrics.GetScrollableRect());

  return !painted.Contains(visible);
}

SideBits GetOverscrollSideBits(const ParentLayerPoint& aOverscrollAmount) {
  SideBits sides = SideBits::eNone;

  if (aOverscrollAmount.x < 0) {
    sides |= SideBits::eLeft;
  } else if (aOverscrollAmount.x > 0) {
    sides |= SideBits::eRight;
  }

  if (aOverscrollAmount.y < 0) {
    sides |= SideBits::eTop;
  } else if (aOverscrollAmount.y > 0) {
    sides |= SideBits::eBottom;
  }

  return sides;
}

}  // namespace apz
}  // namespace layers
}  // namespace mozilla