summaryrefslogtreecommitdiffstats
path: root/dom/events/test/file_coalesce_touchmove_browserchild.html
blob: 28a4ae5252c1b4ed8ec92d6296461b656ee96fcc (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
<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
  <title>touchmove coalescing</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
  <script>
  var receivedSingleTouch = false;
  var receivedMultiTouch = false;
  // This test does three things:
  //   1. Ensures adding a new touch to existing touchmove events
  //      will not be coalesced with the previous single touch touchmove events
  //   2. Ensures touchstart flushes the coalesced touchmove events
  //   3. Ensures touchend flushes the coalesced touchmove event
  async function testBrowserChildCoalescing() {
    var ret = new Promise(function(resolve) {
      SpecialPowers.loadChromeScript(function() {
        /* eslint-env mozilla/chrome-script */
        var element = this.actorParent.rootFrameLoader.ownerElement;
        var rect = element.getBoundingClientRect();
        var win = element.ownerDocument.defaultView;
        var utils = win.windowUtils;
        var x = rect.x + (rect.width / 2);
        var y = Math.floor(rect.y + (rect.height / 4));
        var endYForFirstTouch = Math.floor(rect.y + ((rect.height / 4) * 2));
        var endYForSecondTouch = Math.floor(rect.y + ((rect.height / 4) * 4));
        utils.sendTouchEvent("touchstart", [0], [x], [y], [1], [1], [0], [1],
                             [0], [0], [0], 0, false);
        while (y != endYForFirstTouch) {
          utils.sendTouchEvent("touchmove", [0], [x], [y], [1], [1], [0], [1],
                               [0], [0], [0], 0, false);
          ++y;
        }

        // Add a new touch and move this touch
        utils.sendTouchEvent("touchstart", [0, 1], [x, x], [endYForFirstTouch, endYForFirstTouch], [1, 1], [1, 1], [0, 0], [1, 1],
                             [0, 0], [0, 0], [0, 0], 0, false);
        while (y != endYForSecondTouch) {
          utils.sendTouchEvent("touchmove", [0, 1], [x, x], [endYForFirstTouch, y], [1, 1], [1, 1], [0, 0], [1, 1],
                               [0, 0], [0, 0], [0, 0], 0, false);
          ++y;
        }

        utils.sendTouchEvent("touchend", [0, 1], [x, x], [endYForFirstTouch, endYForSecondTouch], [1, 1], [1, 1], [0, 0], [1, 1],
                             [0, 0], [0, 0], [0, 0], 0, false);
      });

      let touchStartCount = 0;
      let shouldReceiveMultiTouch = false;
      let receivedTouchEnd = false;

      window.addEventListener("touchstart", function() {
        ++touchStartCount;
        if (touchStartCount == 2) {
          shouldReceiveMultiTouch = true;
        }
      }, true);


      window.addEventListener("touchmove", function(e) {
        if (receivedTouchEnd) {
          ok(false, "Shouldn't get any touchmove events after touchend");
        }

        // Make touchmove handling slow
        var start = performance.now();
        while (performance.now() < (start + 10));

        if (shouldReceiveMultiTouch) {
          is(e.touches.length, 2, "Should get two touches for multi touch");
          receivedMultiTouch = true;
        } else {
          is(e.touches.length, 1, "Should get one touch for single touch");
          receivedSingleTouch = true;
        }
      }, true);

      window.addEventListener("touchend", async function(e) {
        receivedTouchEnd = true;
        // Request a tick to ensure touchend has successfully flushed
        // coalesced touchmove events
        await new Promise(r => {
          window.requestAnimationFrame(() => {
            window.requestAnimationFrame(r);
          });
        });

        resolve();
      }, {once: true});
    });

    return ret;
  }

  async function runTests() {
    await SpecialPowers.pushPrefEnv({"set": [["dom.events.coalesce.touchmove", true]]});

    await testBrowserChildCoalescing();

    ok(receivedSingleTouch, "Should've got single touch");
    ok(receivedMultiTouch, "Should've got multi touch");

    opener.finish();
    window.close();
  }

  function init() {
    SpecialPowers.pushPrefEnv({"set": [["dom.w3c_touch_events.enabled", true]]},
                              runTests);
  }
  </script>
</head>
<body onload="SimpleTest.waitForFocus(init);">
</body>
</html>