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
10 #include "InputUtils.h"
11
12 static ScrollGenerationCounter sGenerationCounter;
13
TEST_F(APZCBasicTester,Overzoom)14 TEST_F(APZCBasicTester, Overzoom) {
15 // the visible area of the document in CSS pixels is x=10 y=0 w=100 h=100
16 FrameMetrics fm;
17 fm.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
18 fm.SetScrollableRect(CSSRect(0, 0, 125, 150));
19 fm.SetVisualScrollOffset(CSSPoint(10, 0));
20 fm.SetZoom(CSSToParentLayerScale(1.0));
21 fm.SetIsRootContent(true);
22 apzc->SetFrameMetrics(fm);
23
24 MakeApzcZoomable();
25
26 EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
27
28 PinchWithPinchInputAndCheckStatus(apzc, ScreenIntPoint(50, 50), 0.5, true);
29
30 fm = apzc->GetFrameMetrics();
31 EXPECT_EQ(0.8f, fm.GetZoom().scale);
32 // bug 936721 - PGO builds introduce rounding error so
33 // use a fuzzy match instead
34 EXPECT_LT(std::abs(fm.GetVisualScrollOffset().x), 1e-5);
35 EXPECT_LT(std::abs(fm.GetVisualScrollOffset().y), 1e-5);
36 }
37
TEST_F(APZCBasicTester,SimpleTransform)38 TEST_F(APZCBasicTester, SimpleTransform) {
39 ParentLayerPoint pointOut;
40 AsyncTransform viewTransformOut;
41 apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
42
43 EXPECT_EQ(ParentLayerPoint(), pointOut);
44 EXPECT_EQ(AsyncTransform(), viewTransformOut);
45 }
46
TEST_F(APZCBasicTester,ComplexTransform)47 TEST_F(APZCBasicTester, ComplexTransform) {
48 // This test assumes there is a page that gets rendered to
49 // two layers. In CSS pixels, the first layer is 50x50 and
50 // the second layer is 25x50. The widget scale factor is 3.0
51 // and the presShell resolution is 2.0. Therefore, these layers
52 // end up being 300x300 and 150x300 in layer pixels.
53 //
54 // The second (child) layer has an additional CSS transform that
55 // stretches it by 2.0 on the x-axis. Therefore, after applying
56 // CSS transforms, the two layers are the same size in screen
57 // pixels.
58 //
59 // The screen itself is 24x24 in screen pixels (therefore 4x4 in
60 // CSS pixels). The displayport is 1 extra CSS pixel on all
61 // sides.
62
63 RefPtr<TestAsyncPanZoomController> childApzc =
64 new TestAsyncPanZoomController(LayersId{0}, mcc, tm);
65
66 const char* treeShape = "x(x)";
67 // LayerID 0 1
68 nsIntRegion layerVisibleRegion[] = {
69 nsIntRegion(IntRect(0, 0, 300, 300)),
70 nsIntRegion(IntRect(0, 0, 150, 300)),
71 };
72 Matrix4x4 transforms[] = {
73 Matrix4x4(),
74 Matrix4x4(),
75 };
76 transforms[0].PostScale(
77 0.5f, 0.5f,
78 1.0f); // this results from the 2.0 resolution on the root layer
79 transforms[1].PostScale(
80 2.0f, 1.0f,
81 1.0f); // this is the 2.0 x-axis CSS transform on the child layer
82
83 auto layers = TestWRScrollData::Create(treeShape, *updater,
84 layerVisibleRegion, transforms);
85
86 ScrollMetadata metadata;
87 FrameMetrics& metrics = metadata.GetMetrics();
88 metrics.SetCompositionBounds(ParentLayerRect(0, 0, 24, 24));
89 metrics.SetDisplayPort(CSSRect(-1, -1, 6, 6));
90 metrics.SetVisualScrollOffset(CSSPoint(10, 10));
91 metrics.SetLayoutViewport(CSSRect(10, 10, 8, 8));
92 metrics.SetScrollableRect(CSSRect(0, 0, 50, 50));
93 metrics.SetCumulativeResolution(LayoutDeviceToLayerScale(2));
94 metrics.SetPresShellResolution(2.0f);
95 metrics.SetZoom(CSSToParentLayerScale(6));
96 metrics.SetDevPixelsPerCSSPixel(CSSToLayoutDeviceScale(3));
97 metrics.SetScrollId(ScrollableLayerGuid::START_SCROLL_ID);
98
99 ScrollMetadata childMetadata = metadata;
100 FrameMetrics& childMetrics = childMetadata.GetMetrics();
101 childMetrics.SetScrollId(ScrollableLayerGuid::START_SCROLL_ID + 1);
102
103 layers[0]->AppendScrollMetadata(layers, metadata);
104 layers[1]->AppendScrollMetadata(layers, childMetadata);
105
106 ParentLayerPoint pointOut;
107 AsyncTransform viewTransformOut;
108
109 // Both the parent and child layer should behave exactly the same here,
110 // because the CSS transform on the child layer does not affect the
111 // SampleContentTransformForFrame code
112
113 // initial transform
114 apzc->SetFrameMetrics(metrics);
115 apzc->NotifyLayersUpdated(metadata, true, true);
116 apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
117 EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint()),
118 viewTransformOut);
119 EXPECT_EQ(ParentLayerPoint(60, 60), pointOut);
120
121 childApzc->SetFrameMetrics(childMetrics);
122 childApzc->NotifyLayersUpdated(childMetadata, true, true);
123 childApzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
124 EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint()),
125 viewTransformOut);
126 EXPECT_EQ(ParentLayerPoint(60, 60), pointOut);
127
128 // do an async scroll by 5 pixels and check the transform
129 metrics.ScrollBy(CSSPoint(5, 0));
130 apzc->SetFrameMetrics(metrics);
131 apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
132 EXPECT_EQ(
133 AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)),
134 viewTransformOut);
135 EXPECT_EQ(ParentLayerPoint(90, 60), pointOut);
136
137 childMetrics.ScrollBy(CSSPoint(5, 0));
138 childApzc->SetFrameMetrics(childMetrics);
139 childApzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
140 EXPECT_EQ(
141 AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)),
142 viewTransformOut);
143 EXPECT_EQ(ParentLayerPoint(90, 60), pointOut);
144
145 // do an async zoom of 1.5x and check the transform
146 metrics.ZoomBy(1.5f);
147 apzc->SetFrameMetrics(metrics);
148 apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
149 EXPECT_EQ(
150 AsyncTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)),
151 viewTransformOut);
152 EXPECT_EQ(ParentLayerPoint(135, 90), pointOut);
153
154 childMetrics.ZoomBy(1.5f);
155 childApzc->SetFrameMetrics(childMetrics);
156 childApzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
157 EXPECT_EQ(
158 AsyncTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)),
159 viewTransformOut);
160 EXPECT_EQ(ParentLayerPoint(135, 90), pointOut);
161
162 childApzc->Destroy();
163 }
164
TEST_F(APZCBasicTester,Fling)165 TEST_F(APZCBasicTester, Fling) {
166 SCOPED_GFX_PREF_FLOAT("apz.fling_min_velocity_threshold", 0.0f);
167 int touchStart = 50;
168 int touchEnd = 10;
169 ParentLayerPoint pointOut;
170 AsyncTransform viewTransformOut;
171
172 // Fling down. Each step scroll further down
173 Pan(apzc, touchStart, touchEnd);
174 ParentLayerPoint lastPoint;
175 for (int i = 1; i < 50; i += 1) {
176 apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut,
177 TimeDuration::FromMilliseconds(1));
178 EXPECT_GT(pointOut.y, lastPoint.y);
179 lastPoint = pointOut;
180 }
181 }
182
183 #ifndef MOZ_WIDGET_ANDROID // Maybe fails on Android
TEST_F(APZCBasicTester,ResumeInterruptedTouchDrag_Bug1592435)184 TEST_F(APZCBasicTester, ResumeInterruptedTouchDrag_Bug1592435) {
185 // Start a touch-drag and scroll some amount, not lifting the finger.
186 SCOPED_GFX_PREF_FLOAT("apz.touch_start_tolerance", 1.0f / 1000.0f);
187 ScreenIntPoint touchPos(10, 50);
188 uint64_t touchBlock = TouchDown(apzc, touchPos, mcc->Time()).mInputBlockId;
189 SetDefaultAllowedTouchBehavior(apzc, touchBlock);
190 for (int i = 0; i < 20; ++i) {
191 touchPos.y -= 1;
192 mcc->AdvanceByMillis(1);
193 TouchMove(apzc, touchPos, mcc->Time());
194 }
195
196 // Take note of the scroll offset before the interruption.
197 CSSPoint scrollOffsetBeforeInterruption =
198 apzc->GetFrameMetrics().GetVisualScrollOffset();
199
200 // Have the main thread interrupt the touch-drag by sending
201 // a main thread scroll update to a nearby location.
202 CSSPoint mainThreadOffset = scrollOffsetBeforeInterruption;
203 mainThreadOffset.y -= 5;
204 ScrollMetadata metadata = apzc->GetScrollMetadata();
205 metadata.GetMetrics().SetLayoutScrollOffset(mainThreadOffset);
206 nsTArray<ScrollPositionUpdate> scrollUpdates;
207 scrollUpdates.AppendElement(ScrollPositionUpdate::NewScroll(
208 ScrollOrigin::Other, CSSPoint::ToAppUnits(mainThreadOffset)));
209 metadata.SetScrollUpdates(scrollUpdates);
210 metadata.GetMetrics().SetScrollGeneration(
211 scrollUpdates.LastElement().GetGeneration());
212 apzc->NotifyLayersUpdated(metadata, false, true);
213
214 // Continue and finish the touch-drag gesture.
215 for (int i = 0; i < 20; ++i) {
216 touchPos.y -= 1;
217 mcc->AdvanceByMillis(1);
218 TouchMove(apzc, touchPos, mcc->Time());
219 }
220
221 // Check that the portion of the touch-drag that occurred after
222 // the interruption caused additional scrolling.
223 CSSPoint finalScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
224 EXPECT_GT(finalScrollOffset.y, scrollOffsetBeforeInterruption.y);
225
226 // Now do the same thing, but for a visual scroll update.
227 scrollOffsetBeforeInterruption =
228 apzc->GetFrameMetrics().GetVisualScrollOffset();
229 mainThreadOffset = scrollOffsetBeforeInterruption;
230 mainThreadOffset.y -= 5;
231 metadata = apzc->GetScrollMetadata();
232 metadata.GetMetrics().SetVisualDestination(mainThreadOffset);
233 metadata.GetMetrics().SetScrollGeneration(
234 sGenerationCounter.NewMainThreadGeneration());
235 metadata.GetMetrics().SetVisualScrollUpdateType(FrameMetrics::eMainThread);
236 scrollUpdates.Clear();
237 metadata.SetScrollUpdates(scrollUpdates);
238 apzc->NotifyLayersUpdated(metadata, false, true);
239 for (int i = 0; i < 20; ++i) {
240 touchPos.y -= 1;
241 mcc->AdvanceByMillis(1);
242 TouchMove(apzc, touchPos, mcc->Time());
243 }
244 finalScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
245 EXPECT_GT(finalScrollOffset.y, scrollOffsetBeforeInterruption.y);
246
247 // Clean up by ending the touch gesture.
248 mcc->AdvanceByMillis(1);
249 TouchUp(apzc, touchPos, mcc->Time());
250 }
251 #endif
252
TEST_F(APZCBasicTester,RelativeScrollOffset)253 TEST_F(APZCBasicTester, RelativeScrollOffset) {
254 // Set up initial conditions: zoomed in, layout offset at (100, 100),
255 // visual offset at (120, 120); the relative offset is therefore (20, 20).
256 ScrollMetadata metadata;
257 FrameMetrics& metrics = metadata.GetMetrics();
258 metrics.SetScrollableRect(CSSRect(0, 0, 1000, 1000));
259 metrics.SetLayoutViewport(CSSRect(100, 100, 100, 100));
260 metrics.SetZoom(CSSToParentLayerScale(2.0));
261 metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
262 metrics.SetVisualScrollOffset(CSSPoint(120, 120));
263 metrics.SetIsRootContent(true);
264 apzc->SetFrameMetrics(metrics);
265
266 // Scroll the layout viewport to (200, 200).
267 ScrollMetadata mainThreadMetadata = metadata;
268 FrameMetrics& mainThreadMetrics = mainThreadMetadata.GetMetrics();
269 mainThreadMetrics.SetLayoutScrollOffset(CSSPoint(200, 200));
270 nsTArray<ScrollPositionUpdate> scrollUpdates;
271 scrollUpdates.AppendElement(ScrollPositionUpdate::NewScroll(
272 ScrollOrigin::Other, CSSPoint::ToAppUnits(CSSPoint(200, 200))));
273 mainThreadMetadata.SetScrollUpdates(scrollUpdates);
274 mainThreadMetrics.SetScrollGeneration(
275 scrollUpdates.LastElement().GetGeneration());
276 apzc->NotifyLayersUpdated(mainThreadMetadata, /*isFirstPaint=*/false,
277 /*thisLayerTreeUpdated=*/true);
278
279 // Check that the relative offset has been preserved.
280 metrics = apzc->GetFrameMetrics();
281 EXPECT_EQ(metrics.GetLayoutScrollOffset(), CSSPoint(200, 200));
282 EXPECT_EQ(metrics.GetVisualScrollOffset(), CSSPoint(220, 220));
283 }
284
TEST_F(APZCBasicTester,MultipleSmoothScrollsSmooth)285 TEST_F(APZCBasicTester, MultipleSmoothScrollsSmooth) {
286 // We want to test that if we send multiple smooth scroll requests that we
287 // still smoothly animate, ie that we get non-zero change every frame while
288 // the animation is running.
289
290 ScrollMetadata metadata;
291 FrameMetrics& metrics = metadata.GetMetrics();
292 metrics.SetScrollableRect(CSSRect(0, 0, 100, 10000));
293 metrics.SetLayoutViewport(CSSRect(0, 0, 100, 100));
294 metrics.SetZoom(CSSToParentLayerScale(1.0));
295 metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
296 metrics.SetVisualScrollOffset(CSSPoint(0, 0));
297 metrics.SetIsRootContent(true);
298 apzc->SetFrameMetrics(metrics);
299
300 // Structure of this test.
301 // -send a pure relative smooth scroll request via NotifyLayersUpdated
302 // -advance animations a few times, check that scroll offset is increasing
303 // after the first few advances
304 // -send a pure relative smooth scroll request via NotifyLayersUpdated
305 // -advance animations a few times, check that scroll offset is increasing
306 // -send a pure relative smooth scroll request via NotifyLayersUpdated
307 // -advance animations a few times, check that scroll offset is increasing
308
309 ScrollMetadata metadata2 = metadata;
310 nsTArray<ScrollPositionUpdate> scrollUpdates2;
311 scrollUpdates2.AppendElement(ScrollPositionUpdate::NewPureRelativeScroll(
312 ScrollOrigin::Other, ScrollMode::Smooth,
313 CSSPoint::ToAppUnits(CSSPoint(0, 200))));
314 metadata2.SetScrollUpdates(scrollUpdates2);
315 metadata2.GetMetrics().SetScrollGeneration(
316 scrollUpdates2.LastElement().GetGeneration());
317 apzc->NotifyLayersUpdated(metadata2, /*isFirstPaint=*/false,
318 /*thisLayerTreeUpdated=*/true);
319
320 // Get the animation going
321 for (uint32_t i = 0; i < 3; i++) {
322 SampleAnimationOneFrame();
323 }
324
325 float offset =
326 apzc->GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForCompositing)
327 .y;
328 ASSERT_GT(offset, 0);
329 float lastOffset = offset;
330
331 for (uint32_t i = 0; i < 2; i++) {
332 for (uint32_t j = 0; j < 3; j++) {
333 SampleAnimationOneFrame();
334 offset = apzc->GetCurrentAsyncScrollOffset(
335 AsyncPanZoomController::eForCompositing)
336 .y;
337 ASSERT_GT(offset, lastOffset);
338 lastOffset = offset;
339 }
340
341 ScrollMetadata metadata3 = metadata;
342 nsTArray<ScrollPositionUpdate> scrollUpdates3;
343 scrollUpdates3.AppendElement(ScrollPositionUpdate::NewPureRelativeScroll(
344 ScrollOrigin::Other, ScrollMode::Smooth,
345 CSSPoint::ToAppUnits(CSSPoint(0, 200))));
346 metadata3.SetScrollUpdates(scrollUpdates3);
347 metadata3.GetMetrics().SetScrollGeneration(
348 scrollUpdates3.LastElement().GetGeneration());
349 apzc->NotifyLayersUpdated(metadata3, /*isFirstPaint=*/false,
350 /*thisLayerTreeUpdated=*/true);
351 }
352
353 for (uint32_t j = 0; j < 7; j++) {
354 SampleAnimationOneFrame();
355 offset = apzc->GetCurrentAsyncScrollOffset(
356 AsyncPanZoomController::eForCompositing)
357 .y;
358 ASSERT_GT(offset, lastOffset);
359 lastOffset = offset;
360 }
361 }
362
TEST_F(APZCBasicTester,ZoomAndScrollableRectChangeAfterZoomChange)363 TEST_F(APZCBasicTester, ZoomAndScrollableRectChangeAfterZoomChange) {
364 // We want to check that a small scrollable rect change (which causes us to
365 // reclamp our scroll position, including in the sampled state) does not move
366 // the scroll offset in the sample state based the zoom in the apzc, only
367 // based on the zoom in the sampled state.
368
369 // First we zoom in to the right hand side. Then start zooming out, then send
370 // a scrollable rect change and check that it doesn't change the sampled state
371 // scroll offset.
372
373 ScrollMetadata metadata;
374 FrameMetrics& metrics = metadata.GetMetrics();
375 metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
376 metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
377 metrics.SetLayoutViewport(CSSRect(0, 0, 100, 100));
378 metrics.SetVisualScrollOffset(CSSPoint(0, 0));
379 metrics.SetZoom(CSSToParentLayerScale(1.0));
380 metrics.SetIsRootContent(true);
381 apzc->SetFrameMetrics(metrics);
382
383 MakeApzcZoomable();
384
385 // Zoom to right side.
386 ZoomTarget zoomTarget{CSSRect(75, 25, 25, 25)};
387 apzc->ZoomToRect(zoomTarget, 0);
388
389 // Run the animation to completion, should take 250ms/16.67ms = 15 frames, but
390 // do extra to make sure.
391 for (uint32_t i = 0; i < 30; i++) {
392 SampleAnimationOneFrame();
393 }
394
395 EXPECT_FALSE(apzc->IsAsyncZooming());
396
397 // Zoom out.
398 ZoomTarget zoomTarget2{CSSRect(0, 0, 100, 100)};
399 apzc->ZoomToRect(zoomTarget2, 0);
400
401 // Run the animation a few times to get it going.
402 for (uint32_t i = 0; i < 2; i++) {
403 SampleAnimationOneFrame();
404 }
405
406 // Check that it is decreasing in scale.
407 float prevScale =
408 apzc->GetCurrentPinchZoomScale(AsyncPanZoomController::eForCompositing)
409 .scale;
410 for (uint32_t i = 0; i < 2; i++) {
411 SampleAnimationOneFrame();
412 float scale =
413 apzc->GetCurrentPinchZoomScale(AsyncPanZoomController::eForCompositing)
414 .scale;
415 ASSERT_GT(prevScale, scale);
416 prevScale = scale;
417 }
418
419 float offset =
420 apzc->GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForCompositing)
421 .x;
422
423 // Change the scrollable rect slightly to trigger a reclamp.
424 ScrollMetadata metadata2 = metadata;
425 metadata2.GetMetrics().SetScrollableRect(CSSRect(0, 0, 100, 1000.2));
426 apzc->NotifyLayersUpdated(metadata2, /*isFirstPaint=*/false,
427 /*thisLayerTreeUpdated=*/true);
428
429 float newOffset =
430 apzc->GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForCompositing)
431 .x;
432
433 ASSERT_EQ(newOffset, offset);
434 }
435
TEST_F(APZCBasicTester,ZoomToRectAndCompositionBoundsChange)436 TEST_F(APZCBasicTester, ZoomToRectAndCompositionBoundsChange) {
437 // We want to check that content sending a composition bounds change (due to
438 // addition of scrollbars) during a zoom animation does not cause us to take
439 // the out of date content resolution.
440
441 ScrollMetadata metadata;
442 FrameMetrics& metrics = metadata.GetMetrics();
443 metrics.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
444 metrics.SetCompositionBoundsWidthIgnoringScrollbars(ParentLayerCoord{100});
445 metrics.SetScrollableRect(CSSRect(0, 0, 100, 1000));
446 metrics.SetLayoutViewport(CSSRect(0, 0, 100, 100));
447 metrics.SetVisualScrollOffset(CSSPoint(0, 0));
448 metrics.SetZoom(CSSToParentLayerScale(1.0));
449 metrics.SetIsRootContent(true);
450 apzc->SetFrameMetrics(metrics);
451
452 MakeApzcZoomable();
453
454 // Start a zoom to a rect.
455 ZoomTarget zoomTarget{CSSRect(25, 25, 25, 25)};
456 apzc->ZoomToRect(zoomTarget, 0);
457
458 // Run the animation a few times to get it going.
459 // Check that it is increasing in scale.
460 float prevScale =
461 apzc->GetCurrentPinchZoomScale(AsyncPanZoomController::eForCompositing)
462 .scale;
463 for (uint32_t i = 0; i < 3; i++) {
464 SampleAnimationOneFrame();
465 float scale =
466 apzc->GetCurrentPinchZoomScale(AsyncPanZoomController::eForCompositing)
467 .scale;
468 ASSERT_GE(scale, prevScale);
469 prevScale = scale;
470 }
471
472 EXPECT_TRUE(apzc->IsAsyncZooming());
473
474 // Simulate the appearance of a scrollbar by reducing the width of
475 // the composition bounds, while keeping
476 // mCompositionBoundsWidthIgnoringScrollbars unchanged.
477 ScrollMetadata metadata2 = metadata;
478 metadata2.GetMetrics().SetCompositionBounds(ParentLayerRect(0, 0, 90, 100));
479 apzc->NotifyLayersUpdated(metadata2, /*isFirstPaint=*/false,
480 /*thisLayerTreeUpdated=*/true);
481
482 float scale =
483 apzc->GetCurrentPinchZoomScale(AsyncPanZoomController::eForCompositing)
484 .scale;
485
486 ASSERT_EQ(scale, prevScale);
487
488 // Run the rest of the animation to completion, should take 250ms/16.67ms = 15
489 // frames total, but do extra to make sure.
490 for (uint32_t i = 0; i < 30; i++) {
491 SampleAnimationOneFrame();
492 scale =
493 apzc->GetCurrentPinchZoomScale(AsyncPanZoomController::eForCompositing)
494 .scale;
495 ASSERT_GE(scale, prevScale);
496 prevScale = scale;
497 }
498
499 EXPECT_FALSE(apzc->IsAsyncZooming());
500 }
501