--- a/testing/mochitest/tests/SimpleTest/EventUtils.js
+++ b/testing/mochitest/tests/SimpleTest/EventUtils.js
@@ -2,16 +2,17 @@
* EventUtils provides some utility methods for creating and sending DOM events.
* Current methods:
* sendMouseEvent
* sendDragEvent
* sendChar
* sendString
* sendKey
* sendWheelAndPaint
+ * sendWheelAndPaintNoFlush
* synthesizeMouse
* synthesizeMouseAtCenter
* synthesizePointer
* synthesizeWheel
* synthesizeWheelAtPoint
* synthesizeKey
* synthesizeNativeKey
* synthesizeMouseExpectEvent
@@ -596,40 +597,39 @@ function synthesizeWheelAtPoint(aLeft, a
*/
function synthesizeWheel(aTarget, aOffsetX, aOffsetY, aEvent, aWindow)
{
var rect = aTarget.getBoundingClientRect();
synthesizeWheelAtPoint(rect.left + aOffsetX, rect.top + aOffsetY,
aEvent, aWindow);
}
-/**
- * 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.
- *
- * If no callback is provided, the caller is assumed to have its own method of
- * determining scroll completion and the refresh driver is not automatically
- * restored.
- */
-function sendWheelAndPaint(aTarget, aOffsetX, aOffsetY, aEvent, aCallback, aWindow = window) {
+const _FlushModes = {
+ FLUSH: 0,
+ NOFLUSH: 1
+};
+
+function _sendWheelAndPaint(aTarget, aOffsetX, aOffsetY,
+ aEvent, aCallback,
+ aFlushMode = _FlushModes.FLUSH,
+ 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);
+ _sendWheelAndPaint(aTarget, aOffsetX, aOffsetY,
+ aEvent, aCallback,
+ aFlushMode,
+ aWindow);
});
return;
}
var onwheel = function() {
SpecialPowers.removeSystemEventListener(window, "wheel", onwheel);
// Wait one frame since the wheel event has not caused a refresh observer
@@ -655,17 +655,56 @@ function sendWheelAndPaint(aTarget, aOff
waitForPaints();
}
}, 0);
};
// Listen for the system wheel event, because it happens after all of
// the other wheel events, including legacy events.
SpecialPowers.addSystemEventListener(aWindow, "wheel", onwheel);
- synthesizeWheel(aTarget, aOffsetX, aOffsetY, aEvent, aWindow);
+ if (aFlushMode === _FlushModes.FLUSH) {
+ synthesizeWheel(aTarget, aOffsetX, aOffsetY, aEvent, aWindow);
+ } else {
+ synthesizeWheelAtPoint(aOffsetX, aOffsetY, aEvent, aWindow);
+ }
+}
+
+/**
+ * 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.
+ *
+ * If no callback is provided, the caller is assumed to have its own method of
+ * determining scroll completion and the refresh driver is not automatically
+ * restored.
+ */
+function sendWheelAndPaint(aTarget, aOffsetX, aOffsetY,
+ aEvent, aCallback,
+ aWindow = window) {
+ _sendWheelAndPaint(aTarget, aOffsetX, aOffsetY,
+ aEvent, aCallback,
+ _FlushModes.FLUSH,
+ aWindow);
+}
+
+/**
+ * Similar to sendWheelAndPaint but without flushing layout for obtaining
+ * |aTarget| position in |aWindow| before sending the wheel event.
+ * |aOffsetX| and |aOffsetY| should be offsets against aWindow.
+ */
+function sendWheelAndPaintNoFlush(aTarget, aOffsetX, aOffsetY,
+ aEvent, aCallback,
+ aWindow = window) {
+ _sendWheelAndPaint(aTarget, aOffsetX, aOffsetY,
+ aEvent, aCallback,
+ _FlushModes.NOFLUSH,
+ aWindow);
}
function synthesizeNativeTapAtCenter(aTarget, aLongTap = false, aCallback = null, aWindow = window) {
let rect = aTarget.getBoundingClientRect();
return synthesizeNativeTap(aTarget, rect.width / 2, rect.height / 2, aLongTap, aCallback, aWindow);
}
function synthesizeNativeTap(aTarget, aOffsetX, aOffsetY, aLongTap = false, aCallback = null, aWindow = window) {