Bug 1150452 - Make startAndCompleteDragOperation more robust across all platforms. r=Gijs

This commit is contained in:
Kartikaya Gupta 2015-04-10 08:13:00 -04:00
parent 744a3ec0e6
commit 5586c20adf
2 changed files with 75 additions and 27 deletions

View File

@ -12,7 +12,7 @@ support-files =
[browser_newtab_bug725996.js]
[browser_newtab_bug734043.js]
[browser_newtab_bug735987.js]
skip-if = os == "mac" # Intermittent failures, bug 898317
skip-if = (os == 'mac' && os_version == '10.10') # bug 1122478 - newtab drag-drop tests fail on OS X 10.10
[browser_newtab_bug752841.js]
[browser_newtab_bug765628.js]
[browser_newtab_bug876313.js]
@ -21,9 +21,9 @@ skip-if = os == "mac" # Intermittent failures, bug 898317
[browser_newtab_bug998387.js]
[browser_newtab_disable.js]
[browser_newtab_drag_drop.js]
skip-if = os == "win" && debug || (os == 'mac' && os_version == '10.10') # bug 1097056; test fails in --run-by-dir mode on win8 x64 debug; Bug 1122479 - newtab drag-drop tests fail on OS X 10.10
skip-if = os == "win" || (os == 'mac' && os_version == '10.10') # Bug 1152810 - can't do simulateDrop(0,0) on Windows; Bug 1122478 - newtab drag-drop tests fail on OS X 10.10
[browser_newtab_drag_drop_ext.js]
skip-if = (os == 'mac' && os_version == '10.10') # bug 1122479 - newtab drag-drop tests fail on OS X 10.10
skip-if = (os == 'mac' && os_version == '10.10') # bug 1122478 - newtab drag-drop tests fail on OS X 10.10
[browser_newtab_drop_preview.js]
[browser_newtab_enhanced.js]
[browser_newtab_focus.js]

View File

@ -495,33 +495,81 @@ function simulateExternalDrop(aDestIndex) {
* @param aCallback The function that is called when we're done.
*/
function startAndCompleteDragOperation(aSource, aDest, aCallback) {
// Start by pressing the left mouse button.
synthesizeNativeMouseLDown(aSource);
// The implementation of this function varies by platform because each
// platform has particular quirks that we need to deal with
// Move the mouse in 5px steps until the drag operation starts.
let offset = 0;
let interval = setInterval(() => {
synthesizeNativeMouseDrag(aSource, offset += 5);
}, 10);
// When the drag operation has started we'll move
// the dragged element to its target position.
aSource.addEventListener("dragstart", function onDragStart() {
aSource.removeEventListener("dragstart", onDragStart);
clearInterval(interval);
// Place the cursor above the drag target.
synthesizeNativeMouseMove(aDest);
});
// As soon as the dragged element hovers the target, we'll drop it.
aDest.addEventListener("dragenter", function onDragEnter() {
aDest.removeEventListener("dragenter", onDragEnter);
// Finish the drop operation.
if (isMac) {
// On OS X once the drag starts, Cocoa manages the drag session and
// gives us a limited amount of time to complete the drag operation. In
// some cases as soon as the first mouse-move event is received (the one
// that starts the drag session), Cocoa becomes blind to subsequent mouse
// events and completes the drag session all by itself. Therefore it is
// important that the first mouse-move we send is already positioned at
// the destination.
synthesizeNativeMouseLDown(aSource);
synthesizeNativeMouseDrag(aDest);
// In some tests, aSource and aDest are at the same position, so to ensure
// a drag session is created (instead of it just turning into a click) we
// move the mouse 10 pixels away and then back.
synthesizeNativeMouseDrag(aDest, 10);
synthesizeNativeMouseDrag(aDest);
// Finally, release the drag and have it run the callback when done.
synthesizeNativeMouseLUp(aDest);
aCallback();
});
} else if (isWindows) {
// on Windows once the drag is initiated, Windows doesn't spin our
// message loop at all, so with async event synthesization the async
// messages never get processed while a drag is in progress. So if
// we did a mousedown followed by a mousemove, we would never be able
// to successfully dispatch the mouseup. Instead, we just skip the move
// entirely, so and just generate the up at the destination. This way
// Windows does the drag and also terminates it right away. Note that
// this only works for tests where aSource and aDest are sufficiently
// far to trigger a drag, otherwise it may just end up doing a click.
synthesizeNativeMouseLDown(aSource);
synthesizeNativeMouseLUp(aDest);
aCallback();
} else if (isLinux) {
// Start by pressing the left mouse button.
synthesizeNativeMouseLDown(aSource);
// Move the mouse in 5px steps until the drag operation starts.
// Note that we need to do this with pauses in between otherwise the
// synthesized events get coalesced somewhere in the guts of GTK. In order
// to successfully initiate a drag session in the case where aSource and
// aDest are at the same position, we synthesize a bunch of drags until
// we know the drag session has started, and then move to the destination.
let offset = 0;
let interval = setInterval(() => {
synthesizeNativeMouseDrag(aSource, offset += 5);
}, 10);
// When the drag operation has started we'll move
// the dragged element to its target position.
aSource.addEventListener("dragstart", function onDragStart() {
aSource.removeEventListener("dragstart", onDragStart);
clearInterval(interval);
// Place the cursor above the drag target.
synthesizeNativeMouseMove(aDest);
});
// As soon as the dragged element hovers the target, we'll drop it.
// Note that we need to actually wait for the dragenter event here, because
// the mousemove synthesization is "more async" than the mouseup
// synthesization - they use different gdk APIs. If we don't wait, the
// up could get processed before the moves, dropping the item in the
// wrong position.
aDest.addEventListener("dragenter", function onDragEnter() {
aDest.removeEventListener("dragenter", onDragEnter);
// Finish the drop operation.
synthesizeNativeMouseLUp(aDest, null);
aCallback();
});
} else {
throw "Unsupported platform";
}
}
/**