summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/test/mochitest/helper_relative_scroll_smoothness.html
blob: c8907c6d5d165998e6e5dda2a115e5ea7f78215e (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
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script src="/tests/SimpleTest/NativeKeyCodes.js"></script>
<script src="/tests/SimpleTest/paint_listener.js"></script>
<script src="apz_test_utils.js"></script>
<script src="apz_test_native_event_utils.js"></script>
<title>What happens if main thread scrolls?</title>
<style>
html, body { margin: 0; }

html {
  background:
    repeating-linear-gradient(45deg, transparent 0, transparent 100px, rgba(0,0,0,0.1) 0, rgba(0,0,0,0.1) 200px),
    repeating-linear-gradient(-45deg, transparent 0, transparent 100px, rgba(0,0,0,0.1) 0, rgba(0,0,0,0.1) 200px),
    repeating-linear-gradient(to bottom, transparent 0, transparent 500px, rgba(0,0,0,0.4) 0, rgba(0,0,0,0.4) 1000px),
    repeating-linear-gradient(to bottom, hsl(0, 60%, 80%), hsl(0, 60%, 80%) 200px, hsl(70, 60%, 80%) 0, hsl(70, 60%, 80%) 400px, hsl(140, 60%, 80%) 0, hsl(140, 60%, 80%) 600px, hsl(210, 60%, 80%) 0, hsl(210, 60%, 80%) 800px),
    white;
  background-size:
    283px 283px,
    283px 283px,
    100px 1000px,
    100px 800px;
}

body {
  height: 10000px;
}
</style>

<script>
const searchParams = new URLSearchParams(location.search);
var intervalId;
// Start periodic content expansions after we get a scroll event triggered by
// a key press in test() function below, otherwise we may have same scroll
// offsets caused by this script before we start scrolling.
window.addEventListener("scroll",  () => {
  var offset = 0;
  var initialBodyHeight = 10000;
  intervalId = setInterval(() => {
    // "Add content" at the top. We do this by making the body longer and adjusting the background position.
    offset += 10;
    document.documentElement.style.backgroundPosition = `0px ${offset}px`;
    document.body.style.height = `${initialBodyHeight + offset}px`;

    switch (searchParams.get("scroll-method")) {
      case "scrollBy":
        window.scrollBy(0, 10);
        break;
      case "scrollTop":
        document.scrollingElement.scrollTop += 10;
        break;
      case "scrollTo":
        window.scrollTo(0, window.scrollY + 10);
        break;
      default:
        ok(false, "Unsupported scroll method: " + searchParams.get("scroll-method"));
        break;
    }

    // Simulate some jank.
    var freezeDurationInMilliseconds = 100;
    var startTime = Date.now();
    while (Date.now() - startTime < freezeDurationInMilliseconds) {} // eslint-disable-line no-empty
  }, 300);
}, { once: true });


async function test() {
  // Once this content starts scrolling, it triggers a 100ms jank every 300ms so
  // sending arrow down keys for 1500ms will cause some jank.
  const timeAtStart = performance.now();
  while (performance.now() - timeAtStart < 1500) {
    switch (searchParams.get("input-type")) {
      case "key":
        synthesizeKey("KEY_ArrowDown");
        break;
      case "native-key":
        const DownArrowKeyCode = nativeArrowDownKey();
        ok(synthesizeNativeKey(KEYBOARD_LAYOUT_EN_US,
                               DownArrowKeyCode, {}  /* no modifier */,
                               "", ""),
          "Dispatched an down arrow key event");
        break;
      case "wheel":
        await synthesizeNativeWheel(window, 50, 50, 0, -50);
        break;
      default:
        ok(false, "Unsupported input type: " + searchParams.get("input-type"));
        break;
    }
    await promiseFrame(window);
  }

  // Stop the periodic expansions.
  clearInterval(intervalId);

  const records = collectSampledScrollOffsets(document.scrollingElement);

  let previousRecord = { scrollOffsetY: 0, sampledTimeStamp: 0 };
  for (const record of records) {
    // Ignore offsets before scrolling.
    if (record.scrollOffsetY == 0) {
      continue;
    }
    ok(
      record.scrollOffsetY > previousRecord.scrollOffsetY,
      "scroll offset should be strictly monotonically increasing " +
      "previous offset: " + previousRecord.scrollOffsetY +
      ", offset: " + record.scrollOffsetY
    );
    ok(
      record.sampledTimeStamp > previousRecord.sampledTimeStamp,
      "sampled time stamp should be strictly monotonically increasing " +
      "previous timestamp: " + previousRecord.sampledTimeStamp +
      ", timestamp: " + record.sampledTimeStamp
    );
    previousRecord = record;
  }
}

function isOnChaosMode() {
  return SpecialPowers.Services.env.get("MOZ_CHAOSMODE");
}

if (searchParams.get("input-type") == "native-key" &&
    getPlatform() != "mac" && getPlatform() != "windows") {
  ok(true, "Skipping test because native key events are not supported on " +
     getPlatform());
  subtestDone();
} else if (searchParams.get("input-type") == "native-key" &&
           getPlatform() == "mac" && isOnChaosMode()) {
  ok(true, "Skipping native-key tests on verify runs on Mac");
  subtestDone();
} else {
  waitUntilApzStable()
  .then(test)
  .then(subtestDone, subtestFailed);
}
</script>