812 lines
30 KiB
C++
812 lines
30 KiB
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 "APZCTreeManagerTester.h"
|
|
#include "APZTestCommon.h"
|
|
|
|
#include "InputUtils.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
#include <cmath>
|
|
|
|
class APZCAxisLockCompatTester : public APZCTreeManagerTester,
|
|
public testing::WithParamInterface<int> {
|
|
public:
|
|
APZCAxisLockCompatTester() : oldAxisLockMode(0) { CreateMockHitTester(); }
|
|
|
|
int oldAxisLockMode;
|
|
|
|
UniquePtr<ScopedLayerTreeRegistration> registration;
|
|
|
|
RefPtr<TestAsyncPanZoomController> apzc;
|
|
|
|
void SetUp() {
|
|
APZCTreeManagerTester::SetUp();
|
|
|
|
oldAxisLockMode = Preferences::GetInt("apz.axis_lock.mode");
|
|
|
|
Preferences::SetInt("apz.axis_lock.mode", GetParam());
|
|
}
|
|
|
|
void TearDown() {
|
|
APZCTreeManagerTester::TearDown();
|
|
|
|
Preferences::SetInt("apz.axis_lock.mode", oldAxisLockMode);
|
|
}
|
|
|
|
static std::string PrintFromParam(const testing::TestParamInfo<int>& info) {
|
|
switch (info.param) {
|
|
case 0:
|
|
return "FREE";
|
|
case 1:
|
|
return "STANDARD";
|
|
case 2:
|
|
return "STICKY";
|
|
case 3:
|
|
return "DOMINANT_AXIS";
|
|
case 4:
|
|
return "BREAKABLE";
|
|
default:
|
|
return "UNKNOWN";
|
|
}
|
|
}
|
|
};
|
|
|
|
class APZCAxisLockTester : public APZCTreeManagerTester {
|
|
public:
|
|
APZCAxisLockTester() { CreateMockHitTester(); }
|
|
|
|
UniquePtr<ScopedLayerTreeRegistration> registration;
|
|
|
|
RefPtr<TestAsyncPanZoomController> apzc;
|
|
|
|
void SetupBasicTest() {
|
|
const char* treeShape = "x";
|
|
LayerIntRect layerVisibleRect[] = {
|
|
LayerIntRect(0, 0, 100, 100),
|
|
};
|
|
CreateScrollData(treeShape, layerVisibleRect);
|
|
SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
|
|
CSSRect(0, 0, 500, 500));
|
|
|
|
registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
|
|
|
|
UpdateHitTestingTree();
|
|
}
|
|
|
|
void BreakStickyAxisLockTestGesture(const ScrollDirections& aDirections) {
|
|
float panX = 0;
|
|
float panY = 0;
|
|
|
|
if (aDirections.contains(ScrollDirection::eVertical)) {
|
|
panY = 30;
|
|
}
|
|
if (aDirections.contains(ScrollDirection::eHorizontal)) {
|
|
panX = 30;
|
|
}
|
|
|
|
// Kick off the gesture that may lock onto an axis
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
|
|
ScreenPoint(panX, panY), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
|
|
ScreenPoint(panX, panY), mcc->Time());
|
|
}
|
|
|
|
void BreakStickyAxisLockTest(const ScrollDirections& aDirections) {
|
|
// Create the gesture for the test.
|
|
BreakStickyAxisLockTestGesture(aDirections);
|
|
|
|
// Based on the scroll direction(s) ensure the state is what we expect.
|
|
if (aDirections == ScrollDirection::eVertical) {
|
|
apzc->AssertStateIsPanningLockedY();
|
|
apzc->AssertAxisLocked(ScrollDirection::eVertical);
|
|
EXPECT_GT(apzc->GetVelocityVector().y, 0);
|
|
EXPECT_EQ(apzc->GetVelocityVector().x, 0);
|
|
} else if (aDirections == ScrollDirection::eHorizontal) {
|
|
apzc->AssertStateIsPanningLockedX();
|
|
apzc->AssertAxisLocked(ScrollDirection::eHorizontal);
|
|
EXPECT_GT(apzc->GetVelocityVector().x, 0);
|
|
EXPECT_EQ(apzc->GetVelocityVector().y, 0);
|
|
} else {
|
|
apzc->AssertStateIsPanning();
|
|
apzc->AssertNotAxisLocked();
|
|
EXPECT_GT(apzc->GetVelocityVector().x, 0);
|
|
EXPECT_GT(apzc->GetVelocityVector().y, 0);
|
|
}
|
|
|
|
// Cleanup for next test.
|
|
apzc->AdvanceAnimationsUntilEnd();
|
|
}
|
|
};
|
|
|
|
TEST_F(APZCAxisLockTester, BasicDominantAxisUse) {
|
|
SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 1);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", M_PI / 4.0f);
|
|
|
|
SetupBasicTest();
|
|
|
|
apzc = ApzcOf(root);
|
|
|
|
// Kick off the initial gesture that triggers the momentum scroll.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
|
|
ScreenIntPoint(1, 2), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
|
|
ScreenPoint(15, 30), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
|
|
ScreenPoint(15, 30), mcc->Time());
|
|
|
|
// Should be in a PANNING_LOCKED_Y state with no horizontal velocity.
|
|
apzc->AssertStateIsPanningLockedY();
|
|
apzc->AssertAxisLocked(ScrollDirection::eVertical);
|
|
EXPECT_GT(apzc->GetVelocityVector().y, 0);
|
|
EXPECT_EQ(apzc->GetVelocityVector().x, 0);
|
|
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
|
|
ScreenPoint(0, 0), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
// Ensure that we have not panned on the horizontal axis.
|
|
ParentLayerPoint panEndOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
EXPECT_EQ(panEndOffset.x, 0);
|
|
|
|
// The lock onto the Y axis extends into momentum scroll.
|
|
apzc->AssertAxisLocked(ScrollDirection::eVertical);
|
|
|
|
// Start the momentum scroll.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, manager,
|
|
ScreenIntPoint(50, 50), ScreenPoint(30, 90), mcc->Time());
|
|
mcc->AdvanceByMillis(10);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, manager,
|
|
ScreenIntPoint(50, 50), ScreenPoint(10, 30), mcc->Time());
|
|
mcc->AdvanceByMillis(10);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, manager,
|
|
ScreenIntPoint(50, 50), ScreenPoint(10, 30), mcc->Time());
|
|
mcc->AdvanceByMillis(10);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
// In momentum locking mode, we should still be locked onto the Y axis.
|
|
apzc->AssertStateIsPanMomentum();
|
|
apzc->AssertAxisLocked(ScrollDirection::eVertical);
|
|
EXPECT_GT(apzc->GetVelocityVector().y, 0);
|
|
EXPECT_EQ(apzc->GetVelocityVector().x, 0);
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_MOMENTUMEND, manager,
|
|
ScreenIntPoint(50, 50), ScreenPoint(0, 0), mcc->Time());
|
|
|
|
// After momentum scroll end, ensure we are no longer locked onto an axis.
|
|
apzc->AssertNotAxisLocked();
|
|
|
|
// Wait until the end of the animation and ensure the final state is
|
|
// reasonable.
|
|
apzc->AdvanceAnimationsUntilEnd();
|
|
ParentLayerPoint finalOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
|
|
// Ensure we have scrolled some amount on the Y axis in momentum scroll.
|
|
EXPECT_GT(finalOffset.y, panEndOffset.y);
|
|
EXPECT_EQ(finalOffset.x, 0.0f);
|
|
}
|
|
|
|
TEST_F(APZCAxisLockTester, NewGestureBreaksMomentumAxisLock) {
|
|
SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 1);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", M_PI / 4.0f);
|
|
|
|
SetupBasicTest();
|
|
|
|
apzc = ApzcOf(root);
|
|
|
|
// Kick off the initial gesture that triggers the momentum scroll.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
|
|
ScreenIntPoint(2, 1), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
|
|
ScreenPoint(30, 15), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
|
|
ScreenPoint(30, 15), mcc->Time());
|
|
|
|
// Should be in a PANNING_LOCKED_X state with no vertical velocity.
|
|
apzc->AssertStateIsPanningLockedX();
|
|
apzc->AssertAxisLocked(ScrollDirection::eHorizontal);
|
|
EXPECT_GT(apzc->GetVelocityVector().x, 0);
|
|
EXPECT_EQ(apzc->GetVelocityVector().y, 0);
|
|
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
|
|
ScreenPoint(0, 0), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
// Double check that we have not panned on the vertical axis.
|
|
ParentLayerPoint panEndOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
EXPECT_EQ(panEndOffset.y, 0);
|
|
|
|
// Ensure that the axis locks extends into momentum scroll.
|
|
apzc->AssertAxisLocked(ScrollDirection::eHorizontal);
|
|
|
|
// Start the momentum scroll.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_MOMENTUMSTART, manager,
|
|
ScreenIntPoint(50, 50), ScreenPoint(80, 40), mcc->Time());
|
|
mcc->AdvanceByMillis(10);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, manager,
|
|
ScreenIntPoint(50, 50), ScreenPoint(20, 10), mcc->Time());
|
|
mcc->AdvanceByMillis(10);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_MOMENTUMPAN, manager,
|
|
ScreenIntPoint(50, 50), ScreenPoint(20, 10), mcc->Time());
|
|
mcc->AdvanceByMillis(10);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
// In momentum locking mode, we should still be locked onto the X axis.
|
|
apzc->AssertStateIsPanMomentum();
|
|
apzc->AssertAxisLocked(ScrollDirection::eHorizontal);
|
|
EXPECT_GT(apzc->GetVelocityVector().x, 0);
|
|
EXPECT_EQ(apzc->GetVelocityVector().y, 0);
|
|
|
|
ParentLayerPoint beforeBreakOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
EXPECT_EQ(beforeBreakOffset.y, 0);
|
|
// Ensure we have scrolled some amount on the X axis in momentum scroll.
|
|
EXPECT_GT(beforeBreakOffset.x, panEndOffset.x);
|
|
|
|
// Kick off the gesture that breaks the lock onto the X axis.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
|
|
ScreenIntPoint(1, 2), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
ParentLayerPoint afterBreakOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
|
|
ScreenPoint(15, 30), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
|
|
ScreenPoint(15, 30), mcc->Time());
|
|
|
|
// The lock onto the X axis should be broken and we now should be locked
|
|
// onto the Y axis.
|
|
apzc->AssertStateIsPanningLockedY();
|
|
apzc->AssertAxisLocked(ScrollDirection::eVertical);
|
|
EXPECT_GT(apzc->GetVelocityVector().y, 0);
|
|
EXPECT_EQ(apzc->GetVelocityVector().x, 0);
|
|
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
|
|
ScreenPoint(0, 0), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
// The lock onto the Y axis extends into momentum scroll.
|
|
apzc->AssertAxisLocked(ScrollDirection::eVertical);
|
|
|
|
// Wait until the end of the animation and ensure the final state is
|
|
// reasonable.
|
|
apzc->AdvanceAnimationsUntilEnd();
|
|
ParentLayerPoint finalOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
|
|
EXPECT_GT(finalOffset.y, 0);
|
|
// Ensure that we did not scroll on the X axis after the vertical scroll
|
|
// started.
|
|
EXPECT_EQ(finalOffset.x, afterBreakOffset.x);
|
|
}
|
|
|
|
TEST_F(APZCAxisLockTester, BreakStickyAxisLock) {
|
|
SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", M_PI / 6.0f);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_angle", M_PI / 6.0f);
|
|
|
|
SetupBasicTest();
|
|
|
|
apzc = ApzcOf(root);
|
|
|
|
// Start a gesture to get us locked onto the Y axis.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
|
|
ScreenIntPoint(0, 2), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
// Ensure that we have locked onto the Y axis.
|
|
apzc->AssertStateIsPanningLockedY();
|
|
|
|
// Test switch to locking onto the X axis.
|
|
BreakStickyAxisLockTest(ScrollDirection::eHorizontal);
|
|
|
|
// Test switch back to locking onto the Y axis.
|
|
BreakStickyAxisLockTest(ScrollDirection::eVertical);
|
|
|
|
// Test breaking all axis locks from a Y axis lock.
|
|
BreakStickyAxisLockTest(ScrollDirections(ScrollDirection::eHorizontal,
|
|
ScrollDirection::eVertical));
|
|
|
|
// We should be in a panning state.
|
|
apzc->AssertStateIsPanning();
|
|
apzc->AssertNotAxisLocked();
|
|
|
|
// Lock back to the X axis.
|
|
BreakStickyAxisLockTestGesture(ScrollDirection::eHorizontal);
|
|
|
|
// End the gesture.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
|
|
ScreenPoint(0, 0), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
// Start a gesture to get us locked onto the X axis.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
|
|
ScreenIntPoint(2, 0), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
// Ensure that we have locked onto the X axis.
|
|
apzc->AssertStateIsPanningLockedX();
|
|
|
|
// Test breaking all axis locks from a X axis lock.
|
|
BreakStickyAxisLockTest(ScrollDirections(ScrollDirection::eHorizontal,
|
|
ScrollDirection::eVertical));
|
|
|
|
// We should be in a panning state.
|
|
apzc->AssertStateIsPanning();
|
|
apzc->AssertNotAxisLocked();
|
|
|
|
// Test switch back to locking onto the Y axis.
|
|
BreakStickyAxisLockTest(ScrollDirection::eVertical);
|
|
}
|
|
|
|
TEST_F(APZCAxisLockTester, BreakAxisLockByLockAngle) {
|
|
SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", M_PI / 4.0f);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_angle", M_PI / 8.0f);
|
|
|
|
SetupBasicTest();
|
|
|
|
apzc = ApzcOf(root);
|
|
|
|
// Start a gesture to get us locked onto the Y axis.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
|
|
ScreenIntPoint(1, 10), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
// Ensure that we have locked onto the Y axis.
|
|
apzc->AssertStateIsPanningLockedY();
|
|
|
|
// Stay within 45 degrees from the X axis, and more than 22.5 degrees from
|
|
// the Y axis. This should break the Y lock and lock us to the X axis.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, manager, ScreenIntPoint(50, 50),
|
|
ScreenIntPoint(12, 10), mcc->Time());
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
// Ensure that we have locked onto the X axis.
|
|
apzc->AssertStateIsPanningLockedX();
|
|
|
|
// End the gesture.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
|
|
ScreenPoint(0, 0), mcc->Time());
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
}
|
|
|
|
TEST_F(APZCAxisLockTester, TestCanBreakBreakableAxisLock) {
|
|
SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 4);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", M_PI / 4.0f);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_angle", M_PI / 8.0f);
|
|
|
|
SetupBasicTest();
|
|
|
|
apzc = ApzcOf(root);
|
|
|
|
// Start a gesture to get us locked onto the Y axis.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
|
|
ScreenIntPoint(0, 10), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
// Ensure that we have locked onto the Y axis.
|
|
apzc->AssertStateIsPanningLockedY();
|
|
|
|
// Break the Y axis in a way that would lock onto the X axis if the
|
|
// AxisLockMode is STICKY, but should freely pan if it is BREAKABLE.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, manager, ScreenIntPoint(50, 50),
|
|
ScreenIntPoint(10, 0), mcc->Time());
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
// Ensure that we have broken the Y axis, and are not locked onto the X axis.
|
|
apzc->AssertStateIsPanning();
|
|
|
|
// Do a gesture that would re-lock on the Y axis if we were STICKY.
|
|
// Should not re-lock.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, manager, ScreenIntPoint(50, 50),
|
|
ScreenIntPoint(0, -10), mcc->Time());
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
// Ensure that we have not acquired a lock on the Y axis.
|
|
apzc->AssertStateIsPanning();
|
|
|
|
// End the gesture.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
|
|
ScreenPoint(0, 0), mcc->Time());
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
}
|
|
|
|
TEST_F(APZCAxisLockTester, TestDominantAxisScrolling) {
|
|
SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 3);
|
|
|
|
int panY;
|
|
int panX;
|
|
|
|
SetupBasicTest();
|
|
|
|
apzc = ApzcOf(root);
|
|
|
|
ParentLayerPoint lastOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncPanZoomController::eForEventHandling);
|
|
|
|
// In dominant axis mode, test pan gesture events with varying gesture
|
|
// angles and ensure that we only pan on one axis.
|
|
for (panX = 0, panY = 50; panY >= 0; panY -= 10, panX += 5) {
|
|
// Gesture that should be locked onto one axis
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_START, manager,
|
|
ScreenIntPoint(50, 50), ScreenIntPoint(panX, panY), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
|
|
ScreenPoint(static_cast<float>(panX), static_cast<float>(panY)),
|
|
mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
|
|
ScreenPoint(0, 0), mcc->Time());
|
|
apzc->AdvanceAnimationsUntilEnd();
|
|
|
|
ParentLayerPoint scrollOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncPanZoomController::eForEventHandling);
|
|
|
|
if (panX > panY) {
|
|
// If we're closer to the X axis ensure that we moved on the horizontal
|
|
// axis and there was no movement on the vertical axis.
|
|
EXPECT_GT(scrollOffset.x, lastOffset.x);
|
|
EXPECT_EQ(scrollOffset.y, lastOffset.y);
|
|
} else {
|
|
// If we're closer to the Y axis ensure that we moved on the vertical
|
|
// axis and there was no movement on the horizontal axis.
|
|
EXPECT_GT(scrollOffset.y, lastOffset.y);
|
|
EXPECT_EQ(scrollOffset.x, lastOffset.x);
|
|
}
|
|
|
|
lastOffset = scrollOffset;
|
|
}
|
|
}
|
|
|
|
TEST_F(APZCAxisLockTester, TestCanScrollWithAxisLock) {
|
|
SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
|
|
|
|
SetupBasicTest();
|
|
|
|
apzc = ApzcOf(root);
|
|
|
|
// The axis locks do not impact CanScroll()
|
|
apzc->SetAxisLocked(ScrollDirection::eHorizontal, true);
|
|
EXPECT_EQ(apzc->CanScroll(ParentLayerPoint(10, 0)), true);
|
|
|
|
apzc->SetAxisLocked(ScrollDirection::eHorizontal, false);
|
|
apzc->SetAxisLocked(ScrollDirection::eVertical, true);
|
|
EXPECT_EQ(apzc->CanScroll(ParentLayerPoint(0, 10)), true);
|
|
}
|
|
|
|
TEST_F(APZCAxisLockTester, TestScrollHandoffAxisLockConflict) {
|
|
SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
|
|
|
|
// Create two scrollable frames. One parent frame with one child.
|
|
const char* treeShape = "x(x)";
|
|
LayerIntRect layerVisibleRect[] = {
|
|
LayerIntRect(0, 0, 100, 100),
|
|
LayerIntRect(0, 0, 100, 100),
|
|
};
|
|
CreateScrollData(treeShape, layerVisibleRect);
|
|
SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
|
|
CSSRect(0, 0, 500, 500));
|
|
SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID + 1,
|
|
CSSRect(0, 0, 500, 500));
|
|
SetScrollHandoff(layers[1], root);
|
|
|
|
registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
|
|
|
|
UpdateHitTestingTree();
|
|
|
|
RefPtr<TestAsyncPanZoomController> rootApzc = ApzcOf(root);
|
|
apzc = ApzcOf(layers[1]);
|
|
|
|
// Create a gesture on the y-axis that should lock the x axis.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
|
|
PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
|
|
ScreenIntPoint(0, 2), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
|
|
ScreenPoint(0, 15), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
|
|
PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
|
|
ScreenPoint(0, 0), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimationsUntilEnd();
|
|
|
|
// We are locked onto the y-axis.
|
|
apzc->AssertAxisLocked(ScrollDirection::eVertical);
|
|
|
|
// There should be movement in the child.
|
|
ParentLayerPoint childCurrentOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
EXPECT_GT(childCurrentOffset.y, 0);
|
|
EXPECT_EQ(childCurrentOffset.x, 0);
|
|
|
|
// There should be no movement in the parent.
|
|
ParentLayerPoint parentCurrentOffset = rootApzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
EXPECT_EQ(parentCurrentOffset.y, 0);
|
|
EXPECT_EQ(parentCurrentOffset.x, 0);
|
|
|
|
// Create a gesture on the x-axis, that should be directed
|
|
// at the child, even if the x-axis is locked.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
|
|
PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
|
|
ScreenIntPoint(2, 0), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
|
|
PanGesture(PanGestureInput::PANGESTURE_PAN, apzc, ScreenIntPoint(50, 50),
|
|
ScreenPoint(15, 0), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimations(mcc->GetSampleTime());
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1);
|
|
PanGesture(PanGestureInput::PANGESTURE_END, manager, ScreenIntPoint(50, 50),
|
|
ScreenPoint(0, 0), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimationsUntilEnd();
|
|
|
|
// We broke the y-axis lock and are now locked onto the x-axis.
|
|
apzc->AssertAxisLocked(ScrollDirection::eHorizontal);
|
|
|
|
// There should be some movement in the child on the x-axis.
|
|
ParentLayerPoint childFinalOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
EXPECT_GT(childFinalOffset.x, 0);
|
|
|
|
// There should still be no movement in the parent.
|
|
ParentLayerPoint parentFinalOffset = rootApzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
EXPECT_EQ(parentFinalOffset.y, 0);
|
|
EXPECT_EQ(parentFinalOffset.x, 0);
|
|
}
|
|
|
|
// The delta from the initial pan gesture should be reflected in the
|
|
// current offset for all axis locking modes.
|
|
TEST_P(APZCAxisLockCompatTester, TestPanGestureStart) {
|
|
const char* treeShape = "x";
|
|
LayerIntRect layerVisibleRect[] = {
|
|
LayerIntRect(0, 0, 100, 100),
|
|
};
|
|
CreateScrollData(treeShape, layerVisibleRect);
|
|
SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
|
|
CSSRect(0, 0, 500, 500));
|
|
|
|
registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
|
|
|
|
UpdateHitTestingTree();
|
|
|
|
apzc = ApzcOf(root);
|
|
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
PanGesture(PanGestureInput::PANGESTURE_START, manager, ScreenIntPoint(50, 50),
|
|
ScreenIntPoint(0, 10), mcc->Time());
|
|
mcc->AdvanceByMillis(5);
|
|
apzc->AdvanceAnimationsUntilEnd();
|
|
ParentLayerPoint currentOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
|
|
EXPECT_EQ(currentOffset.x, 0);
|
|
EXPECT_EQ(currentOffset.y, 10);
|
|
}
|
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
|
TEST_F(APZCAxisLockTester, TouchScrollWithStickyAxisLocking) {
|
|
SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_threshold", 10);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_angle", 0.392699);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", 0.523599);
|
|
|
|
SetupBasicTest();
|
|
|
|
apzc = ApzcOf(root);
|
|
|
|
// Scroll somewhere into the middle of the scroll range, so that we have
|
|
// lots of space to scroll in both directions.
|
|
apzc->GetFrameMetrics().SetVisualScrollOffset(CSSPoint(250, 250));
|
|
|
|
UpdateHitTestingTree();
|
|
|
|
// Trigger a touch scroll that will cause us to lock onto the
|
|
// y-axis.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
Unused << TouchDown(apzc, ScreenIntPoint(50, 50), mcc->Time());
|
|
mcc->AdvanceByMillis(50);
|
|
|
|
Unused << TouchMove(apzc, ScreenIntPoint(50, 60), mcc->Time());
|
|
mcc->AdvanceByMillis(400);
|
|
|
|
Unused << TouchMove(apzc, ScreenIntPoint(50, 70), mcc->Time());
|
|
mcc->AdvanceByMillis(400);
|
|
|
|
apzc->AssertStateIsPanningLockedY();
|
|
|
|
ParentLayerPoint currentOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
ParentLayerPoint lastOffset = currentOffset;
|
|
|
|
// A touch scroll in the reverse direction with slight movement
|
|
// on the x-axis should not cause us to break the y-axis lock.
|
|
Unused << TouchMove(apzc, ScreenIntPoint(55, 60), mcc->Time());
|
|
mcc->AdvanceByMillis(200);
|
|
|
|
// We should have scrolled only on the y-axis.
|
|
currentOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
EXPECT_GT(currentOffset.y, lastOffset.y);
|
|
EXPECT_EQ(currentOffset.x, lastOffset.x);
|
|
lastOffset = currentOffset;
|
|
apzc->AssertStateIsPanningLockedY();
|
|
|
|
Unused << TouchMove(apzc, ScreenIntPoint(60, 50), mcc->Time());
|
|
mcc->AdvanceByMillis(200);
|
|
|
|
// We should continue to scroll only on the y-axis.
|
|
currentOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
EXPECT_GT(currentOffset.y, lastOffset.y);
|
|
EXPECT_EQ(currentOffset.x, lastOffset.x);
|
|
apzc->AssertStateIsPanningLockedY();
|
|
lastOffset = currentOffset;
|
|
|
|
Unused << TouchMove(apzc, ScreenIntPoint(60, 40), mcc->Time());
|
|
mcc->AdvanceByMillis(200);
|
|
|
|
currentOffset = apzc->GetCurrentAsyncScrollOffset(
|
|
AsyncTransformConsumer::eForEventHandling);
|
|
EXPECT_GT(currentOffset.y, lastOffset.y);
|
|
EXPECT_EQ(currentOffset.x, lastOffset.x);
|
|
apzc->AssertStateIsPanningLockedY();
|
|
lastOffset = currentOffset;
|
|
|
|
Unused << TouchUp(apzc, ScreenIntPoint(65, 40), mcc->Time());
|
|
}
|
|
#endif
|
|
|
|
// TODO(bug 1915260): Make this test pass.
|
|
#ifdef MOZ_WIDGET_ANDROID
|
|
TEST_F(APZCAxisLockTester, TouchScrollWithStickyAxisLockingBug1915260) {
|
|
SCOPED_GFX_PREF_INT("apz.axis_lock.mode", 2);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_threshold", 10);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.breakout_angle", 0.392699);
|
|
SCOPED_GFX_PREF_FLOAT("apz.axis_lock.lock_angle", 0.523599);
|
|
|
|
SetupBasicTest();
|
|
|
|
apzc = ApzcOf(root);
|
|
|
|
// Scroll somewhere into the middle of the scroll range, so that we have
|
|
// lots of space to scroll in both directions.
|
|
apzc->GetFrameMetrics().SetVisualScrollOffset(CSSPoint(250, 250));
|
|
|
|
// Trigger a touch scroll that will cause us to lock onto the
|
|
// y-axis.
|
|
QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID);
|
|
Unused << TouchDown(apzc, ScreenIntPoint(50, 50), mcc->Time());
|
|
mcc->AdvanceByMillis(10);
|
|
|
|
Unused << TouchMove(apzc, ScreenIntPoint(50, 60), mcc->Time());
|
|
mcc->AdvanceByMillis(200);
|
|
|
|
Unused << TouchMove(apzc, ScreenIntPoint(50, 70), mcc->Time());
|
|
mcc->AdvanceByMillis(200);
|
|
|
|
// We should be locked on the y-axis at this point.
|
|
// apzc->AssertStateIsPanningLockedY();
|
|
|
|
// Assuming the last event in the historical touch scroll buffer
|
|
// we use to determine touch scroll direction is (50,60), this
|
|
// touch-move event will exceed the breakout threshold and will
|
|
// be considered to be a horizontal scroll, thus breaking the
|
|
// lock onto the y-axis.
|
|
Unused << TouchMove(apzc, ScreenIntPoint(60, 60), mcc->Time());
|
|
mcc->AdvanceByMillis(100);
|
|
// TODO(bug 1915260): We should still be be locked on the y-axis at this
|
|
// point.
|
|
// apzc->AssertStateIsPanningLockedY();
|
|
|
|
Unused << TouchUp(apzc, ScreenIntPoint(65, 45), mcc->Time());
|
|
}
|
|
#endif
|
|
|
|
// All APZCAxisLockCompatTester tests should be run for each apz.axis_lock.mode.
|
|
// If another mode is added, the value should be added to this list.
|
|
INSTANTIATE_TEST_SUITE_P(APZCAxisLockCompat, APZCAxisLockCompatTester,
|
|
testing::Values(0, 1, 2, 3, 4),
|
|
APZCAxisLockCompatTester::PrintFromParam);
|