diff options
Diffstat (limited to 'widget/tests/native_mouse_mac_window.xhtml')
-rw-r--r-- | widget/tests/native_mouse_mac_window.xhtml | 770 |
1 files changed, 770 insertions, 0 deletions
diff --git a/widget/tests/native_mouse_mac_window.xhtml b/widget/tests/native_mouse_mac_window.xhtml new file mode 100644 index 0000000000..514664bc69 --- /dev/null +++ b/widget/tests/native_mouse_mac_window.xhtml @@ -0,0 +1,770 @@ +<?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 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.arguments[0].SimpleTest.ok(condition, message); + } + + function is(a, b, message) { + window.arguments[0].SimpleTest.is(a, b, message); + } + + function todo(condition, message) { + window.arguments[0].SimpleTest.todo(condition, message); + } + + function todo_is(a, b, message) { + window.arguments[0].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.arguments[0].SimpleTest; + window.close(); + openerSimpleTest.finish(); + } + + const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + const xulWin = 'data:application/xhtml+xml,<?xml version="1.0"?><?xml-stylesheet href="chrome://global/skin" type="text/css"?><window xmlns="' + XUL_NS + '"/>'; + + const NSEventTypeLeftMouseDown = 1, + NSEventTypeLeftMouseUp = 2, + NSEventTypeRightMouseDown = 3, + NSEventTypeRightMouseUp = 4, + NSEventTypeMouseMoved = 5, + NSEventTypeLeftMouseDragged = 6, + NSEventTypeRightMouseDragged = 7, + NSEventTypeMouseEntered = 8, + NSEventTypeMouseExited = 9, + NSEventTypeKeyDown = 10, + NSEventTypeKeyUp = 11, + NSEventTypeFlagsChanged = 12, + NSEventTypeAppKitDefined = 13, + NSEventTypeSystemDefined = 14, + NSEventTypeApplicationDefined = 15, + NSEventTypePeriodic = 16, + NSEventTypeCursorUpdate = 17, + NSEventTypeScrollWheel = 22, + NSEventTypeTabletPoint = 23, + NSEventTypeTabletProximity = 24, + NSEventTypeOtherMouseDown = 25, + NSEventTypeOtherMouseUp = 26, + NSEventTypeOtherMouseDragged = 27, + NSEventTypeGesture = 29, + NSEventTypeMagnify = 30, + NSEventTypeSwipe = 31, + NSEventTypeRotate = 18, + NSEventTypeBeginGesture = 19, + NSEventTypeEndGesture = 20; + + const NSEventModifierFlagCapsLock = 1 << 16, + NSEventModifierFlagShift = 1 << 17, + NSEventModifierFlagControl = 1 << 18, + NSEventModifierFlagOption = 1 << 19, + NSEventModifierFlagCommand = 1 << 20, + NSEventModifierFlagNumericPad = 1 << 21, + NSEventModifierFlagHelp = 1 << 22, + NSEventModifierFlagFunction = 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.windowUtils; + 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) { + callback(e); + }, {once: true}); + } + + 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) { + 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)); + processEvent(e); + return; + } + 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 = right.document.createElementNS(XUL_NS, "tooltip"); + _tooltip.setAttribute("id", "tip"); + _tooltip.setAttribute("width", "80"); + _tooltip.setAttribute("height", "20"); + right.document.documentElement.appendChild(_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, NSEventTypeMouseMoved, null, left, [ + { type: "mouseover", target: leftElem }, + { type: "mousemove", target: leftElem } + ]], + // Test that moving inside the window fires mousemove events. + [170, 150, NSEventTypeMouseMoved, null, left, [ + { type: "mousemove", target: leftElem }, + ]], + // Leaving the window should fire a mouseout event... + [170, 20, NSEventTypeMouseMoved, null, left, [ + { type: "mouseout", target: leftElem }, + ]], + // ... and entering a mouseover event. + [170, 120, NSEventTypeMouseMoved, 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, NSEventTypeMouseMoved, 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, NSEventTypeLeftMouseDown, null, right, [ + { type: "mousedown", target: rightElem }, + ], NSEventModifierFlagCommand], + [400, 150, NSEventTypeLeftMouseUp, null, right, [ + { type: "mouseup", target: rightElem }, + { type: "click", target: rightElem }, + ], NSEventModifierFlagCommand], + [400, 150, NSEventTypeOtherMouseDown, null, right, [ + { type: "mousedown", target: rightElem }, + ]], + [400, 150, NSEventTypeOtherMouseUp, 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, NSEventTypeLeftMouseDown, null, right, [ + { type: "mouseover", target: rightElem, synthetic: true }, + ]], + [400, 150, NSEventTypeLeftMouseUp, null, right, [ + ]], + // Now it's focused, so we should get a mousedown event when clicking. + [400, 150, NSEventTypeLeftMouseDown, null, right, [ + { type: "mousedown", target: rightElem }, + ]], + // Let's drag to the right without letting the button go. + [410, 150, NSEventTypeLeftMouseDragged, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + // Let go of the mouse. + [410, 150, NSEventTypeLeftMouseUp, null, right, [ + { type: "mouseup", target: rightElem }, + { type: "click", target: rightElem }, + ]], + // Move the mouse back over the left window, which is inactive. + [150, 170, NSEventTypeMouseMoved, 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, NSEventTypeRightMouseDown, 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, NSEventTypeRightMouseUp, 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, NSEventTypeMouseMoved, 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, NSEventTypeMouseMoved, 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, NSEventTypeMouseMoved, null, left, [ + { type: "mouseout", target: gPopup }, + { type: "mouseover", target: leftElem }, + { type: "mousemove", target: leftElem }, + ]], + // Back over the popup... + [190, 80, NSEventTypeMouseMoved, 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, NSEventTypeMouseMoved, null, right, [ + { type: "mouseout", target: gPopup }, + ]], + // Again, no mouse events please, even though a popup is open. (bug 425556) + [400, 180, NSEventTypeMouseMoved, null, right, [ + ]], + // Activate the right window with a click. + // This will close the popup and make the mouse enter the right window. + [400, 180, NSEventTypeLeftMouseDown, null, right, [ + { type: "mouseover", target: rightElem, synthetic: true }, + ]], + [400, 180, NSEventTypeLeftMouseUp, 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, NSEventTypeLeftMouseDown, null, right, [ + { type: "mousedown", target: rightElem }, + ]], + [400, 180, NSEventTypeLeftMouseUp, 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.windowUtils; + utils.sendNativeMouseEvent(410, 180, NSEventTypeMouseMoved, 0, null); + }, + // Now the tooltip is visible. + // Move the mouse a little to the right. + [411, 180, NSEventTypeMouseMoved, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + // Move another pixel. + [412, 180, NSEventTypeMouseMoved, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + // Move up and click to make the tooltip go away. + [412, 80, NSEventTypeMouseMoved, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + [412, 80, NSEventTypeLeftMouseDown, null, right, [ + { type: "mousedown", target: rightElem }, + ]], + [412, 80, NSEventTypeLeftMouseUp, 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, NSEventTypeMouseMoved, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + [390, 171, NSEventTypeMouseMoved, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + [391, 171, NSEventTypeMouseMoved, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + // Now move off the right window, so that the mouse is directly over the + // panel. + [260, 170, NSEventTypeMouseMoved, panel, left, [ + { type: "mouseout", target: rightElem }, + ]], + [260, 171, NSEventTypeMouseMoved, panel, left, [ + ]], + [261, 171, NSEventTypeMouseMoved, panel, left, [ + ]], + // Let's be evil and click it. + [261, 171, NSEventTypeLeftMouseDown, panel, left, [ + ]], + [261, 171, NSEventTypeLeftMouseUp, 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, NSEventTypeMouseMoved, panel, left, [ + { type: "mouseover", target: panel }, + { type: "mousemove", target: panel }, + ]], + [387, 171, NSEventTypeMouseMoved, panel, left, [ + { type: "mousemove", target: panel }, + ]], + [388, 171, NSEventTypeMouseMoved, panel, left, [ + { type: "mousemove", target: panel }, + ]], + // Click the panel. + [388, 171, NSEventTypeLeftMouseDown, panel, left, [ + { type: "mousedown", target: panel } + ]], + [388, 171, NSEventTypeLeftMouseUp, 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, NSEventTypeMouseMoved, null, left, [ + { type: "mouseout", target: panel }, + { type: "mouseover", target: leftElem }, + { type: "mousemove", target: leftElem }, + ]], + [173, 201, NSEventTypeMouseMoved, 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, NSEventTypeMouseMoved, null, left, [ + { type: "mousemove", target: leftElem } + ]], + // Test that moving inside the window fires mousemove events. + [170, 150, NSEventTypeMouseMoved, null, left, [ + { type: "mousemove", target: leftElem }, + ]], + // Leaving the window should fire a mouseout event... + [170, 20, NSEventTypeMouseMoved, null, left, [ + { type: "mouseout", target: leftElem }, + ]], + // ... and entering a mouseover event. + [170, 120, NSEventTypeMouseMoved, 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, NSEventTypeMouseMoved, 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, NSEventTypeLeftMouseDown, null, right, [ + { type: "mousedown", target: rightElem }, + ], NSEventModifierFlagCommand], + [400, 150, NSEventTypeLeftMouseUp, null, right, [ + { type: "mouseup", target: rightElem }, + { type: "click", target: rightElem }, + ], NSEventModifierFlagCommand], + [400, 150, NSEventTypeOtherMouseDown, null, right, [ + { type: "mousedown", target: rightElem }, + ]], + [400, 150, NSEventTypeOtherMouseUp, null, right, [ + { type: "mouseup", target: rightElem }, + { type: "click", target: rightElem }, + ]], + // Clicking an inactive window should make it active + [400, 150, NSEventTypeLeftMouseDown, null, right, [ + { type: "mousedown", target: rightElem }, + ]], + [400, 150, NSEventTypeLeftMouseUp, null, right, [ + { type: "mouseup", target: rightElem }, + { type: "click", target: rightElem }, + ]], + // Now it's focused. + [401, 150, NSEventTypeLeftMouseDown, null, right, [ + { type: "mousedown", target: rightElem }, + ]], + // Let's drag to the right without letting the button go. + [410, 150, NSEventTypeLeftMouseDragged, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + // Let go of the mouse. + [410, 150, NSEventTypeLeftMouseUp, null, right, [ + { type: "mouseup", target: rightElem }, + { type: "click", target: rightElem }, + ]], + // Move the mouse back over the left window, which is inactive. + [150, 170, NSEventTypeMouseMoved, null, left, [ + { type: "mouseout", target: rightElem }, + { type: "mouseover", target: leftElem }, + { type: "mousemove", target: leftElem }, + ]], + // Right-click it. + [150, 170, NSEventTypeRightMouseDown, null, left, [ + { type: "mousedown", target: leftElem }, + ]], + // Let go of the mouse. + [150, 170, NSEventTypeRightMouseUp, 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, NSEventTypeMouseMoved, 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, NSEventTypeMouseMoved, 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, NSEventTypeMouseMoved, null, left, [ + { type: "mouseout", target: gPopup }, + { type: "mouseover", target: leftElem }, + { type: "mousemove", target: leftElem }, + ]], + // Back over the popup... + [190, 80, NSEventTypeMouseMoved, gPopup, left, [ + { type: "mouseout", target: leftElem }, + { type: "mouseover", target: gPopup }, + { type: "mousemove", target: gPopup }, + ]], + // ...and over into the right window. + [400, 170, NSEventTypeMouseMoved, null, right, [ + { type: "mouseout", target: gPopup }, + { type: "mouseover", target: rightElem }, + { type: "mousemove", target: rightElem }, + ]], + [400, 180, NSEventTypeMouseMoved, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + // Activate the right window with a click. + [400, 180, NSEventTypeLeftMouseDown, null, right, [ + { type: "mousedown", target: rightElem }, + ]], + [400, 180, NSEventTypeLeftMouseUp, 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, NSEventTypeLeftMouseDown, null, right, [ + { type: "mousedown", target: rightElem }, + ]], + [400, 180, NSEventTypeLeftMouseUp, 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.windowUtils; + utils.sendNativeMouseEvent(410, 180, NSEventTypeMouseMoved, 0, null); + }, + // Now the tooltip is visible. + // Move the mouse a little to the right. + [411, 180, NSEventTypeMouseMoved, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + // Move another pixel. + [412, 180, NSEventTypeMouseMoved, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + // Move up and click to make the tooltip go away. + [412, 80, NSEventTypeMouseMoved, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + [412, 80, NSEventTypeLeftMouseDown, null, right, [ + { type: "mousedown", target: rightElem }, + ]], + [412, 80, NSEventTypeLeftMouseUp, 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, NSEventTypeMouseMoved, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + [390, 171, NSEventTypeMouseMoved, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + [391, 171, NSEventTypeMouseMoved, null, right, [ + { type: "mousemove", target: rightElem }, + ]], + // Now move off the right window, so that the mouse is directly over the + // panel. + [260, 170, NSEventTypeMouseMoved, panel, left, [ + { type: "mouseout", target: rightElem }, + { type: "mouseover", target: panel }, + { type: "mousemove", target: panel }, + ]], + [260, 171, NSEventTypeMouseMoved, panel, left, [ + { type: "mousemove", target: panel }, + ]], + [261, 171, NSEventTypeMouseMoved, panel, left, [ + { type: "mousemove", target: panel }, + ]], + // Let's be evil and click it. + [261, 171, NSEventTypeLeftMouseDown, panel, left, [ + { type: "mousedown", target: panel }, + ]], + [261, 171, NSEventTypeLeftMouseUp, 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, NSEventTypeMouseMoved, panel, left, [ + { type: "mousemove", target: panel }, + ]], + [387, 171, NSEventTypeMouseMoved, panel, left, [ + { type: "mousemove", target: panel }, + ]], + [388, 171, NSEventTypeMouseMoved, panel, left, [ + { type: "mousemove", target: panel }, + ]], + // Click the panel. + [388, 171, NSEventTypeLeftMouseDown, panel, left, [ + { type: "mousedown", target: panel } + ]], + [388, 171, NSEventTypeLeftMouseUp, 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, NSEventTypeMouseMoved, null, left, [ + { type: "mouseout", target: panel }, + { type: "mouseover", target: leftElem }, + { type: "mousemove", target: leftElem }, + ]], + [173, 201, NSEventTypeMouseMoved, null, left, [ + { type: "mousemove", target: leftElem }, + ]], + ]; + // eslint-disable-next-line consistent-return + function runNextTest() { + if (!tests.length) { + onTestsFinished(); + return; + } + var test = tests.shift(); + if (typeof test == "function") { + test(runNextTest); + return; + } + + var [x, y, msg, elem, win, exp, flags] = test; + testMouse(x, y, msg, elem, win, exp, flags, runNextTest); + } + runNextTest(); + } + + SimpleTest.waitForFocus(start); + + ]]></script> +</window> |