summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/test/mochitest/helper_doubletap_zoom_smooth.html
blob: 65b4c6698f62b8a815bf35a6e5817ab7313815dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=2100"/>
  <title>Check that double tapping zoom out animation is smooth</title>
  <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
  <script type="application/javascript" src="apz_test_utils.js"></script>
  <script src="/tests/SimpleTest/paint_listener.js"></script>
  <script type="application/javascript">

let hasPrev = false;
let zoomingIn = true;
let lastVVLeft = 0, lastVVTop = 0, lastVVWidth = 0, lastVVHeight = 0;
let lastScrollX = 0, lastScrollY = 0;
let lastResolution = 0;

function within(a, b, tolerance) {
  return (Math.abs(a-b) < tolerance);
}

async function afterpaint() {
  info("vv pos " + visualViewport.pageLeft + "," + visualViewport.pageTop);
  info("vv size " + visualViewport.width + "," + visualViewport.height);
  info("win scroll " + window.scrollX + "," + window.scrollY);
  info("res " + await getResolution());
  if (hasPrev) {
    ok(zoomingIn ?
         lastVVLeft <= visualViewport.pageLeft :
         lastVVLeft >= visualViewport.pageLeft,
         "vvleft monotonic");
    // When zooming in pageTop stays 0, when zooming out (at least on mac)
    // the final value of pageTop is 2.5. Hence why the direction of these
    // inequalities.
    ok(zoomingIn ?
         lastVVTop >= visualViewport.pageTop :
         lastVVTop <= visualViewport.pageTop,
         "vvtop monotonic");
    ok(zoomingIn ?
         lastVVWidth >= visualViewport.width :
         lastVVWidth <= visualViewport.width,
         "vvwidth monotonic");
    ok(zoomingIn ?
         lastVVHeight >= visualViewport.height :
         lastVVHeight <= visualViewport.height,
         "vvheight monotonic");
    ok(zoomingIn ?
         lastScrollX <= window.scrollX :
         lastScrollX >= window.scrollX,
         "scrollx monotonic");
    if (!within(lastScrollY, window.scrollY, 2)) {
      ok(zoomingIn ?
           lastScrollY >= window.scrollY :
           lastScrollY <= window.scrollY,
           "scrolly monotonic");
    }

    // At the upper and lower limits of zoom constraints we can briefly go over
    // the limit and then back because of floating point inaccuracies.
    // In apzc callback helper we set the new content resolution to
    // (last presshell resolution that apz knows about) * (apz async zoom)
    // and (apz async zoom) is calculated as (apz zoom) / (last content resolution that apz knows about)
    // and (last content resolution that apz knows about) = (dev pixels per css pixel) * (ps resolution) * (resolution induced by transforms)
    // For simplicity we can assume that (dev pixels per css pixel) == (resolution induced by transforms) == 1
    // and (ps resolution) == (last presshell resolution that apz knows about).
    // The calculation then boils down to
    // (ps resolution) * ((apz zoom) / (ps resolution))
    // The fact that we divide by (ps resolution) first, and then multiply by
    // it means the result is not quite equal to (apz zoom).
    const deviceScale = window.devicePixelRatio;
    const maxZoom = 10.0;
    if (!within(lastResolution, maxZoom/deviceScale, 0.0001) &&
        !within(await getResolution(), maxZoom/deviceScale, 0.0001) &&
        !within(lastResolution, 1, 0.0001) &&
        !within(await getResolution(), 1, 0.0001)) {
      ok(zoomingIn ?
           lastResolution <= await getResolution() :
           lastResolution >= await getResolution(),
           "resolution monotonic");
    }

  } else {
    hasPrev = true;
  }
  lastVVLeft = visualViewport.pageLeft;
  lastVVTop = visualViewport.pageTop;
  lastVVWidth = visualViewport.width;
  lastVVHeight = visualViewport.height;
  lastScrollX = window.scrollX;
  if (!within(lastScrollY, window.scrollY, 2)) {
    lastScrollY = window.scrollY;
  }
  lastResolution = await getResolution();
}

async function test() {
  let useTouchpad = (location.search == "?touchpad");

  info("dpi: " + window.devicePixelRatio);

  window.addEventListener("MozAfterPaint", afterpaint);
  let intervalID = setInterval(afterpaint, 16);

  let resolution = await getResolution();
  ok(resolution > 0,
     "The initial_resolution is " + resolution + ", which is some sane value");

  // Check that double-tapping once on a small element zooms in
  info("sending first double tap");
  await doubleTapOn(document.getElementById("target2"), 10, 10, useTouchpad);
  let prev_resolution = resolution;
  resolution = await getResolution();
  ok(resolution > prev_resolution, "The first double-tap has increased the resolution to " + resolution);

  await promiseApzFlushedRepaints();

  hasPrev = false;
  zoomingIn = false;

  // Double tap, this won't hit anything but the body/html, and so will zoom us out.
  info("sending second double tap");
  await doubleTapOn(document.getElementById("target2"), 5, 65, useTouchpad);
  await promiseApzFlushedRepaints();
  prev_resolution = resolution;
  resolution = await getResolution();
  ok(resolution < prev_resolution, "The second double-tap has decreased the resolution to " + resolution);

  clearInterval(intervalID);
  window.removeEventListener("MozAfterPaint", afterpaint);
}

waitUntilApzStable()
.then(test)
.then(subtestDone, subtestFailed);

  </script>
  <style>
    .container {
      background-color: #eee;
      width: 95vw;
      height: 400vh;
    }
    .smallcontainer {
      background-color: #aaa;
      width: 40px;
      height: 40px;
      position: absolute;
      right: 0;
      top: 20px;
    }
</style>
</head>
<body>

<div id="target" class="container">
</div>
<div id="target2" class="smallcontainer">
</div>

</body>
</html>