4 https://bugzilla.mozilla.org/show_bug.cgi?id=574663
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"/>
13 <a target=
"_blank" href=
"https://bugzilla.mozilla.org/show_bug.cgi?id=574663">Mozilla Bug
574663</a>
15 <div id=
"content" style=
"display: none">
19 <script type=
"application/javascript">
21 /** Test for Bug
574663 **/
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() {
34 var onpaint = function() {
35 if (!utils.isMozAfterPaintPending) {
36 win.removeEventListener(
"MozAfterPaint", onpaint);
40 if (utils.isTestControllingRefreshes) {
41 utils.advanceTimeAndRefresh(
0);
44 win.addEventListener(
"MozAfterPaint", onpaint);
45 if (utils.isTestControllingRefreshes) {
46 utils.advanceTimeAndRefresh(
0);
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.
55 function sendTouchpadScrollMotion(scrollbox, direction, ctrl, momentum, callback) {
56 var win = scrollbox.ownerDocument.defaultView;
57 let winUtils = SpecialPowers.getDOMWindowUtils(win);
60 deltaMode: WheelEvent.DOM_DELTA_PIXEL,
61 deltaY: direction * kDelta,
62 lineOrPageDeltaY: direction,
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 = winUtils.fullZoom;
81 const initialScroll = scrollbox.scrollTop;
83 const effectOfWheelEvent = SimpleTest.promiseWaitForCondition(() =
> {
84 return ((winUtils.fullZoom != initialZoom) || (scrollbox.scrollTop != initialScroll));
85 },
"Mouse wheel should have caused us to either zoom or scroll.");
87 synthesizeWheel(scrollbox,
10,
10, event, win);
89 // then additional pixel scroll
90 event.lineOrPageDeltaY =
0;
91 synthesizeWheel(scrollbox,
10,
10, event, win);
93 effectOfWheelEvent.then(callback);
97 var win = open('bug574663.html', '_blank', 'width=
300,height=
300');
98 let winUtils = SpecialPowers.getDOMWindowUtils(win);
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 const {Services} = ChromeUtils.import(
"resource://gre/modules/Services.jsm");
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");
116 /* eslint-enable no-shadow */
117 chromeScript.promiseOneMessage(
"blank-attribute-removed").then(() =
> {
118 chromeScript.destroy();
119 waitForPaint(win, winUtils, callback);
124 waitUntilPainted(function () {
125 var scrollbox = win.document.getElementById(
"scrollbox");
126 let outstandingTests = [
133 // grab the refresh driver, since we want to make sure
134 // async scrolls happen in deterministic time
135 winUtils.advanceTimeAndRefresh(
1000);
137 function nextTest() {
138 let [ctrlKey, isMomentum] = outstandingTests.shift();
139 let scrollTopBefore = scrollbox.scrollTop;
140 let zoomFactorBefore = winUtils.fullZoom;
142 let check = function() {
144 let postfix = isMomentum ?
", even after releasing the touchpad" :
"";
145 // Normal scroll: scroll
146 is(winUtils.fullZoom, zoomFactorBefore,
"Normal scrolling shouldn't change zoom" + postfix);
147 isnot(scrollbox.scrollTop, scrollTopBefore,
148 "Normal scrolling should scroll" + postfix);
151 isnot(winUtils.fullZoom, 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");
154 is(winUtils.fullZoom, zoomFactorBefore,
"Momentum scrolling shouldn't zoom, even when pressing Ctrl");
155 isnot(scrollbox.scrollTop, scrollTopBefore,
156 "Momentum scrolling should scroll, even when pressing Ctrl");
160 if (!outstandingTests.length) {
161 winUtils.restoreNormalRefresh();
167 // Revert the effect for the next test.
168 sendTouchpadScrollMotion(scrollbox, -
1, ctrlKey, isMomentum, function() {
169 setTimeout(nextTest,
0);
173 sendTouchpadScrollMotion(scrollbox,
1, ctrlKey, isMomentum, check);
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]]}, runTest);
187 SimpleTest.waitForExplicitFinish();