tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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