tor-browser

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

TestOverscroll.cpp (105319B)


      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 "APZCBasicTester.h"
      8 #include "APZCTreeManagerTester.h"
      9 #include "APZTestCommon.h"
     10 #include "mozilla/RelativeTo.h"
     11 #include "mozilla/ScrollPositionUpdate.h"
     12 #include "mozilla/layers/ScrollableLayerGuid.h"
     13 #include "mozilla/layers/WebRenderScrollDataWrapper.h"
     14 
     15 #include "InputUtils.h"
     16 
     17 using LayersUpdateFlags = AsyncPanZoomController::LayersUpdateFlags;
     18 
     19 class APZCOverscrollTester : public APZCBasicTester {
     20 public:
     21  explicit APZCOverscrollTester(
     22      AsyncPanZoomController::GestureBehavior aGestureBehavior =
     23          AsyncPanZoomController::DEFAULT_GESTURES)
     24      : APZCBasicTester(aGestureBehavior) {}
     25 
     26 protected:
     27  UniquePtr<ScopedLayerTreeRegistration> registration;
     28 
     29  void TestOverscroll() {
     30    // Pan sufficiently to hit overscroll behavior
     31    PanIntoOverscroll();
     32 
     33    // Check that we recover from overscroll via an animation.
     34    ParentLayerPoint expectedScrollOffset(0, GetScrollRange().YMost());
     35    SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
     36  }
     37 
     38  void PanIntoOverscroll() {
     39    int touchStart = 500;
     40    int touchEnd = 10;
     41    Pan(apzc, touchStart, touchEnd);
     42    EXPECT_TRUE(apzc->IsOverscrolled());
     43  }
     44 
     45  /**
     46   * Sample animations until we recover from overscroll.
     47   * @param aExpectedScrollOffset the expected reported scroll offset
     48   *                              throughout the animation
     49   */
     50  void SampleAnimationUntilRecoveredFromOverscroll(
     51      const ParentLayerPoint& aExpectedScrollOffset) {
     52    const TimeDuration increment = TimeDuration::FromMilliseconds(1);
     53    bool recoveredFromOverscroll = false;
     54    ParentLayerPoint pointOut;
     55    AsyncTransform viewTransformOut;
     56    while (apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut)) {
     57      // The reported scroll offset should be the same throughout.
     58      EXPECT_EQ(aExpectedScrollOffset, pointOut);
     59 
     60      // Trigger computation of the overscroll tranform, to make sure
     61      // no assetions fire during the calculation.
     62      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
     63 
     64      if (!apzc->IsOverscrolled()) {
     65        recoveredFromOverscroll = true;
     66      }
     67 
     68      mcc->AdvanceBy(increment);
     69    }
     70    EXPECT_TRUE(recoveredFromOverscroll);
     71    apzc->AssertStateIsReset();
     72  }
     73 
     74  ScrollableLayerGuid CreateSimpleRootScrollableForWebRender() {
     75    ScrollableLayerGuid guid;
     76    guid.mScrollId = ScrollableLayerGuid::START_SCROLL_ID;
     77    guid.mLayersId = LayersId{0};
     78 
     79    ScrollMetadata metadata;
     80    FrameMetrics& metrics = metadata.GetMetrics();
     81    metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
     82    metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
     83    metrics.SetScrollId(guid.mScrollId);
     84    metadata.SetIsLayersIdRoot(true);
     85 
     86    WebRenderLayerScrollData rootLayerScrollData;
     87    rootLayerScrollData.InitializeRoot(0);
     88    WebRenderScrollData scrollData;
     89    rootLayerScrollData.AppendScrollMetadata(scrollData, metadata);
     90    scrollData.AddLayerData(std::move(rootLayerScrollData));
     91 
     92    registration = MakeUnique<ScopedLayerTreeRegistration>(guid.mLayersId, mcc);
     93    tm->UpdateHitTestingTree(WebRenderScrollDataWrapper(*updater, &scrollData),
     94                             guid.mLayersId, 0);
     95    return guid;
     96  }
     97 };
     98 
     99 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    100 TEST_F(APZCOverscrollTester, FlingIntoOverscroll) {
    101  // Enable overscrolling.
    102  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    103  SCOPED_GFX_PREF_FLOAT("apz.fling_min_velocity_threshold", 0.0f);
    104 
    105  // Scroll down by 25 px. Don't fling for simplicity.
    106  Pan(apzc, 50, 25, PanOptions::NoFling);
    107 
    108  // Now scroll back up by 20px, this time flinging after.
    109  // The fling should cover the remaining 5 px of room to scroll, then
    110  // go into overscroll, and finally snap-back to recover from overscroll.
    111  Pan(apzc, 25, 45);
    112  const TimeDuration increment = TimeDuration::FromMilliseconds(1);
    113  bool reachedOverscroll = false;
    114  bool recoveredFromOverscroll = false;
    115  while (apzc->AdvanceAnimations(mcc->GetSampleTime())) {
    116    if (!reachedOverscroll && apzc->IsOverscrolled()) {
    117      reachedOverscroll = true;
    118    }
    119    if (reachedOverscroll && !apzc->IsOverscrolled()) {
    120      recoveredFromOverscroll = true;
    121    }
    122    mcc->AdvanceBy(increment);
    123  }
    124  EXPECT_TRUE(reachedOverscroll);
    125  EXPECT_TRUE(recoveredFromOverscroll);
    126 }
    127 #endif
    128 
    129 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    130 TEST_F(APZCOverscrollTester, OverScrollPanning) {
    131  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    132 
    133  TestOverscroll();
    134 }
    135 #endif
    136 
    137 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    138 // Tests that an overscroll animation doesn't trigger an assertion failure
    139 // in the case where a sample has a velocity of zero.
    140 TEST_F(APZCOverscrollTester, OverScroll_Bug1152051a) {
    141  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    142 
    143  // Doctor the prefs to make the velocity zero at the end of the first sample.
    144 
    145  // This ensures our incoming velocity to the overscroll animation is
    146  // a round(ish) number, 4.9 (that being the distance of the pan before
    147  // overscroll, which is 500 - 10 = 490 pixels, divided by the duration of
    148  // the pan, which is 100 ms).
    149  SCOPED_GFX_PREF_FLOAT("apz.fling_friction", 0);
    150 
    151  TestOverscroll();
    152 }
    153 #endif
    154 
    155 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    156 // Tests that ending an overscroll animation doesn't leave around state that
    157 // confuses the next overscroll animation.
    158 TEST_F(APZCOverscrollTester, OverScroll_Bug1152051b) {
    159  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    160  SCOPED_GFX_PREF_FLOAT("apz.overscroll.stop_distance_threshold", 0.1f);
    161 
    162  // Pan sufficiently to hit overscroll behavior
    163  PanIntoOverscroll();
    164 
    165  // Sample animations once, to give the fling animation started on touch-up
    166  // a chance to realize it's overscrolled, and schedule a call to
    167  // HandleFlingOverscroll().
    168  SampleAnimationOnce();
    169 
    170  // This advances the time and runs the HandleFlingOverscroll task scheduled in
    171  // the previous call, which starts an overscroll animation. It then samples
    172  // the overscroll animation once, to get it to initialize the first overscroll
    173  // sample.
    174  SampleAnimationOnce();
    175 
    176  // Do a touch-down to cancel the overscroll animation, and then a touch-up
    177  // to schedule a new one since we're still overscrolled. We don't pan because
    178  // panning can trigger functions that clear the overscroll animation state
    179  // in other ways.
    180  APZEventResult result = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
    181  if (result.GetStatus() != nsEventStatus_eConsumeNoDefault) {
    182    SetDefaultAllowedTouchBehavior(apzc, result.mInputBlockId);
    183  }
    184  TouchUp(apzc, ScreenIntPoint(10, 10), mcc->Time());
    185 
    186  // Sample the second overscroll animation to its end.
    187  // If the ending of the first overscroll animation fails to clear state
    188  // properly, this will assert.
    189  ParentLayerPoint expectedScrollOffset(0, GetScrollRange().YMost());
    190  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
    191 }
    192 #endif
    193 
    194 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    195 // Tests that the page doesn't get stuck in an
    196 // overscroll animation after a low-velocity pan.
    197 TEST_F(APZCOverscrollTester, OverScrollAfterLowVelocityPan_Bug1343775) {
    198  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    199 
    200  // Pan into overscroll with a velocity less than the
    201  // apz.fling_min_velocity_threshold preference.
    202  Pan(apzc, 10, 30);
    203 
    204  EXPECT_TRUE(apzc->IsOverscrolled());
    205 
    206  apzc->AdvanceAnimationsUntilEnd();
    207 
    208  // Check that we recovered from overscroll.
    209  EXPECT_FALSE(apzc->IsOverscrolled());
    210 }
    211 #endif
    212 
    213 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    214 TEST_F(APZCOverscrollTester, OverScrollAbort) {
    215  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    216 
    217  // Pan sufficiently to hit overscroll behavior
    218  int touchStart = 500;
    219  int touchEnd = 10;
    220  Pan(apzc, touchStart, touchEnd);
    221  EXPECT_TRUE(apzc->IsOverscrolled());
    222 
    223  ParentLayerPoint pointOut;
    224  AsyncTransform viewTransformOut;
    225 
    226  // This sample call will run to the end of the fling animation
    227  // and will schedule the overscroll animation.
    228  apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut,
    229                                       TimeDuration::FromMilliseconds(10000));
    230  EXPECT_TRUE(apzc->IsOverscrolled());
    231 
    232  // At this point, we have an active overscroll animation.
    233  // Check that cancelling the animation clears the overscroll.
    234  apzc->CancelAnimation();
    235  EXPECT_FALSE(apzc->IsOverscrolled());
    236  apzc->AssertStateIsReset();
    237 }
    238 #endif
    239 
    240 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    241 TEST_F(APZCOverscrollTester, OverScrollPanningAbort) {
    242  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    243 
    244  // Pan sufficiently to hit overscroll behaviour. Keep the finger down so
    245  // the pan does not end.
    246  int touchStart = 500;
    247  int touchEnd = 10;
    248  Pan(apzc, touchStart, touchEnd, PanOptions::KeepFingerDown);
    249  EXPECT_TRUE(apzc->IsOverscrolled());
    250 
    251  // Check that calling CancelAnimation() while the user is still panning
    252  // (and thus no fling or snap-back animation has had a chance to start)
    253  // clears the overscroll.
    254  apzc->CancelAnimation();
    255  EXPECT_FALSE(apzc->IsOverscrolled());
    256  apzc->AssertStateIsReset();
    257 }
    258 #endif
    259 
    260 #ifndef MOZ_WIDGET_ANDROID  // Maybe fails on Android
    261 TEST_F(APZCOverscrollTester, OverscrollByVerticalPanGestures) {
    262  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    263 
    264  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
    265             ScreenPoint(0, -2), mcc->Time());
    266  mcc->AdvanceByMillis(5);
    267  apzc->AdvanceAnimations(mcc->GetSampleTime());
    268  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    269             ScreenPoint(0, -10), mcc->Time());
    270  mcc->AdvanceByMillis(5);
    271  apzc->AdvanceAnimations(mcc->GetSampleTime());
    272  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    273             ScreenPoint(0, -2), mcc->Time());
    274  mcc->AdvanceByMillis(5);
    275  apzc->AdvanceAnimations(mcc->GetSampleTime());
    276  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
    277             ScreenPoint(0, 0), mcc->Time());
    278 
    279  EXPECT_TRUE(apzc->IsOverscrolled());
    280 
    281  // Check that we recover from overscroll via an animation.
    282  ParentLayerPoint expectedScrollOffset(0, 0);
    283  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
    284 }
    285 #endif
    286 
    287 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    288 TEST_F(APZCOverscrollTester, StuckInOverscroll_Bug1767337) {
    289  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    290 
    291  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
    292             ScreenPoint(0, -2), mcc->Time());
    293  mcc->AdvanceByMillis(5);
    294  apzc->AdvanceAnimations(mcc->GetSampleTime());
    295  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    296             ScreenPoint(0, -10), mcc->Time());
    297  mcc->AdvanceByMillis(5);
    298  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    299             ScreenPoint(0, -10), mcc->Time());
    300  mcc->AdvanceByMillis(5);
    301  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    302             ScreenPoint(0, -10), mcc->Time());
    303  mcc->AdvanceByMillis(5);
    304  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    305             ScreenPoint(0, -10), mcc->Time());
    306  mcc->AdvanceByMillis(5);
    307  apzc->AdvanceAnimations(mcc->GetSampleTime());
    308  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    309             ScreenPoint(0, -2), mcc->Time());
    310  mcc->AdvanceByMillis(5);
    311  apzc->AdvanceAnimations(mcc->GetSampleTime());
    312 
    313  // Send two PANGESTURE_END in a row, to see if the second one gets us
    314  // stuck in overscroll.
    315  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
    316             ScreenPoint(0, 0), mcc->Time(), MODIFIER_NONE, true);
    317  SampleAnimationOnce();
    318  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
    319             ScreenPoint(0, 0), mcc->Time(), MODIFIER_NONE, true);
    320 
    321  EXPECT_TRUE(apzc->IsOverscrolled());
    322 
    323  // Check that we recover from overscroll via an animation.
    324  ParentLayerPoint expectedScrollOffset(0, 0);
    325  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
    326 }
    327 #endif
    328 
    329 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    330 TEST_F(APZCOverscrollTester, OverscrollByVerticalAndHorizontalPanGestures) {
    331  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    332 
    333  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
    334             ScreenPoint(0, -2), mcc->Time());
    335  mcc->AdvanceByMillis(5);
    336  apzc->AdvanceAnimations(mcc->GetSampleTime());
    337  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    338             ScreenPoint(0, -10), mcc->Time());
    339  mcc->AdvanceByMillis(5);
    340  apzc->AdvanceAnimations(mcc->GetSampleTime());
    341  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    342             ScreenPoint(0, -2), mcc->Time());
    343 
    344  mcc->AdvanceByMillis(5);
    345  apzc->AdvanceAnimations(mcc->GetSampleTime());
    346  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    347             ScreenPoint(-10, 0), mcc->Time());
    348  mcc->AdvanceByMillis(5);
    349  apzc->AdvanceAnimations(mcc->GetSampleTime());
    350  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    351             ScreenPoint(-2, 0), mcc->Time());
    352 
    353  mcc->AdvanceByMillis(5);
    354  apzc->AdvanceAnimations(mcc->GetSampleTime());
    355  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
    356             ScreenPoint(0, 0), mcc->Time());
    357 
    358  EXPECT_TRUE(apzc->IsOverscrolled());
    359 
    360  // Check that we recover from overscroll via an animation.
    361  ParentLayerPoint expectedScrollOffset(0, 0);
    362  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
    363 }
    364 #endif
    365 
    366 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    367 TEST_F(APZCOverscrollTester, OverscrollByPanMomentumGestures) {
    368  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    369 
    370  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
    371             ScreenPoint(0, 2), mcc->Time());
    372  mcc->AdvanceByMillis(5);
    373  apzc->AdvanceAnimations(mcc->GetSampleTime());
    374  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    375             ScreenPoint(0, 10), mcc->Time());
    376  mcc->AdvanceByMillis(5);
    377  apzc->AdvanceAnimations(mcc->GetSampleTime());
    378  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    379             ScreenPoint(0, 2), mcc->Time());
    380  mcc->AdvanceByMillis(5);
    381  apzc->AdvanceAnimations(mcc->GetSampleTime());
    382  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
    383             ScreenPoint(0, 0), mcc->Time());
    384 
    385  // Make sure we are not yet in overscrolled region.
    386  EXPECT_TRUE(!apzc->IsOverscrolled());
    387 
    388  mcc->AdvanceByMillis(5);
    389  apzc->AdvanceAnimations(mcc->GetSampleTime());
    390  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
    391             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
    392  mcc->AdvanceByMillis(5);
    393  apzc->AdvanceAnimations(mcc->GetSampleTime());
    394  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    395             ScreenIntPoint(50, 80), ScreenPoint(0, 200), mcc->Time());
    396  mcc->AdvanceByMillis(5);
    397  apzc->AdvanceAnimations(mcc->GetSampleTime());
    398  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    399             ScreenIntPoint(50, 80), ScreenPoint(0, 100), mcc->Time());
    400  mcc->AdvanceByMillis(5);
    401  apzc->AdvanceAnimations(mcc->GetSampleTime());
    402  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    403             ScreenIntPoint(50, 80), ScreenPoint(0, 2), mcc->Time());
    404  mcc->AdvanceByMillis(5);
    405  apzc->AdvanceAnimations(mcc->GetSampleTime());
    406  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
    407             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
    408 
    409  EXPECT_TRUE(apzc->IsOverscrolled());
    410 
    411  // Check that we recover from overscroll via an animation.
    412  ParentLayerPoint expectedScrollOffset(0, GetScrollRange().YMost());
    413  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
    414 }
    415 #endif
    416 
    417 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    418 TEST_F(APZCOverscrollTester, IgnoreMomemtumDuringOverscroll) {
    419  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    420 
    421  float yMost = GetScrollRange().YMost();
    422  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
    423             ScreenPoint(0, yMost / 10), mcc->Time());
    424  mcc->AdvanceByMillis(5);
    425  apzc->AdvanceAnimations(mcc->GetSampleTime());
    426  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    427             ScreenPoint(0, yMost), mcc->Time());
    428  mcc->AdvanceByMillis(5);
    429  apzc->AdvanceAnimations(mcc->GetSampleTime());
    430  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    431             ScreenPoint(0, yMost / 10), mcc->Time());
    432  mcc->AdvanceByMillis(5);
    433  apzc->AdvanceAnimations(mcc->GetSampleTime());
    434  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
    435             ScreenPoint(0, 0), mcc->Time());
    436 
    437  // Make sure we've started an overscroll animation.
    438  EXPECT_TRUE(apzc->IsOverscrolled());
    439  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
    440 
    441  // And check the overscrolled transform value before/after calling PanGesture
    442  // to make sure the overscroll amount isn't affected by momentum events.
    443  mcc->AdvanceByMillis(5);
    444  apzc->AdvanceAnimations(mcc->GetSampleTime());
    445  AsyncTransformComponentMatrix overscrolledTransform =
    446      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    447  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
    448             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
    449  EXPECT_EQ(
    450      overscrolledTransform,
    451      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling));
    452 
    453  mcc->AdvanceByMillis(5);
    454  apzc->AdvanceAnimations(mcc->GetSampleTime());
    455  overscrolledTransform =
    456      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    457  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    458             ScreenIntPoint(50, 80), ScreenPoint(0, 200), mcc->Time());
    459  EXPECT_EQ(
    460      overscrolledTransform,
    461      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling));
    462 
    463  mcc->AdvanceByMillis(5);
    464  apzc->AdvanceAnimations(mcc->GetSampleTime());
    465  overscrolledTransform =
    466      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    467  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    468             ScreenIntPoint(50, 80), ScreenPoint(0, 100), mcc->Time());
    469  EXPECT_EQ(
    470      overscrolledTransform,
    471      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling));
    472 
    473  mcc->AdvanceByMillis(5);
    474  apzc->AdvanceAnimations(mcc->GetSampleTime());
    475  overscrolledTransform =
    476      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    477  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    478             ScreenIntPoint(50, 80), ScreenPoint(0, 2), mcc->Time());
    479  EXPECT_EQ(
    480      overscrolledTransform,
    481      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling));
    482 
    483  mcc->AdvanceByMillis(5);
    484  apzc->AdvanceAnimations(mcc->GetSampleTime());
    485  overscrolledTransform =
    486      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    487  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
    488             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
    489  EXPECT_EQ(
    490      overscrolledTransform,
    491      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling));
    492 
    493  // Check that we've recovered from overscroll via an animation.
    494  ParentLayerPoint expectedScrollOffset(0, GetScrollRange().YMost());
    495  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
    496 }
    497 #endif
    498 
    499 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    500 TEST_F(APZCOverscrollTester, VerticalOnlyOverscroll) {
    501  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    502 
    503  // Make the content scrollable only vertically.
    504  ScrollMetadata metadata;
    505  FrameMetrics& metrics = metadata.GetMetrics();
    506  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
    507  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
    508  apzc->SetFrameMetrics(metrics);
    509 
    510  // Scroll up into overscroll a bit.
    511  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
    512             ScreenPoint(-2, -2), mcc->Time());
    513  mcc->AdvanceByMillis(5);
    514  apzc->AdvanceAnimations(mcc->GetSampleTime());
    515  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    516             ScreenPoint(-10, -10), mcc->Time());
    517  mcc->AdvanceByMillis(5);
    518  apzc->AdvanceAnimations(mcc->GetSampleTime());
    519  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    520             ScreenPoint(-2, -2), mcc->Time());
    521  mcc->AdvanceByMillis(5);
    522  apzc->AdvanceAnimations(mcc->GetSampleTime());
    523  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
    524             ScreenPoint(0, 0), mcc->Time());
    525  // Now it's overscrolled.
    526  EXPECT_TRUE(apzc->IsOverscrolled());
    527  AsyncTransformComponentMatrix overscrolledTransform =
    528      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    529  // The overscroll shouldn't happen horizontally.
    530  EXPECT_TRUE(overscrolledTransform._41 == 0);
    531  // Happens only vertically.
    532  EXPECT_TRUE(overscrolledTransform._42 != 0);
    533 
    534  // Send pan momentum events including horizontal bits.
    535  mcc->AdvanceByMillis(5);
    536  apzc->AdvanceAnimations(mcc->GetSampleTime());
    537  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
    538             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
    539  mcc->AdvanceByMillis(5);
    540  apzc->AdvanceAnimations(mcc->GetSampleTime());
    541  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    542             ScreenIntPoint(50, 80), ScreenPoint(-10, -100), mcc->Time());
    543  overscrolledTransform =
    544      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    545  // The overscroll shouldn't happen horizontally.
    546  EXPECT_TRUE(overscrolledTransform._41 == 0);
    547  EXPECT_TRUE(overscrolledTransform._42 != 0);
    548 
    549  mcc->AdvanceByMillis(5);
    550  apzc->AdvanceAnimations(mcc->GetSampleTime());
    551  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    552             ScreenIntPoint(50, 80), ScreenPoint(-5, -50), mcc->Time());
    553  overscrolledTransform =
    554      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    555  EXPECT_TRUE(overscrolledTransform._41 == 0);
    556  EXPECT_TRUE(overscrolledTransform._42 != 0);
    557 
    558  mcc->AdvanceByMillis(5);
    559  apzc->AdvanceAnimations(mcc->GetSampleTime());
    560  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    561             ScreenIntPoint(50, 80), ScreenPoint(0, -2), mcc->Time());
    562  overscrolledTransform =
    563      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    564  EXPECT_TRUE(overscrolledTransform._41 == 0);
    565  EXPECT_TRUE(overscrolledTransform._42 != 0);
    566 
    567  mcc->AdvanceByMillis(5);
    568  apzc->AdvanceAnimations(mcc->GetSampleTime());
    569  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
    570             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
    571  overscrolledTransform =
    572      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    573  EXPECT_TRUE(overscrolledTransform._41 == 0);
    574  EXPECT_TRUE(overscrolledTransform._42 != 0);
    575 
    576  // Check that we recover from overscroll via an animation.
    577  ParentLayerPoint expectedScrollOffset(0, 0);
    578  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
    579 }
    580 #endif
    581 
    582 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    583 TEST_F(APZCOverscrollTester, VerticalOnlyOverscrollByPanMomentum) {
    584  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    585 
    586  // Make the content scrollable only vertically.
    587  ScrollMetadata metadata;
    588  FrameMetrics& metrics = metadata.GetMetrics();
    589  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
    590  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
    591  // Scrolls the content down a bit.
    592  metrics.SetVisualScrollOffset(CSSPoint(0, 50));
    593  apzc->SetFrameMetrics(metrics);
    594 
    595  // Scroll up a bit where overscroll will not happen.
    596  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
    597             ScreenPoint(0, -2), mcc->Time());
    598  mcc->AdvanceByMillis(5);
    599  apzc->AdvanceAnimations(mcc->GetSampleTime());
    600  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    601             ScreenPoint(0, -10), mcc->Time());
    602  mcc->AdvanceByMillis(5);
    603  apzc->AdvanceAnimations(mcc->GetSampleTime());
    604  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    605             ScreenPoint(0, -2), mcc->Time());
    606  mcc->AdvanceByMillis(5);
    607  apzc->AdvanceAnimations(mcc->GetSampleTime());
    608  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
    609             ScreenPoint(0, 0), mcc->Time());
    610 
    611  // Make sure it's not yet overscrolled.
    612  EXPECT_TRUE(!apzc->IsOverscrolled());
    613 
    614  // Send pan momentum events including horizontal bits.
    615  mcc->AdvanceByMillis(5);
    616  apzc->AdvanceAnimations(mcc->GetSampleTime());
    617  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
    618             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
    619  mcc->AdvanceByMillis(5);
    620  apzc->AdvanceAnimations(mcc->GetSampleTime());
    621  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    622             ScreenIntPoint(50, 80), ScreenPoint(-10, -100), mcc->Time());
    623  // Now it's overscrolled.
    624  EXPECT_TRUE(apzc->IsOverscrolled());
    625 
    626  AsyncTransformComponentMatrix overscrolledTransform =
    627      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    628  // But the overscroll shouldn't happen horizontally.
    629  EXPECT_TRUE(overscrolledTransform._41 == 0);
    630  // Happens only vertically.
    631  EXPECT_TRUE(overscrolledTransform._42 != 0);
    632 
    633  mcc->AdvanceByMillis(5);
    634  apzc->AdvanceAnimations(mcc->GetSampleTime());
    635  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    636             ScreenIntPoint(50, 80), ScreenPoint(-5, -50), mcc->Time());
    637  overscrolledTransform =
    638      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    639  EXPECT_TRUE(overscrolledTransform._41 == 0);
    640  EXPECT_TRUE(overscrolledTransform._42 != 0);
    641 
    642  mcc->AdvanceByMillis(5);
    643  apzc->AdvanceAnimations(mcc->GetSampleTime());
    644  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    645             ScreenIntPoint(50, 80), ScreenPoint(0, -2), mcc->Time());
    646  overscrolledTransform =
    647      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    648  EXPECT_TRUE(overscrolledTransform._41 == 0);
    649  EXPECT_TRUE(overscrolledTransform._42 != 0);
    650 
    651  mcc->AdvanceByMillis(5);
    652  apzc->AdvanceAnimations(mcc->GetSampleTime());
    653  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
    654             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
    655  overscrolledTransform =
    656      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    657  EXPECT_TRUE(overscrolledTransform._41 == 0);
    658  EXPECT_TRUE(overscrolledTransform._42 != 0);
    659 
    660  // Check that we recover from overscroll via an animation.
    661  ParentLayerPoint expectedScrollOffset(0, 0);
    662  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
    663 }
    664 #endif
    665 
    666 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
    667 TEST_F(APZCOverscrollTester, DisallowOverscrollInSingleLineTextControl) {
    668  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    669 
    670  // Create a horizontal scrollable frame with `vertical disregarded direction`.
    671  ScrollMetadata metadata;
    672  FrameMetrics& metrics = metadata.GetMetrics();
    673  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 10));
    674  metrics.SetScrollableRect(CSSRect(0, 0, 1000, 10));
    675  apzc->SetFrameMetrics(metrics);
    676  metadata.SetDisregardedDirection(Some(ScrollDirection::eVertical));
    677  apzc->NotifyLayersUpdated(
    678      metadata,
    679      LayersUpdateFlags{.mIsFirstPaint = false, .mThisLayerTreeUpdated = true});
    680 
    681  // Try to overscroll up and left with pan gestures.
    682  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 5),
    683             ScreenPoint(-2, -2), mcc->Time());
    684  mcc->AdvanceByMillis(5);
    685  apzc->AdvanceAnimations(mcc->GetSampleTime());
    686  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 5),
    687             ScreenPoint(-10, -10), mcc->Time());
    688  mcc->AdvanceByMillis(5);
    689  apzc->AdvanceAnimations(mcc->GetSampleTime());
    690  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 5),
    691             ScreenPoint(-2, -2), mcc->Time());
    692  mcc->AdvanceByMillis(5);
    693  apzc->AdvanceAnimations(mcc->GetSampleTime());
    694  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 5),
    695             ScreenPoint(0, 0), mcc->Time());
    696 
    697  // No overscrolling should happen.
    698  EXPECT_TRUE(!apzc->IsOverscrolled());
    699 
    700  // Send pan momentum events too.
    701  mcc->AdvanceByMillis(5);
    702  apzc->AdvanceAnimations(mcc->GetSampleTime());
    703  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
    704             ScreenIntPoint(50, 5), ScreenPoint(0, 0), mcc->Time());
    705  mcc->AdvanceByMillis(5);
    706  apzc->AdvanceAnimations(mcc->GetSampleTime());
    707  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    708             ScreenIntPoint(50, 5), ScreenPoint(-100, -100), mcc->Time());
    709  mcc->AdvanceByMillis(5);
    710  apzc->AdvanceAnimations(mcc->GetSampleTime());
    711  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    712             ScreenIntPoint(50, 5), ScreenPoint(-50, -50), mcc->Time());
    713  mcc->AdvanceByMillis(5);
    714  apzc->AdvanceAnimations(mcc->GetSampleTime());
    715  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    716             ScreenIntPoint(50, 5), ScreenPoint(-2, -2), mcc->Time());
    717  mcc->AdvanceByMillis(5);
    718  apzc->AdvanceAnimations(mcc->GetSampleTime());
    719  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
    720             ScreenIntPoint(50, 5), ScreenPoint(0, 0), mcc->Time());
    721  // No overscrolling should happen either.
    722  EXPECT_TRUE(!apzc->IsOverscrolled());
    723 }
    724 #endif
    725 
    726 #ifndef MOZ_WIDGET_ANDROID  // Maybe fails on Android
    727 // Tests that horizontal overscroll animation keeps running with vertical
    728 // pan momentum scrolling.
    729 TEST_F(APZCOverscrollTester,
    730       HorizontalOverscrollAnimationWithVerticalPanMomentumScrolling) {
    731  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    732 
    733  ScrollMetadata metadata;
    734  FrameMetrics& metrics = metadata.GetMetrics();
    735  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
    736  metrics.SetScrollableRect(CSSRect(0, 0, 1000, 5000));
    737  apzc->SetFrameMetrics(metrics);
    738 
    739  // Try to overscroll left with pan gestures.
    740  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
    741             ScreenPoint(-2, 0), mcc->Time());
    742  mcc->AdvanceByMillis(5);
    743  apzc->AdvanceAnimations(mcc->GetSampleTime());
    744  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    745             ScreenPoint(-10, 0), mcc->Time());
    746  mcc->AdvanceByMillis(5);
    747  apzc->AdvanceAnimations(mcc->GetSampleTime());
    748  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    749             ScreenPoint(-2, 0), mcc->Time());
    750  mcc->AdvanceByMillis(5);
    751  apzc->AdvanceAnimations(mcc->GetSampleTime());
    752  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
    753             ScreenPoint(0, 0), mcc->Time());
    754 
    755  // Make sure we've started an overscroll animation.
    756  EXPECT_TRUE(apzc->IsOverscrolled());
    757  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
    758  AsyncTransformComponentMatrix initialOverscrolledTransform =
    759      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    760 
    761  // Send lengthy downward momentums to make sure the overscroll animation
    762  // doesn't clobber the momentums scrolling.
    763  mcc->AdvanceByMillis(5);
    764  apzc->AdvanceAnimations(mcc->GetSampleTime());
    765  // The overscroll amount on X axis has started being managed by the overscroll
    766  // animation.
    767  AsyncTransformComponentMatrix currentOverscrolledTransform =
    768      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    769  EXPECT_NE(initialOverscrolledTransform._41, currentOverscrolledTransform._41);
    770  // There is no overscroll on Y axis.
    771  EXPECT_EQ(currentOverscrolledTransform._42, 0);
    772  ParentLayerPoint scrollOffset = apzc->GetCurrentAsyncScrollOffset(
    773      AsyncPanZoomController::eForEventHandling);
    774  // The scroll offset shouldn't be changed by the overscroll animation.
    775  EXPECT_EQ(scrollOffset.y, 0);
    776 
    777  // Simple gesture on the Y axis to ensure that we can send a vertical
    778  // momentum scroll
    779  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
    780             ScreenPoint(0, -2), mcc->Time());
    781  mcc->AdvanceByMillis(5);
    782  apzc->AdvanceAnimations(mcc->GetSampleTime());
    783  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    784             ScreenPoint(0, 2), mcc->Time());
    785  mcc->AdvanceByMillis(5);
    786  apzc->AdvanceAnimations(mcc->GetSampleTime());
    787  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
    788             ScreenPoint(0, 0), mcc->Time());
    789 
    790  ParentLayerPoint offsetAfterPan = apzc->GetCurrentAsyncScrollOffset(
    791      AsyncPanZoomController::eForEventHandling);
    792 
    793  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
    794             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
    795  EXPECT_TRUE(apzc->IsOverscrolled());
    796  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
    797  // The overscroll amount on both axes shouldn't be changed by this pan
    798  // momentum start event since the displacement is zero.
    799  EXPECT_EQ(
    800      currentOverscrolledTransform._41,
    801      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
    802          ._41);
    803  EXPECT_EQ(
    804      currentOverscrolledTransform._42,
    805      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
    806          ._42);
    807 
    808  mcc->AdvanceByMillis(5);
    809  apzc->AdvanceAnimations(mcc->GetSampleTime());
    810  // The overscroll amount should be managed by the overscroll animation.
    811  EXPECT_NE(
    812      currentOverscrolledTransform._41,
    813      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
    814          ._41);
    815  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
    816      AsyncPanZoomController::eForEventHandling);
    817  // Not yet started scrolling.
    818  EXPECT_EQ(scrollOffset.y, offsetAfterPan.y);
    819  EXPECT_EQ(scrollOffset.x, 0);
    820 
    821  currentOverscrolledTransform =
    822      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    823 
    824  // Send a long pan momentum.
    825  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    826             ScreenIntPoint(50, 80), ScreenPoint(0, 200), mcc->Time());
    827  EXPECT_TRUE(apzc->IsOverscrolled());
    828  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
    829  // The overscroll amount on X axis shouldn't be changed by this momentum pan.
    830  EXPECT_EQ(
    831      currentOverscrolledTransform._41,
    832      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
    833          ._41);
    834  // Now it started scrolling vertically.
    835  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
    836      AsyncPanZoomController::eForEventHandling);
    837  EXPECT_GT(scrollOffset.y, 0);
    838  EXPECT_EQ(scrollOffset.x, 0);
    839 
    840  currentOverscrolledTransform =
    841      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    842  mcc->AdvanceByMillis(5);
    843  apzc->AdvanceAnimations(mcc->GetSampleTime());
    844  // The overscroll on X axis keeps being managed by the overscroll animation.
    845  EXPECT_NE(
    846      currentOverscrolledTransform._41,
    847      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
    848          ._41);
    849  // The scroll offset on Y axis shouldn't be changed by the overscroll
    850  // animation.
    851  EXPECT_EQ(scrollOffset.y, apzc->GetCurrentAsyncScrollOffset(
    852                                    AsyncPanZoomController::eForEventHandling)
    853                                .y);
    854 
    855  currentOverscrolledTransform =
    856      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    857  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
    858      AsyncPanZoomController::eForEventHandling);
    859  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    860             ScreenIntPoint(50, 80), ScreenPoint(0, 100), mcc->Time());
    861  EXPECT_TRUE(apzc->IsOverscrolled());
    862  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
    863  // The overscroll amount on X axis shouldn't be changed by this momentum pan.
    864  EXPECT_EQ(
    865      currentOverscrolledTransform._41,
    866      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
    867          ._41);
    868  // Scrolling keeps going by momentum.
    869  EXPECT_GT(apzc->GetCurrentAsyncScrollOffset(
    870                    AsyncPanZoomController::eForEventHandling)
    871                .y,
    872            scrollOffset.y);
    873 
    874  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
    875      AsyncPanZoomController::eForEventHandling);
    876  mcc->AdvanceByMillis(5);
    877  apzc->AdvanceAnimations(mcc->GetSampleTime());
    878  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    879             ScreenIntPoint(50, 80), ScreenPoint(0, 10), mcc->Time());
    880  EXPECT_TRUE(apzc->IsOverscrolled());
    881  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
    882  // Scrolling keeps going by momentum.
    883  EXPECT_GT(apzc->GetCurrentAsyncScrollOffset(
    884                    AsyncPanZoomController::eForEventHandling)
    885                .y,
    886            scrollOffset.y);
    887 
    888  currentOverscrolledTransform =
    889      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    890  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
    891      AsyncPanZoomController::eForEventHandling);
    892  mcc->AdvanceByMillis(5);
    893  apzc->AdvanceAnimations(mcc->GetSampleTime());
    894  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
    895             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
    896  EXPECT_TRUE(apzc->IsOverscrolled());
    897  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
    898  // This momentum event doesn't change the scroll offset since its
    899  // displacement is zero.
    900  EXPECT_EQ(apzc->GetCurrentAsyncScrollOffset(
    901                    AsyncPanZoomController::eForEventHandling)
    902                .y,
    903            scrollOffset.y);
    904 
    905  // Check that we recover from the horizontal overscroll via the animation.
    906  ParentLayerPoint expectedScrollOffset(0, scrollOffset.y);
    907  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
    908 }
    909 #endif
    910 
    911 #ifndef MOZ_WIDGET_ANDROID  // Maybe fails on Android
    912 // Similar to above
    913 // HorizontalOverscrollAnimationWithVerticalPanMomentumScrolling,
    914 // but having OverscrollAnimation on both axes initially.
    915 TEST_F(APZCOverscrollTester,
    916       BothAxesOverscrollAnimationWithPanMomentumScrolling) {
    917  // TODO: This test currently requires gestures that cause movement on both
    918  // axis, which excludes DOMINANT_AXIS locking mode. The gestures should be
    919  // broken up into multiple gestures to cause the overscroll.
    920  SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
    921  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
    922 
    923  ScrollMetadata metadata;
    924  FrameMetrics& metrics = metadata.GetMetrics();
    925  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
    926  metrics.SetScrollableRect(CSSRect(0, 0, 1000, 5000));
    927  apzc->SetFrameMetrics(metrics);
    928 
    929  // Try to overscroll up and left with pan gestures.
    930  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
    931             ScreenPoint(-2, -2), mcc->Time());
    932  mcc->AdvanceByMillis(5);
    933  apzc->AdvanceAnimations(mcc->GetSampleTime());
    934  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    935             ScreenPoint(-10, -10), mcc->Time());
    936  mcc->AdvanceByMillis(5);
    937  apzc->AdvanceAnimations(mcc->GetSampleTime());
    938  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
    939             ScreenPoint(-2, -2), mcc->Time());
    940  mcc->AdvanceByMillis(5);
    941  apzc->AdvanceAnimations(mcc->GetSampleTime());
    942  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
    943             ScreenPoint(0, 0), mcc->Time());
    944 
    945  // Make sure we've started an overscroll animation.
    946  EXPECT_TRUE(apzc->IsOverscrolled());
    947  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
    948  AsyncTransformComponentMatrix initialOverscrolledTransform =
    949      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    950 
    951  // Send lengthy downward momentums to make sure the overscroll animation
    952  // doesn't clobber the momentums scrolling.
    953  mcc->AdvanceByMillis(5);
    954  apzc->AdvanceAnimations(mcc->GetSampleTime());
    955  // The overscroll amount has started being managed by the overscroll
    956  // animation.
    957  AsyncTransformComponentMatrix currentOverscrolledTransform =
    958      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    959  EXPECT_NE(initialOverscrolledTransform._41, currentOverscrolledTransform._41);
    960  EXPECT_NE(initialOverscrolledTransform._42, currentOverscrolledTransform._42);
    961 
    962  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
    963             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
    964  EXPECT_TRUE(apzc->IsOverscrolled());
    965  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
    966  // The overscroll amount on both axes shouldn't be changed by this pan
    967  // momentum start event since the displacement is zero.
    968  EXPECT_EQ(
    969      currentOverscrolledTransform._41,
    970      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
    971          ._41);
    972  EXPECT_EQ(
    973      currentOverscrolledTransform._42,
    974      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
    975          ._42);
    976 
    977  mcc->AdvanceByMillis(5);
    978  apzc->AdvanceAnimations(mcc->GetSampleTime());
    979  // Still being managed by the overscroll animation.
    980  EXPECT_NE(
    981      currentOverscrolledTransform._41,
    982      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
    983          ._41);
    984  EXPECT_NE(
    985      currentOverscrolledTransform._42,
    986      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
    987          ._42);
    988 
    989  currentOverscrolledTransform =
    990      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
    991  // Send a long pan momentum.
    992  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
    993             ScreenIntPoint(50, 80), ScreenPoint(0, 200), mcc->Time());
    994  EXPECT_TRUE(apzc->IsOverscrolled());
    995  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
    996  // The overscroll amount on X axis shouldn't be changed by this momentum pan.
    997  EXPECT_EQ(
    998      currentOverscrolledTransform._41,
    999      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1000          ._41);
   1001  // But now the overscroll amount on Y axis should be changed by this momentum
   1002  // pan.
   1003  EXPECT_NE(
   1004      currentOverscrolledTransform._42,
   1005      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1006          ._42);
   1007  // Actually it's no longer overscrolled.
   1008  EXPECT_EQ(
   1009      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1010          ._42,
   1011      0);
   1012 
   1013  ParentLayerPoint currentScrollOffset = apzc->GetCurrentAsyncScrollOffset(
   1014      AsyncPanZoomController::eForEventHandling);
   1015  // Now it started scrolling.
   1016  EXPECT_GT(currentScrollOffset.y, 0);
   1017 
   1018  currentOverscrolledTransform =
   1019      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
   1020  mcc->AdvanceByMillis(5);
   1021  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1022  // The overscroll on X axis keeps being managed by the overscroll animation.
   1023  EXPECT_NE(
   1024      currentOverscrolledTransform._41,
   1025      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1026          ._41);
   1027  // But the overscroll on Y axis is no longer affected by the overscroll
   1028  // animation.
   1029  EXPECT_EQ(
   1030      currentOverscrolledTransform._42,
   1031      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1032          ._42);
   1033  // The scroll offset on Y axis shouldn't be changed by the overscroll
   1034  // animation.
   1035  EXPECT_EQ(currentScrollOffset.y,
   1036            apzc->GetCurrentAsyncScrollOffset(
   1037                    AsyncPanZoomController::eForEventHandling)
   1038                .y);
   1039 
   1040  currentOverscrolledTransform =
   1041      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
   1042  currentScrollOffset = apzc->GetCurrentAsyncScrollOffset(
   1043      AsyncPanZoomController::eForEventHandling);
   1044  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
   1045             ScreenIntPoint(50, 80), ScreenPoint(0, 100), mcc->Time());
   1046  EXPECT_TRUE(apzc->IsOverscrolled());
   1047  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   1048  // The overscroll amount on X axis shouldn't be changed by this momentum pan.
   1049  EXPECT_EQ(
   1050      currentOverscrolledTransform._41,
   1051      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1052          ._41);
   1053  // Keeping no overscrolling on Y axis.
   1054  EXPECT_EQ(
   1055      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1056          ._42,
   1057      0);
   1058  // Scrolling keeps going by momentum.
   1059  EXPECT_GT(apzc->GetCurrentAsyncScrollOffset(
   1060                    AsyncPanZoomController::eForEventHandling)
   1061                .y,
   1062            currentScrollOffset.y);
   1063 
   1064  currentScrollOffset = apzc->GetCurrentAsyncScrollOffset(
   1065      AsyncPanZoomController::eForEventHandling);
   1066  mcc->AdvanceByMillis(5);
   1067  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1068  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
   1069             ScreenIntPoint(50, 80), ScreenPoint(0, 10), mcc->Time());
   1070  EXPECT_TRUE(apzc->IsOverscrolled());
   1071  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   1072  // Keeping no overscrolling on Y axis.
   1073  EXPECT_EQ(
   1074      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1075          ._42,
   1076      0);
   1077  // Scrolling keeps going by momentum.
   1078  EXPECT_GT(apzc->GetCurrentAsyncScrollOffset(
   1079                    AsyncPanZoomController::eForEventHandling)
   1080                .y,
   1081            currentScrollOffset.y);
   1082 
   1083  currentOverscrolledTransform =
   1084      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
   1085  currentScrollOffset = apzc->GetCurrentAsyncScrollOffset(
   1086      AsyncPanZoomController::eForEventHandling);
   1087  mcc->AdvanceByMillis(5);
   1088  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1089  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
   1090             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
   1091  EXPECT_TRUE(apzc->IsOverscrolled());
   1092  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   1093  // Keeping no overscrolling on Y axis.
   1094  EXPECT_EQ(
   1095      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1096          ._42,
   1097      0);
   1098  // This momentum event doesn't change the scroll offset since its
   1099  // displacement is zero.
   1100  EXPECT_EQ(apzc->GetCurrentAsyncScrollOffset(
   1101                    AsyncPanZoomController::eForEventHandling)
   1102                .y,
   1103            currentScrollOffset.y);
   1104 
   1105  // Check that we recover from the horizontal overscroll via the animation.
   1106  ParentLayerPoint expectedScrollOffset(0, currentScrollOffset.y);
   1107  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
   1108 }
   1109 #endif
   1110 
   1111 #ifndef MOZ_WIDGET_ANDROID  // Maybe fails on Android
   1112 // This is another variant of
   1113 // HorizontalOverscrollAnimationWithVerticalPanMomentumScrolling. In this test,
   1114 // after a horizontal overscroll animation started, upwards pan moments happen,
   1115 // thus there should be a new vertical overscroll animation in addition to
   1116 // the horizontal one.
   1117 TEST_F(
   1118    APZCOverscrollTester,
   1119    VerticalOverscrollAnimationInAdditionToExistingHorizontalOverscrollAnimation) {
   1120  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1121 
   1122  ScrollMetadata metadata;
   1123  FrameMetrics& metrics = metadata.GetMetrics();
   1124  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
   1125  metrics.SetScrollableRect(CSSRect(0, 0, 1000, 5000));
   1126  // Scrolls the content 50px down.
   1127  metrics.SetVisualScrollOffset(CSSPoint(0, 50));
   1128  apzc->SetFrameMetrics(metrics);
   1129 
   1130  // Try to overscroll left with pan gestures.
   1131  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
   1132             ScreenPoint(-2, 0), mcc->Time());
   1133  mcc->AdvanceByMillis(5);
   1134  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1135  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
   1136             ScreenPoint(-10, 0), mcc->Time());
   1137  mcc->AdvanceByMillis(5);
   1138  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1139  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
   1140             ScreenPoint(-2, 0), mcc->Time());
   1141  mcc->AdvanceByMillis(5);
   1142  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1143  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
   1144             ScreenPoint(0, 0), mcc->Time());
   1145 
   1146  // Make sure we've started an overscroll animation.
   1147  EXPECT_TRUE(apzc->IsOverscrolled());
   1148  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   1149  AsyncTransformComponentMatrix initialOverscrolledTransform =
   1150      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
   1151 
   1152  // Send lengthy __upward__ momentums to make sure the overscroll animation
   1153  // doesn't clobber the momentums scrolling.
   1154  mcc->AdvanceByMillis(5);
   1155  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1156  // The overscroll amount on X axis has started being managed by the overscroll
   1157  // animation.
   1158  AsyncTransformComponentMatrix currentOverscrolledTransform =
   1159      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
   1160  EXPECT_NE(initialOverscrolledTransform._41, currentOverscrolledTransform._41);
   1161  // There is no overscroll on Y axis.
   1162  EXPECT_EQ(
   1163      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1164          ._42,
   1165      0);
   1166  ParentLayerPoint scrollOffset = apzc->GetCurrentAsyncScrollOffset(
   1167      AsyncPanZoomController::eForEventHandling);
   1168  // The scroll offset shouldn't be changed by the overscroll animation.
   1169  EXPECT_EQ(scrollOffset.y, 50);
   1170 
   1171  // Simple gesture on the Y axis to ensure that we can send a vertical
   1172  // momentum scroll
   1173  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
   1174             ScreenPoint(0, -2), mcc->Time());
   1175  mcc->AdvanceByMillis(5);
   1176  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1177  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
   1178             ScreenPoint(0, 2), mcc->Time());
   1179  mcc->AdvanceByMillis(5);
   1180  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1181  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
   1182             ScreenPoint(0, 0), mcc->Time());
   1183 
   1184  ParentLayerPoint offsetAfterPan = apzc->GetCurrentAsyncScrollOffset(
   1185      AsyncPanZoomController::eForEventHandling);
   1186 
   1187  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
   1188             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
   1189  EXPECT_TRUE(apzc->IsOverscrolled());
   1190  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   1191  // The overscroll amount on both axes shouldn't be changed by this pan
   1192  // momentum start event since the displacement is zero.
   1193  EXPECT_EQ(
   1194      currentOverscrolledTransform._41,
   1195      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1196          ._41);
   1197  EXPECT_EQ(
   1198      currentOverscrolledTransform._42,
   1199      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1200          ._42);
   1201 
   1202  mcc->AdvanceByMillis(5);
   1203  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1204  // The overscroll amount should be managed by the overscroll animation.
   1205  EXPECT_NE(
   1206      currentOverscrolledTransform._41,
   1207      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1208          ._41);
   1209  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
   1210      AsyncPanZoomController::eForEventHandling);
   1211  // Not yet started scrolling.
   1212  EXPECT_EQ(scrollOffset.y, offsetAfterPan.y);
   1213  EXPECT_EQ(scrollOffset.x, 0);
   1214 
   1215  currentOverscrolledTransform =
   1216      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
   1217 
   1218  // Send a long pan momentum.
   1219  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
   1220             ScreenIntPoint(50, 80), ScreenPoint(0, -200), mcc->Time());
   1221  EXPECT_TRUE(apzc->IsOverscrolled());
   1222  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   1223  // The overscroll amount on X axis shouldn't be changed by this momentum pan.
   1224  EXPECT_EQ(
   1225      currentOverscrolledTransform._41,
   1226      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1227          ._41);
   1228  // Now it started scrolling vertically.
   1229  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
   1230      AsyncPanZoomController::eForEventHandling);
   1231  EXPECT_EQ(scrollOffset.y, 0);
   1232  EXPECT_EQ(scrollOffset.x, 0);
   1233  // Actually it's also vertically overscrolled.
   1234  EXPECT_GT(
   1235      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1236          ._42,
   1237      0);
   1238 
   1239  currentOverscrolledTransform =
   1240      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
   1241  mcc->AdvanceByMillis(5);
   1242  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1243  // The overscroll on X axis keeps being managed by the overscroll animation.
   1244  EXPECT_NE(
   1245      currentOverscrolledTransform._41,
   1246      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1247          ._41);
   1248  // The overscroll on Y Axis hasn't been changed by the overscroll animation at
   1249  // this moment, sine the last displacement was consumed in the last pan
   1250  // momentum.
   1251  EXPECT_EQ(
   1252      currentOverscrolledTransform._42,
   1253      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1254          ._42);
   1255 
   1256  currentOverscrolledTransform =
   1257      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
   1258  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
   1259             ScreenIntPoint(50, 80), ScreenPoint(0, -100), mcc->Time());
   1260  EXPECT_TRUE(apzc->IsOverscrolled());
   1261  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   1262  // The overscroll amount on X axis shouldn't be changed by this momentum pan.
   1263  EXPECT_EQ(
   1264      currentOverscrolledTransform._41,
   1265      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1266          ._41);
   1267  // Now the overscroll amount on Y axis shouldn't be changed by this momentum
   1268  // pan either.
   1269  EXPECT_EQ(
   1270      currentOverscrolledTransform._42,
   1271      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1272          ._42);
   1273 
   1274  currentOverscrolledTransform =
   1275      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
   1276  mcc->AdvanceByMillis(5);
   1277  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1278  EXPECT_NE(
   1279      currentOverscrolledTransform._41,
   1280      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1281          ._41);
   1282  // And now the overscroll on Y Axis should be also managed by the overscroll
   1283  // animation.
   1284  EXPECT_NE(
   1285      currentOverscrolledTransform._42,
   1286      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1287          ._42);
   1288 
   1289  currentOverscrolledTransform =
   1290      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
   1291  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
   1292             ScreenIntPoint(50, 80), ScreenPoint(0, -10), mcc->Time());
   1293  EXPECT_TRUE(apzc->IsOverscrolled());
   1294  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   1295  // The overscroll amount on both axes shouldn't be changed by momentum event.
   1296  EXPECT_EQ(
   1297      currentOverscrolledTransform._41,
   1298      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1299          ._41);
   1300  EXPECT_EQ(
   1301      currentOverscrolledTransform._42,
   1302      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
   1303          ._42);
   1304 
   1305  currentOverscrolledTransform =
   1306      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
   1307  mcc->AdvanceByMillis(5);
   1308  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1309  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
   1310             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
   1311  EXPECT_TRUE(apzc->IsOverscrolled());
   1312  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   1313 
   1314  // Check that we recover from the horizontal overscroll via the animation.
   1315  ParentLayerPoint expectedScrollOffset(0, 0);
   1316  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
   1317 }
   1318 #endif
   1319 
   1320 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
   1321 TEST_F(APZCOverscrollTester, OverscrollByPanGesturesInterruptedByReflowZoom) {
   1322  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1323  SCOPED_GFX_PREF_INT("mousewheel.with_control.action", 3);  // reflow zoom.
   1324 
   1325  // A sanity check that pan gestures with ctrl modifier will not be handled by
   1326  // APZ.
   1327  PanGestureInput panInput(PanGestureInput::PANGESTURE_START, mcc->Time(),
   1328                           ScreenIntPoint(5, 5), ScreenPoint(0, -2),
   1329                           MODIFIER_CONTROL);
   1330  WidgetWheelEvent wheelEvent = panInput.ToWidgetEvent(nullptr);
   1331  EXPECT_FALSE(APZInputBridge::ActionForWheelEvent(&wheelEvent).isSome());
   1332 
   1333  ScrollableLayerGuid rootGuid = CreateSimpleRootScrollableForWebRender();
   1334  RefPtr<AsyncPanZoomController> apzc =
   1335      tm->GetTargetAPZC(rootGuid.mLayersId, rootGuid.mScrollId);
   1336 
   1337  PanGesture(PanGestureInput::PANGESTURE_START, tm, ScreenIntPoint(50, 80),
   1338             ScreenPoint(0, -2), mcc->Time());
   1339  mcc->AdvanceByMillis(5);
   1340  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1341  PanGesture(PanGestureInput::PANGESTURE_PAN, tm, ScreenIntPoint(50, 80),
   1342             ScreenPoint(0, -10), mcc->Time());
   1343  mcc->AdvanceByMillis(5);
   1344  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1345 
   1346  // Make sure overscrolling has started.
   1347  EXPECT_TRUE(apzc->IsOverscrolled());
   1348 
   1349  // Press ctrl until PANGESTURE_END.
   1350  PanGestureWithModifiers(PanGestureInput::PANGESTURE_PAN, MODIFIER_CONTROL, tm,
   1351                          ScreenIntPoint(50, 80), ScreenPoint(0, -2),
   1352                          mcc->Time());
   1353  mcc->AdvanceByMillis(5);
   1354  apzc->AdvanceAnimations(mcc->GetSampleTime());
   1355  // At this moment (i.e. PANGESTURE_PAN), still in overscrolling state.
   1356  EXPECT_TRUE(apzc->IsOverscrolled());
   1357 
   1358  PanGestureWithModifiers(PanGestureInput::PANGESTURE_END, MODIFIER_CONTROL, tm,
   1359                          ScreenIntPoint(50, 80), ScreenPoint(0, 0),
   1360                          mcc->Time());
   1361  // The overscrolling state should have been restored.
   1362  EXPECT_TRUE(!apzc->IsOverscrolled());
   1363 }
   1364 #endif
   1365 
   1366 #ifndef MOZ_WIDGET_ANDROID  // Only applies to GenericOverscrollEffect
   1367 TEST_F(APZCOverscrollTester, SmoothTransitionFromPanToAnimation) {
   1368  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1369 
   1370  ScrollMetadata metadata;
   1371  FrameMetrics& metrics = metadata.GetMetrics();
   1372  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
   1373  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
   1374  // Start scrolled down to y=500px.
   1375  metrics.SetVisualScrollOffset(CSSPoint(0, 500));
   1376  apzc->SetFrameMetrics(metrics);
   1377 
   1378  int frameLength = 10;    // milliseconds; 10 to keep the math simple
   1379  float panVelocity = 10;  // pixels per millisecond
   1380  int panPixelsPerFrame = frameLength * panVelocity;  // 100 pixels per frame
   1381 
   1382  ScreenIntPoint panPoint(50, 50);
   1383  PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
   1384             ScreenPoint(0, -1), mcc->Time());
   1385  // Pan up for 6 frames at 100 pixels per frame. This should reduce
   1386  // the vertical scroll offset from 500 to 0, and get us into overscroll.
   1387  for (int i = 0; i < 6; ++i) {
   1388    mcc->AdvanceByMillis(frameLength);
   1389    PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
   1390               ScreenPoint(0, -panPixelsPerFrame), mcc->Time());
   1391  }
   1392  EXPECT_TRUE(apzc->IsOverscrolled());
   1393 
   1394  // Pan further into overscroll at the same input velocity, enough
   1395  // for the frames while we are in overscroll to dominate the computation
   1396  // in the velocity tracker.
   1397  // Importantly, while the input velocity is still 100 pixels per frame,
   1398  // in the overscrolled state the page only visual moves by at most 8 pixels
   1399  // per frame.
   1400  int frames = StaticPrefs::apz_velocity_relevance_time_ms() / frameLength;
   1401  for (int i = 0; i < frames; ++i) {
   1402    mcc->AdvanceByMillis(frameLength);
   1403    PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
   1404               ScreenPoint(0, -panPixelsPerFrame), mcc->Time());
   1405  }
   1406  EXPECT_TRUE(apzc->IsOverscrolled());
   1407 
   1408  // End the pan, allowing an overscroll animation to start.
   1409  mcc->AdvanceByMillis(frameLength);
   1410  PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
   1411             mcc->Time());
   1412  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   1413 
   1414  // Check that the velocity reflects the actual movement (no more than 8
   1415  // pixels/frame ==> 0.8 pixels per millisecond), not the input velocity
   1416  // (100 pixels/frame ==> 10 pixels per millisecond). This ensures that
   1417  // the transition from the pan to the animation appears smooth.
   1418  // (Note: velocities are negative since they are upwards.)
   1419  EXPECT_LT(apzc->GetVelocityVector().y, 0);
   1420  EXPECT_GT(apzc->GetVelocityVector().y, -0.8);
   1421 }
   1422 #endif
   1423 
   1424 #ifndef MOZ_WIDGET_ANDROID  // Only applies to GenericOverscrollEffect
   1425 TEST_F(APZCOverscrollTester, NoOverscrollForMousewheel) {
   1426  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1427 
   1428  ScrollMetadata metadata;
   1429  FrameMetrics& metrics = metadata.GetMetrics();
   1430  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
   1431  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
   1432  // Start scrolled down just a few pixels from the top.
   1433  metrics.SetVisualScrollOffset(CSSPoint(0, 3));
   1434  // Set line and page scroll amounts. Otherwise, even though Wheel() uses
   1435  // SCROLLDELTA_PIXEL, the wheel handling code will get confused by things
   1436  // like the "don't scroll more than one page" check.
   1437  metadata.SetPageScrollAmount(LayoutDeviceIntSize(50, 100));
   1438  metadata.SetLineScrollAmount(LayoutDeviceIntSize(5, 10));
   1439  apzc->SetScrollMetadata(metadata);
   1440 
   1441  // Send a wheel with enough delta to scrollto y=0 *and* overscroll.
   1442  Wheel(apzc, ScreenIntPoint(10, 10), ScreenPoint(0, -10), mcc->Time());
   1443 
   1444  // Check that we did not actually go into overscroll.
   1445  EXPECT_FALSE(apzc->IsOverscrolled());
   1446 }
   1447 #endif
   1448 
   1449 #ifndef MOZ_WIDGET_ANDROID  // Only applies to GenericOverscrollEffect
   1450 TEST_F(APZCOverscrollTester, ClickWhileOverscrolled) {
   1451  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1452 
   1453  ScrollMetadata metadata;
   1454  FrameMetrics& metrics = metadata.GetMetrics();
   1455  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
   1456  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
   1457  metrics.SetVisualScrollOffset(CSSPoint(0, 0));
   1458  apzc->SetFrameMetrics(metrics);
   1459 
   1460  // Pan into overscroll at the top.
   1461  ScreenIntPoint panPoint(50, 50);
   1462  PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
   1463             ScreenPoint(0, -1), mcc->Time());
   1464  mcc->AdvanceByMillis(10);
   1465  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
   1466             ScreenPoint(0, -100), mcc->Time());
   1467  EXPECT_TRUE(apzc->IsOverscrolled());
   1468  EXPECT_TRUE(apzc->GetOverscrollAmount().y < 0);  // overscrolled at top
   1469 
   1470  // End the pan. This should start an overscroll animation.
   1471  mcc->AdvanceByMillis(10);
   1472  PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
   1473             mcc->Time());
   1474  EXPECT_TRUE(apzc->GetOverscrollAmount().y < 0);  // overscrolled at top
   1475  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   1476 
   1477  // Send a mouse-down. This should interrupt the animation but not relieve
   1478  // overscroll yet.
   1479  ParentLayerPoint overscrollBefore = apzc->GetOverscrollAmount();
   1480  MouseDown(apzc, panPoint, mcc->Time());
   1481  EXPECT_FALSE(apzc->IsOverscrollAnimationRunning());
   1482  EXPECT_EQ(overscrollBefore, apzc->GetOverscrollAmount());
   1483 
   1484  // Send a mouse-up. This should start an overscroll animation again.
   1485  MouseUp(apzc, panPoint, mcc->Time());
   1486  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   1487 
   1488  SampleAnimationUntilRecoveredFromOverscroll(ParentLayerPoint(0, 0));
   1489 }
   1490 #endif
   1491 
   1492 #ifndef MOZ_WIDGET_ANDROID  // Only applies to GenericOverscrollEffect
   1493 TEST_F(APZCOverscrollTester, DynamicallyLoadingContent) {
   1494  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1495 
   1496  ScrollMetadata metadata;
   1497  FrameMetrics& metrics = metadata.GetMetrics();
   1498  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
   1499  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
   1500  metrics.SetVisualScrollOffset(CSSPoint(0, 0));
   1501  apzc->SetFrameMetrics(metrics);
   1502 
   1503  // Pan to the bottom of the page, and further, into overscroll.
   1504  ScreenIntPoint panPoint(50, 50);
   1505  PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
   1506             ScreenPoint(0, 1), mcc->Time());
   1507  for (int i = 0; i < 12; ++i) {
   1508    mcc->AdvanceByMillis(10);
   1509    PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
   1510               ScreenPoint(0, 100), mcc->Time());
   1511  }
   1512  EXPECT_TRUE(apzc->IsOverscrolled());
   1513  EXPECT_TRUE(apzc->GetOverscrollAmount().y > 0);  // overscrolled at bottom
   1514 
   1515  // Grow the scrollable rect at the bottom, simulating the page loading content
   1516  // dynamically.
   1517  CSSRect scrollableRect = metrics.GetScrollableRect();
   1518  scrollableRect.height += 500;
   1519  metrics.SetScrollableRect(scrollableRect);
   1520  apzc->NotifyLayersUpdated(
   1521      metadata,
   1522      LayersUpdateFlags{.mIsFirstPaint = false, .mThisLayerTreeUpdated = true});
   1523 
   1524  // Check that the modified scrollable rect cleared the overscroll.
   1525  EXPECT_FALSE(apzc->IsOverscrolled());
   1526 
   1527  // Pan back up to the top, and further, into overscroll.
   1528  PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
   1529             ScreenPoint(0, -1), mcc->Time());
   1530  for (int i = 0; i < 12; ++i) {
   1531    mcc->AdvanceByMillis(10);
   1532    PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
   1533               ScreenPoint(0, -100), mcc->Time());
   1534  }
   1535  EXPECT_TRUE(apzc->IsOverscrolled());
   1536  ParentLayerPoint overscrollAmount = apzc->GetOverscrollAmount();
   1537  EXPECT_TRUE(overscrollAmount.y < 0);  // overscrolled at top
   1538 
   1539  // Grow the scrollable rect at the bottom again.
   1540  scrollableRect = metrics.GetScrollableRect();
   1541  scrollableRect.height += 500;
   1542  metrics.SetScrollableRect(scrollableRect);
   1543  apzc->NotifyLayersUpdated(
   1544      metadata,
   1545      LayersUpdateFlags{.mIsFirstPaint = false, .mThisLayerTreeUpdated = true});
   1546 
   1547  // Check that the modified scrollable rect did NOT clear overscroll at the
   1548  // top.
   1549  EXPECT_TRUE(apzc->IsOverscrolled());
   1550  EXPECT_EQ(overscrollAmount,
   1551            apzc->GetOverscrollAmount());  // overscroll did not change at all
   1552 }
   1553 #endif
   1554 
   1555 #ifndef MOZ_WIDGET_ANDROID  // Only applies to GenericOverscrollEffect
   1556 TEST_F(APZCOverscrollTester, SmallAmountOfOverscroll) {
   1557  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1558 
   1559  ScrollMetadata metadata;
   1560  FrameMetrics& metrics = metadata.GetMetrics();
   1561  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
   1562  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
   1563 
   1564  // Do vertical overscroll first.
   1565  ScreenIntPoint panPoint(50, 50);
   1566  PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
   1567             ScreenPoint(0, -10), mcc->Time());
   1568  mcc->AdvanceByMillis(10);
   1569  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
   1570             ScreenPoint(0, -10), mcc->Time());
   1571  mcc->AdvanceByMillis(10);
   1572  PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
   1573             mcc->Time());
   1574  mcc->AdvanceByMillis(10);
   1575 
   1576  // Then do small horizontal overscroll which will be considered as "finished"
   1577  // by our overscroll animation physics model.
   1578  PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
   1579             ScreenPoint(-0.1, 0), mcc->Time());
   1580  mcc->AdvanceByMillis(10);
   1581  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
   1582             ScreenPoint(-0.2, 0), mcc->Time());
   1583  mcc->AdvanceByMillis(10);
   1584  PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
   1585             mcc->Time());
   1586  mcc->AdvanceByMillis(10);
   1587 
   1588  EXPECT_TRUE(apzc->IsOverscrolled());
   1589  EXPECT_TRUE(apzc->GetOverscrollAmount().y < 0);  // overscrolled at top
   1590  EXPECT_TRUE(apzc->GetOverscrollAmount().x < 0);  // and overscrolled at left
   1591 
   1592  // Then do vertical scroll.
   1593  PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
   1594             ScreenPoint(0, 10), mcc->Time());
   1595  mcc->AdvanceByMillis(10);
   1596  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
   1597             ScreenPoint(0, 100), mcc->Time());
   1598  mcc->AdvanceByMillis(10);
   1599  PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
   1600             mcc->Time());
   1601 
   1602  ParentLayerPoint scrollOffset = apzc->GetCurrentAsyncScrollOffset(
   1603      AsyncPanZoomController::eForEventHandling);
   1604  EXPECT_GT(scrollOffset.y, 0);  // Make sure the vertical scroll offset is
   1605                                 // greater than zero.
   1606 
   1607  // The small horizontal overscroll amount should be restored to zero.
   1608  ParentLayerPoint expectedScrollOffset(0, scrollOffset.y);
   1609  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
   1610 }
   1611 #endif
   1612 
   1613 #ifdef MOZ_WIDGET_ANDROID
   1614 TEST_F(APZCOverscrollTester, StretchUpDown_Bug1892177) {
   1615  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1616 
   1617  ScrollMetadata metadata;
   1618  FrameMetrics& metrics = metadata.GetMetrics();
   1619  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
   1620  // Composition bounds show all of the horizontal space of that scrollable rect
   1621  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
   1622  apzc->SetFrameMetrics(metrics);
   1623 
   1624  MockFunction<void(std::string checkPointName)> checkScroll;
   1625  {
   1626    // Motion of the scrollable screen:
   1627    // - Up to the vertical y limit of the page.
   1628    // - Right
   1629    InSequence s;
   1630    EXPECT_CALL(checkScroll, Call("Touch Scroll Diagonally Upwards Start"));
   1631 
   1632    // Even though the touch gesture includes horizontal movement,
   1633    // do not show a horizontal overscroll effect because the page
   1634    // is not scrollable horizontally.
   1635    EXPECT_CALL(*mcc, UpdateOverscrollOffset(_, 0, _, _)).Times(AtLeast(1));
   1636 
   1637    EXPECT_CALL(checkScroll, Call("Touch Scroll Diagonally Upwards End"));
   1638  }
   1639 
   1640  checkScroll.Call("Touch Scroll Diagonally Upwards Start");
   1641  // Scroll up
   1642  ScreenIntPoint startPoint(10, 50);
   1643  ScreenIntPoint endPoint(20, 100);
   1644  Pan(apzc, startPoint, endPoint, PanOptions::KeepFingerDown);
   1645 
   1646  checkScroll.Call("Touch Scroll Diagonally Upwards End");
   1647 
   1648  EXPECT_TRUE(apzc->IsOverscrolled());
   1649 }
   1650 #endif
   1651 
   1652 #ifdef MOZ_WIDGET_ANDROID  // Only applies to WidgetOverscrollEffect
   1653 TEST_F(APZCOverscrollTester, StuckInOverscroll_Bug1786452) {
   1654  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1655 
   1656  ScrollMetadata metadata;
   1657  FrameMetrics& metrics = metadata.GetMetrics();
   1658  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
   1659  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
   1660 
   1661  // Over the course of the test, expect one or more calls to
   1662  // UpdateOverscrollOffset(), followed by a call to UpdateOverscrollVelocity().
   1663  // The latter ensures the widget has a chance to end its overscroll effect.
   1664  InSequence s;
   1665  EXPECT_CALL(*mcc, UpdateOverscrollOffset(_, _, _, _)).Times(AtLeast(1));
   1666  EXPECT_CALL(*mcc, UpdateOverscrollVelocity(_, _, _, _)).Times(1);
   1667 
   1668  // Pan into overscroll, keeping the finger down
   1669  ScreenIntPoint startPoint(10, 500);
   1670  ScreenIntPoint endPoint(10, 10);
   1671  Pan(apzc, startPoint, endPoint, PanOptions::KeepFingerDown);
   1672  EXPECT_TRUE(apzc->IsOverscrolled());
   1673 
   1674  // Linger a while to cause the velocity to drop to very low or zero
   1675  mcc->AdvanceByMillis(100);
   1676  TouchMove(apzc, endPoint, mcc->Time());
   1677  EXPECT_LT(apzc->GetVelocityVector().Length(),
   1678            StaticPrefs::apz_fling_min_velocity_threshold());
   1679  EXPECT_TRUE(apzc->IsOverscrolled());
   1680 
   1681  // Lift the finger
   1682  mcc->AdvanceByMillis(20);
   1683  TouchUp(apzc, endPoint, mcc->Time());
   1684  EXPECT_FALSE(apzc->IsOverscrolled());
   1685 }
   1686 #endif
   1687 
   1688 class APZCOverscrollTesterMock : public APZCTreeManagerTester {
   1689 public:
   1690  APZCOverscrollTesterMock() { CreateMockHitTester(); }
   1691 
   1692  UniquePtr<ScopedLayerTreeRegistration> registration;
   1693  TestAsyncPanZoomController* rootApzc;
   1694 };
   1695 
   1696 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
   1697 TEST_F(APZCOverscrollTesterMock, OverscrollHandoff) {
   1698  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1699 
   1700  const char* treeShape = "x(x)";
   1701  LayerIntRect layerVisibleRect[] = {LayerIntRect(0, 0, 100, 100),
   1702                                     LayerIntRect(0, 0, 100, 50)};
   1703  CreateScrollData(treeShape, layerVisibleRect);
   1704  SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
   1705                            CSSRect(0, 0, 200, 200));
   1706  SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID + 1,
   1707                            // same size as the visible region so that
   1708                            // the container is not scrollable in any directions
   1709                            // actually. This is simulating overflow: hidden
   1710                            // iframe document in Fission, though we don't set
   1711                            // a different layers id.
   1712                            CSSRect(0, 0, 100, 50));
   1713 
   1714  SetScrollHandoff(layers[1], root);
   1715 
   1716  registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
   1717  UpdateHitTestingTree();
   1718  rootApzc = ApzcOf(root);
   1719  rootApzc->GetFrameMetrics().SetIsRootContent(true);
   1720 
   1721  // A pan gesture on the child scroller (which is not scrollable though).
   1722  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1723  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 20),
   1724             ScreenPoint(0, -2), mcc->Time());
   1725  EXPECT_TRUE(rootApzc->IsOverscrolled());
   1726 }
   1727 #endif
   1728 
   1729 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
   1730 TEST_F(APZCOverscrollTesterMock, VerticalOverscrollHandoffToScrollableRoot) {
   1731  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1732 
   1733  // Create a layer tree having two vertical scrollable layers.
   1734  const char* treeShape = "x(x)";
   1735  LayerIntRect layerVisibleRect[] = {LayerIntRect(0, 0, 100, 100),
   1736                                     LayerIntRect(0, 0, 100, 50)};
   1737  CreateScrollData(treeShape, layerVisibleRect);
   1738  SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
   1739                            CSSRect(0, 0, 100, 200));
   1740  SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID + 1,
   1741                            CSSRect(0, 0, 100, 200));
   1742 
   1743  SetScrollHandoff(layers[1], root);
   1744 
   1745  registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
   1746  UpdateHitTestingTree();
   1747  rootApzc = ApzcOf(root);
   1748  rootApzc->GetFrameMetrics().SetIsRootContent(true);
   1749 
   1750  // A vertical pan gesture on the child scroller which will be handed off to
   1751  // the root APZC.
   1752  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1753  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 20),
   1754             ScreenPoint(0, -2), mcc->Time());
   1755  EXPECT_TRUE(rootApzc->IsOverscrolled());
   1756  EXPECT_FALSE(ApzcOf(layers[1])->IsOverscrolled());
   1757 }
   1758 #endif
   1759 
   1760 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
   1761 TEST_F(APZCOverscrollTesterMock, NoOverscrollHandoffToNonScrollableRoot) {
   1762  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1763 
   1764  // Create a layer tree having non-scrollable root and a vertical scrollable
   1765  // child.
   1766  const char* treeShape = "x(x)";
   1767  LayerIntRect layerVisibleRect[] = {LayerIntRect(0, 0, 100, 100),
   1768                                     LayerIntRect(0, 0, 100, 50)};
   1769  CreateScrollData(treeShape, layerVisibleRect);
   1770  SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
   1771                            CSSRect(0, 0, 100, 100));
   1772  SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID + 1,
   1773                            CSSRect(0, 0, 100, 200));
   1774 
   1775  SetScrollHandoff(layers[1], root);
   1776 
   1777  registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
   1778  UpdateHitTestingTree();
   1779  rootApzc = ApzcOf(root);
   1780  rootApzc->GetFrameMetrics().SetIsRootContent(true);
   1781 
   1782  // A vertical pan gesture on the child scroller which should not be handed
   1783  // off the root APZC.
   1784  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1785  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 20),
   1786             ScreenPoint(0, -2), mcc->Time());
   1787  EXPECT_FALSE(rootApzc->IsOverscrolled());
   1788  EXPECT_TRUE(ApzcOf(layers[1])->IsOverscrolled());
   1789 }
   1790 #endif
   1791 
   1792 #ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
   1793 TEST_F(APZCOverscrollTesterMock, NoOverscrollHandoffOrthogonalPanGesture) {
   1794  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1795 
   1796  // Create a layer tree having horizontal scrollable root and a vertical
   1797  // scrollable child.
   1798  const char* treeShape = "x(x)";
   1799  LayerIntRect layerVisibleRect[] = {LayerIntRect(0, 0, 100, 100),
   1800                                     LayerIntRect(0, 0, 100, 50)};
   1801  CreateScrollData(treeShape, layerVisibleRect);
   1802  SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
   1803                            CSSRect(0, 0, 200, 100));
   1804  SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID + 1,
   1805                            CSSRect(0, 0, 100, 200));
   1806 
   1807  SetScrollHandoff(layers[1], root);
   1808 
   1809  registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
   1810  UpdateHitTestingTree();
   1811  rootApzc = ApzcOf(root);
   1812  rootApzc->GetFrameMetrics().SetIsRootContent(true);
   1813 
   1814  // A vertical pan gesture on the child scroller which should not be handed
   1815  // off the root APZC because the root APZC is not scrollable vertically.
   1816  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1817  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 20),
   1818             ScreenPoint(0, -2), mcc->Time());
   1819  EXPECT_FALSE(rootApzc->IsOverscrolled());
   1820  EXPECT_TRUE(ApzcOf(layers[1])->IsOverscrolled());
   1821 }
   1822 #endif
   1823 
   1824 #ifndef MOZ_WIDGET_ANDROID  // Only applies to GenericOverscrollEffect
   1825 TEST_F(APZCOverscrollTesterMock,
   1826       RetriggerCancelledOverscrollAnimationByNewPanGesture) {
   1827  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1828 
   1829  // Create a layer tree having vertical scrollable root and a horizontal
   1830  // scrollable child.
   1831  const char* treeShape = "x(x)";
   1832  LayerIntRect layerVisibleRect[] = {LayerIntRect(0, 0, 100, 100),
   1833                                     LayerIntRect(0, 0, 100, 50)};
   1834  CreateScrollData(treeShape, layerVisibleRect);
   1835  SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
   1836                            CSSRect(0, 0, 100, 200));
   1837  SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID + 1,
   1838                            CSSRect(0, 0, 200, 50));
   1839 
   1840  SetScrollHandoff(layers[1], root);
   1841 
   1842  registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
   1843  UpdateHitTestingTree();
   1844  rootApzc = ApzcOf(root);
   1845  rootApzc->GetFrameMetrics().SetIsRootContent(true);
   1846 
   1847  ScreenIntPoint panPoint(50, 20);
   1848  // A vertical pan gesture on the child scroller which should be handed off the
   1849  // root APZC.
   1850  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1851  PanGesture(PanGestureInput::PANGESTURE_START, manager, panPoint,
   1852             ScreenPoint(0, -2), mcc->Time());
   1853  mcc->AdvanceByMillis(10);
   1854  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1855  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, panPoint,
   1856             ScreenPoint(0, -10), mcc->Time());
   1857  mcc->AdvanceByMillis(10);
   1858  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1859  PanGesture(PanGestureInput::PANGESTURE_END, manager, panPoint,
   1860             ScreenPoint(0, 0), mcc->Time());
   1861 
   1862  // The root APZC should be overscrolled and the child APZC should not be.
   1863  EXPECT_TRUE(rootApzc->IsOverscrolled());
   1864  EXPECT_FALSE(ApzcOf(layers[1])->IsOverscrolled());
   1865 
   1866  mcc->AdvanceByMillis(10);
   1867 
   1868  // Make sure the root APZC is still overscrolled.
   1869  EXPECT_TRUE(rootApzc->IsOverscrolled());
   1870 
   1871  // Start a new horizontal pan gesture on the child scroller which should be
   1872  // handled by the child APZC now.
   1873  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1874  APZEventResult result = PanGesture(PanGestureInput::PANGESTURE_START, manager,
   1875                                     panPoint, ScreenPoint(-2, 0), mcc->Time());
   1876  // The above horizontal pan start event was flagged as "this event may trigger
   1877  // swipe" and either the root scrollable frame or the horizontal child
   1878  // scrollable frame is not scrollable in the pan start direction, thus the pan
   1879  // start event run into the short circuit path for swipe-to-navigation in
   1880  // InputQueue::ReceivePanGestureInput, which means it's waiting for the
   1881  // content response, so we need to respond explicitly here.
   1882  manager->ContentReceivedInputBlock(result.mInputBlockId, false);
   1883  mcc->AdvanceByMillis(10);
   1884  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1885  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, panPoint,
   1886             ScreenPoint(-10, 0), mcc->Time());
   1887  mcc->AdvanceByMillis(10);
   1888  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1889  PanGesture(PanGestureInput::PANGESTURE_END, manager, panPoint,
   1890             ScreenPoint(0, 0), mcc->Time());
   1891 
   1892  // Now both APZCs should be overscrolled.
   1893  EXPECT_TRUE(rootApzc->IsOverscrolled());
   1894  EXPECT_TRUE(ApzcOf(layers[1])->IsOverscrolled());
   1895 
   1896  // Sample all animations until all of them have been finished.
   1897  while (SampleAnimationsOnce());
   1898 
   1899  // After the animations finished, all overscrolled states should have been
   1900  // restored.
   1901  EXPECT_FALSE(rootApzc->IsOverscrolled());
   1902  EXPECT_FALSE(ApzcOf(layers[1])->IsOverscrolled());
   1903 }
   1904 #endif
   1905 
   1906 #ifndef MOZ_WIDGET_ANDROID  // Only applies to GenericOverscrollEffect
   1907 TEST_F(APZCOverscrollTesterMock, RetriggeredOverscrollAnimationVelocity) {
   1908  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1909 
   1910  // Setup two nested vertical scrollable frames.
   1911  const char* treeShape = "x(x)";
   1912  LayerIntRect layerVisibleRect[] = {LayerIntRect(0, 0, 100, 100),
   1913                                     LayerIntRect(0, 0, 100, 50)};
   1914  CreateScrollData(treeShape, layerVisibleRect);
   1915  SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
   1916                            CSSRect(0, 0, 100, 200));
   1917  SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID + 1,
   1918                            CSSRect(0, 0, 100, 200));
   1919 
   1920  SetScrollHandoff(layers[1], root);
   1921 
   1922  registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
   1923  UpdateHitTestingTree();
   1924  rootApzc = ApzcOf(root);
   1925  rootApzc->GetFrameMetrics().SetIsRootContent(true);
   1926 
   1927  ScreenIntPoint panPoint(50, 20);
   1928  // A vertical upward pan gesture on the child scroller which should be handed
   1929  // off the root APZC.
   1930  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1931  PanGesture(PanGestureInput::PANGESTURE_START, manager, panPoint,
   1932             ScreenPoint(0, -2), mcc->Time());
   1933  mcc->AdvanceByMillis(10);
   1934  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1935  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, panPoint,
   1936             ScreenPoint(0, -10), mcc->Time());
   1937  mcc->AdvanceByMillis(10);
   1938  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1939  PanGesture(PanGestureInput::PANGESTURE_END, manager, panPoint,
   1940             ScreenPoint(0, 0), mcc->Time());
   1941 
   1942  // The root APZC should be overscrolled and the child APZC should not be.
   1943  EXPECT_TRUE(rootApzc->IsOverscrolled());
   1944  EXPECT_FALSE(ApzcOf(layers[1])->IsOverscrolled());
   1945 
   1946  mcc->AdvanceByMillis(10);
   1947 
   1948  // Make sure the root APZC is still overscrolled and there's an overscroll
   1949  // animation.
   1950  EXPECT_TRUE(rootApzc->IsOverscrolled());
   1951  EXPECT_TRUE(rootApzc->IsOverscrollAnimationRunning());
   1952 
   1953  // And make sure the overscroll animation's velocity is a certain amount in
   1954  // the upward direction.
   1955  EXPECT_LT(rootApzc->GetVelocityVector().y, 0);
   1956 
   1957  // Start a new downward pan gesture on the child scroller which
   1958  // should be handled by the child APZC now.
   1959  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1960  PanGesture(PanGestureInput::PANGESTURE_START, manager, panPoint,
   1961             ScreenPoint(0, 2), mcc->Time());
   1962  mcc->AdvanceByMillis(10);
   1963  // The new pan-start gesture stops the overscroll animation at this moment.
   1964  EXPECT_TRUE(!rootApzc->IsOverscrollAnimationRunning());
   1965 
   1966  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1967  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, panPoint,
   1968             ScreenPoint(0, 10), mcc->Time());
   1969  mcc->AdvanceByMillis(10);
   1970  // There's no overscroll animation yet even if the root APZC is still
   1971  // overscrolled.
   1972  EXPECT_TRUE(!rootApzc->IsOverscrollAnimationRunning());
   1973  EXPECT_TRUE(rootApzc->IsOverscrolled());
   1974 
   1975  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
   1976  PanGesture(PanGestureInput::PANGESTURE_END, manager, panPoint,
   1977             ScreenPoint(0, 10), mcc->Time());
   1978 
   1979  // Now an overscroll animation should have been triggered by the pan-end
   1980  // gesture.
   1981  EXPECT_TRUE(rootApzc->IsOverscrollAnimationRunning());
   1982  EXPECT_TRUE(rootApzc->IsOverscrolled());
   1983  // And the newly created overscroll animation's positions should never exceed
   1984  // 0.
   1985  while (SampleAnimationsOnce()) {
   1986    EXPECT_LE(rootApzc->GetOverscrollAmount().y, 0);
   1987  }
   1988 }
   1989 #endif
   1990 
   1991 #ifndef MOZ_WIDGET_ANDROID  // Only applies to GenericOverscrollEffect
   1992 TEST_F(APZCOverscrollTesterMock, OverscrollIntoPreventDefault) {
   1993  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   1994 
   1995  const char* treeShape = "x";
   1996  LayerIntRect layerVisibleRects[] = {LayerIntRect(0, 0, 100, 100)};
   1997  CreateScrollData(treeShape, layerVisibleRects);
   1998  SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
   1999                            CSSRect(0, 0, 100, 200));
   2000 
   2001  registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
   2002  UpdateHitTestingTree();
   2003  rootApzc = ApzcOf(root);
   2004 
   2005  // Start a pan gesture a few pixels below the 20px DTC region.
   2006  ScreenIntPoint cursorLocation(10, 25);
   2007  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
   2008  APZEventResult result =
   2009      PanGesture(PanGestureInput::PANGESTURE_START, manager, cursorLocation,
   2010                 ScreenPoint(0, -2), mcc->Time());
   2011 
   2012  // At this point, we should be overscrolled.
   2013  EXPECT_TRUE(rootApzc->IsOverscrolled());
   2014 
   2015  // Pan further, until the DTC region is under the cursor.
   2016  // Note that, due to ApplyResistance(), we need a large input delta to cause a
   2017  // visual transform enough to bridge the 5px to the DTC region.
   2018  mcc->AdvanceByMillis(10);
   2019  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
   2020  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, cursorLocation,
   2021             ScreenPoint(0, -100), mcc->Time());
   2022 
   2023  // At this point, we are still overscrolled. Record the overscroll amount.
   2024  EXPECT_TRUE(rootApzc->IsOverscrolled());
   2025  float overscrollY = rootApzc->GetOverscrollAmount().y;
   2026 
   2027  // Send a content response with preventDefault = true.
   2028  manager->SetTargetAPZC(result.mInputBlockId, {result.mTargetGuid});
   2029  manager->ContentReceivedInputBlock(result.mInputBlockId,
   2030                                     /*aPreventDefault=*/true);
   2031 
   2032  // The content response has the effect of interrupting the input block
   2033  // but no processing happens yet (as there are no events in the block).
   2034  EXPECT_TRUE(rootApzc->IsOverscrolled());
   2035  EXPECT_EQ(overscrollY, rootApzc->GetOverscrollAmount().y);
   2036 
   2037  // Send one more pan event. This starts a new, *unconfirmed* input block
   2038  // (via the "transmogrify" codepath).
   2039  mcc->AdvanceByMillis(10);
   2040  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID,
   2041                     {CompositorHitTestFlags::eVisibleToHitTest,
   2042                      CompositorHitTestFlags::eIrregularArea});
   2043  result = PanGesture(PanGestureInput::PANGESTURE_PAN, manager, cursorLocation,
   2044                      ScreenPoint(0, -10), mcc->Time());
   2045 
   2046  // No overscroll occurs (the event is waiting in the queue for confirmation).
   2047  EXPECT_TRUE(rootApzc->IsOverscrolled());
   2048  EXPECT_EQ(overscrollY, rootApzc->GetOverscrollAmount().y);
   2049 
   2050  // preventDefault the new event as well
   2051  manager->SetTargetAPZC(result.mInputBlockId, {result.mTargetGuid});
   2052  manager->ContentReceivedInputBlock(result.mInputBlockId,
   2053                                     /*aPreventDefault=*/true);
   2054 
   2055  // This should trigger clearing the overscrolling and resetting the state.
   2056  EXPECT_FALSE(rootApzc->IsOverscrolled());
   2057  rootApzc->AssertStateIsReset();
   2058 
   2059  // If there are momentum events after this point, they should not cause
   2060  // further scrolling or overscorll.
   2061  mcc->AdvanceByMillis(10);
   2062  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
   2063  result = PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, manager,
   2064                      cursorLocation, ScreenPoint(0, -100), mcc->Time());
   2065  mcc->AdvanceByMillis(10);
   2066  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
   2067  result = PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, manager,
   2068                      cursorLocation, ScreenPoint(0, -100), mcc->Time());
   2069  EXPECT_FALSE(rootApzc->IsOverscrolled());
   2070  EXPECT_EQ(rootApzc->GetFrameMetrics().GetVisualScrollOffset(),
   2071            CSSPoint(0, 0));
   2072 }
   2073 #endif
   2074 
   2075 #ifndef MOZ_WIDGET_ANDROID  // Only applies to GenericOverscrollEffect
   2076 TEST_F(APZCOverscrollTesterMock, StuckInOverscroll_Bug1810935) {
   2077  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   2078 
   2079  using ViewID = ScrollableLayerGuid::ViewID;
   2080  ViewID rootScrollId = ScrollableLayerGuid::START_SCROLL_ID;
   2081  ViewID subframeScrollId = ScrollableLayerGuid::START_SCROLL_ID + 1;
   2082 
   2083  const char* treeShape = "x(x)";
   2084  LayerIntRect layerVisibleRects[] = {LayerIntRect(0, 0, 100, 100),
   2085                                      LayerIntRect(50, 0, 50, 100)};
   2086  CreateScrollData(treeShape, layerVisibleRects);
   2087  SetScrollableFrameMetrics(root, rootScrollId, CSSRect(0, 0, 100, 200));
   2088  SetScrollableFrameMetrics(layers[1], subframeScrollId,
   2089                            CSSRect(0, 0, 50, 200));
   2090  SetScrollHandoff(layers[1], root);
   2091 
   2092  registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
   2093  UpdateHitTestingTree();
   2094  rootApzc = ApzcOf(root);
   2095  auto* subframeApzc = ApzcOf(layers[1]);
   2096  rootApzc->GetFrameMetrics().SetIsRootContent(true);
   2097 
   2098  // Try to scroll upwards over the subframe.
   2099  ScreenIntPoint panPoint(75, 50);
   2100  QueueMockHitResult(subframeScrollId);
   2101  PanGesture(PanGestureInput::PANGESTURE_START, manager, panPoint,
   2102             ScreenPoint(0, -10), mcc->Time());
   2103  mcc->AdvanceByMillis(10);
   2104  QueueMockHitResult(subframeScrollId);
   2105  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, panPoint,
   2106             ScreenPoint(0, -50), mcc->Time());
   2107  mcc->AdvanceByMillis(10);
   2108  QueueMockHitResult(subframeScrollId);
   2109  PanGesture(PanGestureInput::PANGESTURE_END, manager, panPoint,
   2110             ScreenPoint(0, 0), mcc->Time());
   2111 
   2112  // The root APZC should be overscrolled. (The subframe APZC should be be.)
   2113  EXPECT_TRUE(rootApzc->IsOverscrolled());
   2114  EXPECT_FALSE(subframeApzc->IsOverscrolled());
   2115 
   2116  // Give the overscroll animation on the root a chance to start.
   2117  mcc->AdvanceByMillis(10);
   2118  EXPECT_TRUE(rootApzc->IsOverscrollAnimationRunning());
   2119 
   2120  // Scroll the subframe downwards, with a large delta.
   2121  QueueMockHitResult(subframeScrollId);
   2122  PanGesture(PanGestureInput::PANGESTURE_START, manager, panPoint,
   2123             ScreenPoint(0, 50), mcc->Time());
   2124 
   2125  // Already after the first event, the overscroll animation should be
   2126  // interrupted.
   2127  EXPECT_FALSE(rootApzc->IsOverscrollAnimationRunning());
   2128 
   2129  // Cotninue the downward scroll gesture.
   2130  mcc->AdvanceByMillis(10);
   2131  QueueMockHitResult(subframeScrollId);
   2132  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, panPoint,
   2133             ScreenPoint(0, 100), mcc->Time());
   2134  mcc->AdvanceByMillis(10);
   2135  QueueMockHitResult(subframeScrollId);
   2136  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, panPoint,
   2137             ScreenPoint(0, 100), mcc->Time());
   2138  mcc->AdvanceByMillis(10);
   2139  QueueMockHitResult(subframeScrollId);
   2140  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, panPoint,
   2141             ScreenPoint(0, 100), mcc->Time());
   2142  mcc->AdvanceByMillis(10);
   2143  QueueMockHitResult(subframeScrollId);
   2144  // Important: pass aSimulateMomentum=true for the pan-end to exercise the bug.
   2145  PanGesture(PanGestureInput::PANGESTURE_END, manager, panPoint,
   2146             ScreenPoint(0, 0), mcc->Time(), MODIFIER_NONE,
   2147             /*aSimulateMomentum=*/true);
   2148 
   2149  // The root and the subframe should both be overscrolled.
   2150  EXPECT_TRUE(rootApzc->IsOverscrolled());
   2151  EXPECT_TRUE(subframeApzc->IsOverscrolled());
   2152 
   2153  // Sample animations until all of them have been finished.
   2154  while (SampleAnimationsOnce());
   2155 
   2156  // All overscrolled APZCs should have snapped back.
   2157  EXPECT_FALSE(rootApzc->IsOverscrolled());
   2158  EXPECT_FALSE(subframeApzc->IsOverscrolled());
   2159 }
   2160 #endif
   2161 
   2162 #ifndef MOZ_WIDGET_ANDROID  // Not valid on Android
   2163 // Tests that the scroll offset is shifted with the overscroll amount when the
   2164 // content scroll range got expaned.
   2165 TEST_F(APZCOverscrollTester, FillOutGutterWhilePanning) {
   2166  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   2167 
   2168  // Scroll to the bottom edge.
   2169  ScrollMetadata metadata = apzc->GetScrollMetadata();
   2170  metadata.GetMetrics().SetLayoutScrollOffset(
   2171      CSSPoint(0, GetScrollRange().YMost()));
   2172  nsTArray<ScrollPositionUpdate> scrollUpdates;
   2173  scrollUpdates.AppendElement(ScrollPositionUpdate::NewScroll(
   2174      ScrollOrigin::Other,
   2175      CSSPoint::ToAppUnits(CSSPoint(0, GetScrollRange().YMost()))));
   2176  metadata.SetScrollUpdates(scrollUpdates);
   2177  metadata.GetMetrics().SetScrollGeneration(
   2178      scrollUpdates.LastElement().GetGeneration());
   2179  apzc->NotifyLayersUpdated(
   2180      metadata,
   2181      LayersUpdateFlags{.mIsFirstPaint = false, .mThisLayerTreeUpdated = true});
   2182 
   2183  CSSPoint scrollOffset = metadata.GetMetrics().GetLayoutScrollOffset();
   2184 
   2185  // Start panning to overscroll the content.
   2186  Pan(apzc, 20, 10, PanOptions::KeepFingerDown);
   2187  EXPECT_TRUE(apzc->IsOverscrolled());
   2188  float overscrollY = apzc->GetOverscrollAmount().y;
   2189  EXPECT_GT(overscrollY, 0);
   2190 
   2191  // Expand the content scroll range.
   2192  metadata = apzc->GetScrollMetadata();
   2193  FrameMetrics& metrics = metadata.GetMetrics();
   2194  const CSSRect& scrollableRect = metrics.GetScrollableRect();
   2195  metrics.SetScrollableRect(scrollableRect +
   2196                            CSSSize(0, scrollableRect.height + 10));
   2197  apzc->NotifyLayersUpdated(
   2198      metadata,
   2199      LayersUpdateFlags{.mIsFirstPaint = false, .mThisLayerTreeUpdated = true});
   2200 
   2201  // Now that the scroll position was shifted with the overscroll amount.
   2202  EXPECT_EQ(apzc->GetScrollMetadata().GetMetrics().GetVisualScrollOffset().y,
   2203            scrollOffset.y + overscrollY);
   2204  EXPECT_FALSE(apzc->IsOverscrolled());
   2205 }
   2206 
   2207 // Similar to FillOutGutterWhilePanning but expanding the content while an
   2208 // overscroll animation is running.
   2209 TEST_F(APZCOverscrollTester, FillOutGutterWhileAnimating) {
   2210  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   2211 
   2212  // Scroll to the bottom edge.
   2213  ScrollMetadata metadata = apzc->GetScrollMetadata();
   2214  metadata.GetMetrics().SetLayoutScrollOffset(
   2215      CSSPoint(0, GetScrollRange().YMost()));
   2216  nsTArray<ScrollPositionUpdate> scrollUpdates;
   2217  scrollUpdates.AppendElement(ScrollPositionUpdate::NewScroll(
   2218      ScrollOrigin::Other,
   2219      CSSPoint::ToAppUnits(CSSPoint(0, GetScrollRange().YMost()))));
   2220  metadata.SetScrollUpdates(scrollUpdates);
   2221  metadata.GetMetrics().SetScrollGeneration(
   2222      scrollUpdates.LastElement().GetGeneration());
   2223  apzc->NotifyLayersUpdated(
   2224      metadata,
   2225      LayersUpdateFlags{.mIsFirstPaint = false, .mThisLayerTreeUpdated = true});
   2226 
   2227  CSSPoint scrollOffset = metadata.GetMetrics().GetLayoutScrollOffset();
   2228 
   2229  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
   2230             ScreenPoint(0, 20), mcc->Time());
   2231  mcc->AdvanceByMillis(5);
   2232  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 60),
   2233             ScreenPoint(0, 10), mcc->Time());
   2234  mcc->AdvanceByMillis(5);
   2235  apzc->AdvanceAnimations(mcc->GetSampleTime());
   2236  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
   2237             ScreenPoint(0, 10), mcc->Time());
   2238  mcc->AdvanceByMillis(5);
   2239  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 50),
   2240             ScreenPoint(0, 0), mcc->Time());
   2241  mcc->AdvanceByMillis(5);
   2242 
   2243  EXPECT_TRUE(apzc->IsOverscrolled());
   2244  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   2245  float overscrollY = apzc->GetOverscrollAmount().y;
   2246  EXPECT_GT(overscrollY, 0);
   2247 
   2248  // Expand the content scroll range.
   2249  metadata = apzc->GetScrollMetadata();
   2250  FrameMetrics& metrics = metadata.GetMetrics();
   2251  const CSSRect& scrollableRect = metrics.GetScrollableRect();
   2252  metrics.SetScrollableRect(scrollableRect +
   2253                            CSSSize(0, scrollableRect.height + 10));
   2254  apzc->NotifyLayersUpdated(
   2255      metadata,
   2256      LayersUpdateFlags{.mIsFirstPaint = false, .mThisLayerTreeUpdated = true});
   2257 
   2258  // Now that the scroll position was shifted with the overscroll amount.
   2259  EXPECT_EQ(apzc->GetScrollMetadata().GetMetrics().GetVisualScrollOffset().y,
   2260            scrollOffset.y + overscrollY);
   2261  EXPECT_FALSE(apzc->IsOverscrolled());
   2262 }
   2263 #endif
   2264 
   2265 // Test that a programmatic scroll animation does NOT trigger overscroll.
   2266 TEST_F(APZCOverscrollTester, ProgrammaticScroll) {
   2267  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   2268 
   2269  // Send a SmoothMsd scroll update to a destination far outside of the
   2270  // scroll range (here, y=100000). This probably shouldn't happen in the
   2271  // first place, but even if it does for whatever reason, the smooth scroll
   2272  // should not trigger overscroll.
   2273  ScrollMetadata metadata = apzc->GetScrollMetadata();
   2274  nsTArray<ScrollPositionUpdate> scrollUpdates;
   2275  scrollUpdates.AppendElement(ScrollPositionUpdate::NewSmoothScroll(
   2276      ScrollMode::SmoothMsd, ScrollOrigin::Other,
   2277      CSSPoint::ToAppUnits(CSSPoint(0, 100000)), ScrollTriggeredByScript::Yes,
   2278      nullptr, ViewportType::Visual));
   2279  metadata.SetScrollUpdates(scrollUpdates);
   2280  metadata.GetMetrics().SetScrollGeneration(
   2281      scrollUpdates.LastElement().GetGeneration());
   2282  apzc->NotifyLayersUpdated(
   2283      metadata,
   2284      LayersUpdateFlags{.mIsFirstPaint = false, .mThisLayerTreeUpdated = true});
   2285 
   2286  apzc->AssertInSmoothMsdScroll();
   2287 
   2288  while (SampleAnimationOneFrame()) {
   2289    EXPECT_FALSE(apzc->IsOverscrolled());
   2290  }
   2291 }
   2292 
   2293 // A touchpad hold gesture should pause any ongoing overscroll animation (so
   2294 // that the page is not moving while the fingers are down on the touchpad),
   2295 // but should not cancel it. The animation should continue if the finger is
   2296 // lifted.
   2297 #ifndef MOZ_WIDGET_ANDROID  // Requires GenericOverscrollEffect
   2298 TEST_F(APZCOverscrollTester, HoldGestureDuringOverscroll) {
   2299  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   2300 
   2301  ScrollMetadata metadata;
   2302  FrameMetrics& metrics = metadata.GetMetrics();
   2303  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
   2304  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
   2305  metrics.SetVisualScrollOffset(CSSPoint(0, 0));
   2306  apzc->SetFrameMetrics(metrics);
   2307 
   2308  // Pan into overscroll at the top.
   2309  ScreenIntPoint panPoint(50, 50);
   2310  PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
   2311             ScreenPoint(0, -1), mcc->Time());
   2312  mcc->AdvanceByMillis(10);
   2313  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
   2314             ScreenPoint(0, -100), mcc->Time());
   2315  EXPECT_TRUE(apzc->IsOverscrolled());
   2316  EXPECT_TRUE(apzc->GetOverscrollAmount().y < 0);  // overscrolled at top
   2317 
   2318  // End the pan. This should start an overscroll animation.
   2319  mcc->AdvanceByMillis(10);
   2320  PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
   2321             mcc->Time());
   2322  EXPECT_TRUE(apzc->GetOverscrollAmount().y < 0);  // overscrolled at top
   2323  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   2324 
   2325  // Start a hold gesture (represented using PANGESTURE_MAYSTART).
   2326  // This should interrupt the animation but not relieve overscroll yet.
   2327  ParentLayerPoint overscrollBefore = apzc->GetOverscrollAmount();
   2328  mcc->AdvanceByMillis(10);
   2329  PanGesture(PanGestureInput::PANGESTURE_MAYSTART, apzc, panPoint,
   2330             ScreenPoint(0, 0), mcc->Time());
   2331  EXPECT_FALSE(apzc->IsOverscrollAnimationRunning());
   2332  EXPECT_EQ(overscrollBefore, apzc->GetOverscrollAmount());
   2333 
   2334  // End the hold gesture (represented using PANGESTURE_CANCELLED).
   2335  // This should start an overscroll animation again.
   2336  mcc->AdvanceByMillis(10);
   2337  PanGesture(PanGestureInput::PANGESTURE_CANCELLED, apzc, panPoint,
   2338             ScreenPoint(0, 0), mcc->Time());
   2339  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
   2340 
   2341  SampleAnimationUntilRecoveredFromOverscroll(ParentLayerPoint(0, 0));
   2342 }
   2343 #endif
   2344 
   2345 #ifdef MOZ_WIDGET_ANDROID  // Only testable with WidgetOverscrollEffect
   2346 TEST_F(APZCOverscrollTester, NoResetTouchInputStateCalled) {
   2347  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   2348 
   2349  MakeApzcWaitForMainThread();
   2350 
   2351  InSequence s;
   2352  // The UpdateOverscrollVelocity should never be called since there's no
   2353  // overscrolling state.
   2354  EXPECT_CALL(*mcc, UpdateOverscrollVelocity(_, _, _, _)).Times(0);
   2355 
   2356  ScreenIntPoint touchPoint(5, 5);
   2357  APZEventResult result = TouchDown(apzc, touchPoint, mcc->Time());
   2358  SetDefaultAllowedTouchBehavior(apzc, result.mInputBlockId);
   2359  apzc->ContentReceivedInputBlock(result.mInputBlockId,
   2360                                  /*aPreventDefault=*/true);
   2361 
   2362  for (int i = 0; i < 5; ++i) {
   2363    touchPoint.y -= 1;
   2364    mcc->AdvanceByMillis(10);
   2365    TouchMove(apzc, touchPoint, mcc->Time());
   2366  }
   2367 
   2368  mcc->AdvanceByMillis(10);
   2369  TouchUp(apzc, touchPoint, mcc->Time());
   2370 }
   2371 #endif
   2372 
   2373 #ifdef MOZ_WIDGET_ANDROID  // Only testable with WidgetOverscrollEffect
   2374 TEST_F(APZCOverscrollTester, ResetTouchInputStateJustOnce) {
   2375  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   2376  SCOPED_GFX_PREF_FLOAT("apz.touch_start_tolerance", 0.1f);
   2377  SCOPED_GFX_PREF_FLOAT("apz.touch_move_tolerance", 0.0f);
   2378  // To avoid falling into a fast fling state so that the second touch-start
   2379  // event can be preventDefault-ed.
   2380  SCOPED_GFX_PREF_FLOAT("apz.fling_stop_on_tap_threshold", 1000.0f);
   2381 
   2382  InSequence s;
   2383  // The UpdateOverscrollVelocity should be called just once for the second
   2384  // touchdown event which will be preventDefault-ed.
   2385  EXPECT_CALL(*mcc, UpdateOverscrollVelocity(_, _, _, _)).Times(1);
   2386 
   2387  // Overscroll once.
   2388  PanIntoOverscroll();
   2389 
   2390  // Now the touch-start event will be preventDefault-ed.
   2391  MakeApzcWaitForMainThread();
   2392 
   2393  ScreenIntPoint touchPoint(5, 5);
   2394  APZEventResult result = TouchDown(apzc, touchPoint, mcc->Time());
   2395  SetDefaultAllowedTouchBehavior(apzc, result.mInputBlockId);
   2396  apzc->ContentReceivedInputBlock(result.mInputBlockId,
   2397                                  /*aPreventDefault=*/true);
   2398 
   2399  for (int i = 0; i < 5; ++i) {
   2400    touchPoint.y -= 1;
   2401    mcc->AdvanceByMillis(10);
   2402    TouchMove(apzc, touchPoint, mcc->Time());
   2403  }
   2404 
   2405  mcc->AdvanceByMillis(10);
   2406  TouchUp(apzc, touchPoint, mcc->Time());
   2407 }
   2408 #endif
   2409 
   2410 #ifdef MOZ_WIDGET_ANDROID  // Only testable with WidgetOverscrollEffect
   2411 TEST_F(APZCOverscrollTester, NoResetPanGestureInputStateCalled) {
   2412  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   2413 
   2414  MakeApzcWaitForMainThread();
   2415 
   2416  InSequence s;
   2417  // The UpdateOverscrollVelocity should never be called since there's no
   2418  // overscrolling state.
   2419  EXPECT_CALL(*mcc, UpdateOverscrollVelocity(_, _, _, _)).Times(0);
   2420 
   2421  ScreenIntPoint panPoint(5, 5);
   2422  APZEventResult result = PanGesture(PanGestureInput::PANGESTURE_START, apzc,
   2423                                     panPoint, ScreenPoint(0, 1), mcc->Time());
   2424  apzc->ContentReceivedInputBlock(result.mInputBlockId,
   2425                                  /*aPreventDefault=*/true);
   2426  for (int i = 0; i < 5; ++i) {
   2427    mcc->AdvanceByMillis(10);
   2428    PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
   2429               ScreenPoint(0, 1), mcc->Time());
   2430  }
   2431 
   2432  mcc->AdvanceByMillis(10);
   2433  PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
   2434             mcc->Time());
   2435 }
   2436 #endif
   2437 
   2438 #ifdef MOZ_WIDGET_ANDROID  // Only testable with WidgetOverscrollEffect
   2439 TEST_F(APZCOverscrollTester, ResetPanGestureInputStateJustOnce) {
   2440  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled", true);
   2441 
   2442  InSequence s;
   2443  // The UpdateOverscrollVelocity should be called just once because
   2444  // the second pan-start event (wheel event) during overscrolling
   2445  // which will be preventDefault-ed.
   2446  EXPECT_CALL(*mcc, UpdateOverscrollVelocity(_, _, _, _)).Times(1);
   2447 
   2448  // NOTE: PanIntoOverscroll uses touch events. We do overscroll with pan
   2449  // gestures.
   2450  ScreenIntPoint panPoint(5, 5);
   2451  PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
   2452             ScreenPoint(0, -10), mcc->Time());
   2453  mcc->AdvanceByMillis(10);
   2454  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
   2455             ScreenPoint(0, -100), mcc->Time());
   2456  // Make sure it's overscrolling.
   2457  EXPECT_TRUE(apzc->IsOverscrolled());
   2458  // Finish the pan gesture.
   2459  mcc->AdvanceByMillis(10);
   2460  PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
   2461             mcc->Time());
   2462 
   2463  // Now the next pan gesture event will be preventDefault-ed.
   2464  MakeApzcWaitForMainThread();
   2465 
   2466  APZEventResult result = PanGesture(PanGestureInput::PANGESTURE_START, apzc,
   2467                                     panPoint, ScreenPoint(0, 10), mcc->Time());
   2468  apzc->ContentReceivedInputBlock(result.mInputBlockId,
   2469                                  /*aPreventDefault=*/true);
   2470  for (int i = 0; i < 5; ++i) {
   2471    mcc->AdvanceByMillis(10);
   2472    PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
   2473               ScreenPoint(0, 10), mcc->Time());
   2474  }
   2475 
   2476  mcc->AdvanceByMillis(10);
   2477  PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
   2478             mcc->Time());
   2479 }
   2480 #endif