2013-06-24 23:24:42 +04:00
|
|
|
/* vim:set ts=2 sw=2 sts=2 et: */
|
|
|
|
/* Any copyright is dedicated to the Public Domain.
|
|
|
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
#include "gmock/gmock.h"
|
|
|
|
|
2013-08-15 16:03:31 +04:00
|
|
|
#include "mozilla/Attributes.h"
|
2013-06-24 23:24:42 +04:00
|
|
|
#include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform
|
|
|
|
#include "mozilla/layers/AsyncPanZoomController.h"
|
|
|
|
#include "mozilla/layers/GeckoContentController.h"
|
2013-07-30 22:03:41 +04:00
|
|
|
#include "mozilla/layers/CompositorParent.h"
|
|
|
|
#include "mozilla/layers/APZCTreeManager.h"
|
2013-12-12 04:39:06 +04:00
|
|
|
#include "base/task.h"
|
2013-06-24 23:24:42 +04:00
|
|
|
#include "Layers.h"
|
2013-07-02 20:27:17 +04:00
|
|
|
#include "TestLayers.h"
|
2014-02-28 21:45:27 +04:00
|
|
|
#include "gfxPrefs.h"
|
2013-06-24 23:24:42 +04:00
|
|
|
|
|
|
|
using namespace mozilla;
|
|
|
|
using namespace mozilla::gfx;
|
|
|
|
using namespace mozilla::layers;
|
|
|
|
using ::testing::_;
|
2014-01-15 19:03:16 +04:00
|
|
|
using ::testing::NiceMock;
|
2013-12-07 21:45:19 +04:00
|
|
|
using ::testing::AtLeast;
|
2014-01-15 19:03:16 +04:00
|
|
|
using ::testing::AtMost;
|
2014-02-13 20:24:53 +04:00
|
|
|
using ::testing::MockFunction;
|
|
|
|
using ::testing::InSequence;
|
2013-06-24 23:24:42 +04:00
|
|
|
|
2013-12-12 04:39:06 +04:00
|
|
|
class Task;
|
|
|
|
|
2014-02-28 21:45:27 +04:00
|
|
|
class APZCTreeManagerTester : public ::testing::Test {
|
|
|
|
protected:
|
|
|
|
virtual void SetUp() {
|
2014-03-04 21:26:33 +04:00
|
|
|
gfxPrefs::GetSingleton();
|
2014-05-02 19:12:47 +04:00
|
|
|
AsyncPanZoomController::SetThreadAssertionsEnabled(false);
|
2014-02-28 21:45:27 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-07-15 03:07:53 +04:00
|
|
|
template<class T>
|
|
|
|
class ScopedGfxPref {
|
|
|
|
public:
|
|
|
|
ScopedGfxPref(T (*aGetPrefFunc)(void), void (*aSetPrefFunc)(T), T aVal)
|
|
|
|
: mSetPrefFunc(aSetPrefFunc)
|
|
|
|
{
|
|
|
|
mOldVal = aGetPrefFunc();
|
|
|
|
aSetPrefFunc(aVal);
|
2014-07-11 16:25:13 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:53 +04:00
|
|
|
~ScopedGfxPref() {
|
|
|
|
mSetPrefFunc(mOldVal);
|
2014-07-11 16:25:13 +04:00
|
|
|
}
|
2014-07-15 03:07:53 +04:00
|
|
|
|
|
|
|
private:
|
|
|
|
void (*mSetPrefFunc)(T);
|
|
|
|
T mOldVal;
|
2014-07-11 16:25:13 +04:00
|
|
|
};
|
|
|
|
|
2014-07-15 03:07:53 +04:00
|
|
|
#define SCOPED_GFX_PREF(prefBase, prefType, prefValue) \
|
|
|
|
ScopedGfxPref<prefType> pref_##prefBase( \
|
|
|
|
&(gfxPrefs::prefBase), \
|
|
|
|
&(gfxPrefs::Set##prefBase), \
|
|
|
|
prefValue)
|
|
|
|
|
2013-06-24 23:24:42 +04:00
|
|
|
class MockContentController : public GeckoContentController {
|
|
|
|
public:
|
|
|
|
MOCK_METHOD1(RequestContentRepaint, void(const FrameMetrics&));
|
2014-02-06 02:43:20 +04:00
|
|
|
MOCK_METHOD2(AcknowledgeScrollUpdate, void(const FrameMetrics::ViewID&, const uint32_t& aScrollGeneration));
|
2014-03-12 23:27:45 +04:00
|
|
|
MOCK_METHOD3(HandleDoubleTap, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&));
|
|
|
|
MOCK_METHOD3(HandleSingleTap, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&));
|
|
|
|
MOCK_METHOD3(HandleLongTap, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&));
|
|
|
|
MOCK_METHOD3(HandleLongTapUp, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&));
|
2013-11-09 04:07:00 +04:00
|
|
|
MOCK_METHOD3(SendAsyncScrollDOMEvent, void(bool aIsRoot, const CSSRect &aContentRect, const CSSSize &aScrollableSize));
|
2013-06-24 23:24:42 +04:00
|
|
|
MOCK_METHOD2(PostDelayedTask, void(Task* aTask, int aDelayMs));
|
|
|
|
};
|
|
|
|
|
2013-12-12 04:39:06 +04:00
|
|
|
class MockContentControllerDelayed : public MockContentController {
|
|
|
|
public:
|
2014-02-11 19:42:42 +04:00
|
|
|
MockContentControllerDelayed()
|
|
|
|
{
|
|
|
|
}
|
2013-12-12 04:39:06 +04:00
|
|
|
|
|
|
|
void PostDelayedTask(Task* aTask, int aDelayMs) {
|
2014-03-27 16:04:39 +04:00
|
|
|
mTaskQueue.AppendElement(aTask);
|
2013-12-12 04:39:06 +04:00
|
|
|
}
|
|
|
|
|
2014-02-11 19:42:42 +04:00
|
|
|
void CheckHasDelayedTask() {
|
2014-03-27 16:04:39 +04:00
|
|
|
EXPECT_TRUE(mTaskQueue.Length() > 0);
|
2014-02-11 19:42:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClearDelayedTask() {
|
2014-03-27 16:04:39 +04:00
|
|
|
mTaskQueue.RemoveElementAt(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DestroyOldestTask() {
|
|
|
|
delete mTaskQueue[0];
|
|
|
|
mTaskQueue.RemoveElementAt(0);
|
2014-02-11 19:42:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Note that deleting mCurrentTask is important in order to
|
|
|
|
// release the reference to the callee object. Without this
|
|
|
|
// that object might be leaked. This is also why we don't
|
2014-03-27 16:04:39 +04:00
|
|
|
// expose mTaskQueue to any users of MockContentControllerDelayed.
|
2014-02-11 19:42:42 +04:00
|
|
|
void RunDelayedTask() {
|
2014-03-27 16:04:39 +04:00
|
|
|
mTaskQueue[0]->Run();
|
|
|
|
delete mTaskQueue[0];
|
|
|
|
mTaskQueue.RemoveElementAt(0);
|
2013-12-12 04:39:06 +04:00
|
|
|
}
|
|
|
|
|
2014-06-27 02:37:44 +04:00
|
|
|
// Run all the tasks in the queue, returning the number of tasks
|
|
|
|
// run. Note that if a task queues another task while running, that
|
|
|
|
// new task will not be run. Therefore, there may be still be tasks
|
|
|
|
// in the queue after this function is called. Only when the return
|
|
|
|
// value is 0 is the queue guaranteed to be empty.
|
|
|
|
int RunThroughDelayedTasks() {
|
|
|
|
int numTasks = mTaskQueue.Length();
|
|
|
|
for (int i = 0; i < numTasks; i++) {
|
|
|
|
RunDelayedTask();
|
|
|
|
}
|
|
|
|
return numTasks;
|
|
|
|
}
|
|
|
|
|
2013-12-12 04:39:06 +04:00
|
|
|
private:
|
2014-03-27 16:04:39 +04:00
|
|
|
nsTArray<Task*> mTaskQueue;
|
2013-12-12 04:39:06 +04:00
|
|
|
};
|
|
|
|
|
2013-07-30 22:03:40 +04:00
|
|
|
class TestAsyncPanZoomController : public AsyncPanZoomController {
|
|
|
|
public:
|
2013-11-30 01:40:21 +04:00
|
|
|
TestAsyncPanZoomController(uint64_t aLayersId, MockContentController* aMcc,
|
2013-12-11 21:19:33 +04:00
|
|
|
APZCTreeManager* aTreeManager = nullptr,
|
|
|
|
GestureBehavior aBehavior = DEFAULT_GESTURES)
|
|
|
|
: AsyncPanZoomController(aLayersId, aTreeManager, aMcc, aBehavior)
|
2013-07-30 22:03:40 +04:00
|
|
|
{}
|
|
|
|
|
|
|
|
void SetFrameMetrics(const FrameMetrics& metrics) {
|
2013-07-31 16:53:16 +04:00
|
|
|
ReentrantMonitorAutoEnter lock(mMonitor);
|
2013-07-30 22:03:40 +04:00
|
|
|
mFrameMetrics = metrics;
|
|
|
|
}
|
2013-10-10 20:21:50 +04:00
|
|
|
|
2014-07-16 16:33:50 +04:00
|
|
|
FrameMetrics& GetFrameMetrics() {
|
|
|
|
ReentrantMonitorAutoEnter lock(mMonitor);
|
|
|
|
return mFrameMetrics;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FrameMetrics& GetFrameMetrics() const {
|
2013-10-10 20:21:50 +04:00
|
|
|
ReentrantMonitorAutoEnter lock(mMonitor);
|
|
|
|
return mFrameMetrics;
|
|
|
|
}
|
2014-05-30 10:00:31 +04:00
|
|
|
|
|
|
|
void AssertStateIsReset() {
|
|
|
|
ReentrantMonitorAutoEnter lock(mMonitor);
|
|
|
|
EXPECT_EQ(NOTHING, mState);
|
|
|
|
}
|
2013-07-30 22:03:40 +04:00
|
|
|
};
|
|
|
|
|
2013-07-30 22:03:41 +04:00
|
|
|
class TestAPZCTreeManager : public APZCTreeManager {
|
2013-11-30 01:40:21 +04:00
|
|
|
public:
|
2014-05-23 01:17:39 +04:00
|
|
|
// Expose these so test code can call it directly.
|
2013-11-30 01:40:21 +04:00
|
|
|
void BuildOverscrollHandoffChain(AsyncPanZoomController* aApzc) {
|
|
|
|
APZCTreeManager::BuildOverscrollHandoffChain(aApzc);
|
|
|
|
}
|
2014-05-23 01:17:39 +04:00
|
|
|
void ClearOverscrollHandoffChain() {
|
|
|
|
APZCTreeManager::ClearOverscrollHandoffChain();
|
|
|
|
}
|
2013-07-30 22:03:41 +04:00
|
|
|
};
|
|
|
|
|
2014-07-15 03:07:53 +04:00
|
|
|
static FrameMetrics
|
|
|
|
TestFrameMetrics()
|
|
|
|
{
|
2013-06-24 23:24:42 +04:00
|
|
|
FrameMetrics fm;
|
|
|
|
|
|
|
|
fm.mDisplayPort = CSSRect(0, 0, 10, 10);
|
2014-07-04 16:12:41 +04:00
|
|
|
fm.mCompositionBounds = ParentLayerRect(0, 0, 10, 10);
|
2013-06-24 23:24:42 +04:00
|
|
|
fm.mCriticalDisplayPort = CSSRect(0, 0, 10, 10);
|
|
|
|
fm.mScrollableRect = CSSRect(0, 0, 100, 100);
|
|
|
|
fm.mViewport = CSSRect(0, 0, 10, 10);
|
|
|
|
|
|
|
|
return fm;
|
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
class APZCBasicTester : public ::testing::Test {
|
2014-07-15 03:07:54 +04:00
|
|
|
public:
|
|
|
|
APZCBasicTester(AsyncPanZoomController::GestureBehavior aGestureBehavior = AsyncPanZoomController::DEFAULT_GESTURES)
|
|
|
|
: mGestureBehavior(aGestureBehavior)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual void SetUp()
|
|
|
|
{
|
2014-07-15 03:07:54 +04:00
|
|
|
gfxPrefs::GetSingleton();
|
|
|
|
AsyncPanZoomController::SetThreadAssertionsEnabled(false);
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
testStartTime = TimeStamp::Now();
|
|
|
|
AsyncPanZoomController::SetFrameTime(testStartTime);
|
|
|
|
|
|
|
|
mcc = new NiceMock<MockContentControllerDelayed>();
|
|
|
|
tm = new TestAPZCTreeManager();
|
|
|
|
apzc = new TestAsyncPanZoomController(0, mcc, tm, mGestureBehavior);
|
|
|
|
apzc->SetFrameMetrics(TestFrameMetrics());
|
2014-07-17 21:41:53 +04:00
|
|
|
|
|
|
|
// Since most tests pass inputs directly to the APZC instead of going through
|
|
|
|
// the tree manager, we need to build the overscroll handoff chain explicitly
|
|
|
|
// for panning and animation-cancelling to work correctly.
|
|
|
|
tm->BuildOverscrollHandoffChain(apzc);
|
2014-07-15 03:07:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void TearDown()
|
|
|
|
{
|
2014-07-17 21:41:53 +04:00
|
|
|
tm->ClearOverscrollHandoffChain();
|
2014-07-15 03:07:54 +04:00
|
|
|
apzc->Destroy();
|
|
|
|
}
|
|
|
|
|
2014-07-16 16:33:50 +04:00
|
|
|
void SetMayHaveTouchListeners()
|
2014-07-15 03:07:54 +04:00
|
|
|
{
|
2014-07-16 16:33:50 +04:00
|
|
|
apzc->GetFrameMetrics().mMayHaveTouchListeners = true;
|
2014-07-15 03:07:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void MakeApzcZoomable()
|
|
|
|
{
|
|
|
|
apzc->UpdateZoomConstraints(ZoomConstraints(true, true, CSSToScreenScale(0.25f), CSSToScreenScale(4.0f)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MakeApzcUnzoomable()
|
|
|
|
{
|
|
|
|
apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0f), CSSToScreenScale(1.0f)));
|
|
|
|
}
|
|
|
|
|
|
|
|
AsyncPanZoomController::GestureBehavior mGestureBehavior;
|
|
|
|
TimeStamp testStartTime;
|
|
|
|
nsRefPtr<MockContentControllerDelayed> mcc;
|
|
|
|
nsRefPtr<TestAPZCTreeManager> tm;
|
|
|
|
nsRefPtr<TestAsyncPanZoomController> apzc;
|
|
|
|
};
|
|
|
|
|
|
|
|
class APZCGestureDetectorTester : public APZCBasicTester {
|
|
|
|
public:
|
|
|
|
APZCGestureDetectorTester()
|
|
|
|
: APZCBasicTester(AsyncPanZoomController::USE_GESTURE_DETECTOR)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-07-15 03:07:53 +04:00
|
|
|
static nsEventStatus
|
|
|
|
ApzcDown(AsyncPanZoomController* apzc, int aX, int aY, int& aTime)
|
|
|
|
{
|
|
|
|
MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, aTime, TimeStamp(), 0);
|
|
|
|
mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0));
|
|
|
|
return apzc->ReceiveInputEvent(mti);
|
|
|
|
}
|
|
|
|
|
|
|
|
static nsEventStatus
|
|
|
|
ApzcUp(AsyncPanZoomController* apzc, int aX, int aY, int& aTime)
|
|
|
|
{
|
|
|
|
MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, aTime, TimeStamp(), 0);
|
|
|
|
mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0));
|
|
|
|
return apzc->ReceiveInputEvent(mti);
|
|
|
|
}
|
|
|
|
|
2014-07-17 21:41:53 +04:00
|
|
|
static void
|
|
|
|
ApzcTap(AsyncPanZoomController* aApzc, int aX, int aY, int& aTime, int aTapLength,
|
|
|
|
nsEventStatus (*aOutEventStatuses)[2] = nullptr)
|
2014-07-15 03:07:53 +04:00
|
|
|
{
|
2014-07-17 21:41:53 +04:00
|
|
|
nsEventStatus status = ApzcDown(aApzc, aX, aY, aTime);
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[0] = status;
|
2014-07-15 03:07:53 +04:00
|
|
|
}
|
|
|
|
aTime += aTapLength;
|
2014-07-17 21:41:53 +04:00
|
|
|
status = ApzcUp(aApzc, aX, aY, aTime);
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[1] = status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ApzcTapAndCheckStatus(AsyncPanZoomController* aApzc, int aX, int aY, int& aTime, int aTapLength)
|
|
|
|
{
|
|
|
|
nsEventStatus statuses[2];
|
|
|
|
ApzcTap(aApzc, aX, aY, aTime, aTapLength, &statuses);
|
|
|
|
EXPECT_EQ(nsEventStatus_eConsumeNoDefault, statuses[0]);
|
|
|
|
EXPECT_EQ(nsEventStatus_eIgnore, statuses[1]);
|
2014-07-15 03:07:53 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-07-15 03:07:53 +04:00
|
|
|
ApzcPan(AsyncPanZoomController* aApzc,
|
2014-07-15 03:07:53 +04:00
|
|
|
int& aTime,
|
|
|
|
int aTouchStartY,
|
|
|
|
int aTouchEndY,
|
2014-07-15 03:07:53 +04:00
|
|
|
bool aKeepFingerDown = false,
|
2014-07-15 03:07:53 +04:00
|
|
|
nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr,
|
2014-07-15 03:07:53 +04:00
|
|
|
nsEventStatus (*aOutEventStatuses)[4] = nullptr)
|
2014-07-15 03:07:53 +04:00
|
|
|
{
|
2013-06-24 23:24:42 +04:00
|
|
|
const int TIME_BETWEEN_TOUCH_EVENT = 100;
|
|
|
|
const int OVERCOME_TOUCH_TOLERANCE = 100;
|
|
|
|
|
2014-07-15 03:07:53 +04:00
|
|
|
// Make sure the move is large enough to not be handled as a tap
|
|
|
|
nsEventStatus status = ApzcDown(aApzc, 10, aTouchStartY + OVERCOME_TOUCH_TOLERANCE, aTime);
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[0] = status;
|
2014-02-13 20:24:53 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:53 +04:00
|
|
|
aTime += TIME_BETWEEN_TOUCH_EVENT;
|
2013-06-24 23:24:42 +04:00
|
|
|
|
2014-04-14 22:59:20 +04:00
|
|
|
// Allowed touch behaviours must be set after sending touch-start.
|
2014-07-15 03:07:53 +04:00
|
|
|
if (gfxPrefs::TouchActionEnabled() && aAllowedTouchBehaviors) {
|
2014-07-15 03:07:53 +04:00
|
|
|
aApzc->SetAllowedTouchBehavior(*aAllowedTouchBehaviors);
|
2014-04-14 22:59:20 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:53 +04:00
|
|
|
MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, aTime, TimeStamp(), 0);
|
|
|
|
mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(10, aTouchStartY), ScreenSize(0, 0), 0, 0));
|
|
|
|
status = aApzc->ReceiveInputEvent(mti);
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[1] = status;
|
2014-01-15 19:03:16 +04:00
|
|
|
}
|
|
|
|
|
2013-06-24 23:24:42 +04:00
|
|
|
aTime += TIME_BETWEEN_TOUCH_EVENT;
|
|
|
|
|
2014-07-15 03:07:53 +04:00
|
|
|
mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, aTime, TimeStamp(), 0);
|
2013-06-24 23:24:42 +04:00
|
|
|
mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(10, aTouchEndY), ScreenSize(0, 0), 0, 0));
|
2014-07-15 03:07:53 +04:00
|
|
|
status = aApzc->ReceiveInputEvent(mti);
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[2] = status;
|
|
|
|
}
|
|
|
|
|
|
|
|
aTime += TIME_BETWEEN_TOUCH_EVENT;
|
2013-06-24 23:24:42 +04:00
|
|
|
|
2014-07-14 20:54:41 +04:00
|
|
|
if (!aKeepFingerDown) {
|
2014-07-15 03:07:53 +04:00
|
|
|
status = ApzcUp(aApzc, 10, aTouchEndY, aTime);
|
|
|
|
} else {
|
2014-07-15 03:07:54 +04:00
|
|
|
status = (nsEventStatus)-1;
|
2014-07-15 03:07:53 +04:00
|
|
|
}
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[3] = status;
|
2014-07-14 20:54:41 +04:00
|
|
|
}
|
2014-07-15 03:07:53 +04:00
|
|
|
|
2014-07-15 03:07:53 +04:00
|
|
|
aTime += TIME_BETWEEN_TOUCH_EVENT;
|
2013-06-24 23:24:42 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:53 +04:00
|
|
|
/*
|
|
|
|
* Dispatches mock touch events to the apzc and checks whether apzc properly
|
|
|
|
* consumed them and triggered scrolling behavior.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ApzcPanAndCheckStatus(AsyncPanZoomController* aApzc,
|
|
|
|
int& aTime,
|
|
|
|
int aTouchStartY,
|
|
|
|
int aTouchEndY,
|
|
|
|
bool expectIgnoredPan,
|
|
|
|
bool hasTouchListeners,
|
|
|
|
nsTArray<uint32_t>* aAllowedTouchBehaviors)
|
|
|
|
{
|
|
|
|
nsEventStatus statuses[4]; // down, move, move, up
|
2014-07-17 21:41:53 +04:00
|
|
|
ApzcPan(aApzc, aTime, aTouchStartY, aTouchEndY, false, aAllowedTouchBehaviors, &statuses);
|
2014-07-15 03:07:53 +04:00
|
|
|
|
|
|
|
nsEventStatus touchStartStatus;
|
2014-07-16 16:33:50 +04:00
|
|
|
if (hasTouchListeners || gfxPrefs::TouchActionEnabled()) {
|
2014-07-15 03:07:53 +04:00
|
|
|
// APZC shouldn't consume the start event now, instead queueing it up
|
2014-07-16 16:33:50 +04:00
|
|
|
// waiting for content's response and/or allowed behavior.
|
|
|
|
touchStartStatus = nsEventStatus_eConsumeDoDefault;
|
2014-07-15 03:07:53 +04:00
|
|
|
} else {
|
|
|
|
// APZC should go into the touching state and therefore consume the event.
|
|
|
|
touchStartStatus = nsEventStatus_eConsumeNoDefault;
|
|
|
|
}
|
|
|
|
EXPECT_EQ(touchStartStatus, statuses[0]);
|
|
|
|
|
|
|
|
nsEventStatus touchMoveStatus;
|
2014-07-16 16:33:50 +04:00
|
|
|
if (hasTouchListeners) {
|
|
|
|
// APZC will queue up this event while waiting for content's response.
|
|
|
|
touchMoveStatus = nsEventStatus_eConsumeDoDefault;
|
|
|
|
} else if (expectIgnoredPan) {
|
2014-07-15 03:07:53 +04:00
|
|
|
// APZC should ignore panning, be in TOUCHING state and therefore return eIgnore.
|
|
|
|
// The same applies to all consequent touch move events.
|
|
|
|
touchMoveStatus = nsEventStatus_eIgnore;
|
|
|
|
} else {
|
|
|
|
// APZC should go into the panning state and therefore consume the event.
|
|
|
|
touchMoveStatus = nsEventStatus_eConsumeNoDefault;
|
|
|
|
}
|
|
|
|
EXPECT_EQ(touchMoveStatus, statuses[1]);
|
|
|
|
EXPECT_EQ(touchMoveStatus, statuses[2]);
|
|
|
|
}
|
|
|
|
|
2014-07-17 21:41:54 +04:00
|
|
|
static void
|
|
|
|
ApzcPanNoFling(AsyncPanZoomController* aApzc,
|
|
|
|
int& aTime,
|
|
|
|
int aTouchStartY,
|
|
|
|
int aTouchEndY)
|
|
|
|
{
|
|
|
|
ApzcPan(aApzc, aTime, aTouchStartY, aTouchEndY);
|
|
|
|
aApzc->CancelAnimation();
|
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
static void
|
|
|
|
ApzcPinchWithPinchInput(AsyncPanZoomController* aApzc,
|
|
|
|
int aFocusX, int aFocusY, float aScale,
|
|
|
|
nsEventStatus (*aOutEventStatuses)[3] = nullptr)
|
|
|
|
{
|
|
|
|
nsEventStatus actualStatus = aApzc->HandleGestureEvent(
|
|
|
|
PinchGestureInput(PinchGestureInput::PINCHGESTURE_START,
|
|
|
|
0, TimeStamp(), ScreenPoint(aFocusX, aFocusY),
|
|
|
|
10.0, 10.0, 0));
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[0] = actualStatus;
|
2014-05-05 19:23:00 +04:00
|
|
|
}
|
2014-07-15 03:07:54 +04:00
|
|
|
actualStatus = aApzc->HandleGestureEvent(
|
|
|
|
PinchGestureInput(PinchGestureInput::PINCHGESTURE_SCALE,
|
|
|
|
0, TimeStamp(), ScreenPoint(aFocusX, aFocusY),
|
|
|
|
10.0 * aScale, 10.0, 0));
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[1] = actualStatus;
|
|
|
|
}
|
|
|
|
actualStatus = aApzc->HandleGestureEvent(
|
|
|
|
PinchGestureInput(PinchGestureInput::PINCHGESTURE_END,
|
|
|
|
0, TimeStamp(), ScreenPoint(aFocusX, aFocusY),
|
|
|
|
// note: negative values here tell APZC
|
|
|
|
// not to turn the pinch into a pan
|
|
|
|
-1.0, -1.0, 0));
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[2] = actualStatus;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ApzcPinchWithPinchInputAndCheckStatus(AsyncPanZoomController* aApzc,
|
|
|
|
int aFocusX, int aFocusY, float aScale,
|
|
|
|
bool aShouldTriggerPinch)
|
|
|
|
{
|
|
|
|
nsEventStatus statuses[3]; // scalebegin, scale, scaleend
|
|
|
|
ApzcPinchWithPinchInput(aApzc, aFocusX, aFocusY, aScale, &statuses);
|
2014-05-05 19:23:00 +04:00
|
|
|
|
|
|
|
nsEventStatus expectedStatus = aShouldTriggerPinch
|
2014-07-15 03:07:54 +04:00
|
|
|
? nsEventStatus_eConsumeNoDefault
|
|
|
|
: nsEventStatus_eIgnore;
|
|
|
|
EXPECT_EQ(expectedStatus, statuses[0]);
|
|
|
|
EXPECT_EQ(expectedStatus, statuses[1]);
|
2014-05-05 19:23:00 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
static void
|
|
|
|
ApzcPinchWithTouchInput(AsyncPanZoomController* aApzc,
|
|
|
|
int aFocusX, int aFocusY, float aScale,
|
|
|
|
int& inputId,
|
|
|
|
nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr,
|
|
|
|
nsEventStatus (*aOutEventStatuses)[4] = nullptr)
|
|
|
|
{
|
2014-05-05 19:23:00 +04:00
|
|
|
// Having pinch coordinates in float type may cause problems with high-precision scale values
|
|
|
|
// since SingleTouchData accepts integer value. But for trivial tests it should be ok.
|
|
|
|
float pinchLength = 100.0;
|
|
|
|
float pinchLengthScaled = pinchLength * aScale;
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
MultiTouchInput mtiStart = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0);
|
2014-05-05 19:23:00 +04:00
|
|
|
mtiStart.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX, aFocusY), ScreenSize(0, 0), 0, 0));
|
|
|
|
mtiStart.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX, aFocusY), ScreenSize(0, 0), 0, 0));
|
2014-07-15 03:07:54 +04:00
|
|
|
nsEventStatus status = aApzc->ReceiveInputEvent(mtiStart);
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[0] = status;
|
|
|
|
}
|
2014-05-05 19:23:00 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
if (gfxPrefs::TouchActionEnabled() && aAllowedTouchBehaviors) {
|
2014-05-05 19:23:00 +04:00
|
|
|
aApzc->SetAllowedTouchBehavior(*aAllowedTouchBehaviors);
|
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
MultiTouchInput mtiMove1 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0);
|
2014-05-05 19:23:00 +04:00
|
|
|
mtiMove1.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLength, aFocusY), ScreenSize(0, 0), 0, 0));
|
|
|
|
mtiMove1.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLength, aFocusY), ScreenSize(0, 0), 0, 0));
|
2014-07-15 03:07:54 +04:00
|
|
|
status = aApzc->ReceiveInputEvent(mtiMove1);
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[1] = status;
|
|
|
|
}
|
2014-05-05 19:23:00 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
MultiTouchInput mtiMove2 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0);
|
2014-05-05 19:23:00 +04:00
|
|
|
mtiMove2.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0));
|
|
|
|
mtiMove2.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0));
|
2014-07-15 03:07:54 +04:00
|
|
|
status = aApzc->ReceiveInputEvent(mtiMove2);
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[2] = status;
|
|
|
|
}
|
2014-05-05 19:23:00 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
MultiTouchInput mtiEnd = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, 0, TimeStamp(), 0);
|
2014-05-05 19:23:00 +04:00
|
|
|
mtiEnd.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0));
|
|
|
|
mtiEnd.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0));
|
2014-07-15 03:07:54 +04:00
|
|
|
status = aApzc->ReceiveInputEvent(mtiEnd);
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[3] = status;
|
|
|
|
}
|
|
|
|
|
2014-05-05 19:23:00 +04:00
|
|
|
inputId += 2;
|
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
static void
|
|
|
|
ApzcPinchWithTouchInputAndCheckStatus(AsyncPanZoomController* aApzc,
|
|
|
|
int aFocusX, int aFocusY, float aScale,
|
|
|
|
int& inputId, bool aShouldTriggerPinch,
|
|
|
|
nsTArray<uint32_t>* aAllowedTouchBehaviors)
|
|
|
|
{
|
|
|
|
nsEventStatus statuses[4]; // down, move, move, up
|
|
|
|
ApzcPinchWithTouchInput(aApzc, aFocusX, aFocusY, aScale, inputId, aAllowedTouchBehaviors, &statuses);
|
|
|
|
|
|
|
|
nsEventStatus expectedStatus = aShouldTriggerPinch
|
|
|
|
? nsEventStatus_eConsumeNoDefault
|
|
|
|
: nsEventStatus_eIgnore;
|
|
|
|
EXPECT_EQ(statuses[1], expectedStatus);
|
|
|
|
EXPECT_EQ(statuses[2], expectedStatus);
|
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
class APZCPinchTester : public APZCBasicTester {
|
|
|
|
public:
|
|
|
|
APZCPinchTester(AsyncPanZoomController::GestureBehavior aGestureBehavior = AsyncPanZoomController::DEFAULT_GESTURES)
|
|
|
|
: APZCBasicTester(aGestureBehavior)
|
|
|
|
{
|
2014-05-05 19:23:00 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
protected:
|
2014-07-16 16:33:50 +04:00
|
|
|
FrameMetrics GetPinchableFrameMetrics()
|
2014-07-15 03:07:54 +04:00
|
|
|
{
|
|
|
|
FrameMetrics fm;
|
|
|
|
fm.mViewport = CSSRect(0, 0, 980, 480);
|
|
|
|
fm.mCompositionBounds = ParentLayerRect(200, 200, 100, 200);
|
|
|
|
fm.mScrollableRect = CSSRect(0, 0, 980, 1000);
|
|
|
|
fm.SetScrollOffset(CSSPoint(300, 300));
|
|
|
|
fm.SetZoom(CSSToScreenScale(2.0));
|
|
|
|
// the visible area of the document in CSS pixels is x=300 y=300 w=50 h=100
|
2014-07-16 16:33:50 +04:00
|
|
|
return fm;
|
|
|
|
}
|
2014-07-15 03:07:54 +04:00
|
|
|
|
2014-07-16 16:33:50 +04:00
|
|
|
void DoPinchTest(bool aShouldTriggerPinch,
|
|
|
|
nsTArray<uint32_t> *aAllowedTouchBehaviors = nullptr)
|
|
|
|
{
|
|
|
|
apzc->SetFrameMetrics(GetPinchableFrameMetrics());
|
2014-07-15 03:07:54 +04:00
|
|
|
MakeApzcZoomable();
|
|
|
|
|
|
|
|
if (aShouldTriggerPinch) {
|
|
|
|
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
|
|
|
|
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
|
|
|
} else {
|
|
|
|
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtMost(2));
|
|
|
|
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
|
|
|
|
}
|
2014-05-05 19:23:00 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
int touchInputId = 0;
|
|
|
|
if (mGestureBehavior == AsyncPanZoomController::USE_GESTURE_DETECTOR) {
|
|
|
|
ApzcPinchWithTouchInputAndCheckStatus(apzc, 250, 300, 1.25, touchInputId, aShouldTriggerPinch, aAllowedTouchBehaviors);
|
|
|
|
} else {
|
|
|
|
ApzcPinchWithPinchInputAndCheckStatus(apzc, 250, 300, 1.25, aShouldTriggerPinch);
|
|
|
|
}
|
2014-05-05 19:23:00 +04:00
|
|
|
|
2014-07-16 16:33:50 +04:00
|
|
|
FrameMetrics fm = apzc->GetFrameMetrics();
|
2014-07-15 03:07:54 +04:00
|
|
|
|
|
|
|
if (aShouldTriggerPinch) {
|
|
|
|
// the visible area of the document in CSS pixels is now x=305 y=310 w=40 h=80
|
|
|
|
EXPECT_EQ(2.5f, fm.GetZoom().scale);
|
|
|
|
EXPECT_EQ(305, fm.GetScrollOffset().x);
|
|
|
|
EXPECT_EQ(310, fm.GetScrollOffset().y);
|
|
|
|
} else {
|
|
|
|
// The frame metrics should stay the same since touch-action:none makes
|
|
|
|
// apzc ignore pinch gestures.
|
|
|
|
EXPECT_EQ(2.0f, fm.GetZoom().scale);
|
|
|
|
EXPECT_EQ(300, fm.GetScrollOffset().x);
|
|
|
|
EXPECT_EQ(300, fm.GetScrollOffset().y);
|
|
|
|
}
|
2014-05-05 19:23:00 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
// part 2 of the test, move to the top-right corner of the page and pinch and
|
|
|
|
// make sure we stay in the correct spot
|
|
|
|
fm.SetZoom(CSSToScreenScale(2.0));
|
|
|
|
fm.SetScrollOffset(CSSPoint(930, 5));
|
|
|
|
apzc->SetFrameMetrics(fm);
|
|
|
|
// the visible area of the document in CSS pixels is x=930 y=5 w=50 h=100
|
|
|
|
|
|
|
|
if (mGestureBehavior == AsyncPanZoomController::USE_GESTURE_DETECTOR) {
|
|
|
|
ApzcPinchWithTouchInputAndCheckStatus(apzc, 250, 300, 0.5, touchInputId, aShouldTriggerPinch, aAllowedTouchBehaviors);
|
|
|
|
} else {
|
|
|
|
ApzcPinchWithPinchInputAndCheckStatus(apzc, 250, 300, 0.5, aShouldTriggerPinch);
|
|
|
|
}
|
2014-05-05 19:23:00 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
fm = apzc->GetFrameMetrics();
|
|
|
|
|
|
|
|
if (aShouldTriggerPinch) {
|
|
|
|
// the visible area of the document in CSS pixels is now x=880 y=0 w=100 h=200
|
|
|
|
EXPECT_EQ(1.0f, fm.GetZoom().scale);
|
|
|
|
EXPECT_EQ(880, fm.GetScrollOffset().x);
|
|
|
|
EXPECT_EQ(0, fm.GetScrollOffset().y);
|
|
|
|
} else {
|
|
|
|
EXPECT_EQ(2.0f, fm.GetZoom().scale);
|
|
|
|
EXPECT_EQ(930, fm.GetScrollOffset().x);
|
|
|
|
EXPECT_EQ(5, fm.GetScrollOffset().y);
|
|
|
|
}
|
2014-05-05 19:23:00 +04:00
|
|
|
}
|
2014-07-15 03:07:54 +04:00
|
|
|
};
|
2014-05-05 19:23:00 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
class APZCPinchGestureDetectorTester : public APZCPinchTester {
|
|
|
|
public:
|
|
|
|
APZCPinchGestureDetectorTester()
|
|
|
|
: APZCPinchTester(AsyncPanZoomController::USE_GESTURE_DETECTOR)
|
|
|
|
{
|
2014-05-05 19:23:00 +04:00
|
|
|
}
|
2014-07-15 03:07:54 +04:00
|
|
|
};
|
2013-11-10 18:48:12 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCPinchTester, Pinch_DefaultGestures_NoTouchAction) {
|
|
|
|
DoPinchTest(true);
|
2014-05-05 19:23:00 +04:00
|
|
|
}
|
2014-01-22 22:37:30 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_NoTouchAction) {
|
|
|
|
DoPinchTest(true);
|
2014-05-05 19:23:00 +04:00
|
|
|
}
|
2014-01-15 19:03:16 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_TouchActionNone) {
|
2014-07-15 03:07:53 +04:00
|
|
|
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
2014-05-05 19:23:00 +04:00
|
|
|
nsTArray<uint32_t> behaviors;
|
|
|
|
behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::NONE);
|
|
|
|
behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::NONE);
|
2014-07-15 03:07:54 +04:00
|
|
|
DoPinchTest(false, &behaviors);
|
2014-05-05 19:23:00 +04:00
|
|
|
}
|
2014-01-15 19:03:16 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_TouchActionZoom) {
|
2014-07-15 03:07:53 +04:00
|
|
|
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
2014-05-05 19:23:00 +04:00
|
|
|
nsTArray<uint32_t> behaviors;
|
|
|
|
behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM);
|
|
|
|
behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM);
|
2014-07-15 03:07:54 +04:00
|
|
|
DoPinchTest(true, &behaviors);
|
2014-05-05 19:23:00 +04:00
|
|
|
}
|
2014-01-15 19:03:16 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_TouchActionNotAllowZoom) {
|
2014-07-15 03:07:53 +04:00
|
|
|
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
2014-05-05 19:23:00 +04:00
|
|
|
nsTArray<uint32_t> behaviors;
|
|
|
|
behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
|
|
|
|
behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM);
|
2014-07-15 03:07:54 +04:00
|
|
|
DoPinchTest(false, &behaviors);
|
2014-01-15 19:03:16 +04:00
|
|
|
}
|
|
|
|
|
2014-07-16 16:33:50 +04:00
|
|
|
TEST_F(APZCPinchGestureDetectorTester, Pinch_PreventDefault) {
|
|
|
|
FrameMetrics originalMetrics = GetPinchableFrameMetrics();
|
|
|
|
apzc->SetFrameMetrics(originalMetrics);
|
|
|
|
|
|
|
|
SetMayHaveTouchListeners();
|
|
|
|
MakeApzcZoomable();
|
|
|
|
|
|
|
|
int touchInputId = 0;
|
|
|
|
ApzcPinchWithTouchInput(apzc, 250, 300, 1.25, touchInputId);
|
|
|
|
|
|
|
|
// Send the prevent-default notification for the touch block
|
|
|
|
apzc->ContentReceivedTouch(true);
|
|
|
|
|
|
|
|
// Run all pending tasks (this should include at least the
|
|
|
|
// prevent-default timer).
|
|
|
|
EXPECT_LE(1, mcc->RunThroughDelayedTasks());
|
|
|
|
|
|
|
|
// verify the metrics didn't change (i.e. the pinch was ignored)
|
|
|
|
FrameMetrics fm = apzc->GetFrameMetrics();
|
|
|
|
EXPECT_EQ(originalMetrics.GetZoom().scale, fm.GetZoom().scale);
|
|
|
|
EXPECT_EQ(originalMetrics.GetScrollOffset().x, fm.GetScrollOffset().x);
|
|
|
|
EXPECT_EQ(originalMetrics.GetScrollOffset().y, fm.GetScrollOffset().y);
|
|
|
|
|
|
|
|
apzc->AssertStateIsReset();
|
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCBasicTester, Overzoom) {
|
|
|
|
// the visible area of the document in CSS pixels is x=10 y=0 w=100 h=100
|
2013-10-11 01:00:29 +04:00
|
|
|
FrameMetrics fm;
|
|
|
|
fm.mViewport = CSSRect(0, 0, 100, 100);
|
2014-07-04 16:12:41 +04:00
|
|
|
fm.mCompositionBounds = ParentLayerRect(0, 0, 100, 100);
|
2013-10-11 01:00:29 +04:00
|
|
|
fm.mScrollableRect = CSSRect(0, 0, 125, 150);
|
2014-03-13 10:34:34 +04:00
|
|
|
fm.SetScrollOffset(CSSPoint(10, 0));
|
2014-03-12 20:46:57 +04:00
|
|
|
fm.SetZoom(CSSToScreenScale(1.0));
|
2013-10-11 01:00:29 +04:00
|
|
|
apzc->SetFrameMetrics(fm);
|
2014-07-15 03:07:54 +04:00
|
|
|
|
|
|
|
MakeApzcZoomable();
|
2013-10-11 01:00:29 +04:00
|
|
|
|
2013-12-07 21:45:19 +04:00
|
|
|
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
|
2013-10-11 01:00:29 +04:00
|
|
|
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
ApzcPinchWithPinchInputAndCheckStatus(apzc, 50, 50, 0.5, true);
|
2013-10-11 01:00:29 +04:00
|
|
|
|
|
|
|
fm = apzc->GetFrameMetrics();
|
2014-04-16 01:56:05 +04:00
|
|
|
EXPECT_EQ(0.8f, fm.GetZoom().scale);
|
2013-11-10 18:47:27 +04:00
|
|
|
// bug 936721 - PGO builds introduce rounding error so
|
|
|
|
// use a fuzzy match instead
|
2014-03-13 10:34:34 +04:00
|
|
|
EXPECT_LT(abs(fm.GetScrollOffset().x), 1e-5);
|
|
|
|
EXPECT_LT(abs(fm.GetScrollOffset().y), 1e-5);
|
2013-10-11 01:00:29 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCBasicTester, SimpleTransform) {
|
2013-06-24 23:24:42 +04:00
|
|
|
ScreenPoint pointOut;
|
|
|
|
ViewTransform viewTransformOut;
|
2013-07-30 22:03:41 +04:00
|
|
|
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
2013-06-24 23:24:42 +04:00
|
|
|
|
2014-04-16 01:56:05 +04:00
|
|
|
EXPECT_EQ(ScreenPoint(), pointOut);
|
|
|
|
EXPECT_EQ(ViewTransform(), viewTransformOut);
|
2013-06-24 23:24:42 +04:00
|
|
|
}
|
|
|
|
|
2013-07-08 23:53:51 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCBasicTester, ComplexTransform) {
|
2013-07-08 23:53:51 +04:00
|
|
|
// This test assumes there is a page that gets rendered to
|
|
|
|
// two layers. In CSS pixels, the first layer is 50x50 and
|
|
|
|
// the second layer is 25x50. The widget scale factor is 3.0
|
|
|
|
// and the presShell resolution is 2.0. Therefore, these layers
|
|
|
|
// end up being 300x300 and 150x300 in layer pixels.
|
|
|
|
//
|
|
|
|
// The second (child) layer has an additional CSS transform that
|
|
|
|
// stretches it by 2.0 on the x-axis. Therefore, after applying
|
|
|
|
// CSS transforms, the two layers are the same size in screen
|
|
|
|
// pixels.
|
|
|
|
//
|
|
|
|
// The screen itself is 24x24 in screen pixels (therefore 4x4 in
|
|
|
|
// CSS pixels). The displayport is 1 extra CSS pixel on all
|
|
|
|
// sides.
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
nsRefPtr<TestAsyncPanZoomController> childApzc = new TestAsyncPanZoomController(0, mcc, tm);
|
2013-07-08 23:53:51 +04:00
|
|
|
|
|
|
|
const char* layerTreeSyntax = "c(c)";
|
|
|
|
// LayerID 0 1
|
|
|
|
nsIntRegion layerVisibleRegion[] = {
|
|
|
|
nsIntRegion(nsIntRect(0, 0, 300, 300)),
|
|
|
|
nsIntRegion(nsIntRect(0, 0, 150, 300)),
|
|
|
|
};
|
|
|
|
gfx3DMatrix transforms[] = {
|
|
|
|
gfx3DMatrix(),
|
|
|
|
gfx3DMatrix(),
|
|
|
|
};
|
|
|
|
transforms[0].ScalePost(0.5f, 0.5f, 1.0f); // this results from the 2.0 resolution on the root layer
|
|
|
|
transforms[1].ScalePost(2.0f, 1.0f, 1.0f); // this is the 2.0 x-axis CSS transform on the child layer
|
|
|
|
|
|
|
|
nsTArray<nsRefPtr<Layer> > layers;
|
|
|
|
nsRefPtr<LayerManager> lm;
|
|
|
|
nsRefPtr<Layer> root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, lm, layers);
|
|
|
|
|
|
|
|
FrameMetrics metrics;
|
2014-07-04 16:12:41 +04:00
|
|
|
metrics.mCompositionBounds = ParentLayerRect(0, 0, 24, 24);
|
2013-07-08 23:53:51 +04:00
|
|
|
metrics.mDisplayPort = CSSRect(-1, -1, 6, 6);
|
|
|
|
metrics.mViewport = CSSRect(0, 0, 4, 4);
|
2014-03-13 10:34:34 +04:00
|
|
|
metrics.SetScrollOffset(CSSPoint(10, 10));
|
2013-07-08 23:53:51 +04:00
|
|
|
metrics.mScrollableRect = CSSRect(0, 0, 50, 50);
|
2013-09-06 02:26:59 +04:00
|
|
|
metrics.mCumulativeResolution = LayoutDeviceToLayerScale(2);
|
|
|
|
metrics.mResolution = ParentLayerToLayerScale(2);
|
2014-03-12 20:46:57 +04:00
|
|
|
metrics.SetZoom(CSSToScreenScale(6));
|
2013-07-08 23:53:51 +04:00
|
|
|
metrics.mDevPixelsPerCSSPixel = CSSToLayoutDeviceScale(3);
|
2014-03-22 01:48:08 +04:00
|
|
|
metrics.SetScrollId(FrameMetrics::START_SCROLL_ID);
|
2013-07-08 23:53:51 +04:00
|
|
|
|
|
|
|
FrameMetrics childMetrics = metrics;
|
2014-03-22 01:48:08 +04:00
|
|
|
childMetrics.SetScrollId(FrameMetrics::START_SCROLL_ID + 1);
|
2013-07-08 23:53:51 +04:00
|
|
|
|
|
|
|
layers[0]->AsContainerLayer()->SetFrameMetrics(metrics);
|
|
|
|
layers[1]->AsContainerLayer()->SetFrameMetrics(childMetrics);
|
|
|
|
|
|
|
|
ScreenPoint pointOut;
|
|
|
|
ViewTransform viewTransformOut;
|
|
|
|
|
|
|
|
// Both the parent and child layer should behave exactly the same here, because
|
|
|
|
// the CSS transform on the child layer does not affect the SampleContentTransformForFrame code
|
|
|
|
|
|
|
|
// initial transform
|
2013-07-30 22:03:40 +04:00
|
|
|
apzc->SetFrameMetrics(metrics);
|
2013-07-08 23:53:51 +04:00
|
|
|
apzc->NotifyLayersUpdated(metrics, true);
|
2013-07-30 22:03:41 +04:00
|
|
|
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
2013-09-06 02:26:59 +04:00
|
|
|
EXPECT_EQ(ViewTransform(LayerPoint(), ParentLayerToScreenScale(2)), viewTransformOut);
|
2013-07-08 23:53:51 +04:00
|
|
|
EXPECT_EQ(ScreenPoint(60, 60), pointOut);
|
|
|
|
|
2013-07-30 22:03:40 +04:00
|
|
|
childApzc->SetFrameMetrics(childMetrics);
|
|
|
|
childApzc->NotifyLayersUpdated(childMetrics, true);
|
2013-07-30 22:03:41 +04:00
|
|
|
childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
2013-09-06 02:26:59 +04:00
|
|
|
EXPECT_EQ(ViewTransform(LayerPoint(), ParentLayerToScreenScale(2)), viewTransformOut);
|
2013-07-08 23:53:51 +04:00
|
|
|
EXPECT_EQ(ScreenPoint(60, 60), pointOut);
|
|
|
|
|
|
|
|
// do an async scroll by 5 pixels and check the transform
|
2014-03-13 10:34:34 +04:00
|
|
|
metrics.ScrollBy(CSSPoint(5, 0));
|
2013-07-30 22:03:40 +04:00
|
|
|
apzc->SetFrameMetrics(metrics);
|
2013-07-30 22:03:41 +04:00
|
|
|
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
2013-09-06 02:26:59 +04:00
|
|
|
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), ParentLayerToScreenScale(2)), viewTransformOut);
|
2013-07-08 23:53:51 +04:00
|
|
|
EXPECT_EQ(ScreenPoint(90, 60), pointOut);
|
|
|
|
|
2014-03-13 10:34:34 +04:00
|
|
|
childMetrics.ScrollBy(CSSPoint(5, 0));
|
2013-07-30 22:03:40 +04:00
|
|
|
childApzc->SetFrameMetrics(childMetrics);
|
2013-07-30 22:03:41 +04:00
|
|
|
childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
2013-09-06 02:26:59 +04:00
|
|
|
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), ParentLayerToScreenScale(2)), viewTransformOut);
|
2013-07-08 23:53:51 +04:00
|
|
|
EXPECT_EQ(ScreenPoint(90, 60), pointOut);
|
|
|
|
|
|
|
|
// do an async zoom of 1.5x and check the transform
|
2014-03-12 20:46:57 +04:00
|
|
|
metrics.ZoomBy(1.5f);
|
2013-07-30 22:03:40 +04:00
|
|
|
apzc->SetFrameMetrics(metrics);
|
2013-07-30 22:03:41 +04:00
|
|
|
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
2013-09-06 02:26:59 +04:00
|
|
|
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), ParentLayerToScreenScale(3)), viewTransformOut);
|
2013-07-08 23:53:51 +04:00
|
|
|
EXPECT_EQ(ScreenPoint(135, 90), pointOut);
|
|
|
|
|
2014-03-12 20:46:57 +04:00
|
|
|
childMetrics.ZoomBy(1.5f);
|
2013-07-30 22:03:40 +04:00
|
|
|
childApzc->SetFrameMetrics(childMetrics);
|
2013-07-30 22:03:41 +04:00
|
|
|
childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
2013-09-06 02:26:59 +04:00
|
|
|
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), ParentLayerToScreenScale(3)), viewTransformOut);
|
2013-07-08 23:53:51 +04:00
|
|
|
EXPECT_EQ(ScreenPoint(135, 90), pointOut);
|
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
class APZCPanningTester : public APZCBasicTester {
|
|
|
|
protected:
|
|
|
|
void DoPanTest(bool aShouldTriggerScroll, uint32_t aBehavior)
|
|
|
|
{
|
|
|
|
if (aShouldTriggerScroll) {
|
|
|
|
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
|
|
|
|
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
|
|
|
} else {
|
|
|
|
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(0);
|
|
|
|
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
|
|
|
|
}
|
2014-07-15 03:07:54 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
int time = 0;
|
|
|
|
int touchStart = 50;
|
|
|
|
int touchEnd = 10;
|
|
|
|
ScreenPoint pointOut;
|
|
|
|
ViewTransform viewTransformOut;
|
|
|
|
|
|
|
|
nsTArray<uint32_t> allowedTouchBehaviors;
|
|
|
|
allowedTouchBehaviors.AppendElement(aBehavior);
|
|
|
|
|
|
|
|
// Pan down
|
2014-07-17 21:41:53 +04:00
|
|
|
ApzcPanAndCheckStatus(apzc, time, touchStart, touchEnd, !aShouldTriggerScroll, false, &allowedTouchBehaviors);
|
2014-07-15 03:07:54 +04:00
|
|
|
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
|
|
|
|
|
|
|
if (aShouldTriggerScroll) {
|
|
|
|
EXPECT_EQ(ScreenPoint(0, -(touchEnd-touchStart)), pointOut);
|
|
|
|
EXPECT_NE(ViewTransform(), viewTransformOut);
|
|
|
|
} else {
|
|
|
|
EXPECT_EQ(ScreenPoint(), pointOut);
|
|
|
|
EXPECT_EQ(ViewTransform(), viewTransformOut);
|
|
|
|
}
|
2014-07-15 03:07:54 +04:00
|
|
|
|
2014-07-17 21:41:54 +04:00
|
|
|
// Clear the fling from the previous pan, or stopping it will
|
|
|
|
// consume the next touchstart
|
|
|
|
apzc->CancelAnimation();
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
// Pan back
|
2014-07-17 21:41:53 +04:00
|
|
|
ApzcPanAndCheckStatus(apzc, time, touchEnd, touchStart, !aShouldTriggerScroll, false, &allowedTouchBehaviors);
|
2014-07-15 03:07:54 +04:00
|
|
|
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
2014-07-15 03:07:54 +04:00
|
|
|
|
|
|
|
EXPECT_EQ(ScreenPoint(), pointOut);
|
|
|
|
EXPECT_EQ(ViewTransform(), viewTransformOut);
|
|
|
|
}
|
2014-07-16 16:33:50 +04:00
|
|
|
|
|
|
|
void DoPanWithPreventDefaultTest()
|
|
|
|
{
|
|
|
|
SetMayHaveTouchListeners();
|
|
|
|
|
|
|
|
int time = 0;
|
|
|
|
int touchStart = 50;
|
|
|
|
int touchEnd = 10;
|
|
|
|
ScreenPoint pointOut;
|
|
|
|
ViewTransform viewTransformOut;
|
|
|
|
|
|
|
|
// Pan down
|
|
|
|
nsTArray<uint32_t> allowedTouchBehaviors;
|
|
|
|
allowedTouchBehaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
|
2014-07-17 21:41:53 +04:00
|
|
|
ApzcPanAndCheckStatus(apzc, time, touchStart, touchEnd, true, true, &allowedTouchBehaviors);
|
2014-07-16 16:33:50 +04:00
|
|
|
|
|
|
|
// Send the signal that content has handled and preventDefaulted the touch
|
|
|
|
// events. This flushes the event queue.
|
|
|
|
apzc->ContentReceivedTouch(true);
|
|
|
|
// Run all pending tasks (this should include at least the
|
|
|
|
// prevent-default timer).
|
|
|
|
EXPECT_LE(1, mcc->RunThroughDelayedTasks());
|
|
|
|
|
|
|
|
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
|
|
|
EXPECT_EQ(ScreenPoint(), pointOut);
|
|
|
|
EXPECT_EQ(ViewTransform(), viewTransformOut);
|
|
|
|
|
|
|
|
apzc->AssertStateIsReset();
|
|
|
|
}
|
2014-07-15 03:07:54 +04:00
|
|
|
};
|
2014-07-15 03:07:54 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCPanningTester, Pan) {
|
2014-07-11 16:25:13 +04:00
|
|
|
DoPanTest(true, mozilla::layers::AllowedTouchBehavior::NONE);
|
2014-01-15 19:03:16 +04:00
|
|
|
}
|
2013-06-24 23:24:42 +04:00
|
|
|
|
2014-01-15 19:03:16 +04:00
|
|
|
// In the each of the following 4 pan tests we are performing two pan gestures: vertical pan from top
|
|
|
|
// to bottom and back - from bottom to top.
|
|
|
|
// According to the pointer-events/touch-action spec AUTO and PAN_Y touch-action values allow vertical
|
|
|
|
// scrolling while NONE and PAN_X forbid it. The first parameter of DoPanTest method specifies this
|
|
|
|
// behavior.
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCPanningTester, PanWithTouchActionAuto) {
|
2014-07-15 03:07:53 +04:00
|
|
|
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
2014-07-11 16:25:13 +04:00
|
|
|
DoPanTest(true, mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN
|
|
|
|
| mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
|
2014-01-15 19:03:16 +04:00
|
|
|
}
|
2013-06-24 23:24:42 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCPanningTester, PanWithTouchActionNone) {
|
2014-07-15 03:07:53 +04:00
|
|
|
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
2014-07-11 16:25:13 +04:00
|
|
|
DoPanTest(false, 0);
|
2014-01-15 19:03:16 +04:00
|
|
|
}
|
2013-06-24 23:24:42 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCPanningTester, PanWithTouchActionPanX) {
|
2014-07-15 03:07:53 +04:00
|
|
|
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
2014-07-11 16:25:13 +04:00
|
|
|
DoPanTest(false, mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN);
|
2014-01-15 19:03:16 +04:00
|
|
|
}
|
2013-06-24 23:24:42 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCPanningTester, PanWithTouchActionPanY) {
|
2014-07-15 03:07:53 +04:00
|
|
|
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
2014-07-11 16:25:13 +04:00
|
|
|
DoPanTest(true, mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
|
2013-06-24 23:24:42 +04:00
|
|
|
}
|
|
|
|
|
2014-07-16 16:33:50 +04:00
|
|
|
TEST_F(APZCPanningTester, PanWithPreventDefaultAndTouchAction) {
|
2014-07-15 03:07:53 +04:00
|
|
|
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
2014-07-16 16:33:50 +04:00
|
|
|
DoPanWithPreventDefaultTest();
|
|
|
|
}
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-16 16:33:50 +04:00
|
|
|
TEST_F(APZCPanningTester, PanWithPreventDefault) {
|
|
|
|
SCOPED_GFX_PREF(TouchActionEnabled, bool, false);
|
|
|
|
DoPanWithPreventDefaultTest();
|
2014-02-13 20:24:53 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCBasicTester, Fling) {
|
2013-12-07 21:45:19 +04:00
|
|
|
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
|
2013-06-24 23:24:42 +04:00
|
|
|
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
|
|
|
|
|
|
|
int time = 0;
|
|
|
|
int touchStart = 50;
|
|
|
|
int touchEnd = 10;
|
|
|
|
ScreenPoint pointOut;
|
|
|
|
ViewTransform viewTransformOut;
|
|
|
|
|
|
|
|
// Fling down. Each step scroll further down
|
2014-07-17 21:41:53 +04:00
|
|
|
ApzcPan(apzc, time, touchStart, touchEnd);
|
2013-06-24 23:24:42 +04:00
|
|
|
ScreenPoint lastPoint;
|
|
|
|
for (int i = 1; i < 50; i+=1) {
|
2013-07-30 22:03:41 +04:00
|
|
|
apzc->SampleContentTransformForFrame(testStartTime+TimeDuration::FromMilliseconds(i), &viewTransformOut, pointOut);
|
2013-06-24 23:24:42 +04:00
|
|
|
EXPECT_GT(pointOut.y, lastPoint.y);
|
|
|
|
lastPoint = pointOut;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
class APZCFlingStopTester : public APZCGestureDetectorTester {
|
|
|
|
protected:
|
|
|
|
// Start a fling, and then tap while the fling is ongoing. When
|
|
|
|
// aSlow is false, the tap will happen while the fling is at a
|
|
|
|
// high velocity, and we check that the tap doesn't trigger sending a tap
|
|
|
|
// to content. If aSlow is true, the tap will happen while the fling
|
|
|
|
// is at a slow velocity, and we check that the tap does trigger sending
|
|
|
|
// a tap to content. See bug 1022956.
|
|
|
|
void DoFlingStopTest(bool aSlow) {
|
|
|
|
int time = 0;
|
|
|
|
int touchStart = 50;
|
|
|
|
int touchEnd = 10;
|
|
|
|
|
|
|
|
// Start the fling down.
|
2014-07-17 21:41:53 +04:00
|
|
|
ApzcPan(apzc, time, touchStart, touchEnd);
|
2014-07-15 03:07:54 +04:00
|
|
|
// The touchstart from the pan will leave some cancelled tasks in the queue, clear them out
|
2014-07-17 21:41:53 +04:00
|
|
|
while (mcc->RunThroughDelayedTasks());
|
2014-07-15 03:07:54 +04:00
|
|
|
|
|
|
|
// If we want to tap while the fling is fast, let the fling advance for 10ms only. If we want
|
|
|
|
// the fling to slow down more, advance to 2000ms. These numbers may need adjusting if our
|
|
|
|
// friction and threshold values change, but they should be deterministic at least.
|
|
|
|
int timeDelta = aSlow ? 2000 : 10;
|
|
|
|
int tapCallsExpected = aSlow ? 1 : 0;
|
|
|
|
|
|
|
|
// Advance the fling animation by timeDelta milliseconds.
|
|
|
|
ScreenPoint pointOut;
|
|
|
|
ViewTransform viewTransformOut;
|
|
|
|
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(timeDelta), &viewTransformOut, pointOut);
|
|
|
|
|
|
|
|
// Deliver a tap to abort the fling. Ensure that we get a HandleSingleTap
|
|
|
|
// call out of it if and only if the fling is slow.
|
|
|
|
EXPECT_CALL(*mcc, HandleSingleTap(_, 0, apzc->GetGuid())).Times(tapCallsExpected);
|
2014-07-17 21:41:53 +04:00
|
|
|
ApzcTap(apzc, 10, 10, time, 0);
|
|
|
|
while (mcc->RunThroughDelayedTasks());
|
2014-07-15 03:07:54 +04:00
|
|
|
|
|
|
|
// Verify that we didn't advance any further after the fling was aborted, in either case.
|
|
|
|
ScreenPoint finalPointOut;
|
|
|
|
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(timeDelta + 1000), &viewTransformOut, finalPointOut);
|
|
|
|
EXPECT_EQ(pointOut.x, finalPointOut.x);
|
|
|
|
EXPECT_EQ(pointOut.y, finalPointOut.y);
|
|
|
|
|
|
|
|
apzc->AssertStateIsReset();
|
|
|
|
}
|
2014-07-17 21:41:53 +04:00
|
|
|
|
|
|
|
void DoFlingStopWithSlowListener(bool aPreventDefault) {
|
|
|
|
SetMayHaveTouchListeners();
|
|
|
|
|
|
|
|
int time = 0;
|
|
|
|
int touchStart = 50;
|
|
|
|
int touchEnd = 10;
|
|
|
|
|
|
|
|
// Start the fling down.
|
|
|
|
ApzcPan(apzc, time, touchStart, touchEnd);
|
|
|
|
apzc->ContentReceivedTouch(false);
|
|
|
|
while (mcc->RunThroughDelayedTasks());
|
|
|
|
|
|
|
|
// Sample the fling a couple of times to ensure it's going.
|
|
|
|
ScreenPoint point, finalPoint;
|
|
|
|
ViewTransform viewTransform;
|
|
|
|
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(10), &viewTransform, point);
|
|
|
|
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(20), &viewTransform, finalPoint);
|
|
|
|
EXPECT_GT(finalPoint.y, point.y);
|
|
|
|
|
|
|
|
// Now we put our finger down to stop the fling
|
|
|
|
ApzcDown(apzc, 10, 10, time);
|
|
|
|
|
|
|
|
// Re-sample to make sure it hasn't moved
|
|
|
|
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(30), &viewTransform, point);
|
|
|
|
EXPECT_EQ(finalPoint.x, point.x);
|
|
|
|
EXPECT_EQ(finalPoint.y, point.y);
|
|
|
|
|
|
|
|
// respond to the touchdown that stopped the fling.
|
|
|
|
// even if we do a prevent-default on it, the animation should remain stopped.
|
|
|
|
apzc->ContentReceivedTouch(aPreventDefault);
|
|
|
|
while (mcc->RunThroughDelayedTasks());
|
|
|
|
|
|
|
|
// Verify the page hasn't moved
|
|
|
|
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(100), &viewTransform, point);
|
|
|
|
EXPECT_EQ(finalPoint.x, point.x);
|
|
|
|
EXPECT_EQ(finalPoint.y, point.y);
|
|
|
|
|
|
|
|
// clean up
|
|
|
|
ApzcUp(apzc, 10, 10, time);
|
|
|
|
while (mcc->RunThroughDelayedTasks());
|
|
|
|
|
|
|
|
apzc->AssertStateIsReset();
|
|
|
|
}
|
2014-07-15 03:07:54 +04:00
|
|
|
};
|
2014-06-27 02:37:44 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCFlingStopTester, FlingStop) {
|
2014-06-27 02:37:44 +04:00
|
|
|
DoFlingStopTest(false);
|
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCFlingStopTester, FlingStopTap) {
|
2014-06-27 02:37:44 +04:00
|
|
|
DoFlingStopTest(true);
|
|
|
|
}
|
|
|
|
|
2014-07-17 21:41:53 +04:00
|
|
|
TEST_F(APZCFlingStopTester, FlingStopSlowListener) {
|
|
|
|
DoFlingStopWithSlowListener(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(APZCFlingStopTester, FlingStopPreventDefault) {
|
|
|
|
DoFlingStopWithSlowListener(true);
|
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCBasicTester, OverScrollPanning) {
|
2014-07-15 03:07:53 +04:00
|
|
|
SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
|
2014-06-28 00:39:11 +04:00
|
|
|
|
2013-06-24 23:24:42 +04:00
|
|
|
// Pan sufficiently to hit overscroll behavior
|
|
|
|
int time = 0;
|
|
|
|
int touchStart = 500;
|
|
|
|
int touchEnd = 10;
|
2014-07-17 21:41:53 +04:00
|
|
|
ApzcPan(apzc, time, touchStart, touchEnd);
|
2014-06-28 00:39:11 +04:00
|
|
|
EXPECT_TRUE(apzc->IsOverscrolled());
|
|
|
|
|
|
|
|
// Note that in the calls to SampleContentTransformForFrame below, the time
|
|
|
|
// increment used is sufficiently large for the animation to have completed. However,
|
|
|
|
// any single call to SampleContentTransformForFrame will not finish an animation
|
|
|
|
// *and* also proceed through the following animation, if there is one.
|
|
|
|
// Therefore the minimum number of calls to go from an overscroll-inducing pan
|
|
|
|
// to a reset state is 3; these are documented further below.
|
|
|
|
|
2013-06-24 23:24:42 +04:00
|
|
|
ScreenPoint pointOut;
|
|
|
|
ViewTransform viewTransformOut;
|
|
|
|
|
2014-06-28 00:39:11 +04:00
|
|
|
// This sample will run to the end of the non-overscrolling fling animation
|
|
|
|
// and will schedule the overscrolling fling animation.
|
|
|
|
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(10000), &viewTransformOut, pointOut);
|
2014-04-16 01:56:05 +04:00
|
|
|
EXPECT_EQ(ScreenPoint(0, 90), pointOut);
|
2014-06-28 00:39:11 +04:00
|
|
|
EXPECT_TRUE(apzc->IsOverscrolled());
|
2014-06-04 20:02:53 +04:00
|
|
|
|
2014-06-28 00:39:11 +04:00
|
|
|
// This sample will run to the end of the overscrolling fling animation and
|
|
|
|
// will schedule the snapback animation.
|
|
|
|
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(20000), &viewTransformOut, pointOut);
|
|
|
|
EXPECT_EQ(ScreenPoint(0, 90), pointOut);
|
|
|
|
EXPECT_TRUE(apzc->IsOverscrolled());
|
|
|
|
|
|
|
|
// This sample will run to the end of the snapback animation and reset the state.
|
|
|
|
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(30000), &viewTransformOut, pointOut);
|
|
|
|
EXPECT_EQ(ScreenPoint(0, 90), pointOut);
|
|
|
|
EXPECT_FALSE(apzc->IsOverscrolled());
|
|
|
|
|
|
|
|
apzc->AssertStateIsReset();
|
2013-06-24 23:24:42 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCBasicTester, OverScrollAbort) {
|
2014-07-15 03:07:53 +04:00
|
|
|
SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
|
2014-06-28 00:39:27 +04:00
|
|
|
|
|
|
|
// Pan sufficiently to hit overscroll behavior
|
|
|
|
int time = 0;
|
|
|
|
int touchStart = 500;
|
|
|
|
int touchEnd = 10;
|
2014-07-17 21:41:53 +04:00
|
|
|
ApzcPan(apzc, time, touchStart, touchEnd);
|
2014-06-28 00:39:27 +04:00
|
|
|
EXPECT_TRUE(apzc->IsOverscrolled());
|
|
|
|
|
|
|
|
ScreenPoint pointOut;
|
|
|
|
ViewTransform viewTransformOut;
|
|
|
|
|
|
|
|
// This sample call will run to the end of the non-overscrolling fling animation
|
|
|
|
// and will schedule the overscrolling fling animation (see comment in OverScrollPanning
|
|
|
|
// above for more explanation).
|
|
|
|
apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(10000), &viewTransformOut, pointOut);
|
|
|
|
EXPECT_TRUE(apzc->IsOverscrolled());
|
|
|
|
|
|
|
|
// At this point, we have an active overscrolling fling animation.
|
|
|
|
// Check that cancelling the animation clears the overscroll.
|
|
|
|
apzc->CancelAnimation();
|
|
|
|
EXPECT_FALSE(apzc->IsOverscrolled());
|
|
|
|
apzc->AssertStateIsReset();
|
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCBasicTester, OverScrollPanningAbort) {
|
2014-07-15 03:07:53 +04:00
|
|
|
SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
|
2014-07-14 20:54:41 +04:00
|
|
|
|
|
|
|
// Pan sufficiently to hit overscroll behaviour. Keep the finger down so
|
|
|
|
// the pan does not end.
|
|
|
|
int time = 0;
|
|
|
|
int touchStart = 500;
|
|
|
|
int touchEnd = 10;
|
2014-07-17 21:41:53 +04:00
|
|
|
ApzcPan(apzc, time, touchStart, touchEnd,
|
2014-07-14 20:54:41 +04:00
|
|
|
true); // keep finger down
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCGestureDetectorTester, ShortPress) {
|
|
|
|
MakeApzcUnzoomable();
|
2013-12-11 21:19:33 +04:00
|
|
|
|
|
|
|
int time = 0;
|
2014-07-17 21:41:53 +04:00
|
|
|
ApzcTapAndCheckStatus(apzc, 10, 10, time, 100);
|
|
|
|
// There will be delayed tasks posted for the long-tap and MAX_TAP timeouts, but
|
|
|
|
// we want to clear those.
|
|
|
|
mcc->ClearDelayedTask();
|
|
|
|
mcc->ClearDelayedTask();
|
2013-12-11 21:19:33 +04:00
|
|
|
|
2014-02-11 19:42:42 +04:00
|
|
|
// This verifies that the single tap notification is sent after the
|
|
|
|
// touchdown is fully processed. The ordering here is important.
|
|
|
|
mcc->CheckHasDelayedTask();
|
|
|
|
|
2014-03-12 23:27:45 +04:00
|
|
|
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
|
2014-02-11 19:42:42 +04:00
|
|
|
mcc->RunDelayedTask();
|
|
|
|
|
2014-05-30 10:00:31 +04:00
|
|
|
apzc->AssertStateIsReset();
|
2013-12-11 21:19:33 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCGestureDetectorTester, MediumPress) {
|
|
|
|
MakeApzcUnzoomable();
|
2013-12-11 21:19:33 +04:00
|
|
|
|
|
|
|
int time = 0;
|
2014-07-17 21:41:53 +04:00
|
|
|
ApzcTapAndCheckStatus(apzc, 10, 10, time, 400);
|
|
|
|
// There will be delayed tasks posted for the long-tap and MAX_TAP timeouts, but
|
|
|
|
// we want to clear those.
|
|
|
|
mcc->ClearDelayedTask();
|
|
|
|
mcc->ClearDelayedTask();
|
2013-12-11 21:19:33 +04:00
|
|
|
|
2014-02-11 19:42:42 +04:00
|
|
|
// This verifies that the single tap notification is sent after the
|
|
|
|
// touchdown is fully processed. The ordering here is important.
|
|
|
|
mcc->CheckHasDelayedTask();
|
|
|
|
|
2014-03-12 23:27:45 +04:00
|
|
|
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
|
2014-02-11 19:42:42 +04:00
|
|
|
mcc->RunDelayedTask();
|
|
|
|
|
2014-05-30 10:00:31 +04:00
|
|
|
apzc->AssertStateIsReset();
|
2013-12-11 21:19:33 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
class APZCLongPressTester : public APZCGestureDetectorTester {
|
|
|
|
protected:
|
|
|
|
void DoLongPressTest(uint32_t aBehavior) {
|
|
|
|
MakeApzcUnzoomable();
|
2013-12-12 04:39:06 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
int time = 0;
|
2013-12-12 04:39:06 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
nsEventStatus status = ApzcDown(apzc, 10, 10, time);
|
2014-07-16 16:33:50 +04:00
|
|
|
if (gfxPrefs::TouchActionEnabled()) {
|
|
|
|
// If touch-action is enabled, then the event is queued until the
|
|
|
|
// allowed touch behavior is set.
|
|
|
|
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status);
|
|
|
|
} else {
|
|
|
|
// Otherwise, it is processed immediately.
|
|
|
|
EXPECT_EQ(nsEventStatus_eConsumeNoDefault, status);
|
|
|
|
}
|
2014-04-14 22:59:20 +04:00
|
|
|
|
2014-07-16 16:33:50 +04:00
|
|
|
if (gfxPrefs::TouchActionEnabled()) {
|
|
|
|
// SetAllowedTouchBehavior() must be called after sending touch-start.
|
|
|
|
nsTArray<uint32_t> allowedTouchBehaviors;
|
|
|
|
allowedTouchBehaviors.AppendElement(aBehavior);
|
|
|
|
apzc->SetAllowedTouchBehavior(allowedTouchBehaviors);
|
|
|
|
}
|
|
|
|
// Have content "respond" to the touchstart
|
|
|
|
apzc->ContentReceivedTouch(false);
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
MockFunction<void(std::string checkPointName)> check;
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
{
|
|
|
|
InSequence s;
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
EXPECT_CALL(check, Call("preHandleLongTap"));
|
|
|
|
EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
|
|
|
|
EXPECT_CALL(check, Call("postHandleLongTap"));
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
EXPECT_CALL(check, Call("preHandleLongTapUp"));
|
|
|
|
EXPECT_CALL(*mcc, HandleLongTapUp(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
|
|
|
|
EXPECT_CALL(check, Call("postHandleLongTapUp"));
|
|
|
|
}
|
2013-12-12 04:39:06 +04:00
|
|
|
|
2014-07-16 16:33:50 +04:00
|
|
|
// There is a longpress event scheduled on a timeout
|
2014-07-15 03:07:54 +04:00
|
|
|
mcc->CheckHasDelayedTask();
|
2014-03-27 16:04:39 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
// Manually invoke the longpress while the touch is currently down.
|
|
|
|
check.Call("preHandleLongTap");
|
|
|
|
mcc->RunDelayedTask();
|
|
|
|
check.Call("postHandleLongTap");
|
|
|
|
|
|
|
|
// Destroy pending MAX_TAP timeout task
|
|
|
|
mcc->DestroyOldestTask();
|
2014-07-16 16:33:50 +04:00
|
|
|
|
|
|
|
// Dispatching the longpress event starts a new touch block, which
|
|
|
|
// needs a new content response and also has a pending timeout task
|
|
|
|
// in the queue. Deal with those here. We do the content response first
|
|
|
|
// with preventDefault=false, and then we run the timeout task which
|
|
|
|
// "loses the race" and does nothing.
|
|
|
|
apzc->ContentReceivedTouch(false);
|
2014-07-15 03:07:54 +04:00
|
|
|
mcc->CheckHasDelayedTask();
|
2014-07-16 16:33:50 +04:00
|
|
|
mcc->RunDelayedTask();
|
2013-12-12 04:39:06 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
time += 1000;
|
2013-12-12 04:39:06 +04:00
|
|
|
|
2014-07-16 16:33:50 +04:00
|
|
|
// Finally, simulate lifting the finger. Since the long-press wasn't
|
|
|
|
// prevent-defaulted, we should get a long-tap-up event.
|
|
|
|
check.Call("preHandleLongTapUp");
|
2014-07-15 03:07:54 +04:00
|
|
|
status = ApzcUp(apzc, 10, 10, time);
|
|
|
|
EXPECT_EQ(nsEventStatus_eIgnore, status);
|
|
|
|
check.Call("postHandleLongTapUp");
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
apzc->AssertStateIsReset();
|
|
|
|
}
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
void DoLongPressPreventDefaultTest(uint32_t aBehavior) {
|
|
|
|
MakeApzcUnzoomable();
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(0);
|
|
|
|
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
int touchX = 10,
|
|
|
|
touchStartY = 10,
|
|
|
|
touchEndY = 50;
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
int time = 0;
|
|
|
|
nsEventStatus status = ApzcDown(apzc, touchX, touchStartY, time);
|
2014-07-16 16:33:50 +04:00
|
|
|
if (gfxPrefs::TouchActionEnabled()) {
|
|
|
|
// If touch-action is enabled, then the event is queued until the
|
|
|
|
// allowed touch behavior is set.
|
|
|
|
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status);
|
|
|
|
} else {
|
|
|
|
// Otherwise, it is processed immediately.
|
|
|
|
EXPECT_EQ(nsEventStatus_eConsumeNoDefault, status);
|
|
|
|
}
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-16 16:33:50 +04:00
|
|
|
if (gfxPrefs::TouchActionEnabled()) {
|
|
|
|
// SetAllowedTouchBehavior() must be called after sending touch-start.
|
|
|
|
nsTArray<uint32_t> allowedTouchBehaviors;
|
|
|
|
allowedTouchBehaviors.AppendElement(aBehavior);
|
|
|
|
apzc->SetAllowedTouchBehavior(allowedTouchBehaviors);
|
|
|
|
}
|
|
|
|
// Have content "respond" to the touchstart
|
|
|
|
apzc->ContentReceivedTouch(false);
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
MockFunction<void(std::string checkPointName)> check;
|
2014-04-21 19:30:15 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
{
|
|
|
|
InSequence s;
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
EXPECT_CALL(check, Call("preHandleLongTap"));
|
|
|
|
EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(touchX, touchStartY), 0, apzc->GetGuid())).Times(1);
|
|
|
|
EXPECT_CALL(check, Call("postHandleLongTap"));
|
|
|
|
}
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
mcc->CheckHasDelayedTask();
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
// Manually invoke the longpress while the touch is currently down.
|
|
|
|
check.Call("preHandleLongTap");
|
|
|
|
mcc->RunDelayedTask();
|
|
|
|
check.Call("postHandleLongTap");
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
// Destroy pending MAX_TAP timeout task
|
|
|
|
mcc->DestroyOldestTask();
|
2014-07-16 16:33:50 +04:00
|
|
|
|
|
|
|
// There should be a TimeoutContentResponse task in the queue still,
|
|
|
|
// waiting for the response from the longtap event dispatched above.
|
|
|
|
// Send the signal that content has handled the long-tap, and then run
|
|
|
|
// the timeout task (it will be a no-op because the content "wins" the
|
|
|
|
// race. This takes the place of the "contextmenu" event.
|
2014-07-15 03:07:54 +04:00
|
|
|
apzc->ContentReceivedTouch(true);
|
2014-07-16 16:33:50 +04:00
|
|
|
mcc->CheckHasDelayedTask();
|
|
|
|
mcc->RunDelayedTask();
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
time += 1000;
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, time, TimeStamp(), 0);
|
|
|
|
mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(touchX, touchEndY), ScreenSize(0, 0), 0, 0));
|
|
|
|
status = apzc->ReceiveInputEvent(mti);
|
|
|
|
EXPECT_EQ(nsEventStatus_eIgnore, status);
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
EXPECT_CALL(*mcc, HandleLongTapUp(CSSPoint(touchX, touchEndY), 0, apzc->GetGuid())).Times(0);
|
|
|
|
status = ApzcUp(apzc, touchX, touchEndY, time);
|
|
|
|
EXPECT_EQ(nsEventStatus_eIgnore, status);
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
ScreenPoint pointOut;
|
|
|
|
ViewTransform viewTransformOut;
|
|
|
|
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
EXPECT_EQ(ScreenPoint(), pointOut);
|
|
|
|
EXPECT_EQ(ViewTransform(), viewTransformOut);
|
2014-02-13 20:24:53 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
apzc->AssertStateIsReset();
|
|
|
|
}
|
|
|
|
};
|
2013-12-12 04:39:06 +04:00
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCLongPressTester, LongPress) {
|
2014-07-11 16:25:13 +04:00
|
|
|
DoLongPressTest(mozilla::layers::AllowedTouchBehavior::NONE);
|
2014-02-24 10:31:18 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCLongPressTester, LongPressWithTouchAction) {
|
2014-07-15 03:07:53 +04:00
|
|
|
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
2014-07-11 16:25:13 +04:00
|
|
|
DoLongPressTest(mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN
|
|
|
|
| mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN
|
|
|
|
| mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM);
|
2014-02-24 10:31:18 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCLongPressTester, LongPressPreventDefault) {
|
2014-07-11 16:25:13 +04:00
|
|
|
DoLongPressPreventDefaultTest(mozilla::layers::AllowedTouchBehavior::NONE);
|
2014-04-21 19:30:15 +04:00
|
|
|
}
|
|
|
|
|
2014-07-15 03:07:54 +04:00
|
|
|
TEST_F(APZCLongPressTester, LongPressPreventDefaultWithTouchAction) {
|
2014-07-15 03:07:53 +04:00
|
|
|
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
2014-07-11 16:25:13 +04:00
|
|
|
DoLongPressPreventDefaultTest(mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN
|
|
|
|
| mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN
|
|
|
|
| mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM);
|
2014-04-21 19:30:15 +04:00
|
|
|
}
|
2014-02-24 10:31:18 +04:00
|
|
|
|
2014-07-16 16:33:50 +04:00
|
|
|
static void
|
|
|
|
ApzcDoubleTap(AsyncPanZoomController* aApzc, int aX, int aY, int& aTime,
|
|
|
|
nsEventStatus (*aOutEventStatuses)[4] = nullptr)
|
|
|
|
{
|
|
|
|
nsEventStatus status = ApzcDown(aApzc, aX, aY, aTime);
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[0] = status;
|
|
|
|
}
|
|
|
|
aTime += 10;
|
|
|
|
status = ApzcUp(aApzc, aX, aY, aTime);
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[1] = status;
|
|
|
|
}
|
|
|
|
aTime += 10;
|
|
|
|
status = ApzcDown(aApzc, aX, aY, aTime);
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[2] = status;
|
|
|
|
}
|
|
|
|
aTime += 10;
|
|
|
|
status = ApzcUp(aApzc, aX, aY, aTime);
|
|
|
|
if (aOutEventStatuses) {
|
|
|
|
(*aOutEventStatuses)[3] = status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ApzcDoubleTapAndCheckStatus(AsyncPanZoomController* aApzc, int aX, int aY, int& aTime)
|
|
|
|
{
|
|
|
|
nsEventStatus statuses[4];
|
|
|
|
ApzcDoubleTap(aApzc, aX, aY, aTime, &statuses);
|
|
|
|
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[0]);
|
|
|
|
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[1]);
|
|
|
|
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[2]);
|
|
|
|
EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[3]);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(APZCGestureDetectorTester, DoubleTap) {
|
|
|
|
SetMayHaveTouchListeners();
|
|
|
|
MakeApzcZoomable();
|
|
|
|
|
|
|
|
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0);
|
|
|
|
EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
|
|
|
|
|
|
|
|
int time = 0;
|
|
|
|
ApzcDoubleTapAndCheckStatus(apzc, 10, 10, time);
|
|
|
|
|
|
|
|
// responses to the two touchstarts
|
|
|
|
apzc->ContentReceivedTouch(false);
|
|
|
|
apzc->ContentReceivedTouch(false);
|
|
|
|
|
|
|
|
while (mcc->RunThroughDelayedTasks());
|
|
|
|
|
|
|
|
apzc->AssertStateIsReset();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(APZCGestureDetectorTester, DoubleTapNotZoomable) {
|
|
|
|
SetMayHaveTouchListeners();
|
|
|
|
MakeApzcUnzoomable();
|
|
|
|
|
|
|
|
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(2);
|
|
|
|
EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0);
|
|
|
|
|
|
|
|
int time = 0;
|
|
|
|
ApzcDoubleTapAndCheckStatus(apzc, 10, 10, time);
|
|
|
|
|
|
|
|
// responses to the two touchstarts
|
|
|
|
apzc->ContentReceivedTouch(false);
|
|
|
|
apzc->ContentReceivedTouch(false);
|
|
|
|
|
|
|
|
while (mcc->RunThroughDelayedTasks());
|
|
|
|
|
|
|
|
apzc->AssertStateIsReset();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(APZCGestureDetectorTester, DoubleTapPreventDefaultFirstOnly) {
|
|
|
|
SetMayHaveTouchListeners();
|
|
|
|
MakeApzcZoomable();
|
|
|
|
|
|
|
|
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
|
|
|
|
EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0);
|
|
|
|
|
|
|
|
int time = 0;
|
|
|
|
ApzcDoubleTapAndCheckStatus(apzc, 10, 10, time);
|
|
|
|
|
|
|
|
// responses to the two touchstarts
|
|
|
|
apzc->ContentReceivedTouch(true);
|
|
|
|
apzc->ContentReceivedTouch(false);
|
|
|
|
|
|
|
|
while (mcc->RunThroughDelayedTasks());
|
|
|
|
|
|
|
|
apzc->AssertStateIsReset();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(APZCGestureDetectorTester, DoubleTapPreventDefaultBoth) {
|
|
|
|
SetMayHaveTouchListeners();
|
|
|
|
MakeApzcZoomable();
|
|
|
|
|
|
|
|
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0);
|
|
|
|
EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0);
|
|
|
|
|
|
|
|
int time = 0;
|
|
|
|
ApzcDoubleTapAndCheckStatus(apzc, 10, 10, time);
|
|
|
|
|
|
|
|
// responses to the two touchstarts
|
|
|
|
apzc->ContentReceivedTouch(true);
|
|
|
|
apzc->ContentReceivedTouch(true);
|
|
|
|
|
|
|
|
while (mcc->RunThroughDelayedTasks());
|
|
|
|
|
|
|
|
apzc->AssertStateIsReset();
|
|
|
|
}
|
|
|
|
|
2013-10-30 23:58:25 +04:00
|
|
|
// Layer tree for HitTesting1
|
2013-07-02 20:27:17 +04:00
|
|
|
static already_AddRefed<mozilla::layers::Layer>
|
2013-10-30 23:58:25 +04:00
|
|
|
CreateTestLayerTree1(nsRefPtr<LayerManager>& aLayerManager, nsTArray<nsRefPtr<Layer> >& aLayers) {
|
|
|
|
const char* layerTreeSyntax = "c(ttcc)";
|
|
|
|
// LayerID 0 1234
|
2013-07-02 20:27:17 +04:00
|
|
|
nsIntRegion layerVisibleRegion[] = {
|
|
|
|
nsIntRegion(nsIntRect(0,0,100,100)),
|
|
|
|
nsIntRegion(nsIntRect(0,0,100,100)),
|
|
|
|
nsIntRegion(nsIntRect(10,10,20,20)),
|
|
|
|
nsIntRegion(nsIntRect(10,10,20,20)),
|
|
|
|
nsIntRegion(nsIntRect(5,5,20,20)),
|
|
|
|
};
|
|
|
|
gfx3DMatrix transforms[] = {
|
|
|
|
gfx3DMatrix(),
|
|
|
|
gfx3DMatrix(),
|
|
|
|
gfx3DMatrix(),
|
|
|
|
gfx3DMatrix(),
|
|
|
|
gfx3DMatrix(),
|
2013-10-30 23:58:25 +04:00
|
|
|
};
|
|
|
|
return CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, aLayerManager, aLayers);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Layer Tree for HitTesting2
|
|
|
|
static already_AddRefed<mozilla::layers::Layer>
|
|
|
|
CreateTestLayerTree2(nsRefPtr<LayerManager>& aLayerManager, nsTArray<nsRefPtr<Layer> >& aLayers) {
|
|
|
|
const char* layerTreeSyntax = "c(cc(c))";
|
|
|
|
// LayerID 0 12 3
|
|
|
|
nsIntRegion layerVisibleRegion[] = {
|
|
|
|
nsIntRegion(nsIntRect(0,0,100,100)),
|
|
|
|
nsIntRegion(nsIntRect(10,10,40,40)),
|
|
|
|
nsIntRegion(nsIntRect(10,60,40,40)),
|
|
|
|
nsIntRegion(nsIntRect(10,60,40,40)),
|
|
|
|
};
|
|
|
|
gfx3DMatrix transforms[] = {
|
|
|
|
gfx3DMatrix(),
|
2013-07-02 20:27:17 +04:00
|
|
|
gfx3DMatrix(),
|
|
|
|
gfx3DMatrix(),
|
|
|
|
gfx3DMatrix(),
|
|
|
|
};
|
|
|
|
return CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, aLayerManager, aLayers);
|
|
|
|
}
|
|
|
|
|
2013-07-30 22:03:41 +04:00
|
|
|
static void
|
2013-10-30 23:58:25 +04:00
|
|
|
SetScrollableFrameMetrics(Layer* aLayer, FrameMetrics::ViewID aScrollId,
|
|
|
|
// The scrollable rect is only used in HitTesting2,
|
|
|
|
// HitTesting1 doesn't care about it.
|
|
|
|
CSSRect aScrollableRect = CSSRect(-1, -1, -1, -1))
|
2013-07-30 22:03:41 +04:00
|
|
|
{
|
|
|
|
ContainerLayer* container = aLayer->AsContainerLayer();
|
|
|
|
FrameMetrics metrics;
|
2014-03-22 01:48:08 +04:00
|
|
|
metrics.SetScrollId(aScrollId);
|
2013-07-30 22:03:41 +04:00
|
|
|
nsIntRect layerBound = aLayer->GetVisibleRegion().GetBounds();
|
2014-07-04 16:12:41 +04:00
|
|
|
metrics.mCompositionBounds = ParentLayerRect(layerBound.x, layerBound.y,
|
|
|
|
layerBound.width, layerBound.height);
|
2013-10-30 23:58:25 +04:00
|
|
|
metrics.mScrollableRect = aScrollableRect;
|
2014-03-13 10:34:34 +04:00
|
|
|
metrics.SetScrollOffset(CSSPoint(0, 0));
|
2013-07-30 22:03:41 +04:00
|
|
|
container->SetFrameMetrics(metrics);
|
|
|
|
}
|
|
|
|
|
2013-08-21 20:03:03 +04:00
|
|
|
static already_AddRefed<AsyncPanZoomController>
|
|
|
|
GetTargetAPZC(APZCTreeManager* manager, const ScreenPoint& aPoint,
|
2013-10-31 22:44:33 +04:00
|
|
|
gfx3DMatrix& aTransformToApzcOut, gfx3DMatrix& aTransformToGeckoOut)
|
2013-08-21 20:03:03 +04:00
|
|
|
{
|
2014-05-22 22:49:43 +04:00
|
|
|
nsRefPtr<AsyncPanZoomController> hit = manager->GetTargetAPZC(aPoint, nullptr);
|
2013-08-21 20:03:03 +04:00
|
|
|
if (hit) {
|
2013-10-31 22:44:33 +04:00
|
|
|
manager->GetInputTransforms(hit.get(), aTransformToApzcOut, aTransformToGeckoOut);
|
2013-08-21 20:03:03 +04:00
|
|
|
}
|
|
|
|
return hit.forget();
|
|
|
|
}
|
|
|
|
|
2013-10-30 23:58:25 +04:00
|
|
|
// A simple hit testing test that doesn't involve any transforms on layers.
|
2014-03-31 09:05:38 +04:00
|
|
|
TEST_F(APZCTreeManagerTester, HitTesting1) {
|
2013-07-30 22:03:41 +04:00
|
|
|
nsTArray<nsRefPtr<Layer> > layers;
|
|
|
|
nsRefPtr<LayerManager> lm;
|
2013-10-30 23:58:25 +04:00
|
|
|
nsRefPtr<Layer> root = CreateTestLayerTree1(lm, layers);
|
2013-07-30 22:03:41 +04:00
|
|
|
|
|
|
|
TimeStamp testStartTime = TimeStamp::Now();
|
|
|
|
AsyncPanZoomController::SetFrameTime(testStartTime);
|
2013-11-19 05:54:22 +04:00
|
|
|
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
|
2013-07-30 22:03:43 +04:00
|
|
|
ScopedLayerTreeRegistration controller(0, root, mcc);
|
2013-07-30 22:03:41 +04:00
|
|
|
|
|
|
|
nsRefPtr<APZCTreeManager> manager = new TestAPZCTreeManager();
|
2013-08-15 16:03:31 +04:00
|
|
|
gfx3DMatrix transformToApzc;
|
2013-10-31 22:44:33 +04:00
|
|
|
gfx3DMatrix transformToGecko;
|
2013-07-30 22:03:41 +04:00
|
|
|
|
|
|
|
// No APZC attached so hit testing will return no APZC at (20,20)
|
2013-10-31 22:44:33 +04:00
|
|
|
nsRefPtr<AsyncPanZoomController> hit = GetTargetAPZC(manager, ScreenPoint(20, 20), transformToApzc, transformToGecko);
|
2013-07-30 22:03:41 +04:00
|
|
|
AsyncPanZoomController* nullAPZC = nullptr;
|
|
|
|
EXPECT_EQ(nullAPZC, hit.get());
|
2013-08-15 16:03:31 +04:00
|
|
|
EXPECT_EQ(gfx3DMatrix(), transformToApzc);
|
2013-10-31 22:44:33 +04:00
|
|
|
EXPECT_EQ(gfx3DMatrix(), transformToGecko);
|
2013-07-30 22:03:41 +04:00
|
|
|
|
2014-05-07 01:26:13 +04:00
|
|
|
uint32_t paintSequenceNumber = 0;
|
|
|
|
|
2013-07-30 22:03:41 +04:00
|
|
|
// Now we have a root APZC that will match the page
|
2013-11-09 04:07:00 +04:00
|
|
|
SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID);
|
2014-05-07 01:26:13 +04:00
|
|
|
manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, paintSequenceNumber++);
|
2013-10-31 22:44:33 +04:00
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToGecko);
|
2013-07-30 22:03:41 +04:00
|
|
|
EXPECT_EQ(root->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
|
|
|
// expect hit point at LayerIntPoint(15, 15)
|
2013-08-15 16:03:31 +04:00
|
|
|
EXPECT_EQ(gfxPoint(15, 15), transformToApzc.Transform(gfxPoint(15, 15)));
|
2013-10-31 22:44:33 +04:00
|
|
|
EXPECT_EQ(gfxPoint(15, 15), transformToGecko.Transform(gfxPoint(15, 15)));
|
2013-07-30 22:03:41 +04:00
|
|
|
|
|
|
|
// Now we have a sub APZC with a better fit
|
2013-11-09 04:07:00 +04:00
|
|
|
SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID + 1);
|
2014-05-07 01:26:13 +04:00
|
|
|
manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, paintSequenceNumber++);
|
2013-07-30 22:03:41 +04:00
|
|
|
EXPECT_NE(root->AsContainerLayer()->GetAsyncPanZoomController(), layers[3]->AsContainerLayer()->GetAsyncPanZoomController());
|
2013-10-31 22:44:33 +04:00
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToGecko);
|
2013-07-30 22:03:41 +04:00
|
|
|
EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
|
|
|
// expect hit point at LayerIntPoint(15, 15)
|
2013-08-15 16:03:31 +04:00
|
|
|
EXPECT_EQ(gfxPoint(15, 15), transformToApzc.Transform(gfxPoint(15, 15)));
|
2013-10-31 22:44:33 +04:00
|
|
|
EXPECT_EQ(gfxPoint(15, 15), transformToGecko.Transform(gfxPoint(15, 15)));
|
2013-07-30 22:03:41 +04:00
|
|
|
|
|
|
|
// Now test hit testing when we have two scrollable layers
|
2013-10-31 22:44:33 +04:00
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToGecko);
|
2013-07-30 22:03:41 +04:00
|
|
|
EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
2013-11-09 04:07:00 +04:00
|
|
|
SetScrollableFrameMetrics(layers[4], FrameMetrics::START_SCROLL_ID + 2);
|
2014-05-07 01:26:13 +04:00
|
|
|
manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, paintSequenceNumber++);
|
2013-10-31 22:44:33 +04:00
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToGecko);
|
2013-07-30 22:03:41 +04:00
|
|
|
EXPECT_EQ(layers[4]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
|
|
|
// expect hit point at LayerIntPoint(15, 15)
|
2013-08-15 16:03:31 +04:00
|
|
|
EXPECT_EQ(gfxPoint(15, 15), transformToApzc.Transform(gfxPoint(15, 15)));
|
2013-10-31 22:44:33 +04:00
|
|
|
EXPECT_EQ(gfxPoint(15, 15), transformToGecko.Transform(gfxPoint(15, 15)));
|
2013-07-30 22:03:41 +04:00
|
|
|
|
|
|
|
// Hit test ouside the reach of layer[3,4] but inside root
|
2013-10-31 22:44:33 +04:00
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(90, 90), transformToApzc, transformToGecko);
|
2013-07-30 22:03:41 +04:00
|
|
|
EXPECT_EQ(root->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
|
|
|
// expect hit point at LayerIntPoint(90, 90)
|
2013-08-15 16:03:31 +04:00
|
|
|
EXPECT_EQ(gfxPoint(90, 90), transformToApzc.Transform(gfxPoint(90, 90)));
|
2013-10-31 22:44:33 +04:00
|
|
|
EXPECT_EQ(gfxPoint(90, 90), transformToGecko.Transform(gfxPoint(90, 90)));
|
2013-07-30 22:03:41 +04:00
|
|
|
|
|
|
|
// Hit test ouside the reach of any layer
|
2013-10-31 22:44:33 +04:00
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(1000, 10), transformToApzc, transformToGecko);
|
2013-07-30 22:03:41 +04:00
|
|
|
EXPECT_EQ(nullAPZC, hit.get());
|
2013-08-15 16:03:31 +04:00
|
|
|
EXPECT_EQ(gfx3DMatrix(), transformToApzc);
|
2013-10-31 22:44:33 +04:00
|
|
|
EXPECT_EQ(gfx3DMatrix(), transformToGecko);
|
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(-1000, 10), transformToApzc, transformToGecko);
|
2013-07-30 22:03:41 +04:00
|
|
|
EXPECT_EQ(nullAPZC, hit.get());
|
2013-08-15 16:03:31 +04:00
|
|
|
EXPECT_EQ(gfx3DMatrix(), transformToApzc);
|
2013-10-31 22:44:33 +04:00
|
|
|
EXPECT_EQ(gfx3DMatrix(), transformToGecko);
|
2013-07-30 22:03:41 +04:00
|
|
|
|
2013-10-30 23:58:25 +04:00
|
|
|
manager->ClearTree();
|
|
|
|
}
|
2013-07-30 22:03:41 +04:00
|
|
|
|
2013-10-30 23:58:25 +04:00
|
|
|
// A more involved hit testing test that involves css and async transforms.
|
2014-02-28 21:45:27 +04:00
|
|
|
TEST_F(APZCTreeManagerTester, HitTesting2) {
|
2013-10-30 23:58:25 +04:00
|
|
|
nsTArray<nsRefPtr<Layer> > layers;
|
|
|
|
nsRefPtr<LayerManager> lm;
|
|
|
|
nsRefPtr<Layer> root = CreateTestLayerTree2(lm, layers);
|
2013-07-30 22:03:41 +04:00
|
|
|
|
2013-10-30 23:58:25 +04:00
|
|
|
TimeStamp testStartTime = TimeStamp::Now();
|
|
|
|
AsyncPanZoomController::SetFrameTime(testStartTime);
|
2013-11-19 05:54:22 +04:00
|
|
|
nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
|
2013-10-30 23:58:25 +04:00
|
|
|
ScopedLayerTreeRegistration controller(0, root, mcc);
|
2013-07-30 22:03:41 +04:00
|
|
|
|
2013-11-30 01:40:21 +04:00
|
|
|
nsRefPtr<TestAPZCTreeManager> manager = new TestAPZCTreeManager();
|
2013-10-30 23:58:25 +04:00
|
|
|
nsRefPtr<AsyncPanZoomController> hit;
|
|
|
|
gfx3DMatrix transformToApzc;
|
2013-10-31 22:44:33 +04:00
|
|
|
gfx3DMatrix transformToGecko;
|
2013-07-30 22:03:41 +04:00
|
|
|
|
2013-10-30 23:58:25 +04:00
|
|
|
// Set a CSS transform on one of the layers.
|
2014-01-27 19:28:33 +04:00
|
|
|
Matrix4x4 transform;
|
|
|
|
transform = transform * Matrix4x4().Scale(2, 1, 1);
|
2013-10-30 23:58:25 +04:00
|
|
|
layers[2]->SetBaseTransform(transform);
|
|
|
|
|
|
|
|
// Make some other layers scrollable.
|
2013-11-09 04:07:00 +04:00
|
|
|
SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID, CSSRect(0, 0, 200, 200));
|
|
|
|
SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID + 1, CSSRect(0, 0, 80, 80));
|
|
|
|
SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID + 2, CSSRect(0, 0, 80, 80));
|
2013-10-30 23:58:25 +04:00
|
|
|
|
2014-05-07 01:26:13 +04:00
|
|
|
manager->UpdatePanZoomControllerTree(nullptr, root, false, 0, 0);
|
2013-10-30 23:58:25 +04:00
|
|
|
|
|
|
|
// At this point, the following holds (all coordinates in screen pixels):
|
|
|
|
// layers[0] has content from (0,0)-(200,200), clipped by composition bounds (0,0)-(100,100)
|
|
|
|
// layers[1] has content from (10,10)-(90,90), clipped by composition bounds (10,10)-(50,50)
|
|
|
|
// layers[2] has content from (20,60)-(100,100). no clipping as it's not a scrollable layer
|
|
|
|
// layers[3] has content from (20,60)-(180,140), clipped by composition bounds (20,60)-(100,100)
|
|
|
|
|
|
|
|
AsyncPanZoomController* apzcroot = root->AsContainerLayer()->GetAsyncPanZoomController();
|
|
|
|
AsyncPanZoomController* apzc1 = layers[1]->AsContainerLayer()->GetAsyncPanZoomController();
|
|
|
|
AsyncPanZoomController* apzc3 = layers[3]->AsContainerLayer()->GetAsyncPanZoomController();
|
|
|
|
|
|
|
|
// Hit an area that's clearly on the root layer but not any of the child layers.
|
2013-10-31 22:44:33 +04:00
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(75, 25), transformToApzc, transformToGecko);
|
2013-10-30 23:58:25 +04:00
|
|
|
EXPECT_EQ(apzcroot, hit.get());
|
|
|
|
EXPECT_EQ(gfxPoint(75, 25), transformToApzc.Transform(gfxPoint(75, 25)));
|
2013-10-31 22:44:33 +04:00
|
|
|
EXPECT_EQ(gfxPoint(75, 25), transformToGecko.Transform(gfxPoint(75, 25)));
|
2013-10-30 23:58:25 +04:00
|
|
|
|
|
|
|
// Hit an area on the root that would be on layers[3] if layers[2]
|
|
|
|
// weren't transformed.
|
|
|
|
// Note that if layers[2] were scrollable, then this would hit layers[2]
|
|
|
|
// because its composition bounds would be at (10,60)-(50,100) (and the
|
|
|
|
// scale-only transform that we set on layers[2] would be invalid because
|
|
|
|
// it would place the layer into overscroll, as its composition bounds
|
|
|
|
// start at x=10 but its content at x=20).
|
2013-10-31 22:44:33 +04:00
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(15, 75), transformToApzc, transformToGecko);
|
2013-10-30 23:58:25 +04:00
|
|
|
EXPECT_EQ(apzcroot, hit.get());
|
|
|
|
EXPECT_EQ(gfxPoint(15, 75), transformToApzc.Transform(gfxPoint(15, 75)));
|
2013-10-31 22:44:33 +04:00
|
|
|
EXPECT_EQ(gfxPoint(15, 75), transformToGecko.Transform(gfxPoint(15, 75)));
|
2013-10-30 23:58:25 +04:00
|
|
|
|
|
|
|
// Hit an area on layers[1].
|
2013-10-31 22:44:33 +04:00
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(25, 25), transformToApzc, transformToGecko);
|
2013-10-30 23:58:25 +04:00
|
|
|
EXPECT_EQ(apzc1, hit.get());
|
|
|
|
EXPECT_EQ(gfxPoint(25, 25), transformToApzc.Transform(gfxPoint(25, 25)));
|
2013-10-31 22:44:33 +04:00
|
|
|
EXPECT_EQ(gfxPoint(25, 25), transformToGecko.Transform(gfxPoint(25, 25)));
|
2013-10-30 23:58:25 +04:00
|
|
|
|
|
|
|
// Hit an area on layers[3].
|
2013-10-31 22:44:33 +04:00
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(25, 75), transformToApzc, transformToGecko);
|
2013-10-30 23:58:25 +04:00
|
|
|
EXPECT_EQ(apzc3, hit.get());
|
|
|
|
// transformToApzc should unapply layers[2]'s transform
|
|
|
|
EXPECT_EQ(gfxPoint(12.5, 75), transformToApzc.Transform(gfxPoint(25, 75)));
|
2013-10-31 22:44:33 +04:00
|
|
|
// and transformToGecko should reapply it
|
|
|
|
EXPECT_EQ(gfxPoint(25, 75), transformToGecko.Transform(gfxPoint(12.5, 75)));
|
2013-10-30 23:58:25 +04:00
|
|
|
|
|
|
|
// Hit an area on layers[3] that would be on the root if layers[2]
|
|
|
|
// weren't transformed.
|
2013-10-31 22:44:33 +04:00
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(75, 75), transformToApzc, transformToGecko);
|
2013-10-30 23:58:25 +04:00
|
|
|
EXPECT_EQ(apzc3, hit.get());
|
|
|
|
// transformToApzc should unapply layers[2]'s transform
|
|
|
|
EXPECT_EQ(gfxPoint(37.5, 75), transformToApzc.Transform(gfxPoint(75, 75)));
|
2013-10-31 22:44:33 +04:00
|
|
|
// and transformToGecko should reapply it
|
|
|
|
EXPECT_EQ(gfxPoint(75, 75), transformToGecko.Transform(gfxPoint(37.5, 75)));
|
2013-10-30 23:58:25 +04:00
|
|
|
|
|
|
|
// Pan the root layer upward by 50 pixels.
|
|
|
|
// This causes layers[1] to scroll out of view, and an async transform
|
|
|
|
// of -50 to be set on the root layer.
|
|
|
|
int time = 0;
|
|
|
|
// Silence GMock warnings about "uninteresting mock function calls".
|
2014-01-22 22:37:30 +04:00
|
|
|
EXPECT_CALL(*mcc, PostDelayedTask(_,_)).Times(AtLeast(1));
|
2013-12-07 21:45:19 +04:00
|
|
|
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
|
2013-10-30 23:58:25 +04:00
|
|
|
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
2014-01-22 22:37:30 +04:00
|
|
|
|
|
|
|
// This first pan will move the APZC by 50 pixels, and dispatch a paint request.
|
|
|
|
// Since this paint request is in the queue to Gecko, transformToGecko will
|
|
|
|
// take it into account.
|
2014-07-17 21:41:53 +04:00
|
|
|
manager->BuildOverscrollHandoffChain(apzcroot);
|
2014-07-17 21:41:54 +04:00
|
|
|
ApzcPanNoFling(apzcroot, time, 100, 50);
|
2014-07-17 21:41:53 +04:00
|
|
|
manager->ClearOverscrollHandoffChain();
|
2013-10-30 23:58:25 +04:00
|
|
|
|
|
|
|
// Hit where layers[3] used to be. It should now hit the root.
|
2013-10-31 22:44:33 +04:00
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(75, 75), transformToApzc, transformToGecko);
|
2013-10-30 23:58:25 +04:00
|
|
|
EXPECT_EQ(apzcroot, hit.get());
|
|
|
|
// transformToApzc doesn't unapply the root's own async transform
|
|
|
|
EXPECT_EQ(gfxPoint(75, 75), transformToApzc.Transform(gfxPoint(75, 75)));
|
2014-01-22 22:37:30 +04:00
|
|
|
// and transformToGecko unapplies it and then reapplies it, because by the
|
|
|
|
// time the event being transformed reaches Gecko the new paint request will
|
|
|
|
// have been handled.
|
|
|
|
EXPECT_EQ(gfxPoint(75, 75), transformToGecko.Transform(gfxPoint(75, 75)));
|
2013-10-30 23:58:25 +04:00
|
|
|
|
|
|
|
// Hit where layers[1] used to be and where layers[3] should now be.
|
2013-10-31 22:44:33 +04:00
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(25, 25), transformToApzc, transformToGecko);
|
2013-10-30 23:58:25 +04:00
|
|
|
EXPECT_EQ(apzc3, hit.get());
|
|
|
|
// transformToApzc unapplies both layers[2]'s css transform and the root's
|
2014-01-22 22:37:30 +04:00
|
|
|
// async transform
|
2013-10-30 23:58:25 +04:00
|
|
|
EXPECT_EQ(gfxPoint(12.5, 75), transformToApzc.Transform(gfxPoint(25, 25)));
|
2014-01-22 22:37:30 +04:00
|
|
|
// transformToGecko reapplies both the css transform and the async transform
|
|
|
|
// because we have already issued a paint request with it.
|
|
|
|
EXPECT_EQ(gfxPoint(25, 25), transformToGecko.Transform(gfxPoint(12.5, 75)));
|
|
|
|
|
|
|
|
// This second pan will move the APZC by another 50 pixels but since the paint
|
|
|
|
// request dispatched above has not "completed", we will not dispatch another
|
|
|
|
// one yet. Now we have an async transform on top of the pending paint request
|
|
|
|
// transform.
|
2014-07-17 21:41:53 +04:00
|
|
|
manager->BuildOverscrollHandoffChain(apzcroot);
|
2014-07-17 21:41:54 +04:00
|
|
|
ApzcPanNoFling(apzcroot, time, 100, 50);
|
2014-07-17 21:41:53 +04:00
|
|
|
manager->ClearOverscrollHandoffChain();
|
2014-01-22 22:37:30 +04:00
|
|
|
|
|
|
|
// Hit where layers[3] used to be. It should now hit the root.
|
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(75, 75), transformToApzc, transformToGecko);
|
|
|
|
EXPECT_EQ(apzcroot, hit.get());
|
|
|
|
// transformToApzc doesn't unapply the root's own async transform
|
|
|
|
EXPECT_EQ(gfxPoint(75, 75), transformToApzc.Transform(gfxPoint(75, 75)));
|
|
|
|
// transformToGecko unapplies the full async transform of -100 pixels, and then
|
|
|
|
// reapplies the "D" transform of -50 leading to an overall adjustment of +50
|
|
|
|
EXPECT_EQ(gfxPoint(75, 125), transformToGecko.Transform(gfxPoint(75, 75)));
|
|
|
|
|
|
|
|
// Hit where layers[1] used to be. It should now hit the root.
|
|
|
|
hit = GetTargetAPZC(manager, ScreenPoint(25, 25), transformToApzc, transformToGecko);
|
|
|
|
EXPECT_EQ(apzcroot, hit.get());
|
|
|
|
// transformToApzc doesn't unapply the root's own async transform
|
|
|
|
EXPECT_EQ(gfxPoint(25, 25), transformToApzc.Transform(gfxPoint(25, 25)));
|
|
|
|
// transformToGecko unapplies the full async transform of -100 pixels, and then
|
|
|
|
// reapplies the "D" transform of -50 leading to an overall adjustment of +50
|
|
|
|
EXPECT_EQ(gfxPoint(25, 75), transformToGecko.Transform(gfxPoint(25, 25)));
|
2013-07-30 22:03:41 +04:00
|
|
|
|
|
|
|
manager->ClearTree();
|
2013-10-31 22:44:33 +04:00
|
|
|
}
|