/src/mozilla-central/gfx/layers/apz/test/gtest/TestPinching.cpp
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 | | #include "APZCBasicTester.h" |
8 | | #include "APZTestCommon.h" |
9 | | #include "InputUtils.h" |
10 | | |
11 | | class APZCPinchTester : public APZCBasicTester { |
12 | | public: |
13 | | explicit APZCPinchTester(AsyncPanZoomController::GestureBehavior aGestureBehavior = AsyncPanZoomController::DEFAULT_GESTURES) |
14 | | : APZCBasicTester(aGestureBehavior) |
15 | 0 | { |
16 | 0 | } |
17 | | |
18 | | protected: |
19 | | FrameMetrics GetPinchableFrameMetrics() |
20 | 0 | { |
21 | 0 | FrameMetrics fm; |
22 | 0 | fm.SetCompositionBounds(ParentLayerRect(0, 0, 100, 200)); |
23 | 0 | fm.SetScrollableRect(CSSRect(0, 0, 980, 1000)); |
24 | 0 | fm.SetScrollOffset(CSSPoint(300, 300)); |
25 | 0 | fm.SetViewport(CSSRect(300, 300, 100, 200)); |
26 | 0 | fm.SetZoom(CSSToParentLayerScale2D(2.0, 2.0)); |
27 | 0 | // APZC only allows zooming on the root scrollable frame. |
28 | 0 | fm.SetIsRootContent(true); |
29 | 0 | // the visible area of the document in CSS pixels is x=300 y=300 w=50 h=100 |
30 | 0 | return fm; |
31 | 0 | } |
32 | | |
33 | | void DoPinchTest(bool aShouldTriggerPinch, |
34 | | nsTArray<uint32_t> *aAllowedTouchBehaviors = nullptr) |
35 | 0 | { |
36 | 0 | apzc->SetFrameMetrics(GetPinchableFrameMetrics()); |
37 | 0 | MakeApzcZoomable(); |
38 | 0 |
|
39 | 0 | if (aShouldTriggerPinch) { |
40 | 0 | // One repaint request for each gesture. |
41 | 0 | EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(2); |
42 | 0 | } else { |
43 | 0 | EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0); |
44 | 0 | } |
45 | 0 |
|
46 | 0 | int touchInputId = 0; |
47 | 0 | if (mGestureBehavior == AsyncPanZoomController::USE_GESTURE_DETECTOR) { |
48 | 0 | PinchWithTouchInputAndCheckStatus(apzc, ScreenIntPoint(250, 300), 1.25, |
49 | 0 | touchInputId, aShouldTriggerPinch, aAllowedTouchBehaviors); |
50 | 0 | } else { |
51 | 0 | PinchWithPinchInputAndCheckStatus(apzc, ScreenIntPoint(250, 300), 1.25, |
52 | 0 | aShouldTriggerPinch); |
53 | 0 | } |
54 | 0 |
|
55 | 0 | apzc->AssertStateIsReset(); |
56 | 0 |
|
57 | 0 | FrameMetrics fm = apzc->GetFrameMetrics(); |
58 | 0 |
|
59 | 0 | if (aShouldTriggerPinch) { |
60 | 0 | // the visible area of the document in CSS pixels is now x=325 y=330 w=40 h=80 |
61 | 0 | EXPECT_EQ(2.5f, fm.GetZoom().ToScaleFactor().scale); |
62 | 0 | EXPECT_EQ(325, fm.GetScrollOffset().x); |
63 | 0 | EXPECT_EQ(330, fm.GetScrollOffset().y); |
64 | 0 | } else { |
65 | 0 | // The frame metrics should stay the same since touch-action:none makes |
66 | 0 | // apzc ignore pinch gestures. |
67 | 0 | EXPECT_EQ(2.0f, fm.GetZoom().ToScaleFactor().scale); |
68 | 0 | EXPECT_EQ(300, fm.GetScrollOffset().x); |
69 | 0 | EXPECT_EQ(300, fm.GetScrollOffset().y); |
70 | 0 | } |
71 | 0 |
|
72 | 0 | // part 2 of the test, move to the top-right corner of the page and pinch and |
73 | 0 | // make sure we stay in the correct spot |
74 | 0 | fm.SetZoom(CSSToParentLayerScale2D(2.0, 2.0)); |
75 | 0 | fm.SetScrollOffset(CSSPoint(930, 5)); |
76 | 0 | apzc->SetFrameMetrics(fm); |
77 | 0 | // the visible area of the document in CSS pixels is x=930 y=5 w=50 h=100 |
78 | 0 |
|
79 | 0 | if (mGestureBehavior == AsyncPanZoomController::USE_GESTURE_DETECTOR) { |
80 | 0 | PinchWithTouchInputAndCheckStatus(apzc, ScreenIntPoint(250, 300), 0.5, |
81 | 0 | touchInputId, aShouldTriggerPinch, aAllowedTouchBehaviors); |
82 | 0 | } else { |
83 | 0 | PinchWithPinchInputAndCheckStatus(apzc, ScreenIntPoint(250, 300), 0.5, |
84 | 0 | aShouldTriggerPinch); |
85 | 0 | } |
86 | 0 |
|
87 | 0 | apzc->AssertStateIsReset(); |
88 | 0 |
|
89 | 0 | fm = apzc->GetFrameMetrics(); |
90 | 0 |
|
91 | 0 | if (aShouldTriggerPinch) { |
92 | 0 | // the visible area of the document in CSS pixels is now x=805 y=0 w=100 h=200 |
93 | 0 | EXPECT_EQ(1.0f, fm.GetZoom().ToScaleFactor().scale); |
94 | 0 | EXPECT_EQ(805, fm.GetScrollOffset().x); |
95 | 0 | EXPECT_EQ(0, fm.GetScrollOffset().y); |
96 | 0 | } else { |
97 | 0 | EXPECT_EQ(2.0f, fm.GetZoom().ToScaleFactor().scale); |
98 | 0 | EXPECT_EQ(930, fm.GetScrollOffset().x); |
99 | 0 | EXPECT_EQ(5, fm.GetScrollOffset().y); |
100 | 0 | } |
101 | 0 | } |
102 | | }; |
103 | | |
104 | | class APZCPinchGestureDetectorTester : public APZCPinchTester { |
105 | | public: |
106 | | APZCPinchGestureDetectorTester() |
107 | | : APZCPinchTester(AsyncPanZoomController::USE_GESTURE_DETECTOR) |
108 | 0 | { |
109 | 0 | } |
110 | | |
111 | 0 | void DoPinchWithPreventDefaultTest() { |
112 | 0 | FrameMetrics originalMetrics = GetPinchableFrameMetrics(); |
113 | 0 | apzc->SetFrameMetrics(originalMetrics); |
114 | 0 |
|
115 | 0 | MakeApzcWaitForMainThread(); |
116 | 0 | MakeApzcZoomable(); |
117 | 0 |
|
118 | 0 | int touchInputId = 0; |
119 | 0 | uint64_t blockId = 0; |
120 | 0 | PinchWithTouchInput(apzc, ScreenIntPoint(250, 300), 1.25, touchInputId, |
121 | 0 | nullptr, nullptr, &blockId); |
122 | 0 |
|
123 | 0 | // Send the prevent-default notification for the touch block |
124 | 0 | apzc->ContentReceivedInputBlock(blockId, true); |
125 | 0 |
|
126 | 0 | // verify the metrics didn't change (i.e. the pinch was ignored) |
127 | 0 | FrameMetrics fm = apzc->GetFrameMetrics(); |
128 | 0 | EXPECT_EQ(originalMetrics.GetZoom(), fm.GetZoom()); |
129 | 0 | EXPECT_EQ(originalMetrics.GetScrollOffset().x, fm.GetScrollOffset().x); |
130 | 0 | EXPECT_EQ(originalMetrics.GetScrollOffset().y, fm.GetScrollOffset().y); |
131 | 0 |
|
132 | 0 | apzc->AssertStateIsReset(); |
133 | 0 | } |
134 | | }; |
135 | | |
136 | | class APZCPinchLockingTester : public APZCPinchTester { |
137 | | private: |
138 | | static const int mDPI = 160; |
139 | | |
140 | | ScreenIntPoint mFocus; |
141 | | float mSpan; |
142 | | |
143 | | public: |
144 | | APZCPinchLockingTester() |
145 | | : APZCPinchTester(AsyncPanZoomController::USE_GESTURE_DETECTOR) |
146 | | , mFocus(ScreenIntPoint(200, 300)) |
147 | | , mSpan(10.0) |
148 | 0 | { |
149 | 0 | } |
150 | | |
151 | 0 | virtual void SetUp() { |
152 | 0 | APZCPinchTester::SetUp(); |
153 | 0 | tm->SetDPI(mDPI); |
154 | 0 | apzc->SetFrameMetrics(GetPinchableFrameMetrics()); |
155 | 0 | MakeApzcZoomable(); |
156 | 0 |
|
157 | 0 | apzc->ReceiveInputEvent( |
158 | 0 | CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_START, |
159 | 0 | mFocus, mSpan, mSpan), |
160 | 0 | nullptr); |
161 | 0 | } |
162 | | |
163 | 0 | void twoFingerPan() { |
164 | 0 | ScreenCoord panDistance |
165 | 0 | = gfxPrefs::APZPinchLockScrollLockThreshold() * 1.2 * tm->GetDPI(); |
166 | 0 |
|
167 | 0 | mFocus = ScreenIntPoint( |
168 | 0 | (int) (mFocus.x + panDistance), |
169 | 0 | (int) (mFocus.y) |
170 | 0 | ); |
171 | 0 |
|
172 | 0 | apzc->ReceiveInputEvent( |
173 | 0 | CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_SCALE, |
174 | 0 | mFocus, mSpan, mSpan), |
175 | 0 | nullptr); |
176 | 0 | } |
177 | | |
178 | 0 | void twoFingerZoom() { |
179 | 0 | float pinchDistance |
180 | 0 | = gfxPrefs::APZPinchLockSpanBreakoutThreshold() * 1.2 * tm->GetDPI(); |
181 | 0 |
|
182 | 0 | float newSpan = mSpan + pinchDistance; |
183 | 0 |
|
184 | 0 | apzc->ReceiveInputEvent( |
185 | 0 | CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_SCALE, |
186 | 0 | mFocus, newSpan, mSpan), |
187 | 0 | nullptr); |
188 | 0 | mSpan = newSpan; |
189 | 0 | } |
190 | | |
191 | 0 | bool isPinchLockActive() { |
192 | 0 | FrameMetrics originalMetrics = apzc->GetFrameMetrics(); |
193 | 0 |
|
194 | 0 | // Send a small scale input to the APZC |
195 | 0 | float pinchDistance |
196 | 0 | = gfxPrefs::APZPinchLockSpanBreakoutThreshold() * 0.8 * tm->GetDPI(); |
197 | 0 | apzc->ReceiveInputEvent( |
198 | 0 | CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_SCALE, |
199 | 0 | mFocus, mSpan + pinchDistance, mSpan), |
200 | 0 | nullptr); |
201 | 0 |
|
202 | 0 | FrameMetrics result = apzc->GetFrameMetrics(); |
203 | 0 | bool lockActive = originalMetrics.GetZoom() == result.GetZoom() |
204 | 0 | && originalMetrics.GetScrollOffset().x == result.GetScrollOffset().x |
205 | 0 | && originalMetrics.GetScrollOffset().y == result.GetScrollOffset().y; |
206 | 0 |
|
207 | 0 | // Avoid side effects, reset to original frame metrics |
208 | 0 | apzc->SetFrameMetrics(originalMetrics); |
209 | 0 | return lockActive; |
210 | 0 | } |
211 | | }; |
212 | | |
213 | 0 | TEST_F(APZCPinchTester, Pinch_DefaultGestures_NoTouchAction) { |
214 | 0 | SCOPED_GFX_PREF(TouchActionEnabled, bool, false); |
215 | 0 | DoPinchTest(true); |
216 | 0 | } |
217 | | |
218 | 0 | TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_NoTouchAction) { |
219 | 0 | SCOPED_GFX_PREF(TouchActionEnabled, bool, false); |
220 | 0 | DoPinchTest(true); |
221 | 0 | } |
222 | | |
223 | 0 | TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_TouchActionNone) { |
224 | 0 | SCOPED_GFX_PREF(TouchActionEnabled, bool, true); |
225 | 0 | nsTArray<uint32_t> behaviors = { mozilla::layers::AllowedTouchBehavior::NONE, |
226 | 0 | mozilla::layers::AllowedTouchBehavior::NONE }; |
227 | 0 | DoPinchTest(false, &behaviors); |
228 | 0 | } |
229 | | |
230 | 0 | TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_TouchActionZoom) { |
231 | 0 | SCOPED_GFX_PREF(TouchActionEnabled, bool, true); |
232 | 0 | nsTArray<uint32_t> behaviors; |
233 | 0 | behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM); |
234 | 0 | behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM); |
235 | 0 | DoPinchTest(true, &behaviors); |
236 | 0 | } |
237 | | |
238 | 0 | TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_TouchActionNotAllowZoom) { |
239 | 0 | SCOPED_GFX_PREF(TouchActionEnabled, bool, true); |
240 | 0 | nsTArray<uint32_t> behaviors; |
241 | 0 | behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN); |
242 | 0 | behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM); |
243 | 0 | DoPinchTest(false, &behaviors); |
244 | 0 | } |
245 | | |
246 | 0 | TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_TouchActionNone_NoAPZZoom) { |
247 | 0 | SCOPED_GFX_PREF(TouchActionEnabled, bool, true); |
248 | 0 | SCOPED_GFX_PREF(APZAllowZooming, bool, false); |
249 | 0 |
|
250 | 0 | // Since we are preventing the pinch action via touch-action we should not be |
251 | 0 | // sending the pinch gesture notifications that would normally be sent when |
252 | 0 | // APZAllowZooming is false. |
253 | 0 | EXPECT_CALL(*mcc, NotifyPinchGesture(_, _, _, _)).Times(0); |
254 | 0 | nsTArray<uint32_t> behaviors = { mozilla::layers::AllowedTouchBehavior::NONE, |
255 | 0 | mozilla::layers::AllowedTouchBehavior::NONE }; |
256 | 0 | DoPinchTest(false, &behaviors); |
257 | 0 | } |
258 | | |
259 | 0 | TEST_F(APZCPinchGestureDetectorTester, Pinch_PreventDefault) { |
260 | 0 | DoPinchWithPreventDefaultTest(); |
261 | 0 | } |
262 | | |
263 | 0 | TEST_F(APZCPinchGestureDetectorTester, Pinch_PreventDefault_NoAPZZoom) { |
264 | 0 | SCOPED_GFX_PREF(APZAllowZooming, bool, false); |
265 | 0 |
|
266 | 0 | // Since we are preventing the pinch action we should not be sending the pinch |
267 | 0 | // gesture notifications that would normally be sent when APZAllowZooming is |
268 | 0 | // false. |
269 | 0 | EXPECT_CALL(*mcc, NotifyPinchGesture(_, _, _, _)).Times(0); |
270 | 0 |
|
271 | 0 | DoPinchWithPreventDefaultTest(); |
272 | 0 | } |
273 | | |
274 | 0 | TEST_F(APZCPinchGestureDetectorTester, Panning_TwoFingerFling_ZoomDisabled) { |
275 | 0 | SCOPED_GFX_PREF(APZFlingMinVelocityThreshold, float, 0.0f); |
276 | 0 |
|
277 | 0 | apzc->SetFrameMetrics(GetPinchableFrameMetrics()); |
278 | 0 | MakeApzcUnzoomable(); |
279 | 0 |
|
280 | 0 | // Perform a two finger pan |
281 | 0 | int touchInputId = 0; |
282 | 0 | uint64_t blockId = 0; |
283 | 0 | PinchWithTouchInput(apzc, ScreenIntPoint(100, 200), ScreenIntPoint(100, 100), |
284 | 0 | 1, touchInputId, nullptr, nullptr, &blockId); |
285 | 0 |
|
286 | 0 | // Expect to be in a flinging state |
287 | 0 | apzc->AssertStateIsFling(); |
288 | 0 | } |
289 | | |
290 | 0 | TEST_F(APZCPinchGestureDetectorTester, Panning_TwoFingerFling_ZoomEnabled) { |
291 | 0 | SCOPED_GFX_PREF(APZFlingMinVelocityThreshold, float, 0.0f); |
292 | 0 |
|
293 | 0 | apzc->SetFrameMetrics(GetPinchableFrameMetrics()); |
294 | 0 | MakeApzcZoomable(); |
295 | 0 |
|
296 | 0 | // Perform a two finger pan |
297 | 0 | int touchInputId = 0; |
298 | 0 | uint64_t blockId = 0; |
299 | 0 | PinchWithTouchInput(apzc, ScreenIntPoint(100, 200), ScreenIntPoint(100, 100), |
300 | 0 | 1, touchInputId, nullptr, nullptr, &blockId); |
301 | 0 |
|
302 | 0 | // Expect to NOT be in flinging state |
303 | 0 | apzc->AssertStateIsReset(); |
304 | 0 | } |
305 | | |
306 | 0 | TEST_F(APZCPinchGestureDetectorTester, Panning_TwoThenOneFingerFling_ZoomEnabled) { |
307 | 0 | SCOPED_GFX_PREF(APZFlingMinVelocityThreshold, float, 0.0f); |
308 | 0 |
|
309 | 0 | apzc->SetFrameMetrics(GetPinchableFrameMetrics()); |
310 | 0 | MakeApzcZoomable(); |
311 | 0 |
|
312 | 0 | // Perform a two finger pan lifting only the first finger |
313 | 0 | int touchInputId = 0; |
314 | 0 | uint64_t blockId = 0; |
315 | 0 | PinchWithTouchInput(apzc, ScreenIntPoint(100, 200), ScreenIntPoint(100, 100), |
316 | 0 | 1, touchInputId, nullptr, nullptr, &blockId, PinchOptions::LiftFinger2); |
317 | 0 |
|
318 | 0 | // Lift second finger after a pause |
319 | 0 | mcc->AdvanceBy(TimeDuration::FromMilliseconds(50)); |
320 | 0 | TouchUp(apzc, ScreenIntPoint(100, 100), mcc->Time()); |
321 | 0 |
|
322 | 0 | // Expect to NOT be in flinging state |
323 | 0 | apzc->AssertStateIsReset(); |
324 | 0 | } |
325 | | |
326 | 0 | TEST_F(APZCPinchTester, Panning_TwoFinger_ZoomDisabled) { |
327 | 0 | // set up APZ |
328 | 0 | apzc->SetFrameMetrics(GetPinchableFrameMetrics()); |
329 | 0 | MakeApzcUnzoomable(); |
330 | 0 |
|
331 | 0 | nsEventStatus statuses[3]; // scalebegin, scale, scaleend |
332 | 0 | PinchWithPinchInput(apzc, ScreenIntPoint(250, 350), ScreenIntPoint(200, 300), |
333 | 0 | 10, &statuses); |
334 | 0 |
|
335 | 0 | FrameMetrics fm = apzc->GetFrameMetrics(); |
336 | 0 |
|
337 | 0 | // It starts from (300, 300), then moves the focus point from (250, 350) to |
338 | 0 | // (200, 300) pans by (50, 50) screen pixels, but there is a 2x zoom, which |
339 | 0 | // causes the scroll offset to change by half of that (25, 25) pixels. |
340 | 0 | EXPECT_EQ(325, fm.GetScrollOffset().x); |
341 | 0 | EXPECT_EQ(325, fm.GetScrollOffset().y); |
342 | 0 | EXPECT_EQ(2.0, fm.GetZoom().ToScaleFactor().scale); |
343 | 0 | } |
344 | | |
345 | 0 | TEST_F(APZCPinchTester, Panning_Beyond_LayoutViewport) { |
346 | 0 | apzc->SetFrameMetrics(GetPinchableFrameMetrics()); |
347 | 0 | MakeApzcZoomable(); |
348 | 0 |
|
349 | 0 | // Case 1 - visual viewport is still inside layout viewport. |
350 | 0 | Pan(apzc, 350, 300, PanOptions::NoFling); |
351 | 0 | FrameMetrics fm = apzc->GetFrameMetrics(); |
352 | 0 | // It starts from (300, 300) pans by (0, 50) screen pixels, but there is a |
353 | 0 | // 2x zoom, which causes the scroll offset to change by half of that (0, 25). |
354 | 0 | // But the visual viewport is still inside the layout viewport. |
355 | 0 | EXPECT_EQ(300, fm.GetScrollOffset().x); |
356 | 0 | EXPECT_EQ(325, fm.GetScrollOffset().y); |
357 | 0 | EXPECT_EQ(300, fm.GetViewport().X()); |
358 | 0 | EXPECT_EQ(300, fm.GetViewport().Y()); |
359 | 0 |
|
360 | 0 | // Case 2 - visual viewport crosses the bottom boundary of the layout |
361 | 0 | // viewport. |
362 | 0 | Pan(apzc, 525, 325, PanOptions::NoFling); |
363 | 0 | fm = apzc->GetFrameMetrics(); |
364 | 0 | // It starts from (300, 325) pans by (0, 200) screen pixels, but there is a |
365 | 0 | // 2x zoom, which causes the scroll offset to change by half of that |
366 | 0 | // (0, 100). The visual viewport crossed the bottom boundary of the layout |
367 | 0 | // viewport by 25px. |
368 | 0 | EXPECT_EQ(300, fm.GetScrollOffset().x); |
369 | 0 | EXPECT_EQ(425, fm.GetScrollOffset().y); |
370 | 0 | EXPECT_EQ(300, fm.GetViewport().X()); |
371 | 0 | EXPECT_EQ(325, fm.GetViewport().Y()); |
372 | 0 |
|
373 | 0 | // Case 3 - visual viewport crosses the top boundary of the layout viewport. |
374 | 0 | Pan(apzc, 425, 775, PanOptions::NoFling); |
375 | 0 | fm = apzc->GetFrameMetrics(); |
376 | 0 | // It starts from (300, 425) pans by (0, -350) screen pixels, but there is a |
377 | 0 | // 2x zoom, which causes the scroll offset to change by half of that |
378 | 0 | // (0, -175). The visual viewport crossed the top of the layout viewport by |
379 | 0 | // 75px. |
380 | 0 | EXPECT_EQ(300, fm.GetScrollOffset().x); |
381 | 0 | EXPECT_EQ(250, fm.GetScrollOffset().y); |
382 | 0 | EXPECT_EQ(300, fm.GetViewport().X()); |
383 | 0 | EXPECT_EQ(250, fm.GetViewport().Y()); |
384 | 0 |
|
385 | 0 | // Case 4 - visual viewport crosses the left boundary of the layout viewport. |
386 | 0 | Pan(apzc, ScreenIntPoint(150, 10), ScreenIntPoint(350, 10), PanOptions::NoFling); |
387 | 0 | fm = apzc->GetFrameMetrics(); |
388 | 0 | // It starts from (300, 250) pans by (-200, 0) screen pixels, but there is a |
389 | 0 | // 2x zoom, which causes the scroll offset to change by half of that |
390 | 0 | // (-100, 0). The visual viewport crossed the left boundary of the layout |
391 | 0 | // viewport by 100px. |
392 | 0 | EXPECT_EQ(200, fm.GetScrollOffset().x); |
393 | 0 | EXPECT_EQ(250, fm.GetScrollOffset().y); |
394 | 0 | EXPECT_EQ(200, fm.GetViewport().X()); |
395 | 0 | EXPECT_EQ(250, fm.GetViewport().Y()); |
396 | 0 |
|
397 | 0 | // Case 5 - visual viewport crosses the right boundary of the layout viewport. |
398 | 0 | Pan(apzc, ScreenIntPoint(350, 10), ScreenIntPoint(150, 10), PanOptions::NoFling); |
399 | 0 | fm = apzc->GetFrameMetrics(); |
400 | 0 | // It starts from (200, 250) pans by (200, 0) screen pixels, but there is a |
401 | 0 | // 2x zoom, which causes the scroll offset to change by half of that |
402 | 0 | // (100, 0). The visual viewport crossed the right boundary of the layout |
403 | 0 | // viewport by 50px. |
404 | 0 | EXPECT_EQ(300, fm.GetScrollOffset().x); |
405 | 0 | EXPECT_EQ(250, fm.GetScrollOffset().y); |
406 | 0 | EXPECT_EQ(250, fm.GetViewport().X()); |
407 | 0 | EXPECT_EQ(250, fm.GetViewport().Y()); |
408 | 0 |
|
409 | 0 | // Case 6 - visual viewport crosses both the vertical and horizontal |
410 | 0 | // boundaries of the layout viewport by moving diagonally towards the |
411 | 0 | // top-right corner. |
412 | 0 | Pan(apzc, ScreenIntPoint(350, 200), ScreenIntPoint(150, 400), PanOptions::NoFling); |
413 | 0 | fm = apzc->GetFrameMetrics(); |
414 | 0 | // It starts from (300, 250) pans by (200, -200) screen pixels, but there is |
415 | 0 | // a 2x zoom, which causes the scroll offset to change by half of that |
416 | 0 | // (100, -100). The visual viewport moved by (100, -100) outside the |
417 | 0 | // boundary of the layout viewport. |
418 | 0 | EXPECT_EQ(400, fm.GetScrollOffset().x); |
419 | 0 | EXPECT_EQ(150, fm.GetScrollOffset().y); |
420 | 0 | EXPECT_EQ(350, fm.GetViewport().X()); |
421 | 0 | EXPECT_EQ(150, fm.GetViewport().Y()); |
422 | 0 | } |
423 | | |
424 | 0 | TEST_F(APZCPinchGestureDetectorTester, Pinch_APZZoom_Disabled) { |
425 | 0 | SCOPED_GFX_PREF(APZAllowZooming, bool, false); |
426 | 0 |
|
427 | 0 | FrameMetrics originalMetrics = GetPinchableFrameMetrics(); |
428 | 0 | apzc->SetFrameMetrics(originalMetrics); |
429 | 0 |
|
430 | 0 | // When APZAllowZooming is false, the ZoomConstraintsClient produces |
431 | 0 | // ZoomConstraints with mAllowZoom set to false. |
432 | 0 | MakeApzcUnzoomable(); |
433 | 0 |
|
434 | 0 | // With APZAllowZooming false, we expect the NotifyPinchGesture function to |
435 | 0 | // get called as the pinch progresses, but the metrics shouldn't change. |
436 | 0 | EXPECT_CALL(*mcc, NotifyPinchGesture(PinchGestureInput::PINCHGESTURE_START, apzc->GetGuid(), LayoutDeviceCoord(0), _)).Times(1); |
437 | 0 | EXPECT_CALL(*mcc, NotifyPinchGesture(PinchGestureInput::PINCHGESTURE_SCALE, apzc->GetGuid(), _, _)).Times(AtLeast(1)); |
438 | 0 | EXPECT_CALL(*mcc, NotifyPinchGesture(PinchGestureInput::PINCHGESTURE_END, apzc->GetGuid(), LayoutDeviceCoord(0), _)).Times(1); |
439 | 0 |
|
440 | 0 | int touchInputId = 0; |
441 | 0 | uint64_t blockId = 0; |
442 | 0 | PinchWithTouchInput(apzc, ScreenIntPoint(250, 300), 1.25, touchInputId, |
443 | 0 | nullptr, nullptr, &blockId); |
444 | 0 |
|
445 | 0 | // verify the metrics didn't change (i.e. the pinch was ignored inside APZ) |
446 | 0 | FrameMetrics fm = apzc->GetFrameMetrics(); |
447 | 0 | EXPECT_EQ(originalMetrics.GetZoom(), fm.GetZoom()); |
448 | 0 | EXPECT_EQ(originalMetrics.GetScrollOffset().x, fm.GetScrollOffset().x); |
449 | 0 | EXPECT_EQ(originalMetrics.GetScrollOffset().y, fm.GetScrollOffset().y); |
450 | 0 |
|
451 | 0 | apzc->AssertStateIsReset(); |
452 | 0 | } |
453 | | |
454 | 0 | TEST_F(APZCPinchGestureDetectorTester, Pinch_NoSpan) { |
455 | 0 | SCOPED_GFX_PREF(APZAllowZooming, bool, false); |
456 | 0 | SCOPED_GFX_PREF(TouchActionEnabled, bool, false); |
457 | 0 |
|
458 | 0 | FrameMetrics originalMetrics = GetPinchableFrameMetrics(); |
459 | 0 | apzc->SetFrameMetrics(originalMetrics); |
460 | 0 |
|
461 | 0 | // When APZAllowZooming is false, the ZoomConstraintsClient produces |
462 | 0 | // ZoomConstraints with mAllowZoom set to false. |
463 | 0 | MakeApzcUnzoomable(); |
464 | 0 |
|
465 | 0 | // With APZAllowZooming false, we expect the NotifyPinchGesture function to |
466 | 0 | // get called as the pinch progresses, but the metrics shouldn't change. |
467 | 0 | EXPECT_CALL(*mcc, NotifyPinchGesture(PinchGestureInput::PINCHGESTURE_START, apzc->GetGuid(), LayoutDeviceCoord(0), _)).Times(1); |
468 | 0 | EXPECT_CALL(*mcc, NotifyPinchGesture(PinchGestureInput::PINCHGESTURE_SCALE, apzc->GetGuid(), _, _)).Times(AtLeast(1)); |
469 | 0 | EXPECT_CALL(*mcc, NotifyPinchGesture(PinchGestureInput::PINCHGESTURE_END, apzc->GetGuid(), LayoutDeviceCoord(0), _)).Times(1); |
470 | 0 |
|
471 | 0 | int inputId = 0; |
472 | 0 | ScreenIntPoint focus(250, 300); |
473 | 0 |
|
474 | 0 | // Do a pinch holding a zero span and moving the focus by y=100 |
475 | 0 |
|
476 | 0 | MultiTouchInput mtiStart = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0); |
477 | 0 | mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId, focus)); |
478 | 0 | mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, focus)); |
479 | 0 | apzc->ReceiveInputEvent(mtiStart, nullptr); |
480 | 0 |
|
481 | 0 | focus.y -= 35 + 1; // this is to get over the PINCH_START_THRESHOLD in GestureEventListener.cpp |
482 | 0 | MultiTouchInput mtiMove1 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0); |
483 | 0 | mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId, focus)); |
484 | 0 | mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, focus)); |
485 | 0 | apzc->ReceiveInputEvent(mtiMove1, nullptr); |
486 | 0 |
|
487 | 0 | focus.y -= 100; // do a two-finger scroll of 100 screen pixels |
488 | 0 | MultiTouchInput mtiMove2 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0); |
489 | 0 | mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId, focus)); |
490 | 0 | mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, focus)); |
491 | 0 | apzc->ReceiveInputEvent(mtiMove2, nullptr); |
492 | 0 |
|
493 | 0 | MultiTouchInput mtiEnd = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, 0, TimeStamp(), 0); |
494 | 0 | mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId, focus)); |
495 | 0 | mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, focus)); |
496 | 0 | apzc->ReceiveInputEvent(mtiEnd, nullptr); |
497 | 0 |
|
498 | 0 | // Done, check the metrics to make sure we scrolled by 100 screen pixels, |
499 | 0 | // which is 50 CSS pixels for the pinchable frame metrics. |
500 | 0 |
|
501 | 0 | FrameMetrics fm = apzc->GetFrameMetrics(); |
502 | 0 | EXPECT_EQ(originalMetrics.GetZoom(), fm.GetZoom()); |
503 | 0 | EXPECT_EQ(originalMetrics.GetScrollOffset().x, fm.GetScrollOffset().x); |
504 | 0 | EXPECT_EQ(originalMetrics.GetScrollOffset().y + 50, fm.GetScrollOffset().y); |
505 | 0 |
|
506 | 0 | apzc->AssertStateIsReset(); |
507 | 0 | } |
508 | | |
509 | 0 | TEST_F(APZCPinchTester, Pinch_TwoFinger_APZZoom_Disabled_Bug1354185) { |
510 | 0 | // Set up APZ such that mZoomConstraints.mAllowZoom is false. |
511 | 0 | SCOPED_GFX_PREF(APZAllowZooming, bool, false); |
512 | 0 | apzc->SetFrameMetrics(GetPinchableFrameMetrics()); |
513 | 0 | MakeApzcUnzoomable(); |
514 | 0 |
|
515 | 0 | // We expect a repaint request for scrolling. |
516 | 0 | EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); |
517 | 0 |
|
518 | 0 | // Send only the PINCHGESTURE_START and PINCHGESTURE_SCALE events, |
519 | 0 | // in order to trigger a call to AsyncPanZoomController::OnScale |
520 | 0 | // but not to AsyncPanZoomController::OnScaleEnd. |
521 | 0 | ScreenIntPoint aFocus(250, 350); |
522 | 0 | ScreenIntPoint aSecondFocus(200, 300); |
523 | 0 | float aScale = 10; |
524 | 0 | apzc->ReceiveInputEvent( |
525 | 0 | CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_START, |
526 | 0 | aFocus, 10.0, 10.0), |
527 | 0 | nullptr); |
528 | 0 |
|
529 | 0 | apzc->ReceiveInputEvent( |
530 | 0 | CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_SCALE, |
531 | 0 | aSecondFocus, 10.0 * aScale, 10.0), |
532 | 0 | nullptr); |
533 | 0 | } |
534 | | |
535 | 0 | TEST_F(APZCPinchLockingTester, Pinch_Locking_Free) { |
536 | 0 | SCOPED_GFX_PREF(APZPinchLockMode, int32_t, 0); // PINCH_FREE |
537 | 0 |
|
538 | 0 | twoFingerPan(); |
539 | 0 | EXPECT_FALSE(isPinchLockActive()); |
540 | 0 | } |
541 | | |
542 | 0 | TEST_F(APZCPinchLockingTester, Pinch_Locking_Normal_Lock) { |
543 | 0 | SCOPED_GFX_PREF(APZPinchLockMode, int32_t, 1); // PINCH_NORMAL |
544 | 0 |
|
545 | 0 | twoFingerPan(); |
546 | 0 | EXPECT_TRUE(isPinchLockActive()); |
547 | 0 | } |
548 | | |
549 | 0 | TEST_F(APZCPinchLockingTester, Pinch_Locking_Normal_Lock_Break) { |
550 | 0 | SCOPED_GFX_PREF(APZPinchLockMode, int32_t, 1); // PINCH_NORMAL |
551 | 0 |
|
552 | 0 | twoFingerPan(); |
553 | 0 | twoFingerZoom(); |
554 | 0 | EXPECT_TRUE(isPinchLockActive()); |
555 | 0 | } |
556 | | |
557 | 0 | TEST_F(APZCPinchLockingTester, Pinch_Locking_Sticky_Lock) { |
558 | 0 | SCOPED_GFX_PREF(APZPinchLockMode, int32_t, 2); // PINCH_STICKY |
559 | 0 |
|
560 | 0 | twoFingerPan(); |
561 | 0 | EXPECT_TRUE(isPinchLockActive()); |
562 | 0 | } |
563 | | |
564 | 0 | TEST_F(APZCPinchLockingTester, Pinch_Locking_Sticky_Lock_Break) { |
565 | 0 | SCOPED_GFX_PREF(APZPinchLockMode, int32_t, 2); // PINCH_STICKY |
566 | 0 |
|
567 | 0 | twoFingerPan(); |
568 | 0 | twoFingerZoom(); |
569 | 0 | EXPECT_FALSE(isPinchLockActive()); |
570 | 0 | } |
571 | | |
572 | 0 | TEST_F(APZCPinchLockingTester, Pinch_Locking_Sticky_Lock_Break_Lock) { |
573 | 0 | SCOPED_GFX_PREF(APZPinchLockMode, int32_t, 2); // PINCH_STICKY |
574 | 0 |
|
575 | 0 | twoFingerPan(); |
576 | 0 | twoFingerZoom(); |
577 | 0 | twoFingerPan(); |
578 | 0 | EXPECT_TRUE(isPinchLockActive()); |
579 | 0 | } |
580 | | |