1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 : */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef mozilla_layers_APZTestCommon_h
8 #define mozilla_layers_APZTestCommon_h
9
10 /**
11 * Defines a set of mock classes and utility functions/classes for
12 * writing APZ gtests.
13 */
14
15 #include "gtest/gtest.h"
16 #include "gmock/gmock.h"
17
18 #include "mozilla/Attributes.h"
19 #include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform
20 #include "mozilla/layers/GeckoContentController.h"
21 #include "mozilla/layers/CompositorBridgeParent.h"
22 #include "mozilla/layers/APZCTreeManager.h"
23 #include "mozilla/layers/LayerMetricsWrapper.h"
24 #include "mozilla/layers/APZThreadUtils.h"
25 #include "mozilla/UniquePtr.h"
26 #include "apz/src/AsyncPanZoomController.h"
27 #include "apz/src/HitTestingTreeNode.h"
28 #include "base/task.h"
29 #include "Layers.h"
30 #include "TestLayers.h"
31 #include "UnitTransforms.h"
32 #include "gfxPrefs.h"
33
34 using namespace mozilla;
35 using namespace mozilla::gfx;
36 using namespace mozilla::layers;
37 using ::testing::_;
38 using ::testing::NiceMock;
39 using ::testing::AtLeast;
40 using ::testing::AtMost;
41 using ::testing::MockFunction;
42 using ::testing::InSequence;
43 typedef mozilla::layers::GeckoContentController::TapType TapType;
44
45 template<class T>
46 class ScopedGfxPref {
47 public:
ScopedGfxPref(T (* aGetPrefFunc)(void),void (* aSetPrefFunc)(T),T aVal)48 ScopedGfxPref(T (*aGetPrefFunc)(void), void (*aSetPrefFunc)(T), T aVal)
49 : mSetPrefFunc(aSetPrefFunc)
50 {
51 mOldVal = aGetPrefFunc();
52 aSetPrefFunc(aVal);
53 }
54
~ScopedGfxPref()55 ~ScopedGfxPref() {
56 mSetPrefFunc(mOldVal);
57 }
58
59 private:
60 void (*mSetPrefFunc)(T);
61 T mOldVal;
62 };
63
64 #define SCOPED_GFX_PREF(prefBase, prefType, prefValue) \
65 ScopedGfxPref<prefType> pref_##prefBase( \
66 &(gfxPrefs::prefBase), \
67 &(gfxPrefs::Set##prefBase), \
68 prefValue)
69
GetStartupTime()70 static TimeStamp GetStartupTime() {
71 static TimeStamp sStartupTime = TimeStamp::Now();
72 return sStartupTime;
73 }
74
75 class MockContentController : public GeckoContentController {
76 public:
77 MOCK_METHOD1(RequestContentRepaint, void(const FrameMetrics&));
78 MOCK_METHOD2(RequestFlingSnap, void(const FrameMetrics::ViewID& aScrollId, const mozilla::CSSPoint& aDestination));
79 MOCK_METHOD2(AcknowledgeScrollUpdate, void(const FrameMetrics::ViewID&, const uint32_t& aScrollGeneration));
80 MOCK_METHOD5(HandleTap, void(TapType, const LayoutDevicePoint&, Modifiers, const ScrollableLayerGuid&, uint64_t));
81 MOCK_METHOD4(NotifyPinchGesture, void(PinchGestureInput::PinchGestureType, const ScrollableLayerGuid&, LayoutDeviceCoord, Modifiers));
82 // Can't use the macros with already_AddRefed :(
PostDelayedTask(already_AddRefed<Runnable> aTask,int aDelayMs)83 void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) {
84 RefPtr<Runnable> task = aTask;
85 }
IsRepaintThread()86 bool IsRepaintThread() {
87 return NS_IsMainThread();
88 }
DispatchToRepaintThread(already_AddRefed<Runnable> aTask)89 void DispatchToRepaintThread(already_AddRefed<Runnable> aTask) {
90 NS_DispatchToMainThread(Move(aTask));
91 }
92 MOCK_METHOD3(NotifyAPZStateChange, void(const ScrollableLayerGuid& aGuid, APZStateChange aChange, int aArg));
93 MOCK_METHOD0(NotifyFlushComplete, void());
94 };
95
96 class MockContentControllerDelayed : public MockContentController {
97 public:
MockContentControllerDelayed()98 MockContentControllerDelayed()
99 : mTime(GetStartupTime())
100 {
101 }
102
Time()103 const TimeStamp& Time() {
104 return mTime;
105 }
106
AdvanceByMillis(int aMillis)107 void AdvanceByMillis(int aMillis) {
108 AdvanceBy(TimeDuration::FromMilliseconds(aMillis));
109 }
110
AdvanceBy(const TimeDuration & aIncrement)111 void AdvanceBy(const TimeDuration& aIncrement) {
112 TimeStamp target = mTime + aIncrement;
113 while (mTaskQueue.Length() > 0 && mTaskQueue[0].second <= target) {
114 RunNextDelayedTask();
115 }
116 mTime = target;
117 }
118
PostDelayedTask(already_AddRefed<Runnable> aTask,int aDelayMs)119 void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) {
120 RefPtr<Runnable> task = aTask;
121 TimeStamp runAtTime = mTime + TimeDuration::FromMilliseconds(aDelayMs);
122 int insIndex = mTaskQueue.Length();
123 while (insIndex > 0) {
124 if (mTaskQueue[insIndex - 1].second <= runAtTime) {
125 break;
126 }
127 insIndex--;
128 }
129 mTaskQueue.InsertElementAt(insIndex, std::make_pair(task, runAtTime));
130 }
131
132 // Run all the tasks in the queue, returning the number of tasks
133 // run. Note that if a task queues another task while running, that
134 // new task will not be run. Therefore, there may be still be tasks
135 // in the queue after this function is called. Only when the return
136 // value is 0 is the queue guaranteed to be empty.
RunThroughDelayedTasks()137 int RunThroughDelayedTasks() {
138 nsTArray<std::pair<RefPtr<Runnable>, TimeStamp>> runQueue;
139 runQueue.SwapElements(mTaskQueue);
140 int numTasks = runQueue.Length();
141 for (int i = 0; i < numTasks; i++) {
142 mTime = runQueue[i].second;
143 runQueue[i].first->Run();
144
145 // Deleting the task is important in order to release the reference to
146 // the callee object.
147 runQueue[i].first = nullptr;
148 }
149 return numTasks;
150 }
151
152 private:
RunNextDelayedTask()153 void RunNextDelayedTask() {
154 std::pair<RefPtr<Runnable>, TimeStamp> next = mTaskQueue[0];
155 mTaskQueue.RemoveElementAt(0);
156 mTime = next.second;
157 next.first->Run();
158 // Deleting the task is important in order to release the reference to
159 // the callee object.
160 next.first = nullptr;
161 }
162
163 // The following array is sorted by timestamp (tasks are inserted in order by
164 // timestamp).
165 nsTArray<std::pair<RefPtr<Runnable>, TimeStamp>> mTaskQueue;
166 TimeStamp mTime;
167 };
168
169 class TestAPZCTreeManager : public APZCTreeManager {
170 public:
TestAPZCTreeManager(MockContentControllerDelayed * aMcc)171 explicit TestAPZCTreeManager(MockContentControllerDelayed* aMcc) : mcc(aMcc) {}
172
GetInputQueue()173 RefPtr<InputQueue> GetInputQueue() const {
174 return mInputQueue;
175 }
176
ClearContentController()177 void ClearContentController() {
178 mcc = nullptr;
179 }
180
181 protected:
182 AsyncPanZoomController* NewAPZCInstance(uint64_t aLayersId,
183 GeckoContentController* aController) override;
184
GetFrameTime()185 TimeStamp GetFrameTime() override {
186 return mcc->Time();
187 }
188
189 private:
190 RefPtr<MockContentControllerDelayed> mcc;
191 };
192
193 class TestAsyncPanZoomController : public AsyncPanZoomController {
194 public:
195 TestAsyncPanZoomController(uint64_t aLayersId, MockContentControllerDelayed* aMcc,
196 TestAPZCTreeManager* aTreeManager,
197 GestureBehavior aBehavior = DEFAULT_GESTURES)
198 : AsyncPanZoomController(aLayersId, aTreeManager, aTreeManager->GetInputQueue(),
199 aMcc, aBehavior)
200 , mWaitForMainThread(false)
201 , mcc(aMcc)
202 {}
203
ReceiveInputEvent(const InputData & aEvent,ScrollableLayerGuid * aDummy,uint64_t * aOutInputBlockId)204 nsEventStatus ReceiveInputEvent(const InputData& aEvent, ScrollableLayerGuid* aDummy, uint64_t* aOutInputBlockId) {
205 // This is a function whose signature matches exactly the ReceiveInputEvent
206 // on APZCTreeManager. This allows us to templates for functions like
207 // TouchDown, TouchUp, etc so that we can reuse the code for dispatching
208 // events into both APZC and APZCTM.
209 return ReceiveInputEvent(aEvent, aOutInputBlockId);
210 }
211
ReceiveInputEvent(const InputData & aEvent,uint64_t * aOutInputBlockId)212 nsEventStatus ReceiveInputEvent(const InputData& aEvent, uint64_t* aOutInputBlockId) {
213 return GetInputQueue()->ReceiveInputEvent(this, !mWaitForMainThread, aEvent, aOutInputBlockId);
214 }
215
ContentReceivedInputBlock(uint64_t aInputBlockId,bool aPreventDefault)216 void ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefault) {
217 GetInputQueue()->ContentReceivedInputBlock(aInputBlockId, aPreventDefault);
218 }
219
ConfirmTarget(uint64_t aInputBlockId)220 void ConfirmTarget(uint64_t aInputBlockId) {
221 RefPtr<AsyncPanZoomController> target = this;
222 GetInputQueue()->SetConfirmedTargetApzc(aInputBlockId, target);
223 }
224
SetAllowedTouchBehavior(uint64_t aInputBlockId,const nsTArray<TouchBehaviorFlags> & aBehaviors)225 void SetAllowedTouchBehavior(uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aBehaviors) {
226 GetInputQueue()->SetAllowedTouchBehavior(aInputBlockId, aBehaviors);
227 }
228
SetFrameMetrics(const FrameMetrics & metrics)229 void SetFrameMetrics(const FrameMetrics& metrics) {
230 ReentrantMonitorAutoEnter lock(mMonitor);
231 mFrameMetrics = metrics;
232 }
233
GetFrameMetrics()234 FrameMetrics& GetFrameMetrics() {
235 ReentrantMonitorAutoEnter lock(mMonitor);
236 return mFrameMetrics;
237 }
238
GetScrollMetadata()239 ScrollMetadata& GetScrollMetadata() {
240 ReentrantMonitorAutoEnter lock(mMonitor);
241 return mScrollMetadata;
242 }
243
GetFrameMetrics()244 const FrameMetrics& GetFrameMetrics() const {
245 ReentrantMonitorAutoEnter lock(mMonitor);
246 return mFrameMetrics;
247 }
248
249 using AsyncPanZoomController::GetVelocityVector;
250
AssertStateIsReset()251 void AssertStateIsReset() const {
252 ReentrantMonitorAutoEnter lock(mMonitor);
253 EXPECT_EQ(NOTHING, mState);
254 }
255
AssertStateIsFling()256 void AssertStateIsFling() const {
257 ReentrantMonitorAutoEnter lock(mMonitor);
258 EXPECT_EQ(FLING, mState);
259 }
260
261 void AdvanceAnimationsUntilEnd(const TimeDuration& aIncrement = TimeDuration::FromMilliseconds(10)) {
262 while (AdvanceAnimations(mcc->Time())) {
263 mcc->AdvanceBy(aIncrement);
264 }
265 }
266
267 bool SampleContentTransformForFrame(AsyncTransform* aOutTransform,
268 ParentLayerPoint& aScrollOffset,
269 const TimeDuration& aIncrement = TimeDuration::FromMilliseconds(0)) {
270 mcc->AdvanceBy(aIncrement);
271 bool ret = AdvanceAnimations(mcc->Time());
272 if (aOutTransform) {
273 *aOutTransform = GetCurrentAsyncTransform(AsyncPanZoomController::NORMAL);
274 }
275 aScrollOffset = GetCurrentAsyncScrollOffset(AsyncPanZoomController::NORMAL);
276 return ret;
277 }
278
SetWaitForMainThread()279 void SetWaitForMainThread() {
280 mWaitForMainThread = true;
281 }
282
283 private:
284 bool mWaitForMainThread;
285 MockContentControllerDelayed* mcc;
286 };
287
288 class APZCTesterBase : public ::testing::Test {
289 public:
APZCTesterBase()290 APZCTesterBase() {
291 mcc = new NiceMock<MockContentControllerDelayed>();
292 }
293
294 template<class InputReceiver>
295 void Tap(const RefPtr<InputReceiver>& aTarget, const ScreenIntPoint& aPoint,
296 TimeDuration aTapLength,
297 nsEventStatus (*aOutEventStatuses)[2] = nullptr,
298 uint64_t* aOutInputBlockId = nullptr);
299
300 template<class InputReceiver>
301 void TapAndCheckStatus(const RefPtr<InputReceiver>& aTarget,
302 const ScreenIntPoint& aPoint, TimeDuration aTapLength);
303
304 template<class InputReceiver>
305 void Pan(const RefPtr<InputReceiver>& aTarget,
306 const ScreenIntPoint& aTouchStart,
307 const ScreenIntPoint& aTouchEnd,
308 bool aKeepFingerDown = false,
309 nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr,
310 nsEventStatus (*aOutEventStatuses)[4] = nullptr,
311 uint64_t* aOutInputBlockId = nullptr);
312
313 /*
314 * A version of Pan() that only takes y coordinates rather than (x, y) points
315 * for the touch start and end points, and uses 10 for the x coordinates.
316 * This is for convenience, as most tests only need to pan in one direction.
317 */
318 template<class InputReceiver>
319 void Pan(const RefPtr<InputReceiver>& aTarget, int aTouchStartY,
320 int aTouchEndY, bool aKeepFingerDown = false,
321 nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr,
322 nsEventStatus (*aOutEventStatuses)[4] = nullptr,
323 uint64_t* aOutInputBlockId = nullptr);
324
325 /*
326 * Dispatches mock touch events to the apzc and checks whether apzc properly
327 * consumed them and triggered scrolling behavior.
328 */
329 template<class InputReceiver>
330 void PanAndCheckStatus(const RefPtr<InputReceiver>& aTarget, int aTouchStartY,
331 int aTouchEndY,
332 bool aExpectConsumed,
333 nsTArray<uint32_t>* aAllowedTouchBehaviors,
334 uint64_t* aOutInputBlockId = nullptr);
335
336 void ApzcPanNoFling(const RefPtr<TestAsyncPanZoomController>& aApzc,
337 int aTouchStartY,
338 int aTouchEndY,
339 uint64_t* aOutInputBlockId = nullptr);
340
341 template<class InputReceiver>
342 void DoubleTap(const RefPtr<InputReceiver>& aTarget,
343 const ScreenIntPoint& aPoint,
344 nsEventStatus (*aOutEventStatuses)[4] = nullptr,
345 uint64_t (*aOutInputBlockIds)[2] = nullptr);
346
347 template<class InputReceiver>
348 void DoubleTapAndCheckStatus(const RefPtr<InputReceiver>& aTarget,
349 const ScreenIntPoint& aPoint,
350 uint64_t (*aOutInputBlockIds)[2] = nullptr);
351
352 protected:
353 RefPtr<MockContentControllerDelayed> mcc;
354 };
355
356 template<class InputReceiver>
357 void
Tap(const RefPtr<InputReceiver> & aTarget,const ScreenIntPoint & aPoint,TimeDuration aTapLength,nsEventStatus (* aOutEventStatuses)[2],uint64_t * aOutInputBlockId)358 APZCTesterBase::Tap(const RefPtr<InputReceiver>& aTarget,
359 const ScreenIntPoint& aPoint, TimeDuration aTapLength,
360 nsEventStatus (*aOutEventStatuses)[2],
361 uint64_t* aOutInputBlockId)
362 {
363 // Even if the caller doesn't care about the block id, we need it to set the
364 // allowed touch behaviour below, so make sure aOutInputBlockId is non-null.
365 uint64_t blockId;
366 if (!aOutInputBlockId) {
367 aOutInputBlockId = &blockId;
368 }
369
370 nsEventStatus status = TouchDown(aTarget, aPoint, mcc->Time(), aOutInputBlockId);
371 if (aOutEventStatuses) {
372 (*aOutEventStatuses)[0] = status;
373 }
374 mcc->AdvanceBy(aTapLength);
375
376 // If touch-action is enabled then simulate the allowed touch behaviour
377 // notification that the main thread is supposed to deliver.
378 if (gfxPrefs::TouchActionEnabled() && status != nsEventStatus_eConsumeNoDefault) {
379 SetDefaultAllowedTouchBehavior(aTarget, *aOutInputBlockId);
380 }
381
382 status = TouchUp(aTarget, aPoint, mcc->Time());
383 if (aOutEventStatuses) {
384 (*aOutEventStatuses)[1] = status;
385 }
386 }
387
388 template<class InputReceiver>
389 void
TapAndCheckStatus(const RefPtr<InputReceiver> & aTarget,const ScreenIntPoint & aPoint,TimeDuration aTapLength)390 APZCTesterBase::TapAndCheckStatus(const RefPtr<InputReceiver>& aTarget,
391 const ScreenIntPoint& aPoint,
392 TimeDuration aTapLength)
393 {
394 nsEventStatus statuses[2];
395 Tap(aTarget, aPoint, aTapLength, &statuses);
396 EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[0]);
397 EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[1]);
398 }
399
400 template<class InputReceiver>
401 void
Pan(const RefPtr<InputReceiver> & aTarget,const ScreenIntPoint & aTouchStart,const ScreenIntPoint & aTouchEnd,bool aKeepFingerDown,nsTArray<uint32_t> * aAllowedTouchBehaviors,nsEventStatus (* aOutEventStatuses)[4],uint64_t * aOutInputBlockId)402 APZCTesterBase::Pan(const RefPtr<InputReceiver>& aTarget,
403 const ScreenIntPoint& aTouchStart,
404 const ScreenIntPoint& aTouchEnd,
405 bool aKeepFingerDown,
406 nsTArray<uint32_t>* aAllowedTouchBehaviors,
407 nsEventStatus (*aOutEventStatuses)[4],
408 uint64_t* aOutInputBlockId)
409 {
410 // Reduce the touch start and move tolerance to a tiny value.
411 // We can't use a scoped pref because this value might be read at some later
412 // time when the events are actually processed, rather than when we deliver
413 // them.
414 gfxPrefs::SetAPZTouchStartTolerance(1.0f / 1000.0f);
415 gfxPrefs::SetAPZTouchMoveTolerance(0.0f);
416 const int OVERCOME_TOUCH_TOLERANCE = 1;
417
418 const TimeDuration TIME_BETWEEN_TOUCH_EVENT = TimeDuration::FromMilliseconds(50);
419
420 // Even if the caller doesn't care about the block id, we need it to set the
421 // allowed touch behaviour below, so make sure aOutInputBlockId is non-null.
422 uint64_t blockId;
423 if (!aOutInputBlockId) {
424 aOutInputBlockId = &blockId;
425 }
426
427 // Make sure the move is large enough to not be handled as a tap
428 nsEventStatus status = TouchDown(aTarget,
429 ScreenIntPoint(aTouchStart.x, aTouchStart.y + OVERCOME_TOUCH_TOLERANCE),
430 mcc->Time(), aOutInputBlockId);
431 if (aOutEventStatuses) {
432 (*aOutEventStatuses)[0] = status;
433 }
434
435 mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT);
436
437 // Allowed touch behaviours must be set after sending touch-start.
438 if (status != nsEventStatus_eConsumeNoDefault) {
439 if (aAllowedTouchBehaviors) {
440 EXPECT_EQ(1UL, aAllowedTouchBehaviors->Length());
441 aTarget->SetAllowedTouchBehavior(*aOutInputBlockId, *aAllowedTouchBehaviors);
442 } else if (gfxPrefs::TouchActionEnabled()) {
443 SetDefaultAllowedTouchBehavior(aTarget, *aOutInputBlockId);
444 }
445 }
446
447 status = TouchMove(aTarget, aTouchStart, mcc->Time());
448 if (aOutEventStatuses) {
449 (*aOutEventStatuses)[1] = status;
450 }
451
452 mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT);
453
454 status = TouchMove(aTarget, aTouchEnd, mcc->Time());
455 if (aOutEventStatuses) {
456 (*aOutEventStatuses)[2] = status;
457 }
458
459 mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT);
460
461 if (!aKeepFingerDown) {
462 status = TouchUp(aTarget, aTouchEnd, mcc->Time());
463 } else {
464 status = nsEventStatus_eIgnore;
465 }
466 if (aOutEventStatuses) {
467 (*aOutEventStatuses)[3] = status;
468 }
469
470 // Don't increment the time here. Animations started on touch-up, such as
471 // flings, are affected by elapsed time, and we want to be able to sample
472 // them immediately after they start, without time having elapsed.
473 }
474
475 template<class InputReceiver>
476 void
Pan(const RefPtr<InputReceiver> & aTarget,int aTouchStartY,int aTouchEndY,bool aKeepFingerDown,nsTArray<uint32_t> * aAllowedTouchBehaviors,nsEventStatus (* aOutEventStatuses)[4],uint64_t * aOutInputBlockId)477 APZCTesterBase::Pan(const RefPtr<InputReceiver>& aTarget,
478 int aTouchStartY, int aTouchEndY, bool aKeepFingerDown,
479 nsTArray<uint32_t>* aAllowedTouchBehaviors,
480 nsEventStatus (*aOutEventStatuses)[4],
481 uint64_t* aOutInputBlockId)
482 {
483 Pan(aTarget, ScreenIntPoint(10, aTouchStartY), ScreenIntPoint(10, aTouchEndY),
484 aKeepFingerDown, aAllowedTouchBehaviors, aOutEventStatuses, aOutInputBlockId);
485 }
486
487 template<class InputReceiver>
488 void
PanAndCheckStatus(const RefPtr<InputReceiver> & aTarget,int aTouchStartY,int aTouchEndY,bool aExpectConsumed,nsTArray<uint32_t> * aAllowedTouchBehaviors,uint64_t * aOutInputBlockId)489 APZCTesterBase::PanAndCheckStatus(const RefPtr<InputReceiver>& aTarget,
490 int aTouchStartY,
491 int aTouchEndY,
492 bool aExpectConsumed,
493 nsTArray<uint32_t>* aAllowedTouchBehaviors,
494 uint64_t* aOutInputBlockId)
495 {
496 nsEventStatus statuses[4]; // down, move, move, up
497 Pan(aTarget, aTouchStartY, aTouchEndY, false, aAllowedTouchBehaviors, &statuses, aOutInputBlockId);
498
499 EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[0]);
500
501 nsEventStatus touchMoveStatus;
502 if (aExpectConsumed) {
503 touchMoveStatus = nsEventStatus_eConsumeDoDefault;
504 } else {
505 touchMoveStatus = nsEventStatus_eIgnore;
506 }
507 EXPECT_EQ(touchMoveStatus, statuses[1]);
508 EXPECT_EQ(touchMoveStatus, statuses[2]);
509 }
510
511 void
ApzcPanNoFling(const RefPtr<TestAsyncPanZoomController> & aApzc,int aTouchStartY,int aTouchEndY,uint64_t * aOutInputBlockId)512 APZCTesterBase::ApzcPanNoFling(const RefPtr<TestAsyncPanZoomController>& aApzc,
513 int aTouchStartY, int aTouchEndY,
514 uint64_t* aOutInputBlockId)
515 {
516 Pan(aApzc, aTouchStartY, aTouchEndY, false, nullptr, nullptr, aOutInputBlockId);
517 aApzc->CancelAnimation();
518 }
519
520 template<class InputReceiver>
521 void
DoubleTap(const RefPtr<InputReceiver> & aTarget,const ScreenIntPoint & aPoint,nsEventStatus (* aOutEventStatuses)[4],uint64_t (* aOutInputBlockIds)[2])522 APZCTesterBase::DoubleTap(const RefPtr<InputReceiver>& aTarget,
523 const ScreenIntPoint& aPoint,
524 nsEventStatus (*aOutEventStatuses)[4],
525 uint64_t (*aOutInputBlockIds)[2])
526 {
527 uint64_t blockId;
528 nsEventStatus status = TouchDown(aTarget, aPoint, mcc->Time(), &blockId);
529 if (aOutEventStatuses) {
530 (*aOutEventStatuses)[0] = status;
531 }
532 if (aOutInputBlockIds) {
533 (*aOutInputBlockIds)[0] = blockId;
534 }
535 mcc->AdvanceByMillis(10);
536
537 // If touch-action is enabled then simulate the allowed touch behaviour
538 // notification that the main thread is supposed to deliver.
539 if (gfxPrefs::TouchActionEnabled() && status != nsEventStatus_eConsumeNoDefault) {
540 SetDefaultAllowedTouchBehavior(aTarget, blockId);
541 }
542
543 status = TouchUp(aTarget, aPoint, mcc->Time());
544 if (aOutEventStatuses) {
545 (*aOutEventStatuses)[1] = status;
546 }
547 mcc->AdvanceByMillis(10);
548 status = TouchDown(aTarget, aPoint, mcc->Time(), &blockId);
549 if (aOutEventStatuses) {
550 (*aOutEventStatuses)[2] = status;
551 }
552 if (aOutInputBlockIds) {
553 (*aOutInputBlockIds)[1] = blockId;
554 }
555 mcc->AdvanceByMillis(10);
556
557 if (gfxPrefs::TouchActionEnabled() && status != nsEventStatus_eConsumeNoDefault) {
558 SetDefaultAllowedTouchBehavior(aTarget, blockId);
559 }
560
561 status = TouchUp(aTarget, aPoint, mcc->Time());
562 if (aOutEventStatuses) {
563 (*aOutEventStatuses)[3] = status;
564 }
565 }
566
567 template<class InputReceiver>
568 void
DoubleTapAndCheckStatus(const RefPtr<InputReceiver> & aTarget,const ScreenIntPoint & aPoint,uint64_t (* aOutInputBlockIds)[2])569 APZCTesterBase::DoubleTapAndCheckStatus(const RefPtr<InputReceiver>& aTarget,
570 const ScreenIntPoint& aPoint,
571 uint64_t (*aOutInputBlockIds)[2])
572 {
573 nsEventStatus statuses[4];
574 DoubleTap(aTarget, aPoint, &statuses, aOutInputBlockIds);
575 EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[0]);
576 EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[1]);
577 EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[2]);
578 EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[3]);
579 }
580
581 AsyncPanZoomController*
NewAPZCInstance(uint64_t aLayersId,GeckoContentController * aController)582 TestAPZCTreeManager::NewAPZCInstance(uint64_t aLayersId,
583 GeckoContentController* aController)
584 {
585 MockContentControllerDelayed* mcc = static_cast<MockContentControllerDelayed*>(aController);
586 return new TestAsyncPanZoomController(aLayersId, mcc, this,
587 AsyncPanZoomController::USE_GESTURE_DETECTOR);
588 }
589
590 FrameMetrics
TestFrameMetrics()591 TestFrameMetrics()
592 {
593 FrameMetrics fm;
594
595 fm.SetDisplayPort(CSSRect(0, 0, 10, 10));
596 fm.SetCompositionBounds(ParentLayerRect(0, 0, 10, 10));
597 fm.SetCriticalDisplayPort(CSSRect(0, 0, 10, 10));
598 fm.SetScrollableRect(CSSRect(0, 0, 100, 100));
599
600 return fm;
601 }
602
603 uint32_t
MillisecondsSinceStartup(TimeStamp aTime)604 MillisecondsSinceStartup(TimeStamp aTime)
605 {
606 return (aTime - GetStartupTime()).ToMilliseconds();
607 }
608
609 #endif // mozilla_layers_APZTestCommon_h
610