Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/apz/test/gtest/TestBasic.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 "gfxPrefs.h"
10
#include "InputUtils.h"
11
12
0
TEST_F(APZCBasicTester, Overzoom) {
13
0
  // the visible area of the document in CSS pixels is x=10 y=0 w=100 h=100
14
0
  FrameMetrics fm;
15
0
  fm.SetCompositionBounds(ParentLayerRect(0, 0, 100, 100));
16
0
  fm.SetScrollableRect(CSSRect(0, 0, 125, 150));
17
0
  fm.SetScrollOffset(CSSPoint(10, 0));
18
0
  fm.SetZoom(CSSToParentLayerScale2D(1.0, 1.0));
19
0
  fm.SetIsRootContent(true);
20
0
  apzc->SetFrameMetrics(fm);
21
0
22
0
  MakeApzcZoomable();
23
0
24
0
  EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
25
0
26
0
  PinchWithPinchInputAndCheckStatus(apzc, ScreenIntPoint(50, 50), 0.5, true);
27
0
28
0
  fm = apzc->GetFrameMetrics();
29
0
  EXPECT_EQ(0.8f, fm.GetZoom().ToScaleFactor().scale);
30
0
  // bug 936721 - PGO builds introduce rounding error so
31
0
  // use a fuzzy match instead
32
0
  EXPECT_LT(std::abs(fm.GetScrollOffset().x), 1e-5);
33
0
  EXPECT_LT(std::abs(fm.GetScrollOffset().y), 1e-5);
34
0
}
35
36
0
TEST_F(APZCBasicTester, SimpleTransform) {
37
0
  ParentLayerPoint pointOut;
38
0
  AsyncTransform viewTransformOut;
39
0
  apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
40
0
41
0
  EXPECT_EQ(ParentLayerPoint(), pointOut);
42
0
  EXPECT_EQ(AsyncTransform(), viewTransformOut);
43
0
}
44
45
46
0
TEST_F(APZCBasicTester, ComplexTransform) {
47
0
  // This test assumes there is a page that gets rendered to
48
0
  // two layers. In CSS pixels, the first layer is 50x50 and
49
0
  // the second layer is 25x50. The widget scale factor is 3.0
50
0
  // and the presShell resolution is 2.0. Therefore, these layers
51
0
  // end up being 300x300 and 150x300 in layer pixels.
52
0
  //
53
0
  // The second (child) layer has an additional CSS transform that
54
0
  // stretches it by 2.0 on the x-axis. Therefore, after applying
55
0
  // CSS transforms, the two layers are the same size in screen
56
0
  // pixels.
57
0
  //
58
0
  // The screen itself is 24x24 in screen pixels (therefore 4x4 in
59
0
  // CSS pixels). The displayport is 1 extra CSS pixel on all
60
0
  // sides.
61
0
62
0
  RefPtr<TestAsyncPanZoomController> childApzc =
63
0
      new TestAsyncPanZoomController(LayersId{0}, mcc, tm);
64
0
65
0
  const char* layerTreeSyntax = "c(c)";
66
0
  // LayerID                     0 1
67
0
  nsIntRegion layerVisibleRegion[] = {
68
0
    nsIntRegion(IntRect(0, 0, 300, 300)),
69
0
    nsIntRegion(IntRect(0, 0, 150, 300)),
70
0
  };
71
0
  Matrix4x4 transforms[] = {
72
0
    Matrix4x4(),
73
0
    Matrix4x4(),
74
0
  };
75
0
  transforms[0].PostScale(0.5f, 0.5f, 1.0f); // this results from the 2.0 resolution on the root layer
76
0
  transforms[1].PostScale(2.0f, 1.0f, 1.0f); // this is the 2.0 x-axis CSS transform on the child layer
77
0
78
0
  nsTArray<RefPtr<Layer> > layers;
79
0
  RefPtr<LayerManager> lm;
80
0
  RefPtr<Layer> root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, lm, layers);
81
0
82
0
  ScrollMetadata metadata;
83
0
  FrameMetrics& metrics = metadata.GetMetrics();
84
0
  metrics.SetCompositionBounds(ParentLayerRect(0, 0, 24, 24));
85
0
  metrics.SetDisplayPort(CSSRect(-1, -1, 6, 6));
86
0
  metrics.SetScrollOffset(CSSPoint(10, 10));
87
0
  metrics.SetScrollableRect(CSSRect(0, 0, 50, 50));
88
0
  metrics.SetCumulativeResolution(LayoutDeviceToLayerScale2D(2, 2));
89
0
  metrics.SetPresShellResolution(2.0f);
90
0
  metrics.SetZoom(CSSToParentLayerScale2D(6, 6));
91
0
  metrics.SetDevPixelsPerCSSPixel(CSSToLayoutDeviceScale(3));
92
0
  metrics.SetScrollId(FrameMetrics::START_SCROLL_ID);
93
0
94
0
  ScrollMetadata childMetadata = metadata;
95
0
  FrameMetrics& childMetrics = childMetadata.GetMetrics();
96
0
  childMetrics.SetScrollId(FrameMetrics::START_SCROLL_ID + 1);
97
0
98
0
  layers[0]->SetScrollMetadata(metadata);
99
0
  layers[1]->SetScrollMetadata(childMetadata);
100
0
101
0
  ParentLayerPoint pointOut;
102
0
  AsyncTransform viewTransformOut;
103
0
104
0
  // Both the parent and child layer should behave exactly the same here, because
105
0
  // the CSS transform on the child layer does not affect the SampleContentTransformForFrame code
106
0
107
0
  // initial transform
108
0
  apzc->SetFrameMetrics(metrics);
109
0
  apzc->NotifyLayersUpdated(metadata, true, true);
110
0
  apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
111
0
  EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint()), viewTransformOut);
112
0
  EXPECT_EQ(ParentLayerPoint(60, 60), pointOut);
113
0
114
0
  childApzc->SetFrameMetrics(childMetrics);
115
0
  childApzc->NotifyLayersUpdated(childMetadata, true, true);
116
0
  childApzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
117
0
  EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint()), viewTransformOut);
118
0
  EXPECT_EQ(ParentLayerPoint(60, 60), pointOut);
119
0
120
0
  // do an async scroll by 5 pixels and check the transform
121
0
  metrics.ScrollBy(CSSPoint(5, 0));
122
0
  apzc->SetFrameMetrics(metrics);
123
0
  apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
124
0
  EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)), viewTransformOut);
125
0
  EXPECT_EQ(ParentLayerPoint(90, 60), pointOut);
126
0
127
0
  childMetrics.ScrollBy(CSSPoint(5, 0));
128
0
  childApzc->SetFrameMetrics(childMetrics);
129
0
  childApzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
130
0
  EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)), viewTransformOut);
131
0
  EXPECT_EQ(ParentLayerPoint(90, 60), pointOut);
132
0
133
0
  // do an async zoom of 1.5x and check the transform
134
0
  metrics.ZoomBy(1.5f);
135
0
  apzc->SetFrameMetrics(metrics);
136
0
  apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
137
0
  EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)), viewTransformOut);
138
0
  EXPECT_EQ(ParentLayerPoint(135, 90), pointOut);
139
0
140
0
  childMetrics.ZoomBy(1.5f);
141
0
  childApzc->SetFrameMetrics(childMetrics);
142
0
  childApzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
143
0
  EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)), viewTransformOut);
144
0
  EXPECT_EQ(ParentLayerPoint(135, 90), pointOut);
145
0
146
0
  childApzc->Destroy();
147
0
}
148
149
0
TEST_F(APZCBasicTester, Fling) {
150
0
  SCOPED_GFX_PREF(APZFlingMinVelocityThreshold, float, 0.0f);
151
0
  int touchStart = 50;
152
0
  int touchEnd = 10;
153
0
  ParentLayerPoint pointOut;
154
0
  AsyncTransform viewTransformOut;
155
0
156
0
  // Fling down. Each step scroll further down
157
0
  Pan(apzc, touchStart, touchEnd);
158
0
  ParentLayerPoint lastPoint;
159
0
  for (int i = 1; i < 50; i+=1) {
160
0
    apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut, TimeDuration::FromMilliseconds(1));
161
0
    EXPECT_GT(pointOut.y, lastPoint.y);
162
0
    lastPoint = pointOut;
163
0
  }
164
0
}
165
166
0
TEST_F(APZCBasicTester, FlingIntoOverscroll) {
167
0
  // Enable overscrolling.
168
0
  SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
169
0
  SCOPED_GFX_PREF(APZFlingMinVelocityThreshold, float, 0.0f);
170
0
171
0
  // Scroll down by 25 px. Don't fling for simplicity.
172
0
  Pan(apzc, 50, 25, PanOptions::NoFling);
173
0
174
0
  // Now scroll back up by 20px, this time flinging after.
175
0
  // The fling should cover the remaining 5 px of room to scroll, then
176
0
  // go into overscroll, and finally snap-back to recover from overscroll.
177
0
  Pan(apzc, 25, 45);
178
0
  const TimeDuration increment = TimeDuration::FromMilliseconds(1);
179
0
  bool reachedOverscroll = false;
180
0
  bool recoveredFromOverscroll = false;
181
0
  while (apzc->AdvanceAnimations(mcc->Time())) {
182
0
    if (!reachedOverscroll && apzc->IsOverscrolled()) {
183
0
      reachedOverscroll = true;
184
0
    }
185
0
    if (reachedOverscroll && !apzc->IsOverscrolled()) {
186
0
      recoveredFromOverscroll = true;
187
0
    }
188
0
    mcc->AdvanceBy(increment);
189
0
  }
190
0
  EXPECT_TRUE(reachedOverscroll);
191
0
  EXPECT_TRUE(recoveredFromOverscroll);
192
0
}
193
194
0
TEST_F(APZCBasicTester, PanningTransformNotifications) {
195
0
  SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
196
0
197
0
  // Scroll down by 25 px. Ensure we only get one set of
198
0
  // state change notifications.
199
0
  //
200
0
  // Then, scroll back up by 20px, this time flinging after.
201
0
  // The fling should cover the remaining 5 px of room to scroll, then
202
0
  // go into overscroll, and finally snap-back to recover from overscroll.
203
0
  // Again, ensure we only get one set of state change notifications for
204
0
  // this entire procedure.
205
0
206
0
  MockFunction<void(std::string checkPointName)> check;
207
0
  {
208
0
    InSequence s;
209
0
    EXPECT_CALL(check, Call("Simple pan"));
210
0
    EXPECT_CALL(*mcc, NotifyAPZStateChange(_,GeckoContentController::APZStateChange::eStartTouch,_)).Times(1);
211
0
    EXPECT_CALL(*mcc, NotifyAPZStateChange(_,GeckoContentController::APZStateChange::eTransformBegin,_)).Times(1);
212
0
    EXPECT_CALL(*mcc, NotifyAPZStateChange(_,GeckoContentController::APZStateChange::eStartPanning,_)).Times(1);
213
0
    EXPECT_CALL(*mcc, NotifyAPZStateChange(_,GeckoContentController::APZStateChange::eEndTouch,_)).Times(1);
214
0
    EXPECT_CALL(*mcc, NotifyAPZStateChange(_,GeckoContentController::APZStateChange::eTransformEnd,_)).Times(1);
215
0
    EXPECT_CALL(check, Call("Complex pan"));
216
0
    EXPECT_CALL(*mcc, NotifyAPZStateChange(_,GeckoContentController::APZStateChange::eStartTouch,_)).Times(1);
217
0
    EXPECT_CALL(*mcc, NotifyAPZStateChange(_,GeckoContentController::APZStateChange::eTransformBegin,_)).Times(1);
218
0
    EXPECT_CALL(*mcc, NotifyAPZStateChange(_,GeckoContentController::APZStateChange::eStartPanning,_)).Times(1);
219
0
    EXPECT_CALL(*mcc, NotifyAPZStateChange(_,GeckoContentController::APZStateChange::eEndTouch,_)).Times(1);
220
0
    EXPECT_CALL(*mcc, NotifyAPZStateChange(_,GeckoContentController::APZStateChange::eTransformEnd,_)).Times(1);
221
0
    EXPECT_CALL(check, Call("Done"));
222
0
  }
223
0
224
0
  check.Call("Simple pan");
225
0
  Pan(apzc, 50, 25, PanOptions::NoFling);
226
0
  check.Call("Complex pan");
227
0
  Pan(apzc, 25, 45);
228
0
  apzc->AdvanceAnimationsUntilEnd();
229
0
  check.Call("Done");
230
0
}
231
232
void APZCBasicTester::PanIntoOverscroll()
233
0
{
234
0
  int touchStart = 500;
235
0
  int touchEnd = 10;
236
0
  Pan(apzc, touchStart, touchEnd);
237
0
  EXPECT_TRUE(apzc->IsOverscrolled());
238
0
}
239
240
void APZCBasicTester::TestOverscroll()
241
0
{
242
0
  // Pan sufficiently to hit overscroll behavior
243
0
  PanIntoOverscroll();
244
0
245
0
  // Check that we recover from overscroll via an animation.
246
0
  ParentLayerPoint expectedScrollOffset(0, GetScrollRange().YMost());
247
0
  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
248
0
}
249
250
251
0
TEST_F(APZCBasicTester, OverScrollPanning) {
252
0
  SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
253
0
254
0
  TestOverscroll();
255
0
}
256
257
// Tests that an overscroll animation doesn't trigger an assertion failure
258
// in the case where a sample has a velocity of zero.
259
0
TEST_F(APZCBasicTester, OverScroll_Bug1152051a) {
260
0
  SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
261
0
262
0
  // Doctor the prefs to make the velocity zero at the end of the first sample.
263
0
264
0
  // This ensures our incoming velocity to the overscroll animation is
265
0
  // a round(ish) number, 4.9 (that being the distance of the pan before
266
0
  // overscroll, which is 500 - 10 = 490 pixels, divided by the duration of
267
0
  // the pan, which is 100 ms).
268
0
  SCOPED_GFX_PREF(APZFlingFriction, float, 0);
269
0
270
0
  // To ensure the velocity after the first sample is 0, set the spring
271
0
  // stiffness to the incoming velocity (4.9) divided by the overscroll
272
0
  // (400 pixels) times the step duration (1 ms).
273
0
  SCOPED_GFX_PREF(APZOverscrollSpringStiffness, float, 0.01225f);
274
0
275
0
  TestOverscroll();
276
0
}
277
278
// Tests that ending an overscroll animation doesn't leave around state that
279
// confuses the next overscroll animation.
280
0
TEST_F(APZCBasicTester, OverScroll_Bug1152051b) {
281
0
  SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
282
0
283
0
  SCOPED_GFX_PREF(APZOverscrollStopDistanceThreshold, float, 0.1f);
284
0
285
0
  // Pan sufficiently to hit overscroll behavior
286
0
  PanIntoOverscroll();
287
0
288
0
  // Sample animations once, to give the fling animation started on touch-up
289
0
  // a chance to realize it's overscrolled, and schedule a call to
290
0
  // HandleFlingOverscroll().
291
0
  SampleAnimationOnce();
292
0
293
0
  // This advances the time and runs the HandleFlingOverscroll task scheduled in
294
0
  // the previous call, which starts an overscroll animation. It then samples
295
0
  // the overscroll animation once, to get it to initialize the first overscroll
296
0
  // sample.
297
0
  SampleAnimationOnce();
298
0
299
0
  // Do a touch-down to cancel the overscroll animation, and then a touch-up
300
0
  // to schedule a new one since we're still overscrolled. We don't pan because
301
0
  // panning can trigger functions that clear the overscroll animation state
302
0
  // in other ways.
303
0
  uint64_t blockId;
304
0
  nsEventStatus status = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time(), &blockId);
305
0
  if (gfxPrefs::TouchActionEnabled() && status != nsEventStatus_eConsumeNoDefault) {
306
0
    SetDefaultAllowedTouchBehavior(apzc, blockId);
307
0
  }
308
0
  TouchUp(apzc, ScreenIntPoint(10, 10), mcc->Time());
309
0
310
0
  // Sample the second overscroll animation to its end.
311
0
  // If the ending of the first overscroll animation fails to clear state
312
0
  // properly, this will assert.
313
0
  ParentLayerPoint expectedScrollOffset(0, GetScrollRange().YMost());
314
0
  SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
315
0
}
316
317
// Tests that the page doesn't get stuck in an
318
// overscroll animation after a low-velocity pan.
319
0
TEST_F(APZCBasicTester, OverScrollAfterLowVelocityPan_Bug1343775) {
320
0
  SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
321
0
322
0
  // Pan into overscroll with a velocity less than the
323
0
  // apz.fling_min_velocity_threshold preference.
324
0
  Pan(apzc, 10, 30);
325
0
326
0
  EXPECT_TRUE(apzc->IsOverscrolled());
327
0
328
0
  apzc->AdvanceAnimationsUntilEnd();
329
0
330
0
  // Check that we recovered from overscroll.
331
0
  EXPECT_FALSE(apzc->IsOverscrolled());
332
0
}
333
334
0
TEST_F(APZCBasicTester, OverScrollAbort) {
335
0
  SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
336
0
337
0
  // Pan sufficiently to hit overscroll behavior
338
0
  int touchStart = 500;
339
0
  int touchEnd = 10;
340
0
  Pan(apzc, touchStart, touchEnd);
341
0
  EXPECT_TRUE(apzc->IsOverscrolled());
342
0
343
0
  ParentLayerPoint pointOut;
344
0
  AsyncTransform viewTransformOut;
345
0
346
0
  // This sample call will run to the end of the fling animation
347
0
  // and will schedule the overscroll animation.
348
0
  apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut, TimeDuration::FromMilliseconds(10000));
349
0
  EXPECT_TRUE(apzc->IsOverscrolled());
350
0
351
0
  // At this point, we have an active overscroll animation.
352
0
  // Check that cancelling the animation clears the overscroll.
353
0
  apzc->CancelAnimation();
354
0
  EXPECT_FALSE(apzc->IsOverscrolled());
355
0
  apzc->AssertStateIsReset();
356
0
}
357
358
0
TEST_F(APZCBasicTester, OverScrollPanningAbort) {
359
0
  SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
360
0
361
0
  // Pan sufficiently to hit overscroll behaviour. Keep the finger down so
362
0
  // the pan does not end.
363
0
  int touchStart = 500;
364
0
  int touchEnd = 10;
365
0
  Pan(apzc, touchStart, touchEnd, PanOptions::KeepFingerDown);
366
0
  EXPECT_TRUE(apzc->IsOverscrolled());
367
0
368
0
  // Check that calling CancelAnimation() while the user is still panning
369
0
  // (and thus no fling or snap-back animation has had a chance to start)
370
0
  // clears the overscroll.
371
0
  apzc->CancelAnimation();
372
0
  EXPECT_FALSE(apzc->IsOverscrolled());
373
0
  apzc->AssertStateIsReset();
374
0
}