diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp
index ad1a98c382f2..a3ac02e990c2 100644
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1033,6 +1033,12 @@ nsDOMWindowUtils::SendWheelEvent(float aX,
widget->DispatchAPZAwareEvent(&wheelEvent);
+ if (gfxPrefs::AsyncPanZoomEnabled()) {
+ // Computing overflow deltas is not compatible with APZ, so if APZ is
+ // enabled, we skip testing it.
+ return NS_OK;
+ }
+
bool failedX = false;
if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_ZERO) &&
wheelEvent.overflowDeltaX != 0) {
diff --git a/dom/events/test/test_bug574663.html b/dom/events/test/test_bug574663.html
index 6150c5b0b9b2..355ba6c844be 100644
--- a/dom/events/test/test_bug574663.html
+++ b/dom/events/test/test_bug574663.html
@@ -20,7 +20,37 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=574663
/** Test for Bug 574663 **/
-function sendTouchpadScrollMotion(scrollbox, direction, ctrl, momentum) {
+// SimpleTest's paint_listener does not work on other windows, so we inline
+// a smaller version here.
+function waitForPaint(win, utils, callback) {
+ win.document.documentElement.getBoundingClientRect();
+ if (!utils.isMozAfterPaintPending) {
+ callback();
+ return;
+ }
+
+ var onpaint = function() {
+ if (!utils.isMozAfterPaintPending) {
+ win.removeEventListener("MozAfterPaint", onpaint);
+ callback();
+ return;
+ }
+ }
+ win.addEventListener("MozAfterPaint", onpaint);
+ if (utils.isTestControllingRefreshes) {
+ utils.advanceTimeAndRefresh(0);
+ }
+}
+
+function forceScrollAndWait(scrollbox, callback) {
+ let win = scrollbox.ownerDocument.defaultView;
+ let utils = SpecialPowers.getDOMWindowUtils(win);
+
+ utils.advanceTimeAndRefresh(1000);
+ waitForPaint(win, utils, callback);
+}
+
+function sendTouchpadScrollMotion(scrollbox, direction, ctrl, momentum, callback) {
var win = scrollbox.ownerDocument.defaultView;
let event = {
deltaMode: WheelEvent.DOM_DELTA_PIXEL,
@@ -29,10 +59,26 @@ function sendTouchpadScrollMotion(scrollbox, direction, ctrl, momentum) {
ctrlKey: ctrl,
isMomentum: momentum
};
+
+ let kExtraEvents = 5;
+
+ var received = 0;
+ var onwheel = function() {
+ if (++received == 1 + kExtraEvents) {
+ // We have captured all the outstanding wheel events. Wait for the
+ // animation to add itself to the refresh driver.
+ scrollbox.removeEventListener("wheel", onwheel);
+ setTimeout(function() {
+ forceScrollAndWait(scrollbox, callback);
+ }, 0);
+ }
+ };
+ scrollbox.addEventListener("wheel", onwheel);
+
synthesizeWheel(scrollbox, 10, 10, event, win);
// then 5 additional pixel scrolls
event.lineOrPageDeltaY = 0;
- for (let i = 0; i < 5; ++i) {
+ for (let i = 1; i <= kExtraEvents; ++i) {
synthesizeWheel(scrollbox, 10, 10, event, win);
}
}
@@ -57,21 +103,11 @@ function runTest() {
winUtils.advanceTimeAndRefresh(1000);
function nextTest() {
- if (!outstandingTests.length) {
- winUtils.restoreNormalRefresh();
- win.close();
- SimpleTest.finish();
- return;
- }
-
let [ctrlKey, isMomentum] = outstandingTests.shift();
let scrollTopBefore = scrollbox.scrollTop;
let zoomFactorBefore = winUtils.fullZoom;
- sendTouchpadScrollMotion(scrollbox, 1, ctrlKey, isMomentum);
- winUtils.advanceTimeAndRefresh(1000); // force scrolling to happen
-
- setTimeout(function () {
+ let check = function() {
if (!ctrlKey) {
let postfix = isMomentum ? ", even after releasing the touchpad" : "";
// Normal scroll: scroll
@@ -86,12 +122,21 @@ function runTest() {
isnot(scrollbox.scrollTop, scrollTopBefore, "Momentum scrolling should scroll, even when pressing Ctrl");
}
}
- // Revert the effect.
- sendTouchpadScrollMotion(scrollbox, -1, ctrlKey, isMomentum);
- winUtils.advanceTimeAndRefresh(1000); // force scrolling to happen
- setTimeout(nextTest, 20);
- }, 20);
+ if (!outstandingTests.length) {
+ winUtils.restoreNormalRefresh();
+ win.close();
+ SimpleTest.finish();
+ return;
+ }
+
+ // Revert the effect for the next test.
+ sendTouchpadScrollMotion(scrollbox, -1, ctrlKey, isMomentum, function() {
+ setTimeout(nextTest, 0);
+ });
+ }
+
+ sendTouchpadScrollMotion(scrollbox, 1, ctrlKey, isMomentum, check);
}
nextTest();
}, win);
@@ -106,7 +151,6 @@ window.onload = function() {
}
SimpleTest.waitForExplicitFinish();
-SimpleTest.requestFlakyTimeout("untriaged");
diff --git a/dom/events/test/window_wheel_default_action.html b/dom/events/test/window_wheel_default_action.html
index 25e6146ec6a3..10ca4897b6f4 100644
--- a/dom/events/test/window_wheel_default_action.html
+++ b/dom/events/test/window_wheel_default_action.html
@@ -4,6 +4,7 @@
Test for default action of WheelEvent
+
@@ -68,6 +69,11 @@ function ok()
window.opener.ok.apply(window.opener, arguments);
}
+function sendWheelAndWait(aX, aY, aEvent, aCallback)
+{
+ sendWheelAndPaint(gScrollableElement, aX, aY, aEvent, aCallback);
+}
+
function hitEventLoop(aFunc, aTimes)
{
winUtils.advanceTimeAndRefresh(100);
@@ -864,9 +870,7 @@ function doTestScroll(aSettings, aCallback)
currentTest.prepare();
}
- synthesizeWheel(gScrollableElement, 10, 10, currentTest.event);
-
- hitEventLoop(function () {
+ sendWheelAndWait(10, 10, currentTest.event, function () {
if (currentTest.expected == kNoScroll) {
is(gScrollableElement.scrollTop, 1000, description + "scrolled vertical");
is(gScrollableElement.scrollLeft, 1000, description + "scrolled horizontal");
@@ -1111,7 +1115,6 @@ function doTestZoom(aSettings, aCallback)
var event = currentTest.event;
event.ctrlKey = true;
- synthesizeWheel(gScrollableElement, 10, 10, event);
// NOTE: Zooming might change scrollTop and scrollLeft by rounding fraction.
// This test assume that zoom happens synchronously and scrolling
@@ -1119,7 +1122,7 @@ function doTestZoom(aSettings, aCallback)
var scrollTop = gScrollableElement.scrollTop;
var scrollLeft = gScrollableElement.scrollLeft;
- hitEventLoop(function () {
+ sendWheelAndWait(10, 10, event, function () {
is(gScrollableElement.scrollTop, scrollTop, description + "scrolled vertical");
is(gScrollableElement.scrollLeft, scrollLeft, description + "scrolled horizontal");
if (!(currentTest.expected & (kNegative | kPositive))) {
@@ -1190,11 +1193,15 @@ function doTestZoomedScroll(aCallback)
}
window.addEventListener("MozMousePixelScroll", mousePixelScrollHandler, true);
window.addEventListener("wheel", wheelHandler, true);
- synthesizeWheel(gScrollableElement, 10, 10,
- { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
- deltaX: 16.0, deltaY: 16.0, lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 });
+ var event = {
+ deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+ deltaX: 16.0,
+ deltaY: 16.0,
+ lineOrPageDeltaX: 0,
+ lineOrPageDeltaY: 0
+ };
// wait scrolled actually.
- hitEventLoop(function () {
+ sendWheelAndWait(10, 10, event, function () {
var scrolledX = gScrollableElement.scrollLeft;
var scrolledY = gScrollableElement.scrollTop;
ok(scrolledX > 1000,
@@ -1208,11 +1215,15 @@ function doTestZoomedScroll(aCallback)
hitEventLoop(function () {
gScrollableElement.scrollTop = 1000;
gScrollableElement.scrollLeft = 1000;
- synthesizeWheel(gScrollableElement, 10, 10,
- { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
- deltaX: 16.0, deltaY: 16.0, lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 });
+ var event = {
+ deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+ deltaX: 16.0,
+ deltaY: 16.0,
+ lineOrPageDeltaX: 0,
+ lineOrPageDeltaY: 0
+ };
// wait scrolled actually.
- hitEventLoop(function () {
+ sendWheelAndWait(10, 10, event, function () {
ok(Math.abs(gScrollableElement.scrollLeft - (1000 + (scrolledX - 1000) / 2)) <= 1,
"doTestZoomedScroll: zoomed horizontal scroll amount by pixel wheel event is different from normal, scrollLeft=" +
gScrollableElement.scrollLeft + ", scrolledX=" + scrolledX);
@@ -1267,11 +1278,15 @@ function doTestZoomedScroll(aCallback)
}
}
window.addEventListener("MozMousePixelScroll", handler, true);
- synthesizeWheel(gScrollableElement, 10, 10,
- { deltaMode: WheelEvent.DOM_DELTA_LINE,
- deltaX: 1.0, deltaY: 1.0, lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 });
+ var event = {
+ deltaMode: WheelEvent.DOM_DELTA_LINE,
+ deltaX: 1.0,
+ deltaY: 1.0,
+ lineOrPageDeltaX: 1,
+ lineOrPageDeltaY: 1
+ };
// wait scrolled actually.
- hitEventLoop(function () {
+ sendWheelAndWait(10, 10, event, function () {
var scrolledX = gScrollableElement.scrollLeft;
var scrolledY = gScrollableElement.scrollTop;
ok(scrolledX > 1000,
@@ -1285,11 +1300,15 @@ function doTestZoomedScroll(aCallback)
hitEventLoop(function () {
gScrollableElement.scrollTop = 1000;
gScrollableElement.scrollLeft = 1000;
- synthesizeWheel(gScrollableElement, 10, 10,
- { deltaMode: WheelEvent.DOM_DELTA_LINE,
- deltaX: 1.0, deltaY: 1.0, lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 });
+ var event = {
+ deltaMode: WheelEvent.DOM_DELTA_LINE,
+ deltaX: 1.0,
+ deltaY: 1.0,
+ lineOrPageDeltaX: 1,
+ lineOrPageDeltaY: 1
+ };
// wait scrolled actually.
- hitEventLoop(function () {
+ sendWheelAndWait(10, 10, event, function () {
ok(Math.abs(gScrollableElement.scrollLeft - scrolledX) <= 1,
"doTestZoomedScroll: zoomed horizontal scroll amount by line wheel event is different from normal, scrollLeft=" +
gScrollableElement.scrollLeft + ", scrolledX=" + scrolledX);
@@ -1549,8 +1568,7 @@ function doTestWholeScroll(aCallback)
if (kTest.prepare) {
kTest.prepare();
}
- synthesizeWheel(gScrollableElement, 10, 10, kTest.event);
- hitEventLoop(function () {
+ sendWheelAndWait(10, 10, kTest.event, function () {
is(gScrollableElement.scrollTop, kTest.expectedScrollTop,
"doTestWholeScroll, " + kTest.description + ": unexpected scrollTop");
is(gScrollableElement.scrollLeft, kTest.expectedScrollLeft,
@@ -1700,8 +1718,7 @@ function doTestActionOverride(aCallback)
SpecialPowers.setIntPref("mousewheel.default.action.override_x", kTest.override_x);
gScrollableElement.scrollTop = 1000;
gScrollableElement.scrollLeft = 1000;
- synthesizeWheel(gScrollableElement, 10, 10, kTest.event);
- hitEventLoop(function () {
+ sendWheelAndWait(10, 10, kTest.event, function () {
if (kTest.expected & kScrollUp) {
ok(gScrollableElement.scrollTop < 1000, description + "not scrolled up, got " + gScrollableElement.scrollTop);
} else if (kTest.expected & kScrollDown) {
diff --git a/layout/generic/test/mochitest.ini b/layout/generic/test/mochitest.ini
index 111c64b39a93..345159e4941d 100644
--- a/layout/generic/test/mochitest.ini
+++ b/layout/generic/test/mochitest.ini
@@ -128,7 +128,7 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
[test_plugin_position.xhtml]
skip-if = e10s
[test_scroll_behavior.html]
-skip-if = e10s || buildapp == 'b2g' # Bug 1062609
+skip-if = buildapp == 'b2g' # Bug 1062609
[test_selection_expanding.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' # b2g(mouse selection not working) b2g-debug(mouse selection not working) b2g-desktop(mouse selection not working)
support-files = selection_expanding_xbl.xml
diff --git a/layout/generic/test/test_bug784410.html b/layout/generic/test/test_bug784410.html
index eff5c12e7f77..133435107b2e 100644
--- a/layout/generic/test/test_bug784410.html
+++ b/layout/generic/test/test_bug784410.html
@@ -4,6 +4,7 @@
Test bug 784410
+
@@ -38,13 +39,16 @@ function doneScroll() {
outer.scrollTop = 0;
break;
case 2:
- synthesizeWheel(inner, 4, 4,
- { deltaMode: WheelEvent.DOM_DELTA_LINE, deltaY: 1 });
+ // Wait for paints to flush, so APZ is notified of the new scroll offset.
+ sendWheelAndPaint(inner, 4, 4,
+ { deltaMode: WheelEvent.DOM_DELTA_LINE, deltaY: 1 },
+ function() {});
break;
case 3:
is(innerScrollOffset(), innerStartScrollOffset, "Inner element should not have scrolled down");
ok(outer.scrollTop > 0, "Outer element should have scrolled down");
+ SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
SimpleTest.finish();
break;
}
diff --git a/layout/generic/test/test_scroll_behavior.html b/layout/generic/test/test_scroll_behavior.html
index ad08abf37fab..4508e84c36f7 100644
--- a/layout/generic/test/test_scroll_behavior.html
+++ b/layout/generic/test/test_scroll_behavior.html
@@ -29,19 +29,28 @@
}
window.addEventListener("load", function(event) {
- if (event.target == document) {
- SpecialPowers.pushPrefEnv(
- { 'set': [['layout.css.scroll-behavior.enabled', true]] },
- function () {
- testScrollBehaviorInterruption(function() {
- testScrollBehaviorFramerate(function() {
- window.scrollTo(0,0);
- SimpleTest.finish();
- });
- });
- }
- );
+ if (event.target != document)
+ return;
+
+ // See bug 1062609 - these tests do not work with APZ yet. If APZ is
+ // enabled, end the tests early.
+ if (SpecialPowers.getBoolPref("layers.async-pan-zoom.enabled")) {
+ todo(false, "This test does not yet work with APZ.");
+ SimpleTest.finish();
+ return;
}
+
+ SpecialPowers.pushPrefEnv(
+ { 'set': [['layout.css.scroll-behavior.enabled', true]] },
+ function () {
+ testScrollBehaviorInterruption(function() {
+ testScrollBehaviorFramerate(function() {
+ window.scrollTo(0,0);
+ SimpleTest.finish();
+ });
+ });
+ }
+ );
}, false);
diff --git a/testing/mochitest/tests/SimpleTest/EventUtils.js b/testing/mochitest/tests/SimpleTest/EventUtils.js
index 12b02beaccc8..74b829b91c75 100644
--- a/testing/mochitest/tests/SimpleTest/EventUtils.js
+++ b/testing/mochitest/tests/SimpleTest/EventUtils.js
@@ -5,6 +5,7 @@
* sendChar
* sendString
* sendKey
+ * sendWheelAndPaint
* synthesizeMouse
* synthesizeMouseAtCenter
* synthesizePointer
@@ -430,6 +431,50 @@ function synthesizeWheel(aTarget, aOffsetX, aOffsetY, aEvent, aWindow)
lineOrPageDeltaX, lineOrPageDeltaY, options);
}
+/**
+ * This is a wrapper around synthesizeWheel that waits for the wheel event
+ * to be dispatched and for the subsequent layout/paints to be flushed.
+ *
+ * This requires including paint_listener.js. Tests must call
+ * DOMWindowUtils.restoreNormalRefresh() before finishing, if they use this
+ * function.
+ */
+function sendWheelAndPaint(aTarget, aOffsetX, aOffsetY, aEvent, aCallback, aWindow) {
+ aWindow = aWindow || window;
+
+ var utils = _getDOMWindowUtils(aWindow);
+ if (!utils)
+ return;
+
+ if (utils.isMozAfterPaintPending) {
+ // If a paint is pending, then APZ may be waiting for a scroll acknowledgement
+ // from the content thread. If we send a wheel event now, it could be ignored
+ // by APZ (or its scroll offset could be overridden). To avoid problems we
+ // just wait for the paint to complete.
+ aWindow.waitForAllPaintsFlushed(function() {
+ sendWheelAndPaint(aTarget, aOffsetX, aOffsetY, aEvent, aCallback, aWindow);
+ });
+ return;
+ }
+
+ var onwheel = function() {
+ window.removeEventListener("wheel", onwheel);
+
+ // Wait one frame since the wheel event has not caused a refresh observer
+ // to be added yet.
+ setTimeout(function() {
+ utils.advanceTimeAndRefresh(1000);
+ aWindow.waitForAllPaintsFlushed(function() {
+ utils.restoreNormalRefresh();
+ aCallback();
+ });
+ }, 0);
+ };
+
+ aWindow.addEventListener("wheel", onwheel);
+ synthesizeWheel(aTarget, aOffsetX, aOffsetY, aEvent, aWindow);
+}
+
function _computeKeyCodeFromChar(aChar)
{
if (aChar.length != 1) {
diff --git a/toolkit/content/tests/chrome/test_mousescroll.xul b/toolkit/content/tests/chrome/test_mousescroll.xul
index fa6f19d69f43..ebd4788b237f 100644
--- a/toolkit/content/tests/chrome/test_mousescroll.xul
+++ b/toolkit/content/tests/chrome/test_mousescroll.xul
@@ -8,6 +8,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=378028
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
@@ -138,46 +139,47 @@ function testRichListbox(id, andThen)
var winUtils = SpecialPowers.getDOMWindowUtils(window);
winUtils.advanceTimeAndRefresh(100);
- function helper()
- {
- var [aStart, aDelta, aIntDelta, aDeltaMode] = tests[0];
- tests.shift();
+ function nextTest() {
+ var [aStart, aDelta, aIntDelta, aDeltaMode] = tests.shift();
listbox.scrollToIndex(aStart);
- synthesizeWheel(listbox, 10, 10,
- { deltaMode: aDeltaMode, deltaY: aDelta,
- lineOrPageDeltaY: aIntDelta });
-
- winUtils.advanceTimeAndRefresh(100);
-
- var change = listbox.getIndexOfFirstVisibleRow() - aStart;
- var direction = (change > 0) - (change < 0);
- var expected = (aDelta > 0) - (aDelta < 0);
- is(direction, expected,
- "testRichListbox(" + id + "): vertical, starting " + aStart +
- " delta " + aDelta + " lineOrPageDelta " + aIntDelta +
- " aDeltaMode " + aDeltaMode);
-
- // Check that horizontal scrolling has no effect
- listbox.scrollToIndex(aStart);
- synthesizeWheel(listbox, 10, 10,
- { deltaMode: aDeltaMode, deltaX: aDelta,
- lineOrPageDeltaX: aIntDelta });
-
- winUtils.advanceTimeAndRefresh(100);
-
- is(listbox.getIndexOfFirstVisibleRow(), aStart,
- "testRichListbox(" + id + "): horizontal, starting " + aStart +
- " delta " + aDelta + " lineOrPageDelta " + aIntDelta +
+ let event = {
+ deltaMode: aDeltaMode,
+ deltaY: aDelta,
+ lineOrPageDeltaY: aIntDelta
+ };
+ sendWheelAndPaint(listbox, 10, 10, event, function() {
+ var change = listbox.getIndexOfFirstVisibleRow() - aStart;
+ var direction = (change > 0) - (change < 0);
+ var expected = (aDelta > 0) - (aDelta < 0);
+ is(direction, expected,
+ "testRichListbox(" + id + "): vertical, starting " + aStart +
+ " delta " + aDelta + " lineOrPageDeltaY " + aIntDelta +
" aDeltaMode " + aDeltaMode);
- if (tests.length) {
- winUtils.advanceTimeAndRefresh(100);
- helper();
- } else {
- winUtils.restoreNormalRefresh();
- andThen();
- }
+ // Check that horizontal scrolling has no effect
+ let event = {
+ deltaMode: aDeltaMode,
+ deltaX: aDelta,
+ lineOrPageDeltaX: aIntDelta
+ };
+
+ listbox.scrollToIndex(aStart);
+ sendWheelAndPaint(listbox, 10, 10, event, function() {
+ is(listbox.getIndexOfFirstVisibleRow(), aStart,
+ "testRichListbox(" + id + "): horizontal, starting " + aStart +
+ " delta " + aDelta + " lineOrPageDeltaX " + aIntDelta +
+ " aDeltaMode " + aDeltaMode);
+
+ if (!tests.length) {
+ winUtils.restoreNormalRefresh();
+ andThen();
+ return;
+ }
+
+ nextTest();
+ });
+ });
}
// richlistbox currently uses native XUL scrolling, so the "line"
@@ -190,7 +192,8 @@ function testRichListbox(id, andThen)
tests.push([5, delta, 1, aDeltaMode]);
tests.push([5, delta, 0, aDeltaMode]);
});
- helper();
+
+ nextTest();
}
function testArrowScrollbox(id)
diff --git a/widget/tests/window_bug478536.xul b/widget/tests/window_bug478536.xul
index ee39b2f5ecda..0a07777b4cf3 100644
--- a/widget/tests/window_bug478536.xul
+++ b/widget/tests/window_bug478536.xul
@@ -6,8 +6,12 @@
onunload="onunload();"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+