gecko/widget/tests/native_mouse_mac_window.xul
Boris Zbarsky f12f1399b7 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
2012-01-10 00:23:29 -05:00

808 lines
33 KiB
XML

<?xml version="1.0"?>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is Native Menus Test code
-
- The Initial Developer of the Original Code is
- Mozilla Corporation.
- Portions created by the Initial Developer are Copyright (C) 2009
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Markus Stange <mstange@themasta.com>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- in which case the provisions of the GPL or the LGPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of either the GPL or the LGPL, and not to allow others to
- use your version of this file under the terms of the MPL, indicate your
- decision by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL or the LGPL. If you do not delete
- the provisions above, a recipient may use your version of this file under
- the terms of any one of the MPL, the GPL or the LGPL.
-
- ***** END LICENSE BLOCK ***** -->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window id="NativeMenuWindow"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
width="600"
height="600"
title="Native Mouse Event Test"
orient="vertical">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<box height="200" id="box"/>
<menupopup id="popup" width="250" height="50"/>
<panel id="panel" width="250" height="50" noautohide="true"/>
<script type="application/javascript"><![CDATA[
function ok(condition, message) {
window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
}
function is(a, b, message) {
window.opener.wrappedJSObject.SimpleTest.is(a, b, message);
}
function todo(condition, message) {
window.opener.wrappedJSObject.SimpleTest.todo(condition, message);
}
function todo_is(a, b, message) {
window.opener.wrappedJSObject.SimpleTest.todo_is(a, b, message);
}
function onTestsFinished() {
clearTimeout(gAfterLoopExecution);
observe(window, eventMonitor, false);
observe(gRightWindow, eventMonitor, false);
observe(gPopup, eventMonitor, false);
gRightWindow.close();
var openerSimpleTest = window.opener.wrappedJSObject.SimpleTest;
window.close();
openerSimpleTest.finish();
}
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const xulWin = 'data:application/vnd.mozilla.xul+xml,<?xml version="1.0"?><?xml-stylesheet href="chrome://global/skin" type="text/css"?><window xmlns="' + XUL_NS + '"/>';
const NSLeftMouseDown = 1,
NSLeftMouseUp = 2,
NSRightMouseDown = 3,
NSRightMouseUp = 4,
NSMouseMoved = 5,
NSLeftMouseDragged = 6,
NSRightMouseDragged = 7,
NSMouseEntered = 8,
NSMouseExited = 9,
NSKeyDown = 10,
NSKeyUp = 11,
NSFlagsChanged = 12,
NSAppKitDefined = 13,
NSSystemDefined = 14,
NSApplicationDefined = 15,
NSPeriodic = 16,
NSCursorUpdate = 17,
NSScrollWheel = 22,
NSTabletPoint = 23,
NSTabletProximity = 24,
NSOtherMouseDown = 25,
NSOtherMouseUp = 26,
NSOtherMouseDragged = 27,
NSEventTypeGesture = 29,
NSEventTypeMagnify = 30,
NSEventTypeSwipe = 31,
NSEventTypeRotate = 18,
NSEventTypeBeginGesture = 19,
NSEventTypeEndGesture = 20;
const NSAlphaShiftKeyMask = 1 << 16,
NSShiftKeyMask = 1 << 17,
NSControlKeyMask = 1 << 18,
NSAlternateKeyMask = 1 << 19,
NSCommandKeyMask = 1 << 20,
NSNumericPadKeyMask = 1 << 21,
NSHelpKeyMask = 1 << 22,
NSFunctionKeyMask = 1 << 23;
const gDebug = false;
function printDebug(msg) { if (gDebug) dump(msg); }
var gExpectedEvents = [];
var gRightWindow = null, gPopup = null;
var gCurrentMouseX = 0, gCurrentMouseY = 0;
var gAfterLoopExecution = 0;
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");
gCurrentMouseX = x;
gCurrentMouseY = y;
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var utils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
var callbackFunc = function() {
clearExpectedEvents();
callback();
}
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) {
elem.addEventListener(name, function(e) {
elem.removeEventListener(name, arguments.callee, false);
callback(e);
}, false);
}
function focusAndThen(win, callback) {
eventListenOnce(win, "focus", callback);
printDebug("focusing a window\n");
win.focus();
}
function eventToString(e) {
return JSON.stringify({
type: e.type, target: e.target.nodeName, screenX: e.screenX, screenY: e.screenY
});
}
function clearExpectedEvents() {
while (gExpectedEvents.length > 0) {
var expectedEvent = gExpectedEvents.shift();
var errFun = expectedEvent.shouldFireButDoesnt ? todo : ok;
errFun(false, "Didn't receive expected event: " + eventToString(expectedEvent));
}
}
var gEventNum = 0;
function eventMonitor(e) {
printDebug("got event: " + eventToString(e) + "\n");
processEvent(e);
}
function processEvent(e) {
if (e.screenX != gCurrentMouseX || e.screenY != gCurrentMouseY) {
todo(false, "Oh no! Received a stray event from a confused tracking area. Aborting test.");
onTestsFinished();
return;
}
var expectedEvent = gExpectedEvents.shift();
if (!expectedEvent) {
ok(false, "received event I didn't expect: " + eventToString(e));
return;
}
if (e.type != expectedEvent.type) {
// Didn't get expectedEvent.
var errFun = expectedEvent.shouldFireButDoesnt ? todo : ok;
errFun(false, "Didn't receive expected event: " + eventToString(expectedEvent));
return processEvent(e);
}
gEventNum++;
is(e.screenX, expectedEvent.screenX, gEventNum + " | wrong X coord for event " + eventToString(e));
is(e.screenY, expectedEvent.screenY, gEventNum + " | wrong Y coord for event " + eventToString(e));
is(e.target, expectedEvent.target, gEventNum + " | wrong target for event " + eventToString(e));
if (expectedEvent.firesButShouldnt) {
todo(false, gEventNum + " | Got an event that should not have fired: " + eventToString(e));
}
}
function observe(elem, fun, add) {
var addOrRemove = add ? "addEventListener" : "removeEventListener";
elem[addOrRemove]("mousemove", fun, false);
elem[addOrRemove]("mouseover", fun, false);
elem[addOrRemove]("mouseout", fun, false);
elem[addOrRemove]("mousedown", fun, false);
elem[addOrRemove]("mouseup", fun, false);
elem[addOrRemove]("click", fun, false);
}
function start() {
window.resizeTo(200, 200);
window.moveTo(50, 50);
gRightWindow = open(xulWin, '', 'chrome,screenX=300,screenY=50,width=200,height=200');
eventListenOnce(gRightWindow, "focus", function () {
focusAndThen(window, runTests);
});
gPopup = document.getElementById("popup");
}
function runTests() {
observe(window, eventMonitor, true);
observe(gRightWindow, eventMonitor, true);
var left = window, right = gRightWindow;
var leftElem = document.getElementById("box");
var rightElem = gRightWindow.document.documentElement;
var panel = document.getElementById("panel");
var tooltip = (function createTooltipInRightWindow() {
var _tooltip = right.document.createElementNS(XUL_NS, "tooltip");
_tooltip.setAttribute("id", "tip");
_tooltip.setAttribute("width", "80");
_tooltip.setAttribute("height", "20");
right.document.documentElement.appendChild(_tooltip);
return _tooltip;
})();
var tests = [
// Part 1: Disallow click-through
function blockClickThrough(callback) {
document.documentElement.setAttribute("clickthrough", "never");
gRightWindow.document.documentElement.setAttribute("clickthrough", "never");
callback();
},
// Enter the left window, which is focused.
[150, 150, NSMouseMoved, null, left, [
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem }
]],
// Test that moving inside the window fires mousemove events.
[170, 150, NSMouseMoved, null, left, [
{ type: "mousemove", target: leftElem },
]],
// Leaving the window should fire a mouseout event...
[170, 20, NSMouseMoved, null, left, [
{ type: "mouseout", target: leftElem },
]],
// ... and entering a mouseover event.
[170, 120, NSMouseMoved, null, left, [
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
// Move over the right window, which is inactive.
// Inactive windows shouldn't respond to mousemove events when clickthrough="never",
// so we should only get a mouseout event, no mouseover event.
[400, 150, NSMouseMoved, null, right, [
{ type: "mouseout", target: leftElem },
]],
// Left-clicking while holding Cmd and middle clicking should work even
// on inactive windows, but without making them active.
[400, 150, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
], NSCommandKeyMask],
[400, 150, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
], NSCommandKeyMask],
[400, 150, NSOtherMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[400, 150, NSOtherMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Clicking an inactive window should make it active and fire a mouseover
// event.
[400, 150, NSLeftMouseDown, null, right, [
{ type: "mouseover", target: rightElem, synthetic: true },
]],
[400, 150, NSLeftMouseUp, null, right, [
]],
// Now it's focused, so we should get a mousedown event when clicking.
[400, 150, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
// Let's drag to the right without letting the button go.
[410, 150, NSLeftMouseDragged, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Let go of the mouse.
[410, 150, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Move the mouse back over the left window, which is inactive.
[150, 170, NSMouseMoved, null, left, [
{ type: "mouseout", target: rightElem },
]],
// Now we're being sneaky. The left window is inactive, but *right*-clicks to it
// should still get through. Test that.
// Ideally we'd be bracketing that event with over and out events, too, but it
// probably doesn't matter too much.
[150, 170, NSRightMouseDown, null, left, [
{ type: "mouseover", target: leftElem, shouldFireButDoesnt: true },
{ type: "mousedown", target: leftElem },
{ type: "mouseout", target: leftElem, shouldFireButDoesnt: true },
]],
// Let go of the mouse.
[150, 170, NSRightMouseUp, null, left, [
{ type: "mouseover", target: leftElem, shouldFireButDoesnt: true },
{ type: "mouseup", target: leftElem },
{ type: "click", target: leftElem },
{ type: "mouseout", target: leftElem, shouldFireButDoesnt: true },
]],
// Right clicking hasn't focused it, so the window is still inactive.
// Let's focus it; this time without the mouse, for variaton's sake.
// Still, mouseout and mouseover events should fire.
function raiseLeftWindow(callback) {
clearExpectedEvents();
gExpectedEvents.push({ screenX: 150, screenY: 170, type: "mouseover", target: leftElem });
// 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, [
{ type: "mousemove", target: leftElem },
]],
// This was boring... let's introduce a popup. It will overlap both the left
// and the right window.
function openPopupInLeftWindow(callback) {
eventListenOnce(gPopup, "popupshown", callback);
gPopup.openPopupAtScreen(150, 50, true);
},
// Move the mouse over the popup.
[200, 80, NSMouseMoved, gPopup, left, [
{ type: "mouseout", target: leftElem },
{ type: "mouseover", target: gPopup },
{ type: "mousemove", target: gPopup },
]],
// Move the mouse back over the left window outside the popup.
[160, 170, NSMouseMoved, null, left, [
{ type: "mouseout", target: gPopup },
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
// Back over the popup...
[190, 80, NSMouseMoved, gPopup, left, [
{ type: "mouseout", target: leftElem },
{ type: "mouseover", target: gPopup },
{ type: "mousemove", target: gPopup },
]],
// ...and over into the right window.
// It's inactive, so it shouldn't get mouseover events yet.
[400, 170, NSMouseMoved, null, right, [
{ type: "mouseout", target: gPopup },
]],
// Again, no mouse events please, even though a popup is open. (bug 425556)
[400, 180, NSMouseMoved, null, right, [
]],
// 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, synthetic: true },
]],
[400, 180, NSLeftMouseUp, null, right, [
]],
function verifyPopupClosed2(callback) {
is(gPopup.popupBoxObject.popupState, "closed", "popup should have closed when clicking");
callback();
},
// Now the right window is active; click it again, just for fun.
[400, 180, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[400, 180, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Time for our next trick: a tooltip!
// Install the tooltip, but don't show it yet.
function setTooltip(callback) {
rightElem.setAttribute("tooltip", "tip");
gExpectedEvents.push({ screenX: 410, screenY: 180, type: "mousemove", target: rightElem });
eventListenOnce(rightElem, "popupshown", callback);
gCurrentMouseX = 410;
gCurrentMouseY = 180;
var utils = right.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
utils.sendNativeMouseEvent(410, 180, NSMouseMoved, 0, null);
},
// Now the tooltip is visible.
// Move the mouse a little to the right.
[411, 180, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Move another pixel.
[412, 180, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Move up and click to make the tooltip go away.
[412, 80, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
[412, 80, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[412, 80, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// OK, next round. Open a panel in the left window, which is inactive.
function openPanel(callback) {
eventListenOnce(panel, "popupshown", callback);
panel.openPopupAtScreen(150, 150, false);
},
// The panel is parented, so it will be z-ordered over its parent but
// under the active window.
// Now we move the mouse over the part where the panel rect intersects the
// right window's rect. Since the panel is under the window, all the events
// should target the right window.
[390, 170, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
[390, 171, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
[391, 171, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Now move off the right window, so that the mouse is directly over the
// panel.
[260, 170, NSMouseMoved, panel, left, [
{ type: "mouseout", target: rightElem },
]],
[260, 171, NSMouseMoved, panel, left, [
]],
[261, 171, NSMouseMoved, panel, left, [
]],
// Let's be evil and click it.
[261, 171, NSLeftMouseDown, panel, left, [
]],
[261, 171, NSLeftMouseUp, panel, left, [
]],
// This didn't focus the window, unfortunately, so let's do it ourselves.
function raiseLeftWindowTakeTwo(callback) {
focusAndThen(left, callback);
},
// Now mouse events should get through to the panel (which is now over the
// right window).
[387, 170, NSMouseMoved, panel, left, [
{ type: "mouseover", target: panel },
{ type: "mousemove", target: panel },
]],
[387, 171, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
[388, 171, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
// Click the panel.
[388, 171, NSLeftMouseDown, panel, left, [
{ type: "mousedown", target: panel }
]],
[388, 171, NSLeftMouseUp, panel, left, [
{ type: "mouseup", target: panel },
{ type: "click", target: panel },
]],
// Last test for this part: Hit testing in the Canyon of Nowhere -
// the pixel row directly south of the panel, over the left window.
// Before bug 515003 we wrongly thought the mouse wasn't over any window.
[173, 200, NSMouseMoved, null, left, [
{ type: "mouseout", target: panel },
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
[173, 201, NSMouseMoved, null, left, [
{ type: "mousemove", target: leftElem },
]],
// Part 2: Allow click-through
function hideThatPanel(callback) {
eventListenOnce(panel, "popuphidden", callback);
panel.hidePopup();
},
function unblockClickThrough(callback) {
document.documentElement.removeAttribute("clickthrough");
gRightWindow.document.documentElement.removeAttribute("clickthrough");
callback();
},
// Enter the left window, which is focused.
[150, 150, NSMouseMoved, null, left, [
{ type: "mousemove", target: leftElem }
]],
// Test that moving inside the window fires mousemove events.
[170, 150, NSMouseMoved, null, left, [
{ type: "mousemove", target: leftElem },
]],
// Leaving the window should fire a mouseout event...
[170, 20, NSMouseMoved, null, left, [
{ type: "mouseout", target: leftElem },
]],
// ... and entering a mouseover event.
[170, 120, NSMouseMoved, null, left, [
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
// Move over the right window, which is inactive but still accepts
// mouse events.
[400, 150, NSMouseMoved, null, right, [
{ type: "mouseout", target: leftElem },
{ type: "mouseover", target: rightElem },
{ type: "mousemove", target: rightElem },
]],
// Left-clicking while holding Cmd and middle clicking should work
// on inactive windows, but without making them active.
[400, 150, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
], NSCommandKeyMask],
[400, 150, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
], NSCommandKeyMask],
[400, 150, NSOtherMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[400, 150, NSOtherMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Clicking an inactive window should make it active
[400, 150, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[400, 150, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Now it's focused.
[401, 150, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
// Let's drag to the right without letting the button go.
[410, 150, NSLeftMouseDragged, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Let go of the mouse.
[410, 150, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Move the mouse back over the left window, which is inactive.
[150, 170, NSMouseMoved, null, left, [
{ type: "mouseout", target: rightElem },
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
// Right-click it.
[150, 170, NSRightMouseDown, null, left, [
{ type: "mousedown", target: leftElem },
]],
// Let go of the mouse.
[150, 170, NSRightMouseUp, null, left, [
{ type: "mouseup", target: leftElem },
{ type: "click", target: leftElem },
]],
// Right clicking hasn't focused it, so the window is still inactive.
// Let's focus it; this time without the mouse, for variaton's sake.
function raiseLeftWindow(callback) {
clearExpectedEvents();
focusAndThen(left, function () { SimpleTest.executeSoon(callback); });
},
// It's active and should still respond to mousemove events.
[150, 170, NSMouseMoved, null, left, [
{ type: "mousemove", target: leftElem },
]],
// This was boring... let's introduce a popup. It will overlap both the left
// and the right window.
function openPopupInLeftWindow(callback) {
eventListenOnce(gPopup, "popupshown", callback);
gPopup.openPopupAtScreen(150, 50, true);
},
// Move the mouse over the popup.
[200, 80, NSMouseMoved, gPopup, left, [
{ type: "mouseout", target: leftElem },
{ type: "mouseover", target: gPopup },
{ type: "mousemove", target: gPopup },
]],
// Move the mouse back over the left window outside the popup.
[160, 170, NSMouseMoved, null, left, [
{ type: "mouseout", target: gPopup },
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
// Back over the popup...
[190, 80, NSMouseMoved, gPopup, left, [
{ type: "mouseout", target: leftElem },
{ type: "mouseover", target: gPopup },
{ type: "mousemove", target: gPopup },
]],
// ...and over into the right window.
[400, 170, NSMouseMoved, null, right, [
{ type: "mouseout", target: gPopup },
{ type: "mouseover", target: rightElem },
{ type: "mousemove", target: rightElem },
]],
[400, 180, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Activate the right window with a click.
[400, 180, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[400, 180, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
function verifyPopupClosed2(callback) {
is(gPopup.popupBoxObject.popupState, "closed", "popup should have closed when clicking");
callback();
},
// Now the right window is active; click it again, just for fun.
[400, 180, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[400, 180, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// Time for our next trick: a tooltip!
// Install the tooltip, but don't show it yet.
function setTooltip2(callback) {
rightElem.setAttribute("tooltip", "tip");
gExpectedEvents.push({ screenX: 410, screenY: 180, type: "mousemove", target: rightElem });
eventListenOnce(rightElem, "popupshown", callback);
gCurrentMouseX = 410;
gCurrentMouseY = 180;
var utils = right.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
utils.sendNativeMouseEvent(410, 180, NSMouseMoved, 0, null);
},
// Now the tooltip is visible.
// Move the mouse a little to the right.
[411, 180, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Move another pixel.
[412, 180, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Move up and click to make the tooltip go away.
[412, 80, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
[412, 80, NSLeftMouseDown, null, right, [
{ type: "mousedown", target: rightElem },
]],
[412, 80, NSLeftMouseUp, null, right, [
{ type: "mouseup", target: rightElem },
{ type: "click", target: rightElem },
]],
// OK, next round. Open a panel in the left window, which is inactive.
function openPanel2(callback) {
eventListenOnce(panel, "popupshown", callback);
panel.openPopupAtScreen(150, 150, false);
},
// The panel is parented, so it will be z-ordered over its parent but
// under the active window.
// Now we move the mouse over the part where the panel rect intersects the
// right window's rect. Since the panel is under the window, all the events
// should target the right window.
[390, 170, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
[390, 171, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
[391, 171, NSMouseMoved, null, right, [
{ type: "mousemove", target: rightElem },
]],
// Now move off the right window, so that the mouse is directly over the
// panel.
[260, 170, NSMouseMoved, panel, left, [
{ type: "mouseout", target: rightElem },
{ type: "mouseover", target: panel },
{ type: "mousemove", target: panel },
]],
[260, 171, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
[261, 171, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
// Let's be evil and click it.
[261, 171, NSLeftMouseDown, panel, left, [
{ type: "mousedown", target: panel },
]],
[261, 171, NSLeftMouseUp, panel, left, [
{ type: "mouseup", target: panel },
{ type: "click", target: panel },
]],
// This didn't focus the window, unfortunately, so let's do it ourselves.
function raiseLeftWindowTakeTwo(callback) {
focusAndThen(left, callback);
},
[387, 170, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
[387, 171, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
[388, 171, NSMouseMoved, panel, left, [
{ type: "mousemove", target: panel },
]],
// Click the panel.
[388, 171, NSLeftMouseDown, panel, left, [
{ type: "mousedown", target: panel }
]],
[388, 171, NSLeftMouseUp, panel, left, [
{ type: "mouseup", target: panel },
{ type: "click", target: panel },
]],
// Last test for today: Hit testing in the Canyon of Nowhere -
// the pixel row directly south of the panel, over the left window.
// Before bug 515003 we wrongly thought the mouse wasn't over any window.
[173, 200, NSMouseMoved, null, left, [
{ type: "mouseout", target: panel },
{ type: "mouseover", target: leftElem },
{ type: "mousemove", target: leftElem },
]],
[173, 201, NSMouseMoved, null, left, [
{ type: "mousemove", target: leftElem },
]],
];
function runNextTest() {
if (!tests.length)
return onTestsFinished();
var test = tests.shift();
if (typeof test == "function")
return test(runNextTest);
var [x, y, msg, elem, win, exp, flags] = test;
testMouse(x, y, msg, elem, win, exp, flags, runNextTest);
}
runNextTest();
}
SimpleTest.waitForFocus(start);
]]></script>
</window>