Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/layers/apz/test/gtest/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 101 kB image not shown  

Quelle  TestOverscroll.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "APZCBasicTester.h"
#include "APZCTreeManagerTester.h"
#include "APZTestCommon.h"
#include "mozilla/ScrollPositionUpdate.h"
#include "mozilla/layers/ScrollableLayerGuid.h"
#include "mozilla/layers/WebRenderScrollDataWrapper.h"

#include "InputUtils.h"

class APZCOverscrollTester : public APZCBasicTester {
 public:
  explicit APZCOverscrollTester(
      AsyncPanZoomController::GestureBehavior aGestureBehavior =
          AsyncPanZoomController::DEFAULT_GESTURES)
      : APZCBasicTester(aGestureBehavior) {}

 protected:
  UniquePtr<ScopedLayerTreeRegistration> registration;

  void TestOverscroll() {
    // Pan sufficiently to hit overscroll behavior
    PanIntoOverscroll();

    // Check that we recover from overscroll via an animation.
    ParentLayerPoint expectedScrollOffset(0, GetScrollRange().YMost());
    SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
  }

  void PanIntoOverscroll() {
    int touchStart = 500;
    int touchEnd = 10;
    Pan(apzc, touchStart, touchEnd);
    EXPECT_TRUE(apzc->IsOverscrolled());
  }

  /**
   * Sample animations until we recover from overscroll.
   * @param aExpectedScrollOffset the expected reported scroll offset
   *                              throughout the animation
   */

  void SampleAnimationUntilRecoveredFromOverscroll(
      const ParentLayerPoint& aExpectedScrollOffset) {
    const TimeDuration increment = TimeDuration::FromMilliseconds(1);
    bool recoveredFromOverscroll = false;
    ParentLayerPoint pointOut;
    AsyncTransform viewTransformOut;
    while (apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut)) {
      // The reported scroll offset should be the same throughout.
      EXPECT_EQ(aExpectedScrollOffset, pointOut);

      // Trigger computation of the overscroll tranform, to make sure
      // no assetions fire during the calculation.
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);

      if (!apzc->IsOverscrolled()) {
        recoveredFromOverscroll = true;
      }

      mcc->AdvanceBy(increment);
    }
    EXPECT_TRUE(recoveredFromOverscroll);
    apzc->AssertStateIsReset();
  }

  ScrollableLayerGuid CreateSimpleRootScrollableForWebRender() {
    ScrollableLayerGuid guid;
    guid.mScrollId = ScrollableLayerGuid::START_SCROLL_ID;
    guid.mLayersId = LayersId{0};

    ScrollMetadata metadata;
    FrameMetrics& metrics = metadata.GetMetrics();
    metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
    metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
    metrics.SetScrollId(guid.mScrollId);
    metadata.SetIsLayersIdRoot(true);

    WebRenderLayerScrollData rootLayerScrollData;
    rootLayerScrollData.InitializeRoot(0);
    WebRenderScrollData scrollData;
    rootLayerScrollData.AppendScrollMetadata(scrollData, metadata);
    scrollData.AddLayerData(std::move(rootLayerScrollData));

    registration = MakeUnique<ScopedLayerTreeRegistration>(guid.mLayersId, mcc);
    tm->UpdateHitTestingTree(WebRenderScrollDataWrapper(*updater, &scrollData),
                             guid.mLayersId, 0);
    return guid;
  }
};

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
TEST_F(APZCOverscrollTester, FlingIntoOverscroll) {
  // Enable overscrolling.
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);
  SCOPED_GFX_PREF_FLOAT("apz.fling_min_velocity_threshold", 0.0f);

  // Scroll down by 25 px. Don't fling for simplicity.
  Pan(apzc, 50, 25, PanOptions::NoFling);

  // Now scroll back up by 20px, this time flinging after.
  // The fling should cover the remaining 5 px of room to scroll, then
  // go into overscroll, and finally snap-back to recover from overscroll.
  Pan(apzc, 25, 45);
  const TimeDuration increment = TimeDuration::FromMilliseconds(1);
  bool reachedOverscroll = false;
  bool recoveredFromOverscroll = false;
  while (apzc->AdvanceAnimations(mcc->GetSampleTime())) {
    if (!reachedOverscroll && apzc->IsOverscrolled()) {
      reachedOverscroll = true;
    }
    if (reachedOverscroll && !apzc->IsOverscrolled()) {
      recoveredFromOverscroll = true;
    }
    mcc->AdvanceBy(increment);
  }
  EXPECT_TRUE(reachedOverscroll);
  EXPECT_TRUE(recoveredFromOverscroll);
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
TEST_F(APZCOverscrollTester, OverScrollPanning) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  TestOverscroll();
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
// Tests that an overscroll animation doesn't trigger an assertion failure
// in the case where a sample has a velocity of zero.
TEST_F(APZCOverscrollTester, OverScroll_Bug1152051a) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  // Doctor the prefs to make the velocity zero at the end of the first sample.

  // This ensures our incoming velocity to the overscroll animation is
  // a round(ish) number, 4.9 (that being the distance of the pan before
  // overscroll, which is 500 - 10 = 490 pixels, divided by the duration of
  // the pan, which is 100 ms).
  SCOPED_GFX_PREF_FLOAT("apz.fling_friction", 0);

  TestOverscroll();
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
// Tests that ending an overscroll animation doesn't leave around state that
// confuses the next overscroll animation.
TEST_F(APZCOverscrollTester, OverScroll_Bug1152051b) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);
  SCOPED_GFX_PREF_FLOAT("apz.overscroll.stop_distance_threshold", 0.1f);

  // Pan sufficiently to hit overscroll behavior
  PanIntoOverscroll();

  // Sample animations once, to give the fling animation started on touch-up
  // a chance to realize it's overscrolled, and schedule a call to
  // HandleFlingOverscroll().
  SampleAnimationOnce();

  // This advances the time and runs the HandleFlingOverscroll task scheduled in
  // the previous call, which starts an overscroll animation. It then samples
  // the overscroll animation once, to get it to initialize the first overscroll
  // sample.
  SampleAnimationOnce();

  // Do a touch-down to cancel the overscroll animation, and then a touch-up
  // to schedule a new one since we're still overscrolled. We don't pan because
  // panning can trigger functions that clear the overscroll animation state
  // in other ways.
  APZEventResult result = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
  if (result.GetStatus() != nsEventStatus_eConsumeNoDefault) {
    SetDefaultAllowedTouchBehavior(apzc, result.mInputBlockId);
  }
  TouchUp(apzc, ScreenIntPoint(10, 10), mcc->Time());

  // Sample the second overscroll animation to its end.
  // If the ending of the first overscroll animation fails to clear state
  // properly, this will assert.
  ParentLayerPoint expectedScrollOffset(0, GetScrollRange().YMost());
  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
// Tests that the page doesn't get stuck in an
// overscroll animation after a low-velocity pan.
TEST_F(APZCOverscrollTester, OverScrollAfterLowVelocityPan_Bug1343775) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  // Pan into overscroll with a velocity less than the
  // apz.fling_min_velocity_threshold preference.
  Pan(apzc, 10, 30);

  EXPECT_TRUE(apzc->IsOverscrolled());

  apzc->AdvanceAnimationsUntilEnd();

  // Check that we recovered from overscroll.
  EXPECT_FALSE(apzc->IsOverscrolled());
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
TEST_F(APZCOverscrollTester, OverScrollAbort) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  // Pan sufficiently to hit overscroll behavior
  int touchStart = 500;
  int touchEnd = 10;
  Pan(apzc, touchStart, touchEnd);
  EXPECT_TRUE(apzc->IsOverscrolled());

  ParentLayerPoint pointOut;
  AsyncTransform viewTransformOut;

  // This sample call will run to the end of the fling animation
  // and will schedule the overscroll animation.
  apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut,
                                       TimeDuration::FromMilliseconds(10000));
  EXPECT_TRUE(apzc->IsOverscrolled());

  // At this point, we have an active overscroll animation.
  // Check that cancelling the animation clears the overscroll.
  apzc->CancelAnimation();
  EXPECT_FALSE(apzc->IsOverscrolled());
  apzc->AssertStateIsReset();
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
TEST_F(APZCOverscrollTester, OverScrollPanningAbort) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  // Pan sufficiently to hit overscroll behaviour. Keep the finger down so
  // the pan does not end.
  int touchStart = 500;
  int touchEnd = 10;
  Pan(apzc, touchStart, touchEnd, PanOptions::KeepFingerDown);
  EXPECT_TRUE(apzc->IsOverscrolled());

  // Check that calling CancelAnimation() while the user is still panning
  // (and thus no fling or snap-back animation has had a chance to start)
  // clears the overscroll.
  apzc->CancelAnimation();
  EXPECT_FALSE(apzc->IsOverscrolled());
  apzc->AssertStateIsReset();
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Maybe fails on Android
TEST_F(APZCOverscrollTester, OverscrollByVerticalPanGestures) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -10), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 0), mcc->Time());

  EXPECT_TRUE(apzc->IsOverscrolled());

  // Check that we recover from overscroll via an animation.
  ParentLayerPoint expectedScrollOffset(0, 0);
  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
TEST_F(APZCOverscrollTester, StuckInOverscroll_Bug1767337) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -10), mcc->Time());
  mcc->AdvanceByMillis(5);
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -10), mcc->Time());
  mcc->AdvanceByMillis(5);
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -10), mcc->Time());
  mcc->AdvanceByMillis(5);
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -10), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());

  // Send two PANGESTURE_END in a row, to see if the second one gets us
  // stuck in overscroll.
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 0), mcc->Time(), MODIFIER_NONE, true);
  SampleAnimationOnce();
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 0), mcc->Time(), MODIFIER_NONE, true);

  EXPECT_TRUE(apzc->IsOverscrolled());

  // Check that we recover from overscroll via an animation.
  ParentLayerPoint expectedScrollOffset(0, 0);
  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
TEST_F(APZCOverscrollTester, OverscrollByVerticalAndHorizontalPanGestures) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -10), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -2), mcc->Time());

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-10, 0), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-2, 0), mcc->Time());

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 0), mcc->Time());

  EXPECT_TRUE(apzc->IsOverscrolled());

  // Check that we recover from overscroll via an animation.
  ParentLayerPoint expectedScrollOffset(0, 0);
  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
TEST_F(APZCOverscrollTester, OverscrollByPanMomentumGestures) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 10), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 0), mcc->Time());

  // Make sure we are not yet in overscrolled region.
  EXPECT_TRUE(!apzc->IsOverscrolled());

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 200), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 100), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());

  EXPECT_TRUE(apzc->IsOverscrolled());

  // Check that we recover from overscroll via an animation.
  ParentLayerPoint expectedScrollOffset(0, GetScrollRange().YMost());
  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
TEST_F(APZCOverscrollTester, IgnoreMomemtumDuringOverscroll) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  float yMost = GetScrollRange().YMost();
  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, yMost / 10), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, yMost), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, yMost / 10), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 0), mcc->Time());

  // Make sure we've started an overscroll animation.
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());

  // And check the overscrolled transform value before/after calling PanGesture
  // to make sure the overscroll amount isn't affected by momentum events.
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  AsyncTransformComponentMatrix overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
  EXPECT_EQ(
      overscrolledTransform,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling));

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 200), mcc->Time());
  EXPECT_EQ(
      overscrolledTransform,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling));

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 100), mcc->Time());
  EXPECT_EQ(
      overscrolledTransform,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling));

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 2), mcc->Time());
  EXPECT_EQ(
      overscrolledTransform,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling));

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
  EXPECT_EQ(
      overscrolledTransform,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling));

  // Check that we've recovered from overscroll via an animation.
  ParentLayerPoint expectedScrollOffset(0, GetScrollRange().YMost());
  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
TEST_F(APZCOverscrollTester, VerticalOnlyOverscroll) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  // Make the content scrollable only vertically.
  ScrollMetadata metadata;
  FrameMetrics& metrics = metadata.GetMetrics();
  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
  apzc->SetFrameMetrics(metrics);

  // Scroll up into overscroll a bit.
  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-2, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-10, -10), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-2, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 0), mcc->Time());
  // Now it's overscrolled.
  EXPECT_TRUE(apzc->IsOverscrolled());
  AsyncTransformComponentMatrix overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  // The overscroll shouldn't happen horizontally.
  EXPECT_TRUE(overscrolledTransform._41 == 0);
  // Happens only vertically.
  EXPECT_TRUE(overscrolledTransform._42 != 0);

  // Send pan momentum events including horizontal bits.
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(-10, -100), mcc->Time());
  overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  // The overscroll shouldn't happen horizontally.
  EXPECT_TRUE(overscrolledTransform._41 == 0);
  EXPECT_TRUE(overscrolledTransform._42 != 0);

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(-5, -50), mcc->Time());
  overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  EXPECT_TRUE(overscrolledTransform._41 == 0);
  EXPECT_TRUE(overscrolledTransform._42 != 0);

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, -2), mcc->Time());
  overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  EXPECT_TRUE(overscrolledTransform._41 == 0);
  EXPECT_TRUE(overscrolledTransform._42 != 0);

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
  overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  EXPECT_TRUE(overscrolledTransform._41 == 0);
  EXPECT_TRUE(overscrolledTransform._42 != 0);

  // Check that we recover from overscroll via an animation.
  ParentLayerPoint expectedScrollOffset(0, 0);
  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
TEST_F(APZCOverscrollTester, VerticalOnlyOverscrollByPanMomentum) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  // Make the content scrollable only vertically.
  ScrollMetadata metadata;
  FrameMetrics& metrics = metadata.GetMetrics();
  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
  // Scrolls the content down a bit.
  metrics.SetVisualScrollOffset(CSSPoint(0, 50));
  apzc->SetFrameMetrics(metrics);

  // Scroll up a bit where overscroll will not happen.
  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -10), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 0), mcc->Time());

  // Make sure it's not yet overscrolled.
  EXPECT_TRUE(!apzc->IsOverscrolled());

  // Send pan momentum events including horizontal bits.
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(-10, -100), mcc->Time());
  // Now it's overscrolled.
  EXPECT_TRUE(apzc->IsOverscrolled());

  AsyncTransformComponentMatrix overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  // But the overscroll shouldn't happen horizontally.
  EXPECT_TRUE(overscrolledTransform._41 == 0);
  // Happens only vertically.
  EXPECT_TRUE(overscrolledTransform._42 != 0);

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(-5, -50), mcc->Time());
  overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  EXPECT_TRUE(overscrolledTransform._41 == 0);
  EXPECT_TRUE(overscrolledTransform._42 != 0);

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, -2), mcc->Time());
  overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  EXPECT_TRUE(overscrolledTransform._41 == 0);
  EXPECT_TRUE(overscrolledTransform._42 != 0);

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
  overscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  EXPECT_TRUE(overscrolledTransform._41 == 0);
  EXPECT_TRUE(overscrolledTransform._42 != 0);

  // Check that we recover from overscroll via an animation.
  ParentLayerPoint expectedScrollOffset(0, 0);
  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
TEST_F(APZCOverscrollTester, DisallowOverscrollInSingleLineTextControl) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  // Create a horizontal scrollable frame with `vertical disregarded direction`.
  ScrollMetadata metadata;
  FrameMetrics& metrics = metadata.GetMetrics();
  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 10));
  metrics.SetScrollableRect(CSSRect(0, 0, 1000, 10));
  apzc->SetFrameMetrics(metrics);
  metadata.SetDisregardedDirection(Some(ScrollDirection::eVertical));
  apzc->NotifyLayersUpdated(metadata, /*aIsFirstPaint=*/false,
                            /*aThisLayerTreeUpdated=*/true);

  // Try to overscroll up and left with pan gestures.
  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 5),
             ScreenPoint(-2, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 5),
             ScreenPoint(-10, -10), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 5),
             ScreenPoint(-2, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 5),
             ScreenPoint(0, 0), mcc->Time());

  // No overscrolling should happen.
  EXPECT_TRUE(!apzc->IsOverscrolled());

  // Send pan momentum events too.
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
             ScreenIntPoint(50, 5), ScreenPoint(0, 0), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 5), ScreenPoint(-100, -100), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 5), ScreenPoint(-50, -50), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 5), ScreenPoint(-2, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
             ScreenIntPoint(50, 5), ScreenPoint(0, 0), mcc->Time());
  // No overscrolling should happen either.
  EXPECT_TRUE(!apzc->IsOverscrolled());
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Maybe fails on Android
// Tests that horizontal overscroll animation keeps running with vertical
// pan momentum scrolling.
TEST_F(APZCOverscrollTester,
       HorizontalOverscrollAnimationWithVerticalPanMomentumScrolling) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  ScrollMetadata metadata;
  FrameMetrics& metrics = metadata.GetMetrics();
  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
  metrics.SetScrollableRect(CSSRect(0, 0, 1000, 5000));
  apzc->SetFrameMetrics(metrics);

  // Try to overscroll left with pan gestures.
  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-2, 0), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-10, 0), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-2, 0), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 0), mcc->Time());

  // Make sure we've started an overscroll animation.
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  AsyncTransformComponentMatrix initialOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);

  // Send lengthy downward momentums to make sure the overscroll animation
  // doesn't clobber the momentums scrolling.
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  // The overscroll amount on X axis has started being managed by the overscroll
  // animation.
  AsyncTransformComponentMatrix currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  EXPECT_NE(initialOverscrolledTransform._41, currentOverscrolledTransform._41);
  // There is no overscroll on Y axis.
  EXPECT_EQ(currentOverscrolledTransform._42, 0);
  ParentLayerPoint scrollOffset = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);
  // The scroll offset shouldn't be changed by the overscroll animation.
  EXPECT_EQ(scrollOffset.y, 0);

  // Simple gesture on the Y axis to ensure that we can send a vertical
  // momentum scroll
  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 0), mcc->Time());

  ParentLayerPoint offsetAfterPan = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);

  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // The overscroll amount on both axes shouldn't be changed by this pan
  // momentum start event since the displacement is zero.
  EXPECT_EQ(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  EXPECT_EQ(
      currentOverscrolledTransform._42,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42);

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  // The overscroll amount should be managed by the overscroll animation.
  EXPECT_NE(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);
  // Not yet started scrolling.
  EXPECT_EQ(scrollOffset.y, offsetAfterPan.y);
  EXPECT_EQ(scrollOffset.x, 0);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);

  // Send a long pan momentum.
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 200), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // The overscroll amount on X axis shouldn't be changed by this momentum pan.
  EXPECT_EQ(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  // Now it started scrolling vertically.
  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);
  EXPECT_GT(scrollOffset.y, 0);
  EXPECT_EQ(scrollOffset.x, 0);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  // The overscroll on X axis keeps being managed by the overscroll animation.
  EXPECT_NE(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  // The scroll offset on Y axis shouldn't be changed by the overscroll
  // animation.
  EXPECT_EQ(scrollOffset.y, apzc->GetCurrentAsyncScrollOffset(
                                    AsyncPanZoomController::eForEventHandling)
                                .y);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 100), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // The overscroll amount on X axis shouldn't be changed by this momentum pan.
  EXPECT_EQ(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  // Scrolling keeps going by momentum.
  EXPECT_GT(apzc->GetCurrentAsyncScrollOffset(
                    AsyncPanZoomController::eForEventHandling)
                .y,
            scrollOffset.y);

  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 10), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // Scrolling keeps going by momentum.
  EXPECT_GT(apzc->GetCurrentAsyncScrollOffset(
                    AsyncPanZoomController::eForEventHandling)
                .y,
            scrollOffset.y);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // This momentum event doesn't change the scroll offset since its
  // displacement is zero.
  EXPECT_EQ(apzc->GetCurrentAsyncScrollOffset(
                    AsyncPanZoomController::eForEventHandling)
                .y,
            scrollOffset.y);

  // Check that we recover from the horizontal overscroll via the animation.
  ParentLayerPoint expectedScrollOffset(0, scrollOffset.y);
  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Maybe fails on Android
// Similar to above
// HorizontalOverscrollAnimationWithVerticalPanMomentumScrolling,
// but having OverscrollAnimation on both axes initially.
TEST_F(APZCOverscrollTester,
       BothAxesOverscrollAnimationWithPanMomentumScrolling) {
  // TODO: This test currently requires gestures that cause movement on both
  // axis, which excludes DOMINANT_AXIS locking mode. The gestures should be
  // broken up into multiple gestures to cause the overscroll.
  SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  ScrollMetadata metadata;
  FrameMetrics& metrics = metadata.GetMetrics();
  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
  metrics.SetScrollableRect(CSSRect(0, 0, 1000, 5000));
  apzc->SetFrameMetrics(metrics);

  // Try to overscroll up and left with pan gestures.
  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-2, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-10, -10), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-2, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 0), mcc->Time());

  // Make sure we've started an overscroll animation.
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  AsyncTransformComponentMatrix initialOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);

  // Send lengthy downward momentums to make sure the overscroll animation
  // doesn't clobber the momentums scrolling.
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  // The overscroll amount has started being managed by the overscroll
  // animation.
  AsyncTransformComponentMatrix currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  EXPECT_NE(initialOverscrolledTransform._41, currentOverscrolledTransform._41);
  EXPECT_NE(initialOverscrolledTransform._42, currentOverscrolledTransform._42);

  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // The overscroll amount on both axes shouldn't be changed by this pan
  // momentum start event since the displacement is zero.
  EXPECT_EQ(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  EXPECT_EQ(
      currentOverscrolledTransform._42,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42);

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  // Still being managed by the overscroll animation.
  EXPECT_NE(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  EXPECT_NE(
      currentOverscrolledTransform._42,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  // Send a long pan momentum.
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 200), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // The overscroll amount on X axis shouldn't be changed by this momentum pan.
  EXPECT_EQ(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  // But now the overscroll amount on Y axis should be changed by this momentum
  // pan.
  EXPECT_NE(
      currentOverscrolledTransform._42,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42);
  // Actually it's no longer overscrolled.
  EXPECT_EQ(
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42,
      0);

  ParentLayerPoint currentScrollOffset = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);
  // Now it started scrolling.
  EXPECT_GT(currentScrollOffset.y, 0);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  // The overscroll on X axis keeps being managed by the overscroll animation.
  EXPECT_NE(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  // But the overscroll on Y axis is no longer affected by the overscroll
  // animation.
  EXPECT_EQ(
      currentOverscrolledTransform._42,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42);
  // The scroll offset on Y axis shouldn't be changed by the overscroll
  // animation.
  EXPECT_EQ(currentScrollOffset.y,
            apzc->GetCurrentAsyncScrollOffset(
                    AsyncPanZoomController::eForEventHandling)
                .y);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  currentScrollOffset = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 100), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // The overscroll amount on X axis shouldn't be changed by this momentum pan.
  EXPECT_EQ(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  // Keeping no overscrolling on Y axis.
  EXPECT_EQ(
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42,
      0);
  // Scrolling keeps going by momentum.
  EXPECT_GT(apzc->GetCurrentAsyncScrollOffset(
                    AsyncPanZoomController::eForEventHandling)
                .y,
            currentScrollOffset.y);

  currentScrollOffset = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 10), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // Keeping no overscrolling on Y axis.
  EXPECT_EQ(
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42,
      0);
  // Scrolling keeps going by momentum.
  EXPECT_GT(apzc->GetCurrentAsyncScrollOffset(
                    AsyncPanZoomController::eForEventHandling)
                .y,
            currentScrollOffset.y);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  currentScrollOffset = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // Keeping no overscrolling on Y axis.
  EXPECT_EQ(
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42,
      0);
  // This momentum event doesn't change the scroll offset since its
  // displacement is zero.
  EXPECT_EQ(apzc->GetCurrentAsyncScrollOffset(
                    AsyncPanZoomController::eForEventHandling)
                .y,
            currentScrollOffset.y);

  // Check that we recover from the horizontal overscroll via the animation.
  ParentLayerPoint expectedScrollOffset(0, currentScrollOffset.y);
  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Maybe fails on Android
// This is another variant of
// HorizontalOverscrollAnimationWithVerticalPanMomentumScrolling. In this test,
// after a horizontal overscroll animation started, upwards pan moments happen,
// thus there should be a new vertical overscroll animation in addition to
// the horizontal one.
TEST_F(
    APZCOverscrollTester,
    VerticalOverscrollAnimationInAdditionToExistingHorizontalOverscrollAnimation) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  ScrollMetadata metadata;
  FrameMetrics& metrics = metadata.GetMetrics();
  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
  metrics.SetScrollableRect(CSSRect(0, 0, 1000, 5000));
  // Scrolls the content 50px down.
  metrics.SetVisualScrollOffset(CSSPoint(0, 50));
  apzc->SetFrameMetrics(metrics);

  // Try to overscroll left with pan gestures.
  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-2, 0), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-10, 0), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(-2, 0), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 0), mcc->Time());

  // Make sure we've started an overscroll animation.
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  AsyncTransformComponentMatrix initialOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);

  // Send lengthy __upward__ momentums to make sure the overscroll animation
  // doesn't clobber the momentums scrolling.
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  // The overscroll amount on X axis has started being managed by the overscroll
  // animation.
  AsyncTransformComponentMatrix currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  EXPECT_NE(initialOverscrolledTransform._41, currentOverscrolledTransform._41);
  // There is no overscroll on Y axis.
  EXPECT_EQ(
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42,
      0);
  ParentLayerPoint scrollOffset = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);
  // The scroll offset shouldn't be changed by the overscroll animation.
  EXPECT_EQ(scrollOffset.y, 50);

  // Simple gesture on the Y axis to ensure that we can send a vertical
  // momentum scroll
  PanGesture(PanGestureInput::PANGESTURE_START, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, ScreenIntPoint(50, 80),
             ScreenPoint(0, 0), mcc->Time());

  ParentLayerPoint offsetAfterPan = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);

  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // The overscroll amount on both axes shouldn't be changed by this pan
  // momentum start event since the displacement is zero.
  EXPECT_EQ(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  EXPECT_EQ(
      currentOverscrolledTransform._42,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42);

  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  // The overscroll amount should be managed by the overscroll animation.
  EXPECT_NE(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);
  // Not yet started scrolling.
  EXPECT_EQ(scrollOffset.y, offsetAfterPan.y);
  EXPECT_EQ(scrollOffset.x, 0);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);

  // Send a long pan momentum.
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, -200), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // The overscroll amount on X axis shouldn't be changed by this momentum pan.
  EXPECT_EQ(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  // Now it started scrolling vertically.
  scrollOffset = apzc->GetCurrentAsyncScrollOffset(
      AsyncPanZoomController::eForEventHandling);
  EXPECT_EQ(scrollOffset.y, 0);
  EXPECT_EQ(scrollOffset.x, 0);
  // Actually it's also vertically overscrolled.
  EXPECT_GT(
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42,
      0);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  // The overscroll on X axis keeps being managed by the overscroll animation.
  EXPECT_NE(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  // The overscroll on Y Axis hasn't been changed by the overscroll animation at
  // this moment, sine the last displacement was consumed in the last pan
  // momentum.
  EXPECT_EQ(
      currentOverscrolledTransform._42,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, -100), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // The overscroll amount on X axis shouldn't be changed by this momentum pan.
  EXPECT_EQ(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  // Now the overscroll amount on Y axis shouldn't be changed by this momentum
  // pan either.
  EXPECT_EQ(
      currentOverscrolledTransform._42,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  EXPECT_NE(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  // And now the overscroll on Y Axis should be also managed by the overscroll
  // animation.
  EXPECT_NE(
      currentOverscrolledTransform._42,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, -10), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());
  // The overscroll amount on both axes shouldn't be changed by momentum event.
  EXPECT_EQ(
      currentOverscrolledTransform._41,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._41);
  EXPECT_EQ(
      currentOverscrolledTransform._42,
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling)
          ._42);

  currentOverscrolledTransform =
      apzc->GetOverscrollTransform(AsyncPanZoomController::eForEventHandling);
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, apzc,
             ScreenIntPoint(50, 80), ScreenPoint(0, 0), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());

  // Check that we recover from the horizontal overscroll via the animation.
  ParentLayerPoint expectedScrollOffset(0, 0);
  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Currently fails on Android
TEST_F(APZCOverscrollTester, OverscrollByPanGesturesInterruptedByReflowZoom) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);
  SCOPED_GFX_PREF_INT("mousewheel.with_control.action", 3);  // reflow zoom.

  // A sanity check that pan gestures with ctrl modifier will not be handled by
  // APZ.
  PanGestureInput panInput(PanGestureInput::PANGESTURE_START, mcc->Time(),
                           ScreenIntPoint(5, 5), ScreenPoint(0, -2),
                           MODIFIER_CONTROL);
  WidgetWheelEvent wheelEvent = panInput.ToWidgetEvent(nullptr);
  EXPECT_FALSE(APZInputBridge::ActionForWheelEvent(&wheelEvent).isSome());

  ScrollableLayerGuid rootGuid = CreateSimpleRootScrollableForWebRender();
  RefPtr<AsyncPanZoomController> apzc =
      tm->GetTargetAPZC(rootGuid.mLayersId, rootGuid.mScrollId);

  PanGesture(PanGestureInput::PANGESTURE_START, tm, ScreenIntPoint(50, 80),
             ScreenPoint(0, -2), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  PanGesture(PanGestureInput::PANGESTURE_PAN, tm, ScreenIntPoint(50, 80),
             ScreenPoint(0, -10), mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());

  // Make sure overscrolling has started.
  EXPECT_TRUE(apzc->IsOverscrolled());

  // Press ctrl until PANGESTURE_END.
  PanGestureWithModifiers(PanGestureInput::PANGESTURE_PAN, MODIFIER_CONTROL, tm,
                          ScreenIntPoint(50, 80), ScreenPoint(0, -2),
                          mcc->Time());
  mcc->AdvanceByMillis(5);
  apzc->AdvanceAnimations(mcc->GetSampleTime());
  // At this moment (i.e. PANGESTURE_PAN), still in overscrolling state.
  EXPECT_TRUE(apzc->IsOverscrolled());

  PanGestureWithModifiers(PanGestureInput::PANGESTURE_END, MODIFIER_CONTROL, tm,
                          ScreenIntPoint(50, 80), ScreenPoint(0, 0),
                          mcc->Time());
  // The overscrolling state should have been restored.
  EXPECT_TRUE(!apzc->IsOverscrolled());
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Only applies to GenericOverscrollEffect
TEST_F(APZCOverscrollTester, SmoothTransitionFromPanToAnimation) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  ScrollMetadata metadata;
  FrameMetrics& metrics = metadata.GetMetrics();
  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
  // Start scrolled down to y=500px.
  metrics.SetVisualScrollOffset(CSSPoint(0, 500));
  apzc->SetFrameMetrics(metrics);

  int frameLength = 10;    // milliseconds; 10 to keep the math simple
  float panVelocity = 10;  // pixels per millisecond
  int panPixelsPerFrame = frameLength * panVelocity;  // 100 pixels per frame

  ScreenIntPoint panPoint(50, 50);
  PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
             ScreenPoint(0, -1), mcc->Time());
  // Pan up for 6 frames at 100 pixels per frame. This should reduce
  // the vertical scroll offset from 500 to 0, and get us into overscroll.
  for (int i = 0; i < 6; ++i) {
    mcc->AdvanceByMillis(frameLength);
    PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
               ScreenPoint(0, -panPixelsPerFrame), mcc->Time());
  }
  EXPECT_TRUE(apzc->IsOverscrolled());

  // Pan further into overscroll at the same input velocity, enough
  // for the frames while we are in overscroll to dominate the computation
  // in the velocity tracker.
  // Importantly, while the input velocity is still 100 pixels per frame,
  // in the overscrolled state the page only visual moves by at most 8 pixels
  // per frame.
  int frames = StaticPrefs::apz_velocity_relevance_time_ms() / frameLength;
  for (int i = 0; i < frames; ++i) {
    mcc->AdvanceByMillis(frameLength);
    PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
               ScreenPoint(0, -panPixelsPerFrame), mcc->Time());
  }
  EXPECT_TRUE(apzc->IsOverscrolled());

  // End the pan, allowing an overscroll animation to start.
  mcc->AdvanceByMillis(frameLength);
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
             mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());

  // Check that the velocity reflects the actual movement (no more than 8
  // pixels/frame ==> 0.8 pixels per millisecond), not the input velocity
  // (100 pixels/frame ==> 10 pixels per millisecond). This ensures that
  // the transition from the pan to the animation appears smooth.
  // (Note: velocities are negative since they are upwards.)
  EXPECT_LT(apzc->GetVelocityVector().y, 0);
  EXPECT_GT(apzc->GetVelocityVector().y, -0.8);
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Only applies to GenericOverscrollEffect
TEST_F(APZCOverscrollTester, NoOverscrollForMousewheel) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  ScrollMetadata metadata;
  FrameMetrics& metrics = metadata.GetMetrics();
  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
  // Start scrolled down just a few pixels from the top.
  metrics.SetVisualScrollOffset(CSSPoint(0, 3));
  // Set line and page scroll amounts. Otherwise, even though Wheel() uses
  // SCROLLDELTA_PIXEL, the wheel handling code will get confused by things
  // like the "don't scroll more than one page" check.
  metadata.SetPageScrollAmount(LayoutDeviceIntSize(50, 100));
  metadata.SetLineScrollAmount(LayoutDeviceIntSize(5, 10));
  apzc->SetScrollMetadata(metadata);

  // Send a wheel with enough delta to scrollto y=0 *and* overscroll.
  Wheel(apzc, ScreenIntPoint(10, 10), ScreenPoint(0, -10), mcc->Time());

  // Check that we did not actually go into overscroll.
  EXPECT_FALSE(apzc->IsOverscrolled());
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Only applies to GenericOverscrollEffect
TEST_F(APZCOverscrollTester, ClickWhileOverscrolled) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  ScrollMetadata metadata;
  FrameMetrics& metrics = metadata.GetMetrics();
  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
  metrics.SetVisualScrollOffset(CSSPoint(0, 0));
  apzc->SetFrameMetrics(metrics);

  // Pan into overscroll at the top.
  ScreenIntPoint panPoint(50, 50);
  PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
             ScreenPoint(0, -1), mcc->Time());
  mcc->AdvanceByMillis(10);
  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
             ScreenPoint(0, -100), mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->GetOverscrollAmount().y < 0);  // overscrolled at top

  // End the pan. This should start an overscroll animation.
  mcc->AdvanceByMillis(10);
  PanGesture(PanGestureInput::PANGESTURE_END, apzc, panPoint, ScreenPoint(0, 0),
             mcc->Time());
  EXPECT_TRUE(apzc->GetOverscrollAmount().y < 0);  // overscrolled at top
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());

  // Send a mouse-down. This should interrupt the animation but not relieve
  // overscroll yet.
  ParentLayerPoint overscrollBefore = apzc->GetOverscrollAmount();
  MouseDown(apzc, panPoint, mcc->Time());
  EXPECT_FALSE(apzc->IsOverscrollAnimationRunning());
  EXPECT_EQ(overscrollBefore, apzc->GetOverscrollAmount());

  // Send a mouse-up. This should start an overscroll animation again.
  MouseUp(apzc, panPoint, mcc->Time());
  EXPECT_TRUE(apzc->IsOverscrollAnimationRunning());

  SampleAnimationUntilRecoveredFromOverscroll(ParentLayerPoint(0, 0));
}
#endif

#ifndef MOZ_WIDGET_ANDROID  // Only applies to GenericOverscrollEffect
TEST_F(APZCOverscrollTester, DynamicallyLoadingContent) {
  SCOPED_GFX_PREF_BOOL("apz.overscroll.enabled"true);

  ScrollMetadata metadata;
  FrameMetrics& metrics = metadata.GetMetrics();
  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
  metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
  metrics.SetVisualScrollOffset(CSSPoint(0, 0));
  apzc->SetFrameMetrics(metrics);

  // Pan to the bottom of the page, and further, into overscroll.
  ScreenIntPoint panPoint(50, 50);
  PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
             ScreenPoint(0, 1), mcc->Time());
  for (int i = 0; i < 12; ++i) {
    mcc->AdvanceByMillis(10);
    PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
               ScreenPoint(0, 100), mcc->Time());
  }
  EXPECT_TRUE(apzc->IsOverscrolled());
  EXPECT_TRUE(apzc->GetOverscrollAmount().y > 0);  // overscrolled at bottom

  // Grow the scrollable rect at the bottom, simulating the page loading content
  // dynamically.
  CSSRect scrollableRect = metrics.GetScrollableRect();
  scrollableRect.height += 500;
  metrics.SetScrollableRect(scrollableRect);
  apzc->NotifyLayersUpdated(metadata, falsetrue);

  // Check that the modified scrollable rect cleared the overscroll.
  EXPECT_FALSE(apzc->IsOverscrolled());

  // Pan back up to the top, and further, into overscroll.
  PanGesture(PanGestureInput::PANGESTURE_START, apzc, panPoint,
             ScreenPoint(0, -1), mcc->Time());
  for (int i = 0; i < 12; ++i) {
    mcc->AdvanceByMillis(10);
    PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, panPoint,
               ScreenPoint(0, -100), mcc->Time());
  }
  EXPECT_TRUE(apzc->IsOverscrolled());
  ParentLayerPoint overscrollAmount = apzc->GetOverscrollAmount();
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=92 H=92 G=91

¤ Dauer der Verarbeitung: 0.13 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.