зеркало из https://github.com/mozilla/pjs.git
Bug 716793. Dispatch synthetic mousemove off the refresh driver, not as fast as we can. r=roc
We use Flush_Display here because mousemoves flush out layout, so we want to do the synthetic one after we've done our normal layout flushing
This commit is contained in:
Родитель
218b374788
Коммит
ec4e4ed1e5
|
@ -5246,7 +5246,8 @@ void PresShell::SynthesizeMouseMove(bool aFromScroll)
|
|||
nsRefPtr<nsSynthMouseMoveEvent> ev =
|
||||
new nsSynthMouseMoveEvent(this, aFromScroll);
|
||||
|
||||
if (NS_FAILED(NS_DispatchToCurrentThread(ev))) {
|
||||
if (!GetPresContext()->RefreshDriver()->AddRefreshObserver(ev,
|
||||
Flush_Display)) {
|
||||
NS_WARNING("failed to dispatch nsSynthMouseMoveEvent");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -852,17 +852,28 @@ private:
|
|||
// over our window or there is no last observed mouse location for some
|
||||
// reason.
|
||||
nsPoint mMouseLocation;
|
||||
class nsSynthMouseMoveEvent : public nsRunnable {
|
||||
class nsSynthMouseMoveEvent : public nsARefreshObserver {
|
||||
public:
|
||||
nsSynthMouseMoveEvent(PresShell* aPresShell, bool aFromScroll)
|
||||
: mPresShell(aPresShell), mFromScroll(aFromScroll) {
|
||||
NS_ASSERTION(mPresShell, "null parameter");
|
||||
}
|
||||
void Revoke() { mPresShell = nsnull; }
|
||||
NS_IMETHOD Run() {
|
||||
~nsSynthMouseMoveEvent() {
|
||||
Revoke();
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(nsSynthMouseMoveEvent)
|
||||
|
||||
void Revoke() {
|
||||
if (mPresShell) {
|
||||
mPresShell->GetPresContext()->RefreshDriver()->
|
||||
RemoveRefreshObserver(this, Flush_Display);
|
||||
mPresShell = nsnull;
|
||||
}
|
||||
}
|
||||
virtual void WillRefresh(mozilla::TimeStamp aTime) {
|
||||
if (mPresShell)
|
||||
mPresShell->ProcessSynthMouseMoveEvent(mFromScroll);
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
PresShell* mPresShell;
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html style="height: 100%">
|
||||
<body style="height: 100%">
|
||||
<!-- Button shouldn't get pointer events because it confuses tests if it
|
||||
can be hovered -->
|
||||
<button style="position: relative; display: table; width: 50%;
|
||||
height: 50%; top: 25%; left: 25%">
|
||||
height: 50%; top: 25%; left: 25%; pointer-events: none">
|
||||
<div style="position: absolute; left: 0; right: 0; top: 0; bottom: 0;
|
||||
background: green"></div>
|
||||
</button>
|
||||
|
|
|
@ -12,8 +12,11 @@
|
|||
</script>
|
||||
</head>
|
||||
<body style="height: 100%" onload="doIt()">
|
||||
<!-- Button shouldn't get pointer events because it confuses tests if it
|
||||
can be hovered -->
|
||||
<button id="x" style="position: relative; display: table; width: 50%;
|
||||
height: 50%; top: 25%; left: 25%">
|
||||
height: 50%; top: 25%; left: 25%;
|
||||
pointer-events: none">
|
||||
</button>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html style="height: 100%">
|
||||
<body style="height: 100%">
|
||||
<!-- Button shouldn't get pointer events because it confuses tests if it
|
||||
can be hovered -->
|
||||
<button style="position: relative; display: table-cell; width: 50%;
|
||||
height: 50%; top: 25%; left: 25%">
|
||||
height: 50%; top: 25%; left: 25%; pointer-events: none">
|
||||
<div style="position: absolute; left: 0; right: 0; top: 0; bottom: 0;
|
||||
background: green"></div>
|
||||
</button>
|
||||
|
|
|
@ -12,8 +12,11 @@
|
|||
</script>
|
||||
</head>
|
||||
<body style="height: 100%" onload="doIt()">
|
||||
<!-- Button shouldn't get pointer events because it confuses tests if it
|
||||
can be hovered -->
|
||||
<button id="x" style="position: relative; display: table-cell; width: 50%;
|
||||
height: 50%; top: 25%; left: 25%">
|
||||
height: 50%; top: 25%; left: 25%;
|
||||
pointer-events: none">
|
||||
</button>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html style="height: 100%">
|
||||
<body style="height: 100%">
|
||||
<!-- Button shouldn't get pointer events because it confuses tests if it
|
||||
can be hovered -->
|
||||
<button style="position: relative; display: table-row; width: 50%;
|
||||
height: 50%; top: 25%; left: 25%">
|
||||
height: 50%; top: 25%; left: 25%; pointer-events: none">
|
||||
<div style="position: absolute; left: 0; right: 0; top: 0; bottom: 0;
|
||||
background: green"></div>
|
||||
</button>
|
||||
|
|
|
@ -12,8 +12,11 @@
|
|||
</script>
|
||||
</head>
|
||||
<body style="height: 100%" onload="doIt()">
|
||||
<!-- Button shouldn't get pointer events because it confuses tests if it
|
||||
can be hovered -->
|
||||
<button id="x" style="position: relative; display: table-row; width: 50%;
|
||||
height: 50%; top: 25%; left: 25%">
|
||||
height: 50%; top: 25%; left: 25%;
|
||||
pointer-events: none">
|
||||
</button>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -135,9 +135,15 @@
|
|||
|
||||
function testMouse(x, y, msg, elem, win, exp, flags, callback) {
|
||||
clearExpectedEvents();
|
||||
var syntheticEvent = null;
|
||||
exp.forEach(function (expEv) {
|
||||
expEv.screenX = x;
|
||||
expEv.screenY = y;
|
||||
if (expEv.synthetic) {
|
||||
is(syntheticEvent, null,
|
||||
"Can't handle two synthetic events in a single testMouse call");
|
||||
syntheticEvent = expEv;
|
||||
}
|
||||
gExpectedEvents.push(expEv);
|
||||
});
|
||||
printDebug("sending event: " + x + ", " + y + " (" + msg + ")\n");
|
||||
|
@ -146,11 +152,23 @@
|
|||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
var utils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
utils.sendNativeMouseEvent(x, y, msg, flags || 0, elem);
|
||||
gAfterLoopExecution = setTimeout(function () {
|
||||
var callbackFunc = function() {
|
||||
clearExpectedEvents();
|
||||
callback();
|
||||
}, 0);
|
||||
}
|
||||
if (syntheticEvent) {
|
||||
// Set up this listener before we sendNativeMouseEvent, just
|
||||
// in case that synchronously calls us.
|
||||
eventListenOnce(syntheticEvent.target, syntheticEvent.type,
|
||||
// Trigger callbackFunc async, so we're not assuming
|
||||
// anything about how our listener gets ordered with
|
||||
// others.
|
||||
function () { SimpleTest.executeSoon(callbackFunc) });
|
||||
}
|
||||
utils.sendNativeMouseEvent(x, y, msg, flags || 0, elem);
|
||||
if (!syntheticEvent) {
|
||||
gAfterLoopExecution = setTimeout(callbackFunc, 0);
|
||||
}
|
||||
}
|
||||
|
||||
function eventListenOnce(elem, name, callback) {
|
||||
|
@ -300,7 +318,7 @@
|
|||
// Clicking an inactive window should make it active and fire a mouseover
|
||||
// event.
|
||||
[400, 150, NSLeftMouseDown, null, right, [
|
||||
{ type: "mouseover", target: rightElem },
|
||||
{ type: "mouseover", target: rightElem, synthetic: true },
|
||||
]],
|
||||
[400, 150, NSLeftMouseUp, null, right, [
|
||||
]],
|
||||
|
@ -343,7 +361,15 @@
|
|||
function raiseLeftWindow(callback) {
|
||||
clearExpectedEvents();
|
||||
gExpectedEvents.push({ screenX: 150, screenY: 170, type: "mouseover", target: leftElem });
|
||||
focusAndThen(left, function () { SimpleTest.executeSoon(callback); });
|
||||
// We have to be a bit careful here. The synthetic mouse event may
|
||||
// not fire for a bit after we focus the left window.
|
||||
eventListenOnce(leftElem, "mouseover", function() {
|
||||
// Trigger callback async, so we're not assuming
|
||||
// anything about how our listener gets ordered with others.
|
||||
SimpleTest.executeSoon(callback);
|
||||
});
|
||||
printDebug("focusing left window");
|
||||
left.focus();
|
||||
},
|
||||
// It's active, so it should respond to mousemove events now.
|
||||
[150, 170, NSMouseMoved, null, left, [
|
||||
|
@ -384,7 +410,7 @@
|
|||
// Activate the right window with a click.
|
||||
// This will close the popup and make the mouse enter the right window.
|
||||
[400, 180, NSLeftMouseDown, null, right, [
|
||||
{ type: "mouseover", target: rightElem },
|
||||
{ type: "mouseover", target: rightElem, synthetic: true },
|
||||
]],
|
||||
[400, 180, NSLeftMouseUp, null, right, [
|
||||
]],
|
||||
|
|
|
@ -109,19 +109,44 @@ function test2() {
|
|||
|
||||
ok(!box.mozMatchesSelector(":hover"), "Box shouldn't be hovered (since the mouse isn't over it and since it's in a non-clickthrough iframe in a background window)");
|
||||
|
||||
// A function to waitForFocus and then wait for synthetic mouse
|
||||
// events to happen. Note that those happen off the refresh driver,
|
||||
// and happen after animation frame requests.
|
||||
function changeFocusAndAwaitSyntheticMouse(callback, winToFocus,
|
||||
elementToWatchForMouseEventOn) {
|
||||
function mouseWatcher() {
|
||||
elementToWatchForMouseEventOn.removeEventListener("mouseover",
|
||||
mouseWatcher,
|
||||
false);
|
||||
elementToWatchForMouseEventOn.removeEventListener("mouseout",
|
||||
mouseWatcher,
|
||||
false);
|
||||
SimpleTest.executeSoon(callback);
|
||||
}
|
||||
elementToWatchForMouseEventOn.addEventListener("mouseover",
|
||||
mouseWatcher,
|
||||
false);
|
||||
elementToWatchForMouseEventOn.addEventListener("mouseout",
|
||||
mouseWatcher,
|
||||
false);
|
||||
// Just pass a dummy function to waitForFocus; the mouseout/over listener
|
||||
// will actually handle things for us.
|
||||
SimpleTest.waitForFocus(function() {}, winToFocus);
|
||||
}
|
||||
|
||||
// Move the mouse over the box.
|
||||
moveMouseTo(100, 150, function () {
|
||||
ok(!box.mozMatchesSelector(":hover"), "Box shouldn't be hovered (since it's in a non-clickthrough iframe in a background window)");
|
||||
// Activate the left window.
|
||||
SimpleTest.waitForFocus(function () {
|
||||
changeFocusAndAwaitSyntheticMouse(function () {
|
||||
ok(gIFrame.mozMatchesSelector(":hover"), "iframe should be hovered");
|
||||
ok(box.mozMatchesSelector(":hover"), "Box should be hovered");
|
||||
// De-activate the window (by activating the right window).
|
||||
SimpleTest.waitForFocus(function () {
|
||||
changeFocusAndAwaitSyntheticMouse(function () {
|
||||
ok(!gIFrame.mozMatchesSelector(":hover"), "iframe shouldn't be hovered");
|
||||
ok(!box.mozMatchesSelector(":hover"), "Box shouldn't be hovered");
|
||||
// Re-activate it.
|
||||
SimpleTest.waitForFocus(function () {
|
||||
changeFocusAndAwaitSyntheticMouse(function () {
|
||||
ok(gIFrame.mozMatchesSelector(":hover"), "iframe should be hovered");
|
||||
ok(box.mozMatchesSelector(":hover"), "Box should be hovered");
|
||||
// Unhover box and iframe by moving the mouse outside the window.
|
||||
|
@ -130,9 +155,9 @@ function test2() {
|
|||
ok(!box.mozMatchesSelector(":hover"), "box shouldn't be hovered");
|
||||
finalize();
|
||||
});
|
||||
}, gLeftWindow);
|
||||
}, gRightWindow);
|
||||
}, gLeftWindow);
|
||||
}, gLeftWindow, box);
|
||||
}, gRightWindow, box);
|
||||
}, gLeftWindow, box);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче