/src/mozilla-central/gfx/layers/apz/test/gtest/APZTestCommon.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #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/gfx/gfxVars.h" |
20 | | #include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform |
21 | | #include "mozilla/layers/GeckoContentController.h" |
22 | | #include "mozilla/layers/CompositorBridgeParent.h" |
23 | | #include "mozilla/layers/LayerMetricsWrapper.h" |
24 | | #include "mozilla/layers/APZThreadUtils.h" |
25 | | #include "mozilla/TypedEnumBits.h" |
26 | | #include "mozilla/UniquePtr.h" |
27 | | #include "apz/src/APZCTreeManager.h" |
28 | | #include "apz/src/AsyncPanZoomController.h" |
29 | | #include "apz/src/HitTestingTreeNode.h" |
30 | | #include "base/task.h" |
31 | | #include "Layers.h" |
32 | | #include "TestLayers.h" |
33 | | #include "UnitTransforms.h" |
34 | | #include "gfxPrefs.h" |
35 | | |
36 | | using namespace mozilla; |
37 | | using namespace mozilla::gfx; |
38 | | using namespace mozilla::layers; |
39 | | using ::testing::_; |
40 | | using ::testing::NiceMock; |
41 | | using ::testing::AtLeast; |
42 | | using ::testing::AtMost; |
43 | | using ::testing::MockFunction; |
44 | | using ::testing::InSequence; |
45 | | typedef mozilla::layers::GeckoContentController::TapType TapType; |
46 | | |
47 | | // Some helper functions for constructing input event objects suitable to be |
48 | | // passed either to an APZC (which expects an transformed point), or to an APZTM |
49 | | // (which expects an untransformed point). We handle both cases by setting both |
50 | | // the transformed and untransformed fields to the same value. |
51 | | SingleTouchData |
52 | | CreateSingleTouchData(int32_t aIdentifier, const ScreenIntPoint& aPoint) |
53 | 0 | { |
54 | 0 | SingleTouchData touch(aIdentifier, aPoint, ScreenSize(0, 0), 0, 0); |
55 | 0 | touch.mLocalScreenPoint = ParentLayerPoint(aPoint.x, aPoint.y); |
56 | 0 | return touch; |
57 | 0 | } |
58 | | |
59 | | // Convenience wrapper for CreateSingleTouchData() that takes loose coordinates. |
60 | | SingleTouchData |
61 | | CreateSingleTouchData(int32_t aIdentifier, ScreenIntCoord aX, ScreenIntCoord aY) |
62 | 0 | { |
63 | 0 | return CreateSingleTouchData(aIdentifier, ScreenIntPoint(aX, aY)); |
64 | 0 | } |
65 | | |
66 | | template<class SetArg, class Storage> |
67 | | class ScopedGfxSetting { |
68 | | public: |
69 | | ScopedGfxSetting(SetArg (*aGetPrefFunc)(void), void (*aSetPrefFunc)(SetArg), SetArg aVal) |
70 | | : mSetPrefFunc(aSetPrefFunc) |
71 | 0 | { |
72 | 0 | mOldVal = aGetPrefFunc(); |
73 | 0 | aSetPrefFunc(aVal); |
74 | 0 | } Unexecuted instantiation: ScopedGfxSetting<float, float>::ScopedGfxSetting(float (*)(), void (*)(float), float) Unexecuted instantiation: ScopedGfxSetting<bool, bool>::ScopedGfxSetting(bool (*)(), void (*)(bool), bool) Unexecuted instantiation: ScopedGfxSetting<bool const&, bool>::ScopedGfxSetting(bool const& (*)(), void (*)(bool const&), bool const&) Unexecuted instantiation: ScopedGfxSetting<int, int>::ScopedGfxSetting(int (*)(), void (*)(int), int) |
75 | | |
76 | 0 | ~ScopedGfxSetting() { |
77 | 0 | mSetPrefFunc(mOldVal); |
78 | 0 | } Unexecuted instantiation: ScopedGfxSetting<float, float>::~ScopedGfxSetting() Unexecuted instantiation: ScopedGfxSetting<bool, bool>::~ScopedGfxSetting() Unexecuted instantiation: ScopedGfxSetting<bool const&, bool>::~ScopedGfxSetting() Unexecuted instantiation: ScopedGfxSetting<int, int>::~ScopedGfxSetting() |
79 | | |
80 | | private: |
81 | | void (*mSetPrefFunc)(SetArg); |
82 | | Storage mOldVal; |
83 | | }; |
84 | | |
85 | | #define SCOPED_GFX_PREF(prefBase, prefType, prefValue) \ |
86 | 0 | ScopedGfxSetting<prefType, prefType> pref_##prefBase( \ |
87 | 0 | &(gfxPrefs::prefBase), \ |
88 | 0 | &(gfxPrefs::Set##prefBase), \ |
89 | 0 | prefValue) |
90 | | |
91 | | #define SCOPED_GFX_VAR(varBase, varType, varValue) \ |
92 | 0 | ScopedGfxSetting<const varType&, varType> var_##varBase( \ |
93 | 0 | &(gfxVars::varBase), \ |
94 | 0 | &(gfxVars::Set##varBase), \ |
95 | 0 | varValue) |
96 | | |
97 | 0 | static TimeStamp GetStartupTime() { |
98 | 0 | static TimeStamp sStartupTime = TimeStamp::Now(); |
99 | 0 | return sStartupTime; |
100 | 0 | } |
101 | | |
102 | | class MockContentController : public GeckoContentController { |
103 | | public: |
104 | | MOCK_METHOD1(RequestContentRepaint, void(const FrameMetrics&)); |
105 | | MOCK_METHOD2(RequestFlingSnap, void(const FrameMetrics::ViewID& aScrollId, const mozilla::CSSPoint& aDestination)); |
106 | | MOCK_METHOD2(AcknowledgeScrollUpdate, void(const FrameMetrics::ViewID&, const uint32_t& aScrollGeneration)); |
107 | | MOCK_METHOD5(HandleTap, void(TapType, const LayoutDevicePoint&, Modifiers, const ScrollableLayerGuid&, uint64_t)); |
108 | | MOCK_METHOD4(NotifyPinchGesture, void(PinchGestureInput::PinchGestureType, const ScrollableLayerGuid&, LayoutDeviceCoord, Modifiers)); |
109 | | // Can't use the macros with already_AddRefed :( |
110 | 0 | void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) { |
111 | 0 | RefPtr<Runnable> task = aTask; |
112 | 0 | } |
113 | 0 | bool IsRepaintThread() { |
114 | 0 | return NS_IsMainThread(); |
115 | 0 | } |
116 | 0 | void DispatchToRepaintThread(already_AddRefed<Runnable> aTask) { |
117 | 0 | NS_DispatchToMainThread(std::move(aTask)); |
118 | 0 | } |
119 | | MOCK_METHOD3(NotifyAPZStateChange, void(const ScrollableLayerGuid& aGuid, APZStateChange aChange, int aArg)); |
120 | | MOCK_METHOD0(NotifyFlushComplete, void()); |
121 | | MOCK_METHOD1(NotifyAsyncScrollbarDragRejected, void(const FrameMetrics::ViewID&)); |
122 | | MOCK_METHOD1(NotifyAsyncAutoscrollRejected, void(const FrameMetrics::ViewID&)); |
123 | | MOCK_METHOD1(CancelAutoscroll, void(const ScrollableLayerGuid&)); |
124 | | }; |
125 | | |
126 | | class MockContentControllerDelayed : public MockContentController { |
127 | | public: |
128 | | MockContentControllerDelayed() |
129 | | : mTime(GetStartupTime()) |
130 | 0 | { |
131 | 0 | } |
132 | | |
133 | 0 | const TimeStamp& Time() { |
134 | 0 | return mTime; |
135 | 0 | } |
136 | | |
137 | 0 | void AdvanceByMillis(int aMillis) { |
138 | 0 | AdvanceBy(TimeDuration::FromMilliseconds(aMillis)); |
139 | 0 | } |
140 | | |
141 | 0 | void AdvanceBy(const TimeDuration& aIncrement) { |
142 | 0 | TimeStamp target = mTime + aIncrement; |
143 | 0 | while (mTaskQueue.Length() > 0 && mTaskQueue[0].second <= target) { |
144 | 0 | RunNextDelayedTask(); |
145 | 0 | } |
146 | 0 | mTime = target; |
147 | 0 | } |
148 | | |
149 | 0 | void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) { |
150 | 0 | RefPtr<Runnable> task = aTask; |
151 | 0 | TimeStamp runAtTime = mTime + TimeDuration::FromMilliseconds(aDelayMs); |
152 | 0 | int insIndex = mTaskQueue.Length(); |
153 | 0 | while (insIndex > 0) { |
154 | 0 | if (mTaskQueue[insIndex - 1].second <= runAtTime) { |
155 | 0 | break; |
156 | 0 | } |
157 | 0 | insIndex--; |
158 | 0 | } |
159 | 0 | mTaskQueue.InsertElementAt(insIndex, std::make_pair(task, runAtTime)); |
160 | 0 | } |
161 | | |
162 | | // Run all the tasks in the queue, returning the number of tasks |
163 | | // run. Note that if a task queues another task while running, that |
164 | | // new task will not be run. Therefore, there may be still be tasks |
165 | | // in the queue after this function is called. Only when the return |
166 | | // value is 0 is the queue guaranteed to be empty. |
167 | 0 | int RunThroughDelayedTasks() { |
168 | 0 | nsTArray<std::pair<RefPtr<Runnable>, TimeStamp>> runQueue; |
169 | 0 | runQueue.SwapElements(mTaskQueue); |
170 | 0 | int numTasks = runQueue.Length(); |
171 | 0 | for (int i = 0; i < numTasks; i++) { |
172 | 0 | mTime = runQueue[i].second; |
173 | 0 | runQueue[i].first->Run(); |
174 | 0 |
|
175 | 0 | // Deleting the task is important in order to release the reference to |
176 | 0 | // the callee object. |
177 | 0 | runQueue[i].first = nullptr; |
178 | 0 | } |
179 | 0 | return numTasks; |
180 | 0 | } |
181 | | |
182 | | private: |
183 | 0 | void RunNextDelayedTask() { |
184 | 0 | std::pair<RefPtr<Runnable>, TimeStamp> next = mTaskQueue[0]; |
185 | 0 | mTaskQueue.RemoveElementAt(0); |
186 | 0 | mTime = next.second; |
187 | 0 | next.first->Run(); |
188 | 0 | // Deleting the task is important in order to release the reference to |
189 | 0 | // the callee object. |
190 | 0 | next.first = nullptr; |
191 | 0 | } |
192 | | |
193 | | // The following array is sorted by timestamp (tasks are inserted in order by |
194 | | // timestamp). |
195 | | nsTArray<std::pair<RefPtr<Runnable>, TimeStamp>> mTaskQueue; |
196 | | TimeStamp mTime; |
197 | | }; |
198 | | |
199 | | class TestAPZCTreeManager : public APZCTreeManager { |
200 | | public: |
201 | | explicit TestAPZCTreeManager(MockContentControllerDelayed* aMcc) |
202 | | : APZCTreeManager(LayersId{0}) |
203 | | , mcc(aMcc) |
204 | 0 | {} |
205 | | |
206 | 0 | RefPtr<InputQueue> GetInputQueue() const { |
207 | 0 | return mInputQueue; |
208 | 0 | } |
209 | | |
210 | 0 | void ClearContentController() { |
211 | 0 | mcc = nullptr; |
212 | 0 | } |
213 | | |
214 | | /** |
215 | | * This function is not currently implemented. |
216 | | * See bug 1468804 for more information. |
217 | | **/ |
218 | 0 | void CancelAnimation() { |
219 | 0 | EXPECT_TRUE(false); |
220 | 0 | } |
221 | | |
222 | | protected: |
223 | | AsyncPanZoomController* NewAPZCInstance(LayersId aLayersId, |
224 | | GeckoContentController* aController) override; |
225 | | |
226 | 0 | TimeStamp GetFrameTime() override { |
227 | 0 | return mcc->Time(); |
228 | 0 | } |
229 | | |
230 | | |
231 | | private: |
232 | | RefPtr<MockContentControllerDelayed> mcc; |
233 | | }; |
234 | | |
235 | | class TestAsyncPanZoomController : public AsyncPanZoomController { |
236 | | public: |
237 | | TestAsyncPanZoomController(LayersId aLayersId, MockContentControllerDelayed* aMcc, |
238 | | TestAPZCTreeManager* aTreeManager, |
239 | | GestureBehavior aBehavior = DEFAULT_GESTURES) |
240 | | : AsyncPanZoomController(aLayersId, aTreeManager, aTreeManager->GetInputQueue(), |
241 | | aMcc, aBehavior) |
242 | | , mWaitForMainThread(false) |
243 | | , mcc(aMcc) |
244 | 0 | {} |
245 | | |
246 | 0 | nsEventStatus ReceiveInputEvent(const InputData& aEvent, ScrollableLayerGuid* aDummy, uint64_t* aOutInputBlockId) { |
247 | 0 | // This is a function whose signature matches exactly the ReceiveInputEvent |
248 | 0 | // on APZCTreeManager. This allows us to templates for functions like |
249 | 0 | // TouchDown, TouchUp, etc so that we can reuse the code for dispatching |
250 | 0 | // events into both APZC and APZCTM. |
251 | 0 | return ReceiveInputEvent(aEvent, aOutInputBlockId); |
252 | 0 | } |
253 | | |
254 | 0 | nsEventStatus ReceiveInputEvent(const InputData& aEvent, uint64_t* aOutInputBlockId) { |
255 | 0 | return GetInputQueue()->ReceiveInputEvent(this, TargetConfirmationFlags{!mWaitForMainThread}, aEvent, aOutInputBlockId); |
256 | 0 | } |
257 | | |
258 | 0 | void ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefault) { |
259 | 0 | GetInputQueue()->ContentReceivedInputBlock(aInputBlockId, aPreventDefault); |
260 | 0 | } |
261 | | |
262 | 0 | void ConfirmTarget(uint64_t aInputBlockId) { |
263 | 0 | RefPtr<AsyncPanZoomController> target = this; |
264 | 0 | GetInputQueue()->SetConfirmedTargetApzc(aInputBlockId, target); |
265 | 0 | } |
266 | | |
267 | 0 | void SetAllowedTouchBehavior(uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aBehaviors) { |
268 | 0 | GetInputQueue()->SetAllowedTouchBehavior(aInputBlockId, aBehaviors); |
269 | 0 | } |
270 | | |
271 | 0 | void SetFrameMetrics(const FrameMetrics& metrics) { |
272 | 0 | RecursiveMutexAutoLock lock(mRecursiveMutex); |
273 | 0 | Metrics() = metrics; |
274 | 0 | } |
275 | | |
276 | 0 | FrameMetrics& GetFrameMetrics() { |
277 | 0 | RecursiveMutexAutoLock lock(mRecursiveMutex); |
278 | 0 | return mScrollMetadata.GetMetrics(); |
279 | 0 | } |
280 | | |
281 | 0 | ScrollMetadata& GetScrollMetadata() { |
282 | 0 | RecursiveMutexAutoLock lock(mRecursiveMutex); |
283 | 0 | return mScrollMetadata; |
284 | 0 | } |
285 | | |
286 | 0 | const FrameMetrics& GetFrameMetrics() const { |
287 | 0 | RecursiveMutexAutoLock lock(mRecursiveMutex); |
288 | 0 | return mScrollMetadata.GetMetrics(); |
289 | 0 | } |
290 | | |
291 | | using AsyncPanZoomController::GetVelocityVector; |
292 | | |
293 | 0 | void AssertStateIsReset() const { |
294 | 0 | RecursiveMutexAutoLock lock(mRecursiveMutex); |
295 | 0 | EXPECT_EQ(NOTHING, mState); |
296 | 0 | } |
297 | | |
298 | 0 | void AssertStateIsFling() const { |
299 | 0 | RecursiveMutexAutoLock lock(mRecursiveMutex); |
300 | 0 | EXPECT_EQ(FLING, mState); |
301 | 0 | } |
302 | | |
303 | 0 | void AssertStateIsSmoothScroll() const { |
304 | 0 | RecursiveMutexAutoLock lock(mRecursiveMutex); |
305 | 0 | EXPECT_EQ(SMOOTH_SCROLL, mState); |
306 | 0 | } |
307 | | |
308 | 0 | void AssertNotAxisLocked() const { |
309 | 0 | RecursiveMutexAutoLock lock(mRecursiveMutex); |
310 | 0 | EXPECT_EQ(PANNING, mState); |
311 | 0 | } |
312 | | |
313 | 0 | void AssertAxisLocked(ScrollDirection aDirection) const { |
314 | 0 | RecursiveMutexAutoLock lock(mRecursiveMutex); |
315 | 0 | switch (aDirection) { |
316 | 0 | case ScrollDirection::eHorizontal: |
317 | 0 | EXPECT_EQ(PANNING_LOCKED_X, mState); |
318 | 0 | break; |
319 | 0 | case ScrollDirection::eVertical: |
320 | 0 | EXPECT_EQ(PANNING_LOCKED_Y, mState); |
321 | 0 | break; |
322 | 0 | } |
323 | 0 | } |
324 | | |
325 | 0 | void AdvanceAnimationsUntilEnd(const TimeDuration& aIncrement = TimeDuration::FromMilliseconds(10)) { |
326 | 0 | while (AdvanceAnimations(mcc->Time())) { |
327 | 0 | mcc->AdvanceBy(aIncrement); |
328 | 0 | } |
329 | 0 | } |
330 | | |
331 | | bool SampleContentTransformForFrame(AsyncTransform* aOutTransform, |
332 | | ParentLayerPoint& aScrollOffset, |
333 | 0 | const TimeDuration& aIncrement = TimeDuration::FromMilliseconds(0)) { |
334 | 0 | mcc->AdvanceBy(aIncrement); |
335 | 0 | bool ret = AdvanceAnimations(mcc->Time()); |
336 | 0 | if (aOutTransform) { |
337 | 0 | *aOutTransform = GetCurrentAsyncTransform(AsyncPanZoomController::eForHitTesting); |
338 | 0 | } |
339 | 0 | aScrollOffset = GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForHitTesting); |
340 | 0 | return ret; |
341 | 0 | } |
342 | | |
343 | 0 | void SetWaitForMainThread() { |
344 | 0 | mWaitForMainThread = true; |
345 | 0 | } |
346 | | |
347 | | private: |
348 | | bool mWaitForMainThread; |
349 | | MockContentControllerDelayed* mcc; |
350 | | }; |
351 | | |
352 | | class APZCTesterBase : public ::testing::Test { |
353 | | public: |
354 | 0 | APZCTesterBase() { |
355 | 0 | mcc = new NiceMock<MockContentControllerDelayed>(); |
356 | 0 | } |
357 | | |
358 | | enum class PanOptions { |
359 | | None = 0, |
360 | | KeepFingerDown = 0x1, |
361 | | /* |
362 | | * Do not adjust the touch-start coordinates to overcome the touch-start |
363 | | * tolerance threshold. If this option is passed, it's up to the caller |
364 | | * to pass in coordinates that are sufficient to overcome the touch-start |
365 | | * tolerance *and* cause the desired amount of scrolling. |
366 | | */ |
367 | | ExactCoordinates = 0x2, |
368 | | NoFling = 0x4 |
369 | | }; |
370 | | |
371 | | enum class PinchOptions { |
372 | | None = 0, |
373 | | LiftFinger1 = 0x1, |
374 | | LiftFinger2 = 0x2, |
375 | | /* |
376 | | * The bitwise OR result of (LiftFinger1 | LiftFinger2). |
377 | | * Defined explicitly here because it is used as the default |
378 | | * argument for PinchWithTouchInput which is defined BEFORE the |
379 | | * definition of operator| for this class. |
380 | | */ |
381 | | LiftBothFingers = 0x3 |
382 | | }; |
383 | | |
384 | | template<class InputReceiver> |
385 | | void Tap(const RefPtr<InputReceiver>& aTarget, const ScreenIntPoint& aPoint, |
386 | | TimeDuration aTapLength, |
387 | | nsEventStatus (*aOutEventStatuses)[2] = nullptr, |
388 | | uint64_t* aOutInputBlockId = nullptr); |
389 | | |
390 | | template<class InputReceiver> |
391 | | void TapAndCheckStatus(const RefPtr<InputReceiver>& aTarget, |
392 | | const ScreenIntPoint& aPoint, TimeDuration aTapLength); |
393 | | |
394 | | template<class InputReceiver> |
395 | | void Pan(const RefPtr<InputReceiver>& aTarget, |
396 | | const ScreenIntPoint& aTouchStart, |
397 | | const ScreenIntPoint& aTouchEnd, |
398 | | PanOptions aOptions = PanOptions::None, |
399 | | nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr, |
400 | | nsEventStatus (*aOutEventStatuses)[4] = nullptr, |
401 | | uint64_t* aOutInputBlockId = nullptr); |
402 | | |
403 | | /* |
404 | | * A version of Pan() that only takes y coordinates rather than (x, y) points |
405 | | * for the touch start and end points, and uses 10 for the x coordinates. |
406 | | * This is for convenience, as most tests only need to pan in one direction. |
407 | | */ |
408 | | template<class InputReceiver> |
409 | | void Pan(const RefPtr<InputReceiver>& aTarget, int aTouchStartY, |
410 | | int aTouchEndY, PanOptions aOptions = PanOptions::None, |
411 | | nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr, |
412 | | nsEventStatus (*aOutEventStatuses)[4] = nullptr, |
413 | | uint64_t* aOutInputBlockId = nullptr); |
414 | | |
415 | | /* |
416 | | * Dispatches mock touch events to the apzc and checks whether apzc properly |
417 | | * consumed them and triggered scrolling behavior. |
418 | | */ |
419 | | template<class InputReceiver> |
420 | | void PanAndCheckStatus(const RefPtr<InputReceiver>& aTarget, int aTouchStartY, |
421 | | int aTouchEndY, |
422 | | bool aExpectConsumed, |
423 | | nsTArray<uint32_t>* aAllowedTouchBehaviors, |
424 | | uint64_t* aOutInputBlockId = nullptr); |
425 | | |
426 | | template<class InputReceiver> |
427 | | void DoubleTap(const RefPtr<InputReceiver>& aTarget, |
428 | | const ScreenIntPoint& aPoint, |
429 | | nsEventStatus (*aOutEventStatuses)[4] = nullptr, |
430 | | uint64_t (*aOutInputBlockIds)[2] = nullptr); |
431 | | |
432 | | template<class InputReceiver> |
433 | | void DoubleTapAndCheckStatus(const RefPtr<InputReceiver>& aTarget, |
434 | | const ScreenIntPoint& aPoint, |
435 | | uint64_t (*aOutInputBlockIds)[2] = nullptr); |
436 | | |
437 | | template<class InputReceiver> |
438 | | void PinchWithTouchInput(const RefPtr<InputReceiver>& aTarget, |
439 | | const ScreenIntPoint& aFocus, const ScreenIntPoint& aSecondFocus, |
440 | | float aScale, |
441 | | int& inputId, |
442 | | nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr, |
443 | | nsEventStatus (*aOutEventStatuses)[4] = nullptr, |
444 | | uint64_t* aOutInputBlockId = nullptr, |
445 | | PinchOptions aOptions = PinchOptions::LiftBothFingers); |
446 | | |
447 | | // Pinch with one focus point. Zooms in place with no panning |
448 | | template<class InputReceiver> |
449 | | void PinchWithTouchInput(const RefPtr<InputReceiver>& aTarget, |
450 | | const ScreenIntPoint& aFocus, float aScale, |
451 | | int& inputId, |
452 | | nsTArray<uint32_t>* aAllowedTouchBehaviors = nullptr, |
453 | | nsEventStatus (*aOutEventStatuses)[4] = nullptr, |
454 | | uint64_t* aOutInputBlockId = nullptr, |
455 | | PinchOptions aOptions = PinchOptions::LiftBothFingers); |
456 | | |
457 | | template<class InputReceiver> |
458 | | void PinchWithTouchInputAndCheckStatus(const RefPtr<InputReceiver>& aTarget, |
459 | | const ScreenIntPoint& aFocus, float aScale, |
460 | | int& inputId, bool aShouldTriggerPinch, |
461 | | nsTArray<uint32_t>* aAllowedTouchBehaviors); |
462 | | |
463 | | protected: |
464 | | RefPtr<MockContentControllerDelayed> mcc; |
465 | | }; |
466 | | |
467 | | MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(APZCTesterBase::PanOptions) |
468 | | MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(APZCTesterBase::PinchOptions) |
469 | | |
470 | | template<class InputReceiver> |
471 | | void |
472 | | APZCTesterBase::Tap(const RefPtr<InputReceiver>& aTarget, |
473 | | const ScreenIntPoint& aPoint, TimeDuration aTapLength, |
474 | | nsEventStatus (*aOutEventStatuses)[2], |
475 | | uint64_t* aOutInputBlockId) |
476 | 0 | { |
477 | 0 | // Even if the caller doesn't care about the block id, we need it to set the |
478 | 0 | // allowed touch behaviour below, so make sure aOutInputBlockId is non-null. |
479 | 0 | uint64_t blockId; |
480 | 0 | if (!aOutInputBlockId) { |
481 | 0 | aOutInputBlockId = &blockId; |
482 | 0 | } |
483 | 0 |
|
484 | 0 | nsEventStatus status = TouchDown(aTarget, aPoint, mcc->Time(), aOutInputBlockId); |
485 | 0 | if (aOutEventStatuses) { |
486 | 0 | (*aOutEventStatuses)[0] = status; |
487 | 0 | } |
488 | 0 | mcc->AdvanceBy(aTapLength); |
489 | 0 |
|
490 | 0 | // If touch-action is enabled then simulate the allowed touch behaviour |
491 | 0 | // notification that the main thread is supposed to deliver. |
492 | 0 | if (gfxPrefs::TouchActionEnabled() && status != nsEventStatus_eConsumeNoDefault) { |
493 | 0 | SetDefaultAllowedTouchBehavior(aTarget, *aOutInputBlockId); |
494 | 0 | } |
495 | 0 |
|
496 | 0 | status = TouchUp(aTarget, aPoint, mcc->Time()); |
497 | 0 | if (aOutEventStatuses) { |
498 | 0 | (*aOutEventStatuses)[1] = status; |
499 | 0 | } |
500 | 0 | } Unexecuted instantiation: void APZCTesterBase::Tap<TestAPZCTreeManager>(RefPtr<TestAPZCTreeManager> const&, mozilla::gfx::IntPointTyped<mozilla::ScreenPixel> const&, mozilla::BaseTimeDuration<mozilla::TimeDurationValueCalculator>, nsEventStatus (*) [2], unsigned long*) Unexecuted instantiation: void APZCTesterBase::Tap<TestAsyncPanZoomController>(RefPtr<TestAsyncPanZoomController> const&, mozilla::gfx::IntPointTyped<mozilla::ScreenPixel> const&, mozilla::BaseTimeDuration<mozilla::TimeDurationValueCalculator>, nsEventStatus (*) [2], unsigned long*) |
501 | | |
502 | | template<class InputReceiver> |
503 | | void |
504 | | APZCTesterBase::TapAndCheckStatus(const RefPtr<InputReceiver>& aTarget, |
505 | | const ScreenIntPoint& aPoint, |
506 | | TimeDuration aTapLength) |
507 | 0 | { |
508 | 0 | nsEventStatus statuses[2]; |
509 | 0 | Tap(aTarget, aPoint, aTapLength, &statuses); |
510 | 0 | EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[0]); |
511 | 0 | EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[1]); |
512 | 0 | } |
513 | | |
514 | | template<class InputReceiver> |
515 | | void |
516 | | APZCTesterBase::Pan(const RefPtr<InputReceiver>& aTarget, |
517 | | const ScreenIntPoint& aTouchStart, |
518 | | const ScreenIntPoint& aTouchEnd, |
519 | | PanOptions aOptions, |
520 | | nsTArray<uint32_t>* aAllowedTouchBehaviors, |
521 | | nsEventStatus (*aOutEventStatuses)[4], |
522 | | uint64_t* aOutInputBlockId) |
523 | 0 | { |
524 | 0 | // Reduce the touch start and move tolerance to a tiny value. |
525 | 0 | // We can't use a scoped pref because this value might be read at some later |
526 | 0 | // time when the events are actually processed, rather than when we deliver |
527 | 0 | // them. |
528 | 0 | gfxPrefs::SetAPZTouchStartTolerance(1.0f / 1000.0f); |
529 | 0 | gfxPrefs::SetAPZTouchMoveTolerance(0.0f); |
530 | 0 | int overcomeTouchToleranceX = 0; |
531 | 0 | int overcomeTouchToleranceY = 0; |
532 | 0 | if (!(aOptions & PanOptions::ExactCoordinates)) { |
533 | 0 | // Have the direction of the adjustment to overcome the touch tolerance |
534 | 0 | // match the direction of the entire gesture, otherwise we run into |
535 | 0 | // trouble such as accidentally activating the axis lock. |
536 | 0 | if (aTouchStart.x != aTouchEnd.x) { |
537 | 0 | overcomeTouchToleranceX = 1; |
538 | 0 | } |
539 | 0 | if (aTouchStart.y != aTouchEnd.y) { |
540 | 0 | overcomeTouchToleranceY = 1; |
541 | 0 | } |
542 | 0 | } |
543 | 0 |
|
544 | 0 | const TimeDuration TIME_BETWEEN_TOUCH_EVENT = TimeDuration::FromMilliseconds(50); |
545 | 0 |
|
546 | 0 | // Even if the caller doesn't care about the block id, we need it to set the |
547 | 0 | // allowed touch behaviour below, so make sure aOutInputBlockId is non-null. |
548 | 0 | uint64_t blockId; |
549 | 0 | if (!aOutInputBlockId) { |
550 | 0 | aOutInputBlockId = &blockId; |
551 | 0 | } |
552 | 0 |
|
553 | 0 | // Make sure the move is large enough to not be handled as a tap |
554 | 0 | nsEventStatus status = TouchDown(aTarget, |
555 | 0 | ScreenIntPoint(aTouchStart.x + overcomeTouchToleranceX, |
556 | 0 | aTouchStart.y + overcomeTouchToleranceY), |
557 | 0 | mcc->Time(), aOutInputBlockId); |
558 | 0 | if (aOutEventStatuses) { |
559 | 0 | (*aOutEventStatuses)[0] = status; |
560 | 0 | } |
561 | 0 |
|
562 | 0 | mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT); |
563 | 0 |
|
564 | 0 | // Allowed touch behaviours must be set after sending touch-start. |
565 | 0 | if (status != nsEventStatus_eConsumeNoDefault) { |
566 | 0 | if (aAllowedTouchBehaviors) { |
567 | 0 | EXPECT_EQ(1UL, aAllowedTouchBehaviors->Length()); |
568 | 0 | aTarget->SetAllowedTouchBehavior(*aOutInputBlockId, *aAllowedTouchBehaviors); |
569 | 0 | } else if (gfxPrefs::TouchActionEnabled()) { |
570 | 0 | SetDefaultAllowedTouchBehavior(aTarget, *aOutInputBlockId); |
571 | 0 | } |
572 | 0 | } |
573 | 0 |
|
574 | 0 | status = TouchMove(aTarget, aTouchStart, mcc->Time()); |
575 | 0 | if (aOutEventStatuses) { |
576 | 0 | (*aOutEventStatuses)[1] = status; |
577 | 0 | } |
578 | 0 |
|
579 | 0 | mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT); |
580 | 0 |
|
581 | 0 | status = TouchMove(aTarget, aTouchEnd, mcc->Time()); |
582 | 0 | if (aOutEventStatuses) { |
583 | 0 | (*aOutEventStatuses)[2] = status; |
584 | 0 | } |
585 | 0 |
|
586 | 0 | mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT); |
587 | 0 |
|
588 | 0 | if (!(aOptions & PanOptions::KeepFingerDown)) { |
589 | 0 | status = TouchUp(aTarget, aTouchEnd, mcc->Time()); |
590 | 0 | } else { |
591 | 0 | status = nsEventStatus_eIgnore; |
592 | 0 | } |
593 | 0 | if (aOutEventStatuses) { |
594 | 0 | (*aOutEventStatuses)[3] = status; |
595 | 0 | } |
596 | 0 |
|
597 | 0 | if ((aOptions & PanOptions::NoFling)) { |
598 | 0 | aTarget->CancelAnimation(); |
599 | 0 | } |
600 | 0 |
|
601 | 0 | // Don't increment the time here. Animations started on touch-up, such as |
602 | 0 | // flings, are affected by elapsed time, and we want to be able to sample |
603 | 0 | // them immediately after they start, without time having elapsed. |
604 | 0 | } Unexecuted instantiation: void APZCTesterBase::Pan<TestAsyncPanZoomController>(RefPtr<TestAsyncPanZoomController> const&, mozilla::gfx::IntPointTyped<mozilla::ScreenPixel> const&, mozilla::gfx::IntPointTyped<mozilla::ScreenPixel> const&, APZCTesterBase::PanOptions, nsTArray<unsigned int>*, nsEventStatus (*) [4], unsigned long*) Unexecuted instantiation: void APZCTesterBase::Pan<TestAPZCTreeManager>(RefPtr<TestAPZCTreeManager> const&, mozilla::gfx::IntPointTyped<mozilla::ScreenPixel> const&, mozilla::gfx::IntPointTyped<mozilla::ScreenPixel> const&, APZCTesterBase::PanOptions, nsTArray<unsigned int>*, nsEventStatus (*) [4], unsigned long*) |
605 | | |
606 | | template<class InputReceiver> |
607 | | void |
608 | | APZCTesterBase::Pan(const RefPtr<InputReceiver>& aTarget, |
609 | | int aTouchStartY, int aTouchEndY, PanOptions aOptions, |
610 | | nsTArray<uint32_t>* aAllowedTouchBehaviors, |
611 | | nsEventStatus (*aOutEventStatuses)[4], |
612 | | uint64_t* aOutInputBlockId) |
613 | 0 | { |
614 | 0 | Pan(aTarget, ScreenIntPoint(10, aTouchStartY), ScreenIntPoint(10, aTouchEndY), |
615 | 0 | aOptions, aAllowedTouchBehaviors, aOutEventStatuses, aOutInputBlockId); |
616 | 0 | } Unexecuted instantiation: void APZCTesterBase::Pan<TestAsyncPanZoomController>(RefPtr<TestAsyncPanZoomController> const&, int, int, APZCTesterBase::PanOptions, nsTArray<unsigned int>*, nsEventStatus (*) [4], unsigned long*) Unexecuted instantiation: void APZCTesterBase::Pan<TestAPZCTreeManager>(RefPtr<TestAPZCTreeManager> const&, int, int, APZCTesterBase::PanOptions, nsTArray<unsigned int>*, nsEventStatus (*) [4], unsigned long*) |
617 | | |
618 | | template<class InputReceiver> |
619 | | void |
620 | | APZCTesterBase::PanAndCheckStatus(const RefPtr<InputReceiver>& aTarget, |
621 | | int aTouchStartY, |
622 | | int aTouchEndY, |
623 | | bool aExpectConsumed, |
624 | | nsTArray<uint32_t>* aAllowedTouchBehaviors, |
625 | | uint64_t* aOutInputBlockId) |
626 | 0 | { |
627 | 0 | nsEventStatus statuses[4]; // down, move, move, up |
628 | 0 | Pan(aTarget, aTouchStartY, aTouchEndY, PanOptions::None, aAllowedTouchBehaviors, &statuses, aOutInputBlockId); |
629 | 0 |
|
630 | 0 | EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[0]); |
631 | 0 |
|
632 | 0 | nsEventStatus touchMoveStatus; |
633 | 0 | if (aExpectConsumed) { |
634 | 0 | touchMoveStatus = nsEventStatus_eConsumeDoDefault; |
635 | 0 | } else { |
636 | 0 | touchMoveStatus = nsEventStatus_eIgnore; |
637 | 0 | } |
638 | 0 | EXPECT_EQ(touchMoveStatus, statuses[1]); |
639 | 0 | EXPECT_EQ(touchMoveStatus, statuses[2]); |
640 | 0 | } |
641 | | |
642 | | template<class InputReceiver> |
643 | | void |
644 | | APZCTesterBase::DoubleTap(const RefPtr<InputReceiver>& aTarget, |
645 | | const ScreenIntPoint& aPoint, |
646 | | nsEventStatus (*aOutEventStatuses)[4], |
647 | | uint64_t (*aOutInputBlockIds)[2]) |
648 | 0 | { |
649 | 0 | uint64_t blockId; |
650 | 0 | nsEventStatus status = TouchDown(aTarget, aPoint, mcc->Time(), &blockId); |
651 | 0 | if (aOutEventStatuses) { |
652 | 0 | (*aOutEventStatuses)[0] = status; |
653 | 0 | } |
654 | 0 | if (aOutInputBlockIds) { |
655 | 0 | (*aOutInputBlockIds)[0] = blockId; |
656 | 0 | } |
657 | 0 | mcc->AdvanceByMillis(10); |
658 | 0 |
|
659 | 0 | // If touch-action is enabled then simulate the allowed touch behaviour |
660 | 0 | // notification that the main thread is supposed to deliver. |
661 | 0 | if (gfxPrefs::TouchActionEnabled() && status != nsEventStatus_eConsumeNoDefault) { |
662 | 0 | SetDefaultAllowedTouchBehavior(aTarget, blockId); |
663 | 0 | } |
664 | 0 |
|
665 | 0 | status = TouchUp(aTarget, aPoint, mcc->Time()); |
666 | 0 | if (aOutEventStatuses) { |
667 | 0 | (*aOutEventStatuses)[1] = status; |
668 | 0 | } |
669 | 0 | mcc->AdvanceByMillis(10); |
670 | 0 | status = TouchDown(aTarget, aPoint, mcc->Time(), &blockId); |
671 | 0 | if (aOutEventStatuses) { |
672 | 0 | (*aOutEventStatuses)[2] = status; |
673 | 0 | } |
674 | 0 | if (aOutInputBlockIds) { |
675 | 0 | (*aOutInputBlockIds)[1] = blockId; |
676 | 0 | } |
677 | 0 | mcc->AdvanceByMillis(10); |
678 | 0 |
|
679 | 0 | if (gfxPrefs::TouchActionEnabled() && status != nsEventStatus_eConsumeNoDefault) { |
680 | 0 | SetDefaultAllowedTouchBehavior(aTarget, blockId); |
681 | 0 | } |
682 | 0 |
|
683 | 0 | status = TouchUp(aTarget, aPoint, mcc->Time()); |
684 | 0 | if (aOutEventStatuses) { |
685 | 0 | (*aOutEventStatuses)[3] = status; |
686 | 0 | } |
687 | 0 | } |
688 | | |
689 | | template<class InputReceiver> |
690 | | void |
691 | | APZCTesterBase::DoubleTapAndCheckStatus(const RefPtr<InputReceiver>& aTarget, |
692 | | const ScreenIntPoint& aPoint, |
693 | | uint64_t (*aOutInputBlockIds)[2]) |
694 | 0 | { |
695 | 0 | nsEventStatus statuses[4]; |
696 | 0 | DoubleTap(aTarget, aPoint, &statuses, aOutInputBlockIds); |
697 | 0 | EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[0]); |
698 | 0 | EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[1]); |
699 | 0 | EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[2]); |
700 | 0 | EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[3]); |
701 | 0 | } |
702 | | |
703 | | template<class InputReceiver> |
704 | | void |
705 | | APZCTesterBase::PinchWithTouchInput(const RefPtr<InputReceiver>& aTarget, |
706 | | const ScreenIntPoint& aFocus, float aScale, |
707 | | int& inputId, |
708 | | nsTArray<uint32_t>* aAllowedTouchBehaviors, |
709 | | nsEventStatus (*aOutEventStatuses)[4], |
710 | | uint64_t* aOutInputBlockId, |
711 | | PinchOptions aOptions) |
712 | 0 | { |
713 | 0 | //Perform a pinch gesture with the same start & end focus point |
714 | 0 | PinchWithTouchInput(aTarget, aFocus, aFocus, aScale, inputId, |
715 | 0 | aAllowedTouchBehaviors, aOutEventStatuses, |
716 | 0 | aOutInputBlockId, aOptions); |
717 | 0 | } |
718 | | |
719 | | template<class InputReceiver> |
720 | | void |
721 | | APZCTesterBase::PinchWithTouchInput(const RefPtr<InputReceiver>& aTarget, |
722 | | const ScreenIntPoint& aFocus, const ScreenIntPoint& aSecondFocus, |
723 | | float aScale, |
724 | | int& inputId, |
725 | | nsTArray<uint32_t>* aAllowedTouchBehaviors, |
726 | | nsEventStatus (*aOutEventStatuses)[4], |
727 | | uint64_t* aOutInputBlockId, |
728 | | PinchOptions aOptions) |
729 | 0 | { |
730 | 0 | // Having pinch coordinates in float type may cause problems with high-precision scale values |
731 | 0 | // since SingleTouchData accepts integer value. But for trivial tests it should be ok. |
732 | 0 | float pinchLength = 100.0; |
733 | 0 | float pinchLengthScaled = pinchLength * aScale; |
734 | 0 |
|
735 | 0 | // Even if the caller doesn't care about the block id, we need it to set the |
736 | 0 | // allowed touch behaviour below, so make sure aOutInputBlockId is non-null. |
737 | 0 | uint64_t blockId; |
738 | 0 | if (!aOutInputBlockId) { |
739 | 0 | aOutInputBlockId = &blockId; |
740 | 0 | } |
741 | 0 |
|
742 | 0 | const TimeDuration TIME_BETWEEN_TOUCH_EVENT = TimeDuration::FromMilliseconds(50); |
743 | 0 |
|
744 | 0 | MultiTouchInput mtiStart = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, 0, mcc->Time(), 0); |
745 | 0 | mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocus)); |
746 | 0 | mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocus)); |
747 | 0 | nsEventStatus status = aTarget->ReceiveInputEvent(mtiStart, aOutInputBlockId); |
748 | 0 | if (aOutEventStatuses) { |
749 | 0 | (*aOutEventStatuses)[0] = status; |
750 | 0 | } |
751 | 0 |
|
752 | 0 | mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT); |
753 | 0 |
|
754 | 0 | if (aAllowedTouchBehaviors) { |
755 | 0 | EXPECT_EQ(2UL, aAllowedTouchBehaviors->Length()); |
756 | 0 | aTarget->SetAllowedTouchBehavior(*aOutInputBlockId, *aAllowedTouchBehaviors); |
757 | 0 | } else if (gfxPrefs::TouchActionEnabled()) { |
758 | 0 | SetDefaultAllowedTouchBehavior(aTarget, *aOutInputBlockId, 2); |
759 | 0 | } |
760 | 0 |
|
761 | 0 | MultiTouchInput mtiMove1 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, mcc->Time(), 0); |
762 | 0 | mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocus.x - pinchLength, aFocus.y)); |
763 | 0 | mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocus.x + pinchLength, aFocus.y)); |
764 | 0 | status = aTarget->ReceiveInputEvent(mtiMove1, nullptr); |
765 | 0 | if (aOutEventStatuses) { |
766 | 0 | (*aOutEventStatuses)[1] = status; |
767 | 0 | } |
768 | 0 |
|
769 | 0 | mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT); |
770 | 0 |
|
771 | 0 | MultiTouchInput mtiMove2 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, mcc->Time(), 0); |
772 | 0 | mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId, aSecondFocus.x - pinchLengthScaled, aSecondFocus.y)); |
773 | 0 | mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aSecondFocus.x + pinchLengthScaled, aSecondFocus.y)); |
774 | 0 | status = aTarget->ReceiveInputEvent(mtiMove2, nullptr); |
775 | 0 | if (aOutEventStatuses) { |
776 | 0 | (*aOutEventStatuses)[2] = status; |
777 | 0 | } |
778 | 0 |
|
779 | 0 | if (aOptions & (PinchOptions::LiftFinger1 | PinchOptions::LiftFinger2)) { |
780 | 0 | mcc->AdvanceBy(TIME_BETWEEN_TOUCH_EVENT); |
781 | 0 |
|
782 | 0 | MultiTouchInput mtiEnd = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, 0, mcc->Time(), 0); |
783 | 0 | if (aOptions & PinchOptions::LiftFinger1) { |
784 | 0 | mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId, aSecondFocus.x - pinchLengthScaled, aSecondFocus.y)); |
785 | 0 | } |
786 | 0 | if (aOptions & PinchOptions::LiftFinger2) { |
787 | 0 | mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aSecondFocus.x + pinchLengthScaled, aSecondFocus.y)); |
788 | 0 | } |
789 | 0 | status = aTarget->ReceiveInputEvent(mtiEnd, nullptr); |
790 | 0 | if (aOutEventStatuses) { |
791 | 0 | (*aOutEventStatuses)[3] = status; |
792 | 0 | } |
793 | 0 | } |
794 | 0 |
|
795 | 0 | inputId += 2; |
796 | 0 | } |
797 | | |
798 | | template<class InputReceiver> |
799 | | void |
800 | | APZCTesterBase::PinchWithTouchInputAndCheckStatus(const RefPtr<InputReceiver>& aTarget, |
801 | | const ScreenIntPoint& aFocus, float aScale, |
802 | | int& inputId, bool aShouldTriggerPinch, |
803 | | nsTArray<uint32_t>* aAllowedTouchBehaviors) |
804 | 0 | { |
805 | 0 | nsEventStatus statuses[4]; // down, move, move, up |
806 | 0 | PinchWithTouchInput(aTarget, aFocus, aScale, inputId, aAllowedTouchBehaviors, &statuses); |
807 | 0 |
|
808 | 0 | nsEventStatus expectedMoveStatus = aShouldTriggerPinch |
809 | 0 | ? nsEventStatus_eConsumeDoDefault |
810 | 0 | : nsEventStatus_eIgnore; |
811 | 0 | EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[0]); |
812 | 0 | EXPECT_EQ(expectedMoveStatus, statuses[1]); |
813 | 0 | EXPECT_EQ(expectedMoveStatus, statuses[2]); |
814 | 0 | } |
815 | | |
816 | | AsyncPanZoomController* |
817 | | TestAPZCTreeManager::NewAPZCInstance(LayersId aLayersId, |
818 | | GeckoContentController* aController) |
819 | 0 | { |
820 | 0 | MockContentControllerDelayed* mcc = static_cast<MockContentControllerDelayed*>(aController); |
821 | 0 | return new TestAsyncPanZoomController(aLayersId, mcc, this, |
822 | 0 | AsyncPanZoomController::USE_GESTURE_DETECTOR); |
823 | 0 | } |
824 | | |
825 | | FrameMetrics |
826 | | TestFrameMetrics() |
827 | 0 | { |
828 | 0 | FrameMetrics fm; |
829 | 0 |
|
830 | 0 | fm.SetDisplayPort(CSSRect(0, 0, 10, 10)); |
831 | 0 | fm.SetCompositionBounds(ParentLayerRect(0, 0, 10, 10)); |
832 | 0 | fm.SetCriticalDisplayPort(CSSRect(0, 0, 10, 10)); |
833 | 0 | fm.SetScrollableRect(CSSRect(0, 0, 100, 100)); |
834 | 0 |
|
835 | 0 | return fm; |
836 | 0 | } |
837 | | |
838 | | uint32_t |
839 | | MillisecondsSinceStartup(TimeStamp aTime) |
840 | 0 | { |
841 | 0 | return (aTime - GetStartupTime()).ToMilliseconds(); |
842 | 0 | } |
843 | | |
844 | | #endif // mozilla_layers_APZTestCommon_h |