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">
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
= SpecialPowers
.getFullZoom(win
);
81 const initialScroll
= scrollbox
.scrollTop
;
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.");
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 /* 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");
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
= SpecialPowers
.getFullZoom(win
);
142 let check = function() {
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
);
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");
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");
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],
185 ["test.events.async.enabled", true]]}, runTest
);
188 SimpleTest
.waitForExplicitFinish();