test_coalesce_mousewheel.html (9986B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>mousewheel coalescing</title> 6 <script src="/tests/SimpleTest/SimpleTest.js"></script> 7 <script src="/tests/SimpleTest/EventUtils.js"></script> 8 <script src="apz_test_utils.js"></script> 9 <script src="apz_test_native_event_utils.js"></script> 10 <link rel="stylesheet" href="/tests/SimpleTest/test.css"/> 11 <script> 12 let wheelEvents = []; 13 function mousewheel(aWheelEvent) { 14 // Make mousewheel handling slow 15 var start = performance.now(); 16 while (performance.now() < (start + 10)); 17 wheelEvents.push(aWheelEvent); 18 } 19 20 function resolveIfProcessed(resolve, minamount) { 21 if (wheelEvents.length >= minamount) { 22 SimpleTest.requestFlakyTimeout("Make sure we got all events."); 23 setTimeout(function() { resolve(); }, 20); 24 } else { 25 setTimeout(function() { resolveIfProcessed(resolve, minamount); }); 26 } 27 } 28 29 const kLineDeltaFactor = 30 SpecialPowers.getBoolPref("mousewheel.system_scroll_override.enabled", false) 31 ? SpecialPowers.getIntPref("mousewheel.system_scroll_override.vertical.factor", 200) / 100 32 : 1; 33 34 function checkWheelEvents(aExpectedDeltaMode, aExpectedSumOfDeltaY, aDescription) { 35 const lineDeltaFactor = 36 aExpectedDeltaMode === WheelEvent.DOM_DELTA_LINE ? kLineDeltaFactor : 1; 37 let succeeded = true; 38 let deltaY = 0; 39 for (const wheelEvent of wheelEvents) { 40 succeeded &= wheelEvent.deltaMode === aExpectedDeltaMode; 41 is(wheelEvent.deltaMode, aExpectedDeltaMode, 42 `When ${aDescription}, the deltaMode of all wheel events should be ${aExpectedDeltaMode}`); 43 deltaY += wheelEvent.deltaY; 44 } 45 succeeded &= deltaY == aExpectedSumOfDeltaY * lineDeltaFactor; 46 is(deltaY, aExpectedSumOfDeltaY * lineDeltaFactor, 47 `When ${aDescription}, sum of the deltaY of all wheel events should be ${aExpectedSumOfDeltaY * lineDeltaFactor}`); 48 return succeeded; 49 } 50 51 async function testOneSingleWheelEvent() { 52 await new Promise(function(resolve) { 53 wheelEvents = []; 54 var element = document.getElementById("wheelEventReceiver"); 55 element.addEventListener("wheel", mousewheel, true); 56 57 synthesizeWheel(element, 10, 10, { deltaY: 3.0, deltaMode: WheelEvent.DOM_DELTA_LINE }); 58 59 setTimeout(function() { resolveIfProcessed(resolve, 1); }); 60 }); 61 is(wheelEvents.length, 1, 62 "Synthesizing a wheel event via the parent process should cause 1 wheel event"); 63 is(wheelEvents[0]?.deltaMode, WheelEvent.DOM_DELTA_LINE, 64 "When Synthesizing a wheel event via the parent process, the deltaMode of a wheel event should be WheelEvent.DOM_DELTA_LINE"); 65 is(wheelEvents[0]?.deltaY, 3 * kLineDeltaFactor, 66 `When Synthesizing a wheel event via the parent process, the deltaY of a wheel event should be ${3 * kLineDeltaFactor}`); 67 } 68 69 const kMaxRetry = 10; 70 71 async function testTwoSingleWheelEvents() { 72 function tryIt() { 73 return new Promise(function(resolve) { 74 info("Synthesizing 2 wheel events via the parent process..."); 75 wheelEvents = []; 76 var element = document.getElementById("wheelEventReceiver"); 77 element.addEventListener("wheel", mousewheel, true); 78 79 synthesizeWheel(element, 10, 10, { deltaY: 3.0, deltaMode: WheelEvent.DOM_DELTA_LINE }); 80 synthesizeWheel(element, 10, 10, { deltaY: 3.0, deltaMode: WheelEvent.DOM_DELTA_LINE }); 81 82 setTimeout(function() { resolveIfProcessed(resolve, 1); }); 83 }); 84 } 85 for (let i = 0; i < kMaxRetry; i++) { 86 await tryIt(); 87 if (wheelEvents.length == 2) { 88 // Even if failed to coalescing, the sum of deltaY values should be same 89 // as sum of the synthesized ones. 90 if (!checkWheelEvents(WheelEvent.DOM_DELTA_LINE, 6, 91 "synthesizing 2 wheel events via the parent process")) { 92 return; 93 } 94 continue; // retry 95 } 96 is(wheelEvents.length, 1, 97 "Synthesizing 2 wheel events via the parent process should cause only 1 wheel event"); 98 checkWheelEvents(WheelEvent.DOM_DELTA_LINE, 6, 99 "synthesizing 2 wheel events via the parent process"); 100 return; 101 } 102 } 103 104 async function testManySingleWheelEvents() { 105 function tryIt() { 106 return new Promise(function(resolve) { 107 info("Synthesizing 5 wheel events via the parent process..."); 108 wheelEvents = []; 109 var element = document.getElementById("wheelEventReceiver"); 110 element.addEventListener("wheel", mousewheel, true); 111 112 synthesizeWheel(element, 10, 10, { deltaY: 3.0, deltaMode: WheelEvent.DOM_DELTA_LINE }); 113 synthesizeWheel(element, 10, 10, { deltaY: 3.0, deltaMode: WheelEvent.DOM_DELTA_LINE }); 114 synthesizeWheel(element, 10, 10, { deltaY: 3.0, deltaMode: WheelEvent.DOM_DELTA_LINE }); 115 synthesizeWheel(element, 10, 10, { deltaY: 3.0, deltaMode: WheelEvent.DOM_DELTA_LINE }); 116 synthesizeWheel(element, 10, 10, { deltaY: 3.0, deltaMode: WheelEvent.DOM_DELTA_LINE }); 117 118 setTimeout(function() { resolveIfProcessed(resolve, 1); }); 119 }); 120 } 121 for (let i = 0; i < kMaxRetry; i++) { 122 await tryIt(); 123 if (wheelEvents.length > 1 && wheelEvents.length <= 5) { 124 // Even if failed to coalescing, the sum of deltaY values should be same 125 // as sum of the synthesized ones. 126 if (!checkWheelEvents(WheelEvent.DOM_DELTA_LINE, 15, 127 "synthesizing 5 wheel events via the parent process")) { 128 return; 129 } 130 continue; // retry 131 } 132 is(wheelEvents.length, 1, 133 "Synthesizing 5 wheel events via the parent process should cause only 1 wheel event"); 134 checkWheelEvents(WheelEvent.DOM_DELTA_LINE, 15, 135 "synthesizing 5 wheel events via the parent process"); 136 return; 137 } 138 } 139 140 async function testMixedWheelEvents() { 141 function tryIt() { 142 return new Promise(function(resolve) { 143 info("Synthesizing 2 line wheel events, 1 page wheel event and 1 line wheel event..."); 144 wheelEvents = []; 145 var element = document.getElementById("wheelEventReceiver"); 146 element.addEventListener("wheel", mousewheel, true); 147 148 synthesizeWheel(element, 10, 10, { deltaY: 3.0, deltaMode: WheelEvent.DOM_DELTA_LINE }); 149 synthesizeWheel(element, 10, 10, { deltaY: 3.0, deltaMode: WheelEvent.DOM_DELTA_LINE }); 150 synthesizeWheel(element, 10, 10, { deltaY: 3.0, deltaMode: WheelEvent.DOM_DELTA_PAGE }); 151 synthesizeWheel(element, 10, 10, { deltaY: 3.0, deltaMode: WheelEvent.DOM_DELTA_LINE }); 152 153 setTimeout(function() { resolveIfProcessed(resolve, 3); }); 154 }); 155 } 156 function checkGroupsOfWheelEvents() { 157 let succeeded = true; 158 let deltaY = [0, 0, 0]; 159 let index = 0; 160 const description = "synthesizing 2 line wheel events, 1 page wheel event and 1 line wheel event"; 161 for (const wheelEvent of wheelEvents) { 162 switch (index) { 163 case 0: 164 if (wheelEvent.deltaMode === WheelEvent.DOM_DELTA_LINE) { 165 is(wheelEvent.deltaMode, WheelEvent.DOM_DELTA_LINE, 166 `When ${description}, the deltaMode of the first group should be WheelEvent.DOM_DELTA_LINE`); 167 break; 168 } 169 index++; 170 // fallthrough 171 case 1: 172 if (wheelEvent.deltaMode === WheelEvent.DOM_DELTA_PAGE) { 173 is(wheelEvent.deltaMode, WheelEvent.DOM_DELTA_PAGE, 174 `When ${description}, the deltaMode of the seconde group should be WheelEvent.DOM_DELTA_PAGE`); 175 break; 176 } 177 index++; 178 // fallthrough 179 case 2: 180 succeeded &= wheelEvent.deltaMode === WheelEvent.DOM_DELTA_LINE; 181 is(wheelEvent.deltaMode, WheelEvent.DOM_DELTA_LINE, 182 `When ${description}, the deltaMode of the last group should be WheelEvent.DOM_DELTA_LINE`); 183 break; 184 } 185 deltaY[index] += wheelEvent.deltaY; 186 } 187 succeeded &= deltaY == [6 * kLineDeltaFactor, 3, 3 * kLineDeltaFactor]; 188 isDeeply(deltaY, [6 * kLineDeltaFactor, 3, 3 * kLineDeltaFactor], 189 `When ${description}, sum of the deltaY of the each wheel event group should be same as sum of the synthesized ones`); 190 return succeeded; 191 } 192 for (let i = 0; i < kMaxRetry; i++) { 193 await tryIt(); 194 if (wheelEvents.length != 3 && wheelEvents.length > 1 && wheelEvents.length <= 5) { 195 // Even if failed to coalescing, the sum of deltaY values should be same 196 // as sum of the synthesized ones and the wheel events shouldn't be 197 // reordered. 198 if (!checkGroupsOfWheelEvents()) { 199 return; 200 } 201 continue; // retry 202 } 203 is(wheelEvents.length, 3, 204 "Synthesizing 2 line wheel events, 1 page wheel event and 1 line wheel event via the parent process should cause only 3 wheel events"); 205 checkGroupsOfWheelEvents(); 206 return; 207 } 208 } 209 210 async function runTests() { 211 var enabled = SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled; 212 213 // Avoid synthesized mousemove events to be fired at the system cursor. 214 await promiseNativeMouseEvent({ 215 type: "mousemove", 216 screenX: 0, 217 screenY: 0, 218 }); 219 220 await SpecialPowers.pushPrefEnv({set: [ 221 ["test.events.async.enabled", true], 222 ["dom.event.wheel-coalesced.testing", true], 223 ]}); 224 await promiseElementReadyForUserInput(document.documentElement); 225 await SpecialPowers.pushPrefEnv({clear: [["test.events.async.enabled"]]}); 226 227 await testOneSingleWheelEvent(); 228 await testTwoSingleWheelEvents(); 229 await testManySingleWheelEvents(); 230 await testMixedWheelEvents(); 231 232 setTimeout(SimpleTest.finish); 233 window.close(); 234 } 235 236 </script> 237 </head> 238 <body onload="SimpleTest.waitForFocus(runTests);"> 239 <div id="wheelEventReceiver" style="width:100px;height:100px;"></div> 240 </body> 241 </html>