summaryrefslogtreecommitdiffstats
path: root/widget/tests/native_mouse_mac_window.xhtml
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /widget/tests/native_mouse_mac_window.xhtml
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'widget/tests/native_mouse_mac_window.xhtml')
-rw-r--r--widget/tests/native_mouse_mac_window.xhtml770
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>