widget/tests/native_mouse_mac_window.xul

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 <?xml version="1.0"?>
     3 <!-- This Source Code Form is subject to the terms of the Mozilla Public
     4    - License, v. 2.0. If a copy of the MPL was not distributed with this
     5    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
     7 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
     9 <window id="NativeMenuWindow"
    10         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    11         xmlns:html="http://www.w3.org/1999/xhtml"
    12         width="600"
    13         height="600"
    14         title="Native Mouse Event Test"
    15         orient="vertical">
    16   <script type="application/javascript"
    17           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
    19   <box height="200" id="box"/>
    20   <menupopup id="popup" width="250" height="50"/>
    21   <panel id="panel" width="250" height="50" noautohide="true"/>
    23   <script type="application/javascript"><![CDATA[
    25     function ok(condition, message) {
    26       window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
    27     }
    29     function is(a, b, message) {
    30       window.opener.wrappedJSObject.SimpleTest.is(a, b, message);
    31     }
    33     function todo(condition, message) {
    34       window.opener.wrappedJSObject.SimpleTest.todo(condition, message);
    35     }
    37     function todo_is(a, b, message) {
    38       window.opener.wrappedJSObject.SimpleTest.todo_is(a, b, message);
    39     }
    41     function onTestsFinished() {
    42       clearTimeout(gAfterLoopExecution);
    43       observe(window, eventMonitor, false);
    44       observe(gRightWindow, eventMonitor, false);
    45       observe(gPopup, eventMonitor, false);
    46       gRightWindow.close();
    47       var openerSimpleTest = window.opener.wrappedJSObject.SimpleTest;
    48       window.close();
    49       openerSimpleTest.finish();
    50     }
    52     const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
    53     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 + '"/>';
    55     const NSLeftMouseDown      = 1,
    56           NSLeftMouseUp        = 2,
    57           NSRightMouseDown     = 3,
    58           NSRightMouseUp       = 4,
    59           NSMouseMoved         = 5,
    60           NSLeftMouseDragged   = 6,
    61           NSRightMouseDragged  = 7,
    62           NSMouseEntered       = 8,
    63           NSMouseExited        = 9,
    64           NSKeyDown            = 10,
    65           NSKeyUp              = 11,
    66           NSFlagsChanged       = 12,
    67           NSAppKitDefined      = 13,
    68           NSSystemDefined      = 14,
    69           NSApplicationDefined = 15,
    70           NSPeriodic           = 16,
    71           NSCursorUpdate       = 17,
    72           NSScrollWheel        = 22,
    73           NSTabletPoint        = 23,
    74           NSTabletProximity    = 24,
    75           NSOtherMouseDown     = 25,
    76           NSOtherMouseUp       = 26,
    77           NSOtherMouseDragged  = 27,
    78           NSEventTypeGesture   = 29,
    79           NSEventTypeMagnify   = 30,
    80           NSEventTypeSwipe     = 31,
    81           NSEventTypeRotate    = 18,
    82           NSEventTypeBeginGesture = 19,
    83           NSEventTypeEndGesture   = 20;
    85     const NSAlphaShiftKeyMask = 1 << 16,
    86           NSShiftKeyMask      = 1 << 17,
    87           NSControlKeyMask    = 1 << 18,
    88           NSAlternateKeyMask  = 1 << 19,
    89           NSCommandKeyMask    = 1 << 20,
    90           NSNumericPadKeyMask = 1 << 21,
    91           NSHelpKeyMask       = 1 << 22,
    92           NSFunctionKeyMask   = 1 << 23;
    94     const gDebug = false;
    96     function printDebug(msg) { if (gDebug) dump(msg); }
    98     var gExpectedEvents = [];
    99     var gRightWindow = null, gPopup = null;
   100     var gCurrentMouseX = 0, gCurrentMouseY = 0;
   101     var gAfterLoopExecution = 0;
   103     function testMouse(x, y, msg, elem, win, exp, flags, callback) {
   104       clearExpectedEvents();
   105       var syntheticEvent = null;
   106       exp.forEach(function (expEv) {
   107         expEv.screenX = x;
   108         expEv.screenY = y;
   109         if (expEv.synthetic) {
   110           is(syntheticEvent, null,
   111              "Can't handle two synthetic events in a single testMouse call");
   112           syntheticEvent = expEv;
   113         }
   114         gExpectedEvents.push(expEv);
   115       });
   116       printDebug("sending event: " + x + ", " + y + " (" + msg + ")\n");
   117       gCurrentMouseX = x;
   118       gCurrentMouseY = y;
   119       var utils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
   120                                      getInterface(Components.interfaces.nsIDOMWindowUtils);
   121       var callbackFunc = function() {
   122         clearExpectedEvents();
   123         callback();
   124       }
   125       if (syntheticEvent) {
   126         // Set up this listener before we sendNativeMouseEvent, just
   127         // in case that synchronously calls us.
   128         eventListenOnce(syntheticEvent.target, syntheticEvent.type,
   129                         // Trigger callbackFunc async, so we're not assuming
   130                         // anything about how our listener gets ordered with
   131                         // others.
   132                         function () { SimpleTest.executeSoon(callbackFunc) });
   133       }
   134       utils.sendNativeMouseEvent(x, y, msg, flags || 0, elem);
   135       if (!syntheticEvent) {
   136         gAfterLoopExecution = setTimeout(callbackFunc, 0);
   137       }
   138     }
   140     function eventListenOnce(elem, name, callback) {
   141       elem.addEventListener(name, function(e) {
   142         elem.removeEventListener(name, arguments.callee, false);
   143         callback(e);
   144       }, false);
   145     }
   147     function focusAndThen(win, callback) {
   148       eventListenOnce(win, "focus", callback);
   149       printDebug("focusing a window\n");
   150       win.focus();
   151     }
   153     function eventToString(e) {
   154       return JSON.stringify({
   155         type: e.type, target: e.target.nodeName, screenX: e.screenX, screenY: e.screenY
   156       });
   157     }
   159     function clearExpectedEvents() {
   160       while (gExpectedEvents.length > 0) {
   161         var expectedEvent = gExpectedEvents.shift();
   162         var errFun = expectedEvent.shouldFireButDoesnt ? todo : ok;
   163         errFun(false, "Didn't receive expected event: " + eventToString(expectedEvent));
   164       }
   165     }
   167     var gEventNum = 0;
   169     function eventMonitor(e) {
   170       printDebug("got event: " + eventToString(e) + "\n");
   171       processEvent(e);
   172     }
   174     function processEvent(e) {
   175       if (e.screenX != gCurrentMouseX || e.screenY != gCurrentMouseY) {
   176         todo(false, "Oh no! Received a stray event from a confused tracking area. Aborting test.");
   177         onTestsFinished();
   178         return;
   179       }
   180       var expectedEvent = gExpectedEvents.shift();
   181       if (!expectedEvent) {
   182         ok(false, "received event I didn't expect: " + eventToString(e));
   183         return;
   184       }
   185       if (e.type != expectedEvent.type) {
   186         // Didn't get expectedEvent.
   187         var errFun = expectedEvent.shouldFireButDoesnt ? todo : ok;
   188         errFun(false, "Didn't receive expected event: " + eventToString(expectedEvent));
   189         return processEvent(e);
   190       }
   191       gEventNum++;
   192       is(e.screenX, expectedEvent.screenX, gEventNum + " | wrong X coord for event " + eventToString(e));
   193       is(e.screenY, expectedEvent.screenY, gEventNum + " | wrong Y coord for event " + eventToString(e));
   194       is(e.target, expectedEvent.target, gEventNum + " | wrong target for event " + eventToString(e));
   195       if (expectedEvent.firesButShouldnt) {
   196         todo(false, gEventNum + " | Got an event that should not have fired: " + eventToString(e));
   197       }
   198     }
   200     function observe(elem, fun, add) {
   201       var addOrRemove = add ? "addEventListener" : "removeEventListener";
   202       elem[addOrRemove]("mousemove", fun, false);
   203       elem[addOrRemove]("mouseover", fun, false);
   204       elem[addOrRemove]("mouseout", fun, false);
   205       elem[addOrRemove]("mousedown", fun, false);
   206       elem[addOrRemove]("mouseup", fun, false);
   207       elem[addOrRemove]("click", fun, false);
   208     }
   210     function start() {
   211       window.resizeTo(200, 200);
   212       window.moveTo(50, 50);
   213       gRightWindow = open(xulWin, '', 'chrome,screenX=300,screenY=50,width=200,height=200');
   214       eventListenOnce(gRightWindow, "focus", function () {
   215         focusAndThen(window, runTests);
   216       });
   217       gPopup = document.getElementById("popup");
   218     }
   220     function runTests() {
   221       observe(window, eventMonitor, true);
   222       observe(gRightWindow, eventMonitor, true);
   223       var left = window, right = gRightWindow;
   224       var leftElem = document.getElementById("box");
   225       var rightElem = gRightWindow.document.documentElement;
   226       var panel = document.getElementById("panel");
   227       var tooltip = (function createTooltipInRightWindow() {
   228         var _tooltip = right.document.createElementNS(XUL_NS, "tooltip");
   229         _tooltip.setAttribute("id", "tip");
   230         _tooltip.setAttribute("width", "80");
   231         _tooltip.setAttribute("height", "20");
   232         right.document.documentElement.appendChild(_tooltip);
   233         return _tooltip;
   234       })();
   235       var tests = [
   237         // Part 1: Disallow click-through
   239         function blockClickThrough(callback) {
   240           document.documentElement.setAttribute("clickthrough", "never");
   241           gRightWindow.document.documentElement.setAttribute("clickthrough", "never");
   242           callback();
   243         },
   244         // Enter the left window, which is focused.
   245         [150, 150, NSMouseMoved, null, left, [
   246           { type: "mouseover", target: leftElem },
   247           { type: "mousemove", target: leftElem }
   248         ]],
   249         // Test that moving inside the window fires mousemove events.
   250         [170, 150, NSMouseMoved, null, left, [
   251           { type: "mousemove", target: leftElem },
   252         ]],
   253         // Leaving the window should fire a mouseout event...
   254         [170, 20, NSMouseMoved, null, left, [
   255           { type: "mouseout", target: leftElem },
   256         ]],
   257         // ... and entering a mouseover event.
   258         [170, 120, NSMouseMoved, null, left, [
   259           { type: "mouseover", target: leftElem },
   260           { type: "mousemove", target: leftElem },
   261         ]],
   262         // Move over the right window, which is inactive.
   263         // Inactive windows shouldn't respond to mousemove events when clickthrough="never",
   264         // so we should only get a mouseout event, no mouseover event.
   265         [400, 150, NSMouseMoved, null, right, [
   266           { type: "mouseout", target: leftElem },
   267         ]],
   268         // Left-clicking while holding Cmd and middle clicking should work even
   269         // on inactive windows, but without making them active.
   270         [400, 150, NSLeftMouseDown, null, right, [
   271           { type: "mousedown", target: rightElem },
   272         ], NSCommandKeyMask],
   273         [400, 150, NSLeftMouseUp, null, right, [
   274           { type: "mouseup", target: rightElem },
   275           { type: "click", target: rightElem },
   276         ], NSCommandKeyMask],
   277         [400, 150, NSOtherMouseDown, null, right, [
   278           { type: "mousedown", target: rightElem },
   279         ]],
   280         [400, 150, NSOtherMouseUp, null, right, [
   281           { type: "mouseup", target: rightElem },
   282           { type: "click", target: rightElem },
   283         ]],
   284         // Clicking an inactive window should make it active and fire a mouseover
   285         // event.
   286         [400, 150, NSLeftMouseDown, null, right, [
   287           { type: "mouseover", target: rightElem, synthetic: true },
   288         ]],
   289         [400, 150, NSLeftMouseUp, null, right, [
   290         ]],
   291         // Now it's focused, so we should get a mousedown event when clicking.
   292         [400, 150, NSLeftMouseDown, null, right, [
   293           { type: "mousedown", target: rightElem },
   294         ]],
   295         // Let's drag to the right without letting the button go.
   296         [410, 150, NSLeftMouseDragged, null, right, [
   297           { type: "mousemove", target: rightElem },
   298         ]],
   299         // Let go of the mouse.
   300         [410, 150, NSLeftMouseUp, null, right, [
   301           { type: "mouseup", target: rightElem },
   302           { type: "click", target: rightElem },
   303         ]],
   304         // Move the mouse back over the left window, which is inactive.
   305         [150, 170, NSMouseMoved, null, left, [
   306           { type: "mouseout", target: rightElem },
   307         ]],
   308         // Now we're being sneaky. The left window is inactive, but *right*-clicks to it
   309         // should still get through. Test that.
   310         // Ideally we'd be bracketing that event with over and out events, too, but it
   311         // probably doesn't matter too much.
   312         [150, 170, NSRightMouseDown, null, left, [
   313           { type: "mouseover", target: leftElem, shouldFireButDoesnt: true },
   314           { type: "mousedown", target: leftElem },
   315           { type: "mouseout", target: leftElem, shouldFireButDoesnt: true },
   316         ]],
   317         // Let go of the mouse.
   318         [150, 170, NSRightMouseUp, null, left, [
   319           { type: "mouseover", target: leftElem, shouldFireButDoesnt: true },
   320           { type: "mouseup", target: leftElem },
   321           { type: "click", target: leftElem },
   322           { type: "mouseout", target: leftElem, shouldFireButDoesnt: true },
   323         ]],
   324         // Right clicking hasn't focused it, so the window is still inactive.
   325         // Let's focus it; this time without the mouse, for variaton's sake.
   326         // Still, mouseout and mouseover events should fire.
   327         function raiseLeftWindow(callback) {
   328           clearExpectedEvents();
   329           gExpectedEvents.push({ screenX: 150, screenY: 170, type: "mouseover", target: leftElem });
   330           // We have to be a bit careful here.  The synthetic mouse event may
   331           // not fire for a bit after we focus the left window.
   332           eventListenOnce(leftElem, "mouseover", function() {
   333             // Trigger callback async, so we're not assuming
   334             // anything about how our listener gets ordered with others.
   335             SimpleTest.executeSoon(callback);
   336           });
   337           printDebug("focusing left window");
   338           left.focus();
   339         },
   340         // It's active, so it should respond to mousemove events now.
   341         [150, 170, NSMouseMoved, null, left, [
   342           { type: "mousemove", target: leftElem },
   343         ]],
   344         // This was boring... let's introduce a popup. It will overlap both the left
   345         // and the right window.
   346         function openPopupInLeftWindow(callback) {
   347           eventListenOnce(gPopup, "popupshown", callback);
   348           gPopup.openPopupAtScreen(150, 50, true);
   349         },
   350         // Move the mouse over the popup.
   351         [200, 80, NSMouseMoved, gPopup, left, [
   352           { type: "mouseout", target: leftElem },
   353           { type: "mouseover", target: gPopup },
   354           { type: "mousemove", target: gPopup },
   355         ]],
   356         // Move the mouse back over the left window outside the popup.
   357         [160, 170, NSMouseMoved, null, left, [
   358           { type: "mouseout", target: gPopup },
   359           { type: "mouseover", target: leftElem },
   360           { type: "mousemove", target: leftElem },
   361         ]],
   362         // Back over the popup...
   363         [190, 80, NSMouseMoved, gPopup, left, [
   364           { type: "mouseout", target: leftElem },
   365           { type: "mouseover", target: gPopup },
   366           { type: "mousemove", target: gPopup },
   367         ]],
   368         // ...and over into the right window.
   369         // It's inactive, so it shouldn't get mouseover events yet.
   370         [400, 170, NSMouseMoved, null, right, [
   371           { type: "mouseout", target: gPopup },
   372         ]],
   373         // Again, no mouse events please, even though a popup is open. (bug 425556)
   374         [400, 180, NSMouseMoved, null, right, [
   375         ]],
   376         // Activate the right window with a click.
   377         // This will close the popup and make the mouse enter the right window.
   378         [400, 180, NSLeftMouseDown, null, right, [
   379           { type: "mouseover", target: rightElem, synthetic: true },
   380         ]],
   381         [400, 180, NSLeftMouseUp, null, right, [
   382         ]],
   383         function verifyPopupClosed2(callback) {
   384           is(gPopup.popupBoxObject.popupState, "closed", "popup should have closed when clicking");
   385           callback();
   386         },
   387         // Now the right window is active; click it again, just for fun.
   388         [400, 180, NSLeftMouseDown, null, right, [
   389           { type: "mousedown", target: rightElem },
   390         ]],
   391         [400, 180, NSLeftMouseUp, null, right, [
   392           { type: "mouseup", target: rightElem },
   393           { type: "click", target: rightElem },
   394         ]],
   396         // Time for our next trick: a tooltip!
   397         // Install the tooltip, but don't show it yet.
   398         function setTooltip(callback) {
   399           rightElem.setAttribute("tooltip", "tip");
   400           gExpectedEvents.push({ screenX: 410, screenY: 180, type: "mousemove", target: rightElem });
   401           eventListenOnce(rightElem, "popupshown", callback);
   402           gCurrentMouseX = 410;
   403           gCurrentMouseY = 180;
   404           var utils = right.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
   405                                getInterface(Components.interfaces.nsIDOMWindowUtils);
   406           utils.sendNativeMouseEvent(410, 180, NSMouseMoved, 0, null);
   407         },
   408         // Now the tooltip is visible.
   409         // Move the mouse a little to the right.
   410         [411, 180, NSMouseMoved, null, right, [
   411           { type: "mousemove", target: rightElem },
   412         ]],
   413         // Move another pixel.
   414         [412, 180, NSMouseMoved, null, right, [
   415           { type: "mousemove", target: rightElem },
   416         ]],
   417         // Move up and click to make the tooltip go away.
   418         [412, 80, NSMouseMoved, null, right, [
   419           { type: "mousemove", target: rightElem },
   420         ]],
   421         [412, 80, NSLeftMouseDown, null, right, [
   422           { type: "mousedown", target: rightElem },
   423         ]],
   424         [412, 80, NSLeftMouseUp, null, right, [
   425           { type: "mouseup", target: rightElem },
   426           { type: "click", target: rightElem },
   427         ]],
   428         // OK, next round. Open a panel in the left window, which is inactive.
   429         function openPanel(callback) {
   430           eventListenOnce(panel, "popupshown", callback);
   431           panel.openPopupAtScreen(150, 150, false);
   432         },
   433         // The panel is parented, so it will be z-ordered over its parent but
   434         // under the active window.
   435         // Now we move the mouse over the part where the panel rect intersects the
   436         // right window's rect. Since the panel is under the window, all the events
   437         // should target the right window.
   438         [390, 170, NSMouseMoved, null, right, [
   439           { type: "mousemove", target: rightElem },
   440         ]],
   441         [390, 171, NSMouseMoved, null, right, [
   442           { type: "mousemove", target: rightElem },
   443         ]],
   444         [391, 171, NSMouseMoved, null, right, [
   445           { type: "mousemove", target: rightElem },
   446         ]],
   447         // Now move off the right window, so that the mouse is directly over the
   448         // panel.
   449         [260, 170, NSMouseMoved, panel, left, [
   450           { type: "mouseout", target: rightElem },
   451         ]],
   452         [260, 171, NSMouseMoved, panel, left, [
   453         ]],
   454         [261, 171, NSMouseMoved, panel, left, [
   455         ]],
   456         // Let's be evil and click it.
   457         [261, 171, NSLeftMouseDown, panel, left, [
   458         ]],
   459         [261, 171, NSLeftMouseUp, panel, left, [
   460         ]],
   461         // This didn't focus the window, unfortunately, so let's do it ourselves.
   462         function raiseLeftWindowTakeTwo(callback) {
   463           focusAndThen(left, callback);
   464         },
   465         // Now mouse events should get through to the panel (which is now over the
   466         // right window).
   467         [387, 170, NSMouseMoved, panel, left, [
   468           { type: "mouseover", target: panel },
   469           { type: "mousemove", target: panel },
   470         ]],
   471         [387, 171, NSMouseMoved, panel, left, [
   472           { type: "mousemove", target: panel },
   473         ]],
   474         [388, 171, NSMouseMoved, panel, left, [
   475           { type: "mousemove", target: panel },
   476         ]],
   477         // Click the panel.
   478         [388, 171, NSLeftMouseDown, panel, left, [
   479           { type: "mousedown", target: panel }
   480         ]],
   481         [388, 171, NSLeftMouseUp, panel, left, [
   482           { type: "mouseup", target: panel },
   483           { type: "click", target: panel },
   484         ]],
   486         // Last test for this part: Hit testing in the Canyon of Nowhere -
   487         // the pixel row directly south of the panel, over the left window.
   488         // Before bug 515003 we wrongly thought the mouse wasn't over any window.
   489         [173, 200, NSMouseMoved, null, left, [
   490           { type: "mouseout", target: panel },
   491           { type: "mouseover", target: leftElem },
   492           { type: "mousemove", target: leftElem },
   493         ]],
   494         [173, 201, NSMouseMoved, null, left, [
   495           { type: "mousemove", target: leftElem },
   496         ]],
   498         // Part 2: Allow click-through
   500         function hideThatPanel(callback) {
   501           eventListenOnce(panel, "popuphidden", callback);
   502           panel.hidePopup();
   503         },
   504         function unblockClickThrough(callback) {
   505           document.documentElement.removeAttribute("clickthrough");
   506           gRightWindow.document.documentElement.removeAttribute("clickthrough");
   507           callback();
   508         },
   509         // Enter the left window, which is focused.
   510         [150, 150, NSMouseMoved, null, left, [
   511           { type: "mousemove", target: leftElem }
   512         ]],
   513         // Test that moving inside the window fires mousemove events.
   514         [170, 150, NSMouseMoved, null, left, [
   515           { type: "mousemove", target: leftElem },
   516         ]],
   517         // Leaving the window should fire a mouseout event...
   518         [170, 20, NSMouseMoved, null, left, [
   519           { type: "mouseout", target: leftElem },
   520         ]],
   521         // ... and entering a mouseover event.
   522         [170, 120, NSMouseMoved, null, left, [
   523           { type: "mouseover", target: leftElem },
   524           { type: "mousemove", target: leftElem },
   525         ]],
   526         // Move over the right window, which is inactive but still accepts
   527         // mouse events.
   528         [400, 150, NSMouseMoved, null, right, [
   529           { type: "mouseout", target: leftElem },
   530           { type: "mouseover", target: rightElem },
   531           { type: "mousemove", target: rightElem },
   532         ]],
   533         // Left-clicking while holding Cmd and middle clicking should work
   534         // on inactive windows, but without making them active.
   535         [400, 150, NSLeftMouseDown, null, right, [
   536           { type: "mousedown", target: rightElem },
   537         ], NSCommandKeyMask],
   538         [400, 150, NSLeftMouseUp, null, right, [
   539           { type: "mouseup", target: rightElem },
   540           { type: "click", target: rightElem },
   541         ], NSCommandKeyMask],
   542         [400, 150, NSOtherMouseDown, null, right, [
   543           { type: "mousedown", target: rightElem },
   544         ]],
   545         [400, 150, NSOtherMouseUp, null, right, [
   546           { type: "mouseup", target: rightElem },
   547           { type: "click", target: rightElem },
   548         ]],
   549         // Clicking an inactive window should make it active
   550         [400, 150, NSLeftMouseDown, null, right, [
   551           { type: "mousedown", target: rightElem },
   552         ]],
   553         [400, 150, NSLeftMouseUp, null, right, [
   554           { type: "mouseup", target: rightElem },
   555           { type: "click", target: rightElem },
   556         ]],
   557         // Now it's focused.
   558         [401, 150, NSLeftMouseDown, null, right, [
   559           { type: "mousedown", target: rightElem },
   560         ]],
   561         // Let's drag to the right without letting the button go.
   562         [410, 150, NSLeftMouseDragged, null, right, [
   563           { type: "mousemove", target: rightElem },
   564         ]],
   565         // Let go of the mouse.
   566         [410, 150, NSLeftMouseUp, null, right, [
   567           { type: "mouseup", target: rightElem },
   568           { type: "click", target: rightElem },
   569         ]],
   570         // Move the mouse back over the left window, which is inactive.
   571         [150, 170, NSMouseMoved, null, left, [
   572           { type: "mouseout", target: rightElem },
   573           { type: "mouseover", target: leftElem },
   574           { type: "mousemove", target: leftElem },
   575         ]],
   576         // Right-click it.
   577         [150, 170, NSRightMouseDown, null, left, [
   578           { type: "mousedown", target: leftElem },
   579         ]],
   580         // Let go of the mouse.
   581         [150, 170, NSRightMouseUp, null, left, [
   582           { type: "mouseup", target: leftElem },
   583           { type: "click", target: leftElem },
   584         ]],
   585         // Right clicking hasn't focused it, so the window is still inactive.
   586         // Let's focus it; this time without the mouse, for variaton's sake.
   587         function raiseLeftWindow(callback) {
   588           clearExpectedEvents();
   589           focusAndThen(left, function () { SimpleTest.executeSoon(callback); });
   590         },
   591         // It's active and should still respond to mousemove events.
   592         [150, 170, NSMouseMoved, null, left, [
   593           { type: "mousemove", target: leftElem },
   594         ]],
   596         // This was boring... let's introduce a popup. It will overlap both the left
   597         // and the right window.
   598         function openPopupInLeftWindow(callback) {
   599           eventListenOnce(gPopup, "popupshown", callback);
   600           gPopup.openPopupAtScreen(150, 50, true);
   601         },
   602         // Move the mouse over the popup.
   603         [200, 80, NSMouseMoved, gPopup, left, [
   604           { type: "mouseout", target: leftElem },
   605           { type: "mouseover", target: gPopup },
   606           { type: "mousemove", target: gPopup },
   607         ]],
   608         // Move the mouse back over the left window outside the popup.
   609         [160, 170, NSMouseMoved, null, left, [
   610           { type: "mouseout", target: gPopup },
   611           { type: "mouseover", target: leftElem },
   612           { type: "mousemove", target: leftElem },
   613         ]],
   614         // Back over the popup...
   615         [190, 80, NSMouseMoved, gPopup, left, [
   616           { type: "mouseout", target: leftElem },
   617           { type: "mouseover", target: gPopup },
   618           { type: "mousemove", target: gPopup },
   619         ]],
   620         // ...and over into the right window.
   621         [400, 170, NSMouseMoved, null, right, [
   622           { type: "mouseout", target: gPopup },
   623           { type: "mouseover", target: rightElem },
   624           { type: "mousemove", target: rightElem },
   625         ]],
   626         [400, 180, NSMouseMoved, null, right, [
   627           { type: "mousemove", target: rightElem },
   628         ]],
   629         // Activate the right window with a click.
   630         [400, 180, NSLeftMouseDown, null, right, [
   631           { type: "mousedown", target: rightElem },
   632         ]],
   633         [400, 180, NSLeftMouseUp, null, right, [
   634           { type: "mouseup", target: rightElem },
   635           { type: "click", target: rightElem },
   636         ]],
   637         function verifyPopupClosed2(callback) {
   638           is(gPopup.popupBoxObject.popupState, "closed", "popup should have closed when clicking");
   639           callback();
   640         },
   641         // Now the right window is active; click it again, just for fun.
   642         [400, 180, NSLeftMouseDown, null, right, [
   643           { type: "mousedown", target: rightElem },
   644         ]],
   645         [400, 180, NSLeftMouseUp, null, right, [
   646           { type: "mouseup", target: rightElem },
   647           { type: "click", target: rightElem },
   648         ]],
   650         // Time for our next trick: a tooltip!
   651         // Install the tooltip, but don't show it yet.
   652         function setTooltip2(callback) {
   653           rightElem.setAttribute("tooltip", "tip");
   654           gExpectedEvents.push({ screenX: 410, screenY: 180, type: "mousemove", target: rightElem });
   655           eventListenOnce(rightElem, "popupshown", callback);
   656           gCurrentMouseX = 410;
   657           gCurrentMouseY = 180;
   658           var utils = right.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
   659                                getInterface(Components.interfaces.nsIDOMWindowUtils);
   660           utils.sendNativeMouseEvent(410, 180, NSMouseMoved, 0, null);
   661         },
   662         // Now the tooltip is visible.
   663         // Move the mouse a little to the right.
   664         [411, 180, NSMouseMoved, null, right, [
   665           { type: "mousemove", target: rightElem },
   666         ]],
   667         // Move another pixel.
   668         [412, 180, NSMouseMoved, null, right, [
   669           { type: "mousemove", target: rightElem },
   670         ]],
   671         // Move up and click to make the tooltip go away.
   672         [412, 80, NSMouseMoved, null, right, [
   673           { type: "mousemove", target: rightElem },
   674         ]],
   675         [412, 80, NSLeftMouseDown, null, right, [
   676           { type: "mousedown", target: rightElem },
   677         ]],
   678         [412, 80, NSLeftMouseUp, null, right, [
   679           { type: "mouseup", target: rightElem },
   680           { type: "click", target: rightElem },
   681         ]],
   682         // OK, next round. Open a panel in the left window, which is inactive.
   683         function openPanel2(callback) {
   684           eventListenOnce(panel, "popupshown", callback);
   685           panel.openPopupAtScreen(150, 150, false);
   686         },
   687         // The panel is parented, so it will be z-ordered over its parent but
   688         // under the active window.
   689         // Now we move the mouse over the part where the panel rect intersects the
   690         // right window's rect. Since the panel is under the window, all the events
   691         // should target the right window.
   692         [390, 170, NSMouseMoved, null, right, [
   693           { type: "mousemove", target: rightElem },
   694         ]],
   695         [390, 171, NSMouseMoved, null, right, [
   696           { type: "mousemove", target: rightElem },
   697         ]],
   698         [391, 171, NSMouseMoved, null, right, [
   699           { type: "mousemove", target: rightElem },
   700         ]],
   701         // Now move off the right window, so that the mouse is directly over the
   702         // panel.
   703         [260, 170, NSMouseMoved, panel, left, [
   704           { type: "mouseout", target: rightElem },
   705           { type: "mouseover", target: panel },
   706           { type: "mousemove", target: panel },
   707         ]],
   708         [260, 171, NSMouseMoved, panel, left, [
   709           { type: "mousemove", target: panel },
   710         ]],
   711         [261, 171, NSMouseMoved, panel, left, [
   712           { type: "mousemove", target: panel },
   713         ]],
   714         // Let's be evil and click it.
   715         [261, 171, NSLeftMouseDown, panel, left, [
   716           { type: "mousedown", target: panel },
   717         ]],
   718         [261, 171, NSLeftMouseUp, panel, left, [
   719           { type: "mouseup", target: panel },
   720           { type: "click", target: panel },
   721         ]],
   722         // This didn't focus the window, unfortunately, so let's do it ourselves.
   723         function raiseLeftWindowTakeTwo(callback) {
   724           focusAndThen(left, callback);
   725         },
   726         [387, 170, NSMouseMoved, panel, left, [
   727           { type: "mousemove", target: panel },
   728         ]],
   729         [387, 171, NSMouseMoved, panel, left, [
   730           { type: "mousemove", target: panel },
   731         ]],
   732         [388, 171, NSMouseMoved, panel, left, [
   733           { type: "mousemove", target: panel },
   734         ]],
   735         // Click the panel.
   736         [388, 171, NSLeftMouseDown, panel, left, [
   737           { type: "mousedown", target: panel }
   738         ]],
   739         [388, 171, NSLeftMouseUp, panel, left, [
   740           { type: "mouseup", target: panel },
   741           { type: "click", target: panel },
   742         ]],
   744         // Last test for today: Hit testing in the Canyon of Nowhere -
   745         // the pixel row directly south of the panel, over the left window.
   746         // Before bug 515003 we wrongly thought the mouse wasn't over any window.
   747         [173, 200, NSMouseMoved, null, left, [
   748           { type: "mouseout", target: panel },
   749           { type: "mouseover", target: leftElem },
   750           { type: "mousemove", target: leftElem },
   751         ]],
   752         [173, 201, NSMouseMoved, null, left, [
   753           { type: "mousemove", target: leftElem },
   754         ]],
   755       ];
   756       function runNextTest() {
   757         if (!tests.length)
   758           return onTestsFinished();
   760         var test = tests.shift();
   761         if (typeof test == "function")
   762           return test(runNextTest);
   764         var [x, y, msg, elem, win, exp, flags] = test;
   765         testMouse(x, y, msg, elem, win, exp, flags, runNextTest);
   766       }
   767       runNextTest();
   768     }
   770     SimpleTest.waitForFocus(start);
   772   ]]></script>
   773 </window>

mercurial