test_bug574663.html (7002B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=574663 5 --> 6 <head> 7 <title>Test for Bug 574663</title> 8 <script src="/tests/SimpleTest/SimpleTest.js"></script> 9 <script src="/tests/SimpleTest/EventUtils.js"></script> 10 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 11 </head> 12 <body> 13 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=574663">Mozilla Bug 574663</a> 14 <p id="display"></p> 15 <div id="content" style="display: none"> 16 17 </div> 18 <pre id="test"> 19 <script> 20 21 /** Test for Bug 574663 */ 22 23 // SimpleTest's paint_listener does not work on other windows, so we inline 24 // a smaller version here. 25 function waitForPaint(win, utils, callback) { 26 win.document.documentElement.getBoundingClientRect(); 27 if (!utils.isMozAfterPaintPending) { 28 win.requestAnimationFrame(function() { 29 setTimeout(callback); 30 }); 31 return; 32 } 33 34 var onpaint = function() { 35 if (!utils.isMozAfterPaintPending) { 36 win.removeEventListener("MozAfterPaint", onpaint); 37 callback(); 38 return; 39 } 40 if (utils.isTestControllingRefreshes) { 41 utils.advanceTimeAndRefresh(0); 42 } 43 } 44 win.addEventListener("MozAfterPaint", onpaint); 45 if (utils.isTestControllingRefreshes) { 46 utils.advanceTimeAndRefresh(0); 47 } 48 } 49 50 // This is a magic number representing how many device pixels we are attempting to 51 // scroll or zoom. We use it for sending the wheel events, but we don't actually 52 // check that we have scrolled by that amount. 53 var kDelta = 3; 54 55 function sendTouchpadScrollMotion(scrollbox, direction, ctrl, momentum, callback) { 56 var win = scrollbox.ownerDocument.defaultView; 57 let winUtils = SpecialPowers.getDOMWindowUtils(win); 58 59 let event = { 60 deltaMode: WheelEvent.DOM_DELTA_PIXEL, 61 deltaY: direction * kDelta, 62 lineOrPageDeltaY: direction, 63 ctrlKey: ctrl, 64 isMomentum: momentum 65 }; 66 67 // Construct a promise that will resolve when either scroll or zoom has changed. 68 // --- Intermittent Warning --- 69 // Two wheel events are sent, but our promise resolves when any change has been 70 // made to scroll or zoom. That makes it possible that the effect of the second 71 // event may not yet be applied when the promise resolves. This shouldn't lead 72 // to any errors, since the two wheel events are moving in the same direction, 73 // and our later checks will only ensure that the value has changed from its 74 // initial value. This was done intentionally, because attempting to wait after 75 // both events yields problems when the second event has no effect, which does 76 // happen in testing. It's not clear why this is happening. Since the testing 77 // pattern is scroll (twice), then scroll back (twice), it's possible that the 78 // first scroll back event is sufficient to return the scrollbox to its minimal 79 // scrollTop position, and so the second event doesn't scroll any further. 80 const initialZoom = SpecialPowers.getFullZoom(win); 81 const initialScroll = scrollbox.scrollTop; 82 83 const effectOfWheelEvent = SimpleTest.promiseWaitForCondition(() => { 84 return ((SpecialPowers.getFullZoom(win) != initialZoom) || (scrollbox.scrollTop != initialScroll)); 85 }, "Mouse wheel should have caused us to either zoom or scroll."); 86 87 synthesizeWheel(scrollbox, 10, 10, event, win); 88 89 // then additional pixel scroll 90 event.lineOrPageDeltaY = 0; 91 synthesizeWheel(scrollbox, 10, 10, event, win); 92 93 effectOfWheelEvent.then(callback); 94 } 95 96 function runTest() { 97 var win = open('bug574663.html', '_blank', 'width=300,height=300'); 98 let winUtils = SpecialPowers.getDOMWindowUtils(win); 99 100 let waitUntilPainted = function(callback) { 101 // Until the first non-blank paint, the parent will set the opacity of our 102 // browser to 0 using the 'blank' attribute. 103 // Until the blank attribute is removed, we can't send scroll events. 104 SimpleTest.waitForFocus(function() { 105 /* eslint-disable no-shadow */ 106 let chromeScript = SpecialPowers.loadChromeScript(_ => { 107 /* eslint-env mozilla/chrome-script */ 108 let win = Services.wm.getMostRecentWindow("navigator:browser"); 109 win.requestAnimationFrame(() => { 110 win.gBrowser.selectedBrowser.removeAttribute("blank"); 111 win.requestAnimationFrame(() => { 112 sendAsyncMessage("blank-attribute-removed"); 113 }); 114 }); 115 }); 116 /* eslint-enable no-shadow */ 117 chromeScript.promiseOneMessage("blank-attribute-removed").then(() => { 118 chromeScript.destroy(); 119 waitForPaint(win, winUtils, callback); 120 }); 121 }, win); 122 }; 123 124 waitUntilPainted(function () { 125 var scrollbox = win.document.getElementById("scrollbox"); 126 let outstandingTests = [ 127 [false, false], 128 [false, true], 129 [true, false], 130 [true, true], 131 ]; 132 133 // grab the refresh driver, since we want to make sure 134 // async scrolls happen in deterministic time 135 winUtils.advanceTimeAndRefresh(1000); 136 137 function nextTest() { 138 let [ctrlKey, isMomentum] = outstandingTests.shift(); 139 let scrollTopBefore = scrollbox.scrollTop; 140 let zoomFactorBefore = SpecialPowers.getFullZoom(win); 141 142 let check = function() { 143 if (!ctrlKey) { 144 let postfix = isMomentum ? ", even after releasing the touchpad" : ""; 145 // Normal scroll: scroll 146 is(SpecialPowers.getFullZoom(win), zoomFactorBefore, "Normal scrolling shouldn't change zoom" + postfix); 147 isnot(scrollbox.scrollTop, scrollTopBefore, 148 "Normal scrolling should scroll" + postfix); 149 } else { 150 if (!isMomentum) { 151 isnot(SpecialPowers.getFullZoom(win), zoomFactorBefore, "Ctrl-scrolling should zoom while the user is touching the touchpad"); 152 is(scrollbox.scrollTop, scrollTopBefore, "Ctrl-scrolling shouldn't scroll while the user is touching the touchpad"); 153 } else { 154 is(SpecialPowers.getFullZoom(win), zoomFactorBefore, "Momentum scrolling shouldn't zoom, even when pressing Ctrl"); 155 isnot(scrollbox.scrollTop, scrollTopBefore, 156 "Momentum scrolling should scroll, even when pressing Ctrl"); 157 } 158 } 159 160 if (!outstandingTests.length) { 161 winUtils.restoreNormalRefresh(); 162 win.close(); 163 SimpleTest.finish(); 164 return; 165 } 166 167 // Revert the effect for the next test. 168 sendTouchpadScrollMotion(scrollbox, -1, ctrlKey, isMomentum, function() { 169 setTimeout(nextTest, 0); 170 }); 171 } 172 173 sendTouchpadScrollMotion(scrollbox, 1, ctrlKey, isMomentum, check); 174 } 175 nextTest(); 176 }); 177 } 178 179 window.onload = function() { 180 SpecialPowers.pushPrefEnv({ 181 "set":[["general.smoothScroll", false], 182 ["mousewheel.acceleration.start", -1], 183 ["mousewheel.system_scroll_override.enabled", false], 184 ["mousewheel.with_control.action", 3], 185 ["test.events.async.enabled", true]]}, runTest); 186 } 187 188 SimpleTest.waitForExplicitFinish(); 189 190 </script> 191 </pre> 192 193 </body> 194 </html>