tor-browser

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

TestAxisLock.cpp (30851B)


      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 "APZCTreeManagerTester.h"
      8 #include "APZTestCommon.h"
      9 
     10 #include "InputUtils.h"
     11 #include "gtest/gtest.h"
     12 
     13 #include <cmath>
     14 
     15 class APZCAxisLockCompatTester : public APZCTreeManagerTester,
     16                                 public testing::WithParamInterface<int> {
     17 public:
     18  APZCAxisLockCompatTester() : oldAxisLockMode(0) { CreateMockHitTester(); }
     19 
     20  int oldAxisLockMode;
     21 
     22  UniquePtr<ScopedLayerTreeRegistration> registration;
     23 
     24  RefPtr<TestAsyncPanZoomController> apzc;
     25 
     26  void SetUp() {
     27    APZCTreeManagerTester::SetUp();
     28 
     29    oldAxisLockMode = Preferences::GetInt("apz.axis_lock.mode");
     30 
     31    Preferences::SetInt("apz.axis_lock.mode", GetParam());
     32  }
     33 
     34  void TearDown() {
     35    APZCTreeManagerTester::TearDown();
     36 
     37    Preferences::SetInt("apz.axis_lock.mode", oldAxisLockMode);
     38  }
     39 
     40  static std::string PrintFromParam(const testing::TestParamInfo<int>& info) {
     41    switch (info.param) {
     42      case 0:
     43        return "FREE";
     44      case 1:
     45        return "STANDARD";
     46      case 2:
     47        return "STICKY";
     48      case 3:
     49        return "DOMINANT_AXIS";
     50      case 4:
     51        return "BREAKABLE";
     52      default:
     53        return "UNKNOWN";
     54    }
     55  }
     56 };
     57 
     58 class APZCAxisLockTester : public APZCTreeManagerTester {
     59 public:
     60  APZCAxisLockTester() { CreateMockHitTester(); }
     61 
     62  UniquePtr<ScopedLayerTreeRegistration> registration;
     63 
     64  RefPtr<TestAsyncPanZoomController> apzc;
     65 
     66  void SetupBasicTest() {
     67    const char* treeShape = "x";
     68    LayerIntRect layerVisibleRect[] = {
     69        LayerIntRect(0, 0, 100, 100),
     70    };
     71    CreateScrollData(treeShape, layerVisibleRect);
     72    SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
     73                              CSSRect(0, 0, 500, 500));
     74 
     75    registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
     76 
     77    UpdateHitTestingTree();
     78  }
     79 
     80  void BreakStickyAxisLockTestGesture(const ScrollDirections& aDirections) {
     81    float panX = 0;
     82    float panY = 0;
     83 
     84    if (aDirections.contains(ScrollDirection::eVertical)) {
     85      panY = 30;
     86    }
     87    if (aDirections.contains(ScrollDirection::eHorizontal)) {
     88      panX = 30;
     89    }
     90 
     91    // Kick off the gesture that may lock onto an axis
     92    QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
     93    PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
     94               ScreenPoint(panX, panY), mcc->Time());
     95    mcc->AdvanceByMillis(5);
     96    apzc->AdvanceAnimations(mcc->GetSampleTime());
     97 
     98    QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
     99    PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
    100               ScreenPoint(panX, panY), mcc->Time());
    101  }
    102 
    103  void BreakStickyAxisLockTest(const ScrollDirections& aDirections) {
    104    // Create the gesture for the test.
    105    BreakStickyAxisLockTestGesture(aDirections);
    106 
    107    // Based on the scroll direction(s) ensure the state is what we expect.
    108    if (aDirections == ScrollDirection::eVertical) {
    109      apzc->AssertStateIsPanningLockedY();
    110      apzc->AssertAxisLocked(ScrollDirection::eVertical);
    111      EXPECT_GT(apzc->GetVelocityVector().y, 0);
    112      EXPECT_EQ(apzc->GetVelocityVector().x, 0);
    113    } else if (aDirections == ScrollDirection::eHorizontal) {
    114      apzc->AssertStateIsPanningLockedX();
    115      apzc->AssertAxisLocked(ScrollDirection::eHorizontal);
    116      EXPECT_GT(apzc->GetVelocityVector().x, 0);
    117      EXPECT_EQ(apzc->GetVelocityVector().y, 0);
    118    } else {
    119      apzc->AssertStateIsPanning();
    120      apzc->AssertNotAxisLocked();
    121      EXPECT_GT(apzc->GetVelocityVector().x, 0);
    122      EXPECT_GT(apzc->GetVelocityVector().y, 0);
    123    }
    124 
    125    // Cleanup for next test.
    126    apzc->AdvanceAnimationsUntilEnd();
    127  }
    128 };
    129 
    130 TEST_F(APZCAxisLockTester, BasicDominantAxisUse) {
    131  SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 1);
    132  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", M_PI / 4.0f);
    133 
    134  SetupBasicTest();
    135 
    136  apzc = ApzcOf(root);
    137 
    138  // Kick off the initial gesture that triggers the momentum scroll.
    139  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    140  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
    141             ScreenIntPoint(1, 2), mcc->Time());
    142  mcc->AdvanceByMillis(5);
    143  apzc->AdvanceAnimations(mcc->GetSampleTime());
    144 
    145  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    146  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
    147             ScreenPoint(15, 30), mcc->Time());
    148  mcc->AdvanceByMillis(5);
    149  apzc->AdvanceAnimations(mcc->GetSampleTime());
    150 
    151  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    152  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
    153             ScreenPoint(15, 30), mcc->Time());
    154 
    155  // Should be in a PANNING_LOCKED_Y state with no horizontal velocity.
    156  apzc->AssertStateIsPanningLockedY();
    157  apzc->AssertAxisLocked(ScrollDirection::eVertical);
    158  EXPECT_GT(apzc->GetVelocityVector().y, 0);
    159  EXPECT_EQ(apzc->GetVelocityVector().x, 0);
    160 
    161  mcc->AdvanceByMillis(5);
    162  apzc->AdvanceAnimations(mcc->GetSampleTime());
    163 
    164  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    165  PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
    166             ScreenPoint(0, 0), mcc->Time());
    167  mcc->AdvanceByMillis(5);
    168  apzc->AdvanceAnimations(mcc->GetSampleTime());
    169 
    170  // Ensure that we have not panned on the horizontal axis.
    171  ParentLayerPoint panEndOffset = apzc->GetCurrentAsyncScrollOffset(
    172      AsyncTransformConsumer::eForEventHandling);
    173  EXPECT_EQ(panEndOffset.x, 0);
    174 
    175  // The lock onto the Y axis extends into momentum scroll.
    176  apzc->AssertAxisLocked(ScrollDirection::eVertical);
    177 
    178  // Start the momentum scroll.
    179  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    180  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, manager,
    181             ScreenIntPoint(50, 50), ScreenPoint(30, 90), mcc->Time());
    182  mcc->AdvanceByMillis(10);
    183  apzc->AdvanceAnimations(mcc->GetSampleTime());
    184 
    185  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    186  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, manager,
    187             ScreenIntPoint(50, 50), ScreenPoint(10, 30), mcc->Time());
    188  mcc->AdvanceByMillis(10);
    189  apzc->AdvanceAnimations(mcc->GetSampleTime());
    190 
    191  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    192  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, manager,
    193             ScreenIntPoint(50, 50), ScreenPoint(10, 30), mcc->Time());
    194  mcc->AdvanceByMillis(10);
    195  apzc->AdvanceAnimations(mcc->GetSampleTime());
    196 
    197  // In momentum locking mode, we should still be locked onto the Y axis.
    198  apzc->AssertStateIsPanMomentum();
    199  apzc->AssertAxisLocked(ScrollDirection::eVertical);
    200  EXPECT_GT(apzc->GetVelocityVector().y, 0);
    201  EXPECT_EQ(apzc->GetVelocityVector().x, 0);
    202 
    203  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    204  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, manager,
    205             ScreenIntPoint(50, 50), ScreenPoint(0, 0), mcc->Time());
    206 
    207  // After momentum scroll end, ensure we are no longer locked onto an axis.
    208  apzc->AssertNotAxisLocked();
    209 
    210  // Wait until the end of the animation and ensure the final state is
    211  // reasonable.
    212  apzc->AdvanceAnimationsUntilEnd();
    213  ParentLayerPoint finalOffset = apzc->GetCurrentAsyncScrollOffset(
    214      AsyncTransformConsumer::eForEventHandling);
    215 
    216  // Ensure we have scrolled some amount on the Y axis in momentum scroll.
    217  EXPECT_GT(finalOffset.y, panEndOffset.y);
    218  EXPECT_EQ(finalOffset.x, 0.0f);
    219 }
    220 
    221 TEST_F(APZCAxisLockTester, NewGestureBreaksMomentumAxisLock) {
    222  SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 1);
    223  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", M_PI / 4.0f);
    224 
    225  SetupBasicTest();
    226 
    227  apzc = ApzcOf(root);
    228 
    229  // Kick off the initial gesture that triggers the momentum scroll.
    230  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    231  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
    232             ScreenIntPoint(2, 1), mcc->Time());
    233  mcc->AdvanceByMillis(5);
    234  apzc->AdvanceAnimations(mcc->GetSampleTime());
    235 
    236  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    237  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
    238             ScreenPoint(30, 15), mcc->Time());
    239  mcc->AdvanceByMillis(5);
    240  apzc->AdvanceAnimations(mcc->GetSampleTime());
    241 
    242  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    243  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
    244             ScreenPoint(30, 15), mcc->Time());
    245 
    246  // Should be in a PANNING_LOCKED_X state with no vertical velocity.
    247  apzc->AssertStateIsPanningLockedX();
    248  apzc->AssertAxisLocked(ScrollDirection::eHorizontal);
    249  EXPECT_GT(apzc->GetVelocityVector().x, 0);
    250  EXPECT_EQ(apzc->GetVelocityVector().y, 0);
    251 
    252  mcc->AdvanceByMillis(5);
    253  apzc->AdvanceAnimations(mcc->GetSampleTime());
    254 
    255  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    256  PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
    257             ScreenPoint(0, 0), mcc->Time());
    258  mcc->AdvanceByMillis(5);
    259  apzc->AdvanceAnimations(mcc->GetSampleTime());
    260 
    261  // Double check that we have not panned on the vertical axis.
    262  ParentLayerPoint panEndOffset = apzc->GetCurrentAsyncScrollOffset(
    263      AsyncTransformConsumer::eForEventHandling);
    264  EXPECT_EQ(panEndOffset.y, 0);
    265 
    266  // Ensure that the axis locks extends into momentum scroll.
    267  apzc->AssertAxisLocked(ScrollDirection::eHorizontal);
    268 
    269  // Start the momentum scroll.
    270  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    271  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, manager,
    272             ScreenIntPoint(50, 50), ScreenPoint(80, 40), mcc->Time());
    273  mcc->AdvanceByMillis(10);
    274  apzc->AdvanceAnimations(mcc->GetSampleTime());
    275 
    276  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    277  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, manager,
    278             ScreenIntPoint(50, 50), ScreenPoint(20, 10), mcc->Time());
    279  mcc->AdvanceByMillis(10);
    280  apzc->AdvanceAnimations(mcc->GetSampleTime());
    281 
    282  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    283  PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, manager,
    284             ScreenIntPoint(50, 50), ScreenPoint(20, 10), mcc->Time());
    285  mcc->AdvanceByMillis(10);
    286  apzc->AdvanceAnimations(mcc->GetSampleTime());
    287 
    288  // In momentum locking mode, we should still be locked onto the X axis.
    289  apzc->AssertStateIsPanMomentum();
    290  apzc->AssertAxisLocked(ScrollDirection::eHorizontal);
    291  EXPECT_GT(apzc->GetVelocityVector().x, 0);
    292  EXPECT_EQ(apzc->GetVelocityVector().y, 0);
    293 
    294  ParentLayerPoint beforeBreakOffset = apzc->GetCurrentAsyncScrollOffset(
    295      AsyncTransformConsumer::eForEventHandling);
    296  EXPECT_EQ(beforeBreakOffset.y, 0);
    297  // Ensure we have scrolled some amount on the X axis in momentum scroll.
    298  EXPECT_GT(beforeBreakOffset.x, panEndOffset.x);
    299 
    300  // Kick off the gesture that breaks the lock onto the X axis.
    301  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    302  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
    303             ScreenIntPoint(1, 2), mcc->Time());
    304  mcc->AdvanceByMillis(5);
    305  apzc->AdvanceAnimations(mcc->GetSampleTime());
    306 
    307  ParentLayerPoint afterBreakOffset = apzc->GetCurrentAsyncScrollOffset(
    308      AsyncTransformConsumer::eForEventHandling);
    309 
    310  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    311  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
    312             ScreenPoint(15, 30), mcc->Time());
    313  mcc->AdvanceByMillis(5);
    314  apzc->AdvanceAnimations(mcc->GetSampleTime());
    315 
    316  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    317  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
    318             ScreenPoint(15, 30), mcc->Time());
    319 
    320  // The lock onto the X axis should be broken and we now should be locked
    321  // onto the Y axis.
    322  apzc->AssertStateIsPanningLockedY();
    323  apzc->AssertAxisLocked(ScrollDirection::eVertical);
    324  EXPECT_GT(apzc->GetVelocityVector().y, 0);
    325  EXPECT_EQ(apzc->GetVelocityVector().x, 0);
    326 
    327  mcc->AdvanceByMillis(5);
    328  apzc->AdvanceAnimations(mcc->GetSampleTime());
    329 
    330  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    331  PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
    332             ScreenPoint(0, 0), mcc->Time());
    333  mcc->AdvanceByMillis(5);
    334  apzc->AdvanceAnimations(mcc->GetSampleTime());
    335 
    336  // The lock onto the Y axis extends into momentum scroll.
    337  apzc->AssertAxisLocked(ScrollDirection::eVertical);
    338 
    339  // Wait until the end of the animation and ensure the final state is
    340  // reasonable.
    341  apzc->AdvanceAnimationsUntilEnd();
    342  ParentLayerPoint finalOffset = apzc->GetCurrentAsyncScrollOffset(
    343      AsyncTransformConsumer::eForEventHandling);
    344 
    345  EXPECT_GT(finalOffset.y, 0);
    346  // Ensure that we did not scroll on the X axis after the vertical scroll
    347  // started.
    348  EXPECT_EQ(finalOffset.x, afterBreakOffset.x);
    349 }
    350 
    351 TEST_F(APZCAxisLockTester, BreakStickyAxisLock) {
    352  SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
    353  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", M_PI / 6.0f);
    354  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_angle", M_PI / 6.0f);
    355 
    356  SetupBasicTest();
    357 
    358  apzc = ApzcOf(root);
    359 
    360  // Start a gesture to get us locked onto the Y axis.
    361  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    362  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
    363             ScreenIntPoint(0, 2), mcc->Time());
    364  mcc->AdvanceByMillis(5);
    365  apzc->AdvanceAnimations(mcc->GetSampleTime());
    366 
    367  // Ensure that we have locked onto the Y axis.
    368  apzc->AssertStateIsPanningLockedY();
    369 
    370  // Test switch to locking onto the X axis.
    371  BreakStickyAxisLockTest(ScrollDirection::eHorizontal);
    372 
    373  // Test switch back to locking onto the Y axis.
    374  BreakStickyAxisLockTest(ScrollDirection::eVertical);
    375 
    376  // Test breaking all axis locks from a Y axis lock.
    377  BreakStickyAxisLockTest(ScrollDirections(ScrollDirection::eHorizontal,
    378                                           ScrollDirection::eVertical));
    379 
    380  // We should be in a panning state.
    381  apzc->AssertStateIsPanning();
    382  apzc->AssertNotAxisLocked();
    383 
    384  // Lock back to the X axis.
    385  BreakStickyAxisLockTestGesture(ScrollDirection::eHorizontal);
    386 
    387  // End the gesture.
    388  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    389  PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
    390             ScreenPoint(0, 0), mcc->Time());
    391  mcc->AdvanceByMillis(5);
    392  apzc->AdvanceAnimations(mcc->GetSampleTime());
    393 
    394  // Start a gesture to get us locked onto the X axis.
    395  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    396  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
    397             ScreenIntPoint(2, 0), mcc->Time());
    398  mcc->AdvanceByMillis(5);
    399  apzc->AdvanceAnimations(mcc->GetSampleTime());
    400 
    401  // Ensure that we have locked onto the X axis.
    402  apzc->AssertStateIsPanningLockedX();
    403 
    404  // Test breaking all axis locks from a X axis lock.
    405  BreakStickyAxisLockTest(ScrollDirections(ScrollDirection::eHorizontal,
    406                                           ScrollDirection::eVertical));
    407 
    408  // We should be in a panning state.
    409  apzc->AssertStateIsPanning();
    410  apzc->AssertNotAxisLocked();
    411 
    412  // Test switch back to locking onto the Y axis.
    413  BreakStickyAxisLockTest(ScrollDirection::eVertical);
    414 }
    415 
    416 TEST_F(APZCAxisLockTester, BreakAxisLockByLockAngle) {
    417  SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
    418  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", M_PI / 4.0f);
    419  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_angle", M_PI / 8.0f);
    420 
    421  SetupBasicTest();
    422 
    423  apzc = ApzcOf(root);
    424 
    425  // Start a gesture to get us locked onto the Y axis.
    426  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    427  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
    428             ScreenIntPoint(1, 10), mcc->Time());
    429  mcc->AdvanceByMillis(5);
    430  apzc->AdvanceAnimations(mcc->GetSampleTime());
    431 
    432  // Ensure that we have locked onto the Y axis.
    433  apzc->AssertStateIsPanningLockedY();
    434 
    435  // Stay within 45 degrees from the X axis, and more than 22.5 degrees from
    436  // the Y axis. This should break the Y lock and lock us to the X axis.
    437  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    438  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, ScreenIntPoint(50, 50),
    439             ScreenIntPoint(12, 10), mcc->Time());
    440  apzc->AdvanceAnimations(mcc->GetSampleTime());
    441 
    442  // Ensure that we have locked onto the X axis.
    443  apzc->AssertStateIsPanningLockedX();
    444 
    445  // End the gesture.
    446  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    447  PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
    448             ScreenPoint(0, 0), mcc->Time());
    449  apzc->AdvanceAnimations(mcc->GetSampleTime());
    450 }
    451 
    452 TEST_F(APZCAxisLockTester, TestCanBreakBreakableAxisLock) {
    453  SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 4);
    454  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", M_PI / 4.0f);
    455  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_angle", M_PI / 8.0f);
    456 
    457  SetupBasicTest();
    458 
    459  apzc = ApzcOf(root);
    460 
    461  // Start a gesture to get us locked onto the Y axis.
    462  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    463  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
    464             ScreenIntPoint(0, 10), mcc->Time());
    465  mcc->AdvanceByMillis(5);
    466  apzc->AdvanceAnimations(mcc->GetSampleTime());
    467 
    468  // Ensure that we have locked onto the Y axis.
    469  apzc->AssertStateIsPanningLockedY();
    470 
    471  // Break the Y axis in a way that would lock onto the X axis if the
    472  // AxisLockMode is STICKY, but should freely pan if it is BREAKABLE.
    473  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    474  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, ScreenIntPoint(50, 50),
    475             ScreenIntPoint(10, 0), mcc->Time());
    476  apzc->AdvanceAnimations(mcc->GetSampleTime());
    477 
    478  // Ensure that we have broken the Y axis, and are not locked onto the X axis.
    479  apzc->AssertStateIsPanning();
    480 
    481  // Do a gesture that would re-lock on the Y axis if we were STICKY.
    482  // Should not re-lock.
    483  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    484  PanGesture(PanGestureInput::PANGESTURE_PAN, manager, ScreenIntPoint(50, 50),
    485             ScreenIntPoint(0, -10), mcc->Time());
    486  apzc->AdvanceAnimations(mcc->GetSampleTime());
    487 
    488  // Ensure that we have not acquired a lock on the Y axis.
    489  apzc->AssertStateIsPanning();
    490 
    491  // End the gesture.
    492  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    493  PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
    494             ScreenPoint(0, 0), mcc->Time());
    495  apzc->AdvanceAnimations(mcc->GetSampleTime());
    496 }
    497 
    498 TEST_F(APZCAxisLockTester, TestDominantAxisScrolling) {
    499  SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 3);
    500 
    501  int panY;
    502  int panX;
    503 
    504  SetupBasicTest();
    505 
    506  apzc = ApzcOf(root);
    507 
    508  ParentLayerPoint lastOffset = apzc->GetCurrentAsyncScrollOffset(
    509      AsyncPanZoomController::eForEventHandling);
    510 
    511  // In dominant axis mode, test pan gesture events with varying gesture
    512  // angles and ensure that we only pan on one axis.
    513  for (panX = 0, panY = 50; panY >= 0; panY -= 10, panX += 5) {
    514    // Gesture that should be locked onto one axis
    515    QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    516    PanGesture(PanGestureInput::PANGESTURE_START, manager,
    517               ScreenIntPoint(50, 50), ScreenIntPoint(panX, panY), mcc->Time());
    518    mcc->AdvanceByMillis(5);
    519    apzc->AdvanceAnimations(mcc->GetSampleTime());
    520 
    521    QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    522    PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
    523               ScreenPoint(static_cast<float>(panX), static_cast<float>(panY)),
    524               mcc->Time());
    525    mcc->AdvanceByMillis(5);
    526    apzc->AdvanceAnimations(mcc->GetSampleTime());
    527 
    528    QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    529    PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
    530               ScreenPoint(0, 0), mcc->Time());
    531    apzc->AdvanceAnimationsUntilEnd();
    532 
    533    ParentLayerPoint scrollOffset = apzc->GetCurrentAsyncScrollOffset(
    534        AsyncPanZoomController::eForEventHandling);
    535 
    536    if (panX > panY) {
    537      // If we're closer to the X axis ensure that we moved on the horizontal
    538      // axis and there was no movement on the vertical axis.
    539      EXPECT_GT(scrollOffset.x, lastOffset.x);
    540      EXPECT_EQ(scrollOffset.y, lastOffset.y);
    541    } else {
    542      // If we're closer to the Y axis ensure that we moved on the vertical
    543      // axis and there was no movement on the horizontal axis.
    544      EXPECT_GT(scrollOffset.y, lastOffset.y);
    545      EXPECT_EQ(scrollOffset.x, lastOffset.x);
    546    }
    547 
    548    lastOffset = scrollOffset;
    549  }
    550 }
    551 
    552 TEST_F(APZCAxisLockTester, TestCanScrollWithAxisLock) {
    553  SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
    554 
    555  SetupBasicTest();
    556 
    557  apzc = ApzcOf(root);
    558 
    559  // The axis locks do not impact CanScroll()
    560  apzc->SetAxisLocked(ScrollDirection::eHorizontal, true);
    561  EXPECT_EQ(apzc->CanScroll(ParentLayerPoint(10, 0)), true);
    562 
    563  apzc->SetAxisLocked(ScrollDirection::eHorizontal, false);
    564  apzc->SetAxisLocked(ScrollDirection::eVertical, true);
    565  EXPECT_EQ(apzc->CanScroll(ParentLayerPoint(0, 10)), true);
    566 }
    567 
    568 TEST_F(APZCAxisLockTester, TestScrollHandoffAxisLockConflict) {
    569  SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
    570 
    571  // Create two scrollable frames. One parent frame with one child.
    572  const char* treeShape = "x(x)";
    573  LayerIntRect layerVisibleRect[] = {
    574      LayerIntRect(0, 0, 100, 100),
    575      LayerIntRect(0, 0, 100, 100),
    576  };
    577  CreateScrollData(treeShape, layerVisibleRect);
    578  SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
    579                            CSSRect(0, 0, 500, 500));
    580  SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID + 1,
    581                            CSSRect(0, 0, 500, 500));
    582  SetScrollHandoff(layers[1], root);
    583 
    584  registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
    585 
    586  UpdateHitTestingTree();
    587 
    588  RefPtr<TestAsyncPanZoomController> rootApzc = ApzcOf(root);
    589  apzc = ApzcOf(layers[1]);
    590 
    591  // Create a gesture on the y-axis that should lock the x axis.
    592  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
    593  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
    594             ScreenIntPoint(0, 2), mcc->Time());
    595  mcc->AdvanceByMillis(5);
    596  apzc->AdvanceAnimations(mcc->GetSampleTime());
    597 
    598  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
    599  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
    600             ScreenPoint(0, 15), mcc->Time());
    601  mcc->AdvanceByMillis(5);
    602  apzc->AdvanceAnimations(mcc->GetSampleTime());
    603 
    604  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
    605  PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
    606             ScreenPoint(0, 0), mcc->Time());
    607  mcc->AdvanceByMillis(5);
    608  apzc->AdvanceAnimationsUntilEnd();
    609 
    610  // We are locked onto the y-axis.
    611  apzc->AssertAxisLocked(ScrollDirection::eVertical);
    612 
    613  // There should be movement in the child.
    614  ParentLayerPoint childCurrentOffset = apzc->GetCurrentAsyncScrollOffset(
    615      AsyncTransformConsumer::eForEventHandling);
    616  EXPECT_GT(childCurrentOffset.y, 0);
    617  EXPECT_EQ(childCurrentOffset.x, 0);
    618 
    619  // There should be no movement in the parent.
    620  ParentLayerPoint parentCurrentOffset = rootApzc->GetCurrentAsyncScrollOffset(
    621      AsyncTransformConsumer::eForEventHandling);
    622  EXPECT_EQ(parentCurrentOffset.y, 0);
    623  EXPECT_EQ(parentCurrentOffset.x, 0);
    624 
    625  // Create a gesture on the x-axis, that should be directed
    626  // at the child, even if the x-axis is locked.
    627  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
    628  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
    629             ScreenIntPoint(2, 0), mcc->Time());
    630  mcc->AdvanceByMillis(5);
    631  apzc->AdvanceAnimations(mcc->GetSampleTime());
    632 
    633  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
    634  PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
    635             ScreenPoint(15, 0), mcc->Time());
    636  mcc->AdvanceByMillis(5);
    637  apzc->AdvanceAnimations(mcc->GetSampleTime());
    638 
    639  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
    640  PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
    641             ScreenPoint(0, 0), mcc->Time());
    642  mcc->AdvanceByMillis(5);
    643  apzc->AdvanceAnimationsUntilEnd();
    644 
    645  // We broke the y-axis lock and are now locked onto the x-axis.
    646  apzc->AssertAxisLocked(ScrollDirection::eHorizontal);
    647 
    648  // There should be some movement in the child on the x-axis.
    649  ParentLayerPoint childFinalOffset = apzc->GetCurrentAsyncScrollOffset(
    650      AsyncTransformConsumer::eForEventHandling);
    651  EXPECT_GT(childFinalOffset.x, 0);
    652 
    653  // There should still be no movement in the parent.
    654  ParentLayerPoint parentFinalOffset = rootApzc->GetCurrentAsyncScrollOffset(
    655      AsyncTransformConsumer::eForEventHandling);
    656  EXPECT_EQ(parentFinalOffset.y, 0);
    657  EXPECT_EQ(parentFinalOffset.x, 0);
    658 }
    659 
    660 // The delta from the initial pan gesture should be reflected in the
    661 // current offset for all axis locking modes.
    662 TEST_P(APZCAxisLockCompatTester, TestPanGestureStart) {
    663  const char* treeShape = "x";
    664  LayerIntRect layerVisibleRect[] = {
    665      LayerIntRect(0, 0, 100, 100),
    666  };
    667  CreateScrollData(treeShape, layerVisibleRect);
    668  SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
    669                            CSSRect(0, 0, 500, 500));
    670 
    671  registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
    672 
    673  UpdateHitTestingTree();
    674 
    675  apzc = ApzcOf(root);
    676 
    677  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    678  PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
    679             ScreenIntPoint(0, 10), mcc->Time());
    680  mcc->AdvanceByMillis(5);
    681  apzc->AdvanceAnimationsUntilEnd();
    682  ParentLayerPoint currentOffset = apzc->GetCurrentAsyncScrollOffset(
    683      AsyncTransformConsumer::eForEventHandling);
    684 
    685  EXPECT_EQ(currentOffset.x, 0);
    686  EXPECT_EQ(currentOffset.y, 10);
    687 }
    688 
    689 #ifdef MOZ_WIDGET_ANDROID
    690 TEST_F(APZCAxisLockTester, TouchScrollWithStickyAxisLocking) {
    691  SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
    692  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_threshold", 10);
    693  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_angle", 0.392699);
    694  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", 0.523599);
    695 
    696  SetupBasicTest();
    697 
    698  apzc = ApzcOf(root);
    699 
    700  // Scroll somewhere into the middle of the scroll range, so that we have
    701  // lots of space to scroll in both directions.
    702  apzc->GetFrameMetrics().SetVisualScrollOffset(CSSPoint(250, 250));
    703 
    704  UpdateHitTestingTree();
    705 
    706  // Trigger a touch scroll that will cause us to lock onto the
    707  // y-axis.
    708  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    709  (void)TouchDown(apzc, ScreenIntPoint(50, 50), mcc->Time());
    710  mcc->AdvanceByMillis(50);
    711 
    712  (void)TouchMove(apzc, ScreenIntPoint(50, 60), mcc->Time());
    713  mcc->AdvanceByMillis(400);
    714 
    715  (void)TouchMove(apzc, ScreenIntPoint(50, 70), mcc->Time());
    716  mcc->AdvanceByMillis(400);
    717 
    718  apzc->AssertStateIsPanningLockedY();
    719 
    720  ParentLayerPoint currentOffset = apzc->GetCurrentAsyncScrollOffset(
    721      AsyncTransformConsumer::eForEventHandling);
    722  ParentLayerPoint lastOffset = currentOffset;
    723 
    724  // A touch scroll in the reverse direction with slight movement
    725  // on the x-axis should not cause us to break the y-axis lock.
    726  (void)TouchMove(apzc, ScreenIntPoint(55, 60), mcc->Time());
    727  mcc->AdvanceByMillis(200);
    728 
    729  // We should have scrolled only on the y-axis.
    730  currentOffset = apzc->GetCurrentAsyncScrollOffset(
    731      AsyncTransformConsumer::eForEventHandling);
    732  EXPECT_GT(currentOffset.y, lastOffset.y);
    733  EXPECT_EQ(currentOffset.x, lastOffset.x);
    734  lastOffset = currentOffset;
    735  apzc->AssertStateIsPanningLockedY();
    736 
    737  (void)TouchMove(apzc, ScreenIntPoint(60, 50), mcc->Time());
    738  mcc->AdvanceByMillis(200);
    739 
    740  // We should continue to scroll only on the y-axis.
    741  currentOffset = apzc->GetCurrentAsyncScrollOffset(
    742      AsyncTransformConsumer::eForEventHandling);
    743  EXPECT_GT(currentOffset.y, lastOffset.y);
    744  EXPECT_EQ(currentOffset.x, lastOffset.x);
    745  apzc->AssertStateIsPanningLockedY();
    746  lastOffset = currentOffset;
    747 
    748  (void)TouchMove(apzc, ScreenIntPoint(60, 40), mcc->Time());
    749  mcc->AdvanceByMillis(200);
    750 
    751  currentOffset = apzc->GetCurrentAsyncScrollOffset(
    752      AsyncTransformConsumer::eForEventHandling);
    753  EXPECT_GT(currentOffset.y, lastOffset.y);
    754  EXPECT_EQ(currentOffset.x, lastOffset.x);
    755  apzc->AssertStateIsPanningLockedY();
    756  lastOffset = currentOffset;
    757 
    758  (void)TouchUp(apzc, ScreenIntPoint(65, 40), mcc->Time());
    759 }
    760 #endif
    761 
    762 // TODO(bug 1915260): Make this test pass.
    763 #ifdef MOZ_WIDGET_ANDROID
    764 TEST_F(APZCAxisLockTester, TouchScrollWithStickyAxisLockingBug1915260) {
    765  SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
    766  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_threshold", 10);
    767  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_angle", 0.392699);
    768  SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", 0.523599);
    769 
    770  SetupBasicTest();
    771 
    772  apzc = ApzcOf(root);
    773 
    774  // Scroll somewhere into the middle of the scroll range, so that we have
    775  // lots of space to scroll in both directions.
    776  apzc->GetFrameMetrics().SetVisualScrollOffset(CSSPoint(250, 250));
    777 
    778  // Trigger a touch scroll that will cause us to lock onto the
    779  // y-axis.
    780  QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
    781  (void)TouchDown(apzc, ScreenIntPoint(50, 50), mcc->Time());
    782  mcc->AdvanceByMillis(10);
    783 
    784  (void)TouchMove(apzc, ScreenIntPoint(50, 60), mcc->Time());
    785  mcc->AdvanceByMillis(200);
    786 
    787  (void)TouchMove(apzc, ScreenIntPoint(50, 70), mcc->Time());
    788  mcc->AdvanceByMillis(200);
    789 
    790  // We should be locked on the y-axis at this point.
    791  // apzc->AssertStateIsPanningLockedY();
    792 
    793  // Assuming the last event in the historical touch scroll buffer
    794  // we use to determine touch scroll direction is (50,60), this
    795  // touch-move event will exceed the breakout threshold and will
    796  // be considered to be a horizontal scroll, thus breaking the
    797  // lock onto the y-axis.
    798  (void)TouchMove(apzc, ScreenIntPoint(60, 60), mcc->Time());
    799  mcc->AdvanceByMillis(100);
    800  // TODO(bug 1915260): We should still be be locked on the y-axis at this
    801  // point.
    802  // apzc->AssertStateIsPanningLockedY();
    803 
    804  (void)TouchUp(apzc, ScreenIntPoint(65, 45), mcc->Time());
    805 }
    806 #endif
    807 
    808 // All APZCAxisLockCompatTester tests should be run for each apz.axis_lock.mode.
    809 // If another mode is added, the value should be added to this list.
    810 INSTANTIATE_TEST_SUITE_P(APZCAxisLockCompat, APZCAxisLockCompatTester,
    811                         testing::Values(0, 1, 2, 3, 4),
    812                         APZCAxisLockCompatTester::PrintFromParam);