summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/test/mochitest/helper_zoom_out_with_mainthread_clamping.html
blob: c15622872a07f74ffee7e3f29eaac792c3554a76 (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
<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, minimum-scale=1.0">
  <title>Tests that zooming out in a way that triggers main-thread scroll re-clamping works properly</title>
  <script src="/tests/SimpleTest/EventUtils.js"></script>
  <script type="application/javascript" src="apz_test_utils.js"></script>
  <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
  <script src="/tests/SimpleTest/paint_listener.js"></script>
</head>
<body>
  <div style="width: 200vw; height: 2000px; background-color: linear-gradient(green,blue)"></div>
  <script type="application/javascript">
    const utils = SpecialPowers.getDOMWindowUtils(window);

    async function test() {
      // Initial state
      is(await getResolution(), 1.0, "should not be zoomed");

      // Zoom in and go to the bottom-right corner. This ensures the layout
      // and visual scroll offsets are nonzero, which increases the chances
      // that the scroll position layer alignment code will mutate the scroll
      // position (see comment below).
      utils.setResolutionAndScaleTo(5.0);
      await promiseApzFlushedRepaints();
      utils.scrollToVisual(document.scrollingElement.clientWidth * 5,
                           document.scrollingElement.clientHeight * 5,
                           utils.UPDATE_TYPE_MAIN_THREAD,
                           utils.SCROLL_MODE_INSTANT);
      await promiseApzFlushedRepaints();

      // Check that we're at the right place
      is(await getResolution(), 5.0, "should be zoomed to 5.0");
      is(window.scrollX, window.scrollMaxX, "layout x-coord should be maxed");
      is(window.scrollY, window.scrollMaxY, "layout y-coord should be maxed");
      ok(visualViewport.offsetLeft > 0, "visual x-coord should be even further");
      ok(visualViewport.offsetTop > 0, "visual y-coord should be even further");

      // Zoom out. This will trigger repaint requests to the main thread,
      // at various intermediate resolutions. The repaint requests will
      // trigger reflows, which will trigger the root scrollframe to re-clamp
      // and layer-align the scroll position as part of the post-reflow action.
      // The test is checking that these mutations don't end up sending a scroll
      // position update to APZ that interrupts the zoom action (see bug 1671284
      // comment 9 for the exact mechanism). In order to maximize the chances of
      // catching the bug, we wait for the main thread repaint after each of the
      // pinch inputs.

      let zoom_out = pinchZoomOutTouchSequenceAtCenter();
      // Do coordinate conversion up-front using the current resolution and
      // visual viewport.
      for (let entry of zoom_out) {
        for (let i = 0; i < entry.length; i++) {
          entry[i] = await coordinatesRelativeToScreen({
            offsetX: entry[i].x,
            offsetY: entry[i].y,
            target: document.body,
          });
        }
      }
      // Dispatch the touch events, waiting for paints after each row in
      // zoom_out.
      let touchIds = [0, 1];
      for (let i = 0; i < zoom_out.length; i++) {
        let entry = zoom_out[i];
        for (let j = 0; j < entry.length; j++) {
          await new Promise(resolve => {
            utils.sendNativeTouchPoint(
              touchIds[j],
              utils.TOUCH_CONTACT,
              entry[j].x,
              entry[j].y,
              1,
              90,
              resolve
            );
          });
        }
        await promiseAllPaintsDone();

        // On the last row also do the touch-up events
        if (i == zoom_out.length - 1) {
          for (let j = 0; j < entry.length; j++) {
            await new Promise(resolve => {
              utils.sendNativeTouchPoint(
                touchIds[j],
                utils.TOUCH_REMOVE,
                entry[j].x,
                entry[j].y,
                1,
                90,
                resolve
              );
            });
          }
        }
      }

      // Wait for everything to stabilize
      await promiseApzFlushedRepaints();

      // Verify that the zoom completed and we're back at 1.0 resolution
      isfuzzy(await getResolution(), 1.0, 0.0001, "should be back at initial resolution");
    }

    waitUntilApzStable().then(test).then(subtestDone, subtestFailed);
  </script>
</body>
</html>