зеркало из https://github.com/mozilla/gecko-dev.git
774 строки
31 KiB
XML
774 строки
31 KiB
XML
<?xml version="1.0"?>
|
|
|
|
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
|
|
|
<?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;
|
|
var utils = win.QueryInterface(Ci.nsIInterfaceRequestor).
|
|
getInterface(Ci.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.state, "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(Ci.nsIInterfaceRequestor).
|
|
getInterface(Ci.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.state, "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(Ci.nsIInterfaceRequestor).
|
|
getInterface(Ci.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>
|