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">