1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/tests/native_mouse_mac_window.xul Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,773 @@ 1.4 +<?xml version="1.0"?> 1.5 + 1.6 +<!-- This Source Code Form is subject to the terms of the Mozilla Public 1.7 + - License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> 1.9 + 1.10 +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> 1.11 + 1.12 +<window id="NativeMenuWindow" 1.13 + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 1.14 + xmlns:html="http://www.w3.org/1999/xhtml" 1.15 + width="600" 1.16 + height="600" 1.17 + title="Native Mouse Event Test" 1.18 + orient="vertical"> 1.19 + <script type="application/javascript" 1.20 + src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> 1.21 + 1.22 + <box height="200" id="box"/> 1.23 + <menupopup id="popup" width="250" height="50"/> 1.24 + <panel id="panel" width="250" height="50" noautohide="true"/> 1.25 + 1.26 + <script type="application/javascript"><![CDATA[ 1.27 + 1.28 + function ok(condition, message) { 1.29 + window.opener.wrappedJSObject.SimpleTest.ok(condition, message); 1.30 + } 1.31 + 1.32 + function is(a, b, message) { 1.33 + window.opener.wrappedJSObject.SimpleTest.is(a, b, message); 1.34 + } 1.35 + 1.36 + function todo(condition, message) { 1.37 + window.opener.wrappedJSObject.SimpleTest.todo(condition, message); 1.38 + } 1.39 + 1.40 + function todo_is(a, b, message) { 1.41 + window.opener.wrappedJSObject.SimpleTest.todo_is(a, b, message); 1.42 + } 1.43 + 1.44 + function onTestsFinished() { 1.45 + clearTimeout(gAfterLoopExecution); 1.46 + observe(window, eventMonitor, false); 1.47 + observe(gRightWindow, eventMonitor, false); 1.48 + observe(gPopup, eventMonitor, false); 1.49 + gRightWindow.close(); 1.50 + var openerSimpleTest = window.opener.wrappedJSObject.SimpleTest; 1.51 + window.close(); 1.52 + openerSimpleTest.finish(); 1.53 + } 1.54 + 1.55 + const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; 1.56 + 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 + '"/>'; 1.57 + 1.58 + const NSLeftMouseDown = 1, 1.59 + NSLeftMouseUp = 2, 1.60 + NSRightMouseDown = 3, 1.61 + NSRightMouseUp = 4, 1.62 + NSMouseMoved = 5, 1.63 + NSLeftMouseDragged = 6, 1.64 + NSRightMouseDragged = 7, 1.65 + NSMouseEntered = 8, 1.66 + NSMouseExited = 9, 1.67 + NSKeyDown = 10, 1.68 + NSKeyUp = 11, 1.69 + NSFlagsChanged = 12, 1.70 + NSAppKitDefined = 13, 1.71 + NSSystemDefined = 14, 1.72 + NSApplicationDefined = 15, 1.73 + NSPeriodic = 16, 1.74 + NSCursorUpdate = 17, 1.75 + NSScrollWheel = 22, 1.76 + NSTabletPoint = 23, 1.77 + NSTabletProximity = 24, 1.78 + NSOtherMouseDown = 25, 1.79 + NSOtherMouseUp = 26, 1.80 + NSOtherMouseDragged = 27, 1.81 + NSEventTypeGesture = 29, 1.82 + NSEventTypeMagnify = 30, 1.83 + NSEventTypeSwipe = 31, 1.84 + NSEventTypeRotate = 18, 1.85 + NSEventTypeBeginGesture = 19, 1.86 + NSEventTypeEndGesture = 20; 1.87 + 1.88 + const NSAlphaShiftKeyMask = 1 << 16, 1.89 + NSShiftKeyMask = 1 << 17, 1.90 + NSControlKeyMask = 1 << 18, 1.91 + NSAlternateKeyMask = 1 << 19, 1.92 + NSCommandKeyMask = 1 << 20, 1.93 + NSNumericPadKeyMask = 1 << 21, 1.94 + NSHelpKeyMask = 1 << 22, 1.95 + NSFunctionKeyMask = 1 << 23; 1.96 + 1.97 + const gDebug = false; 1.98 + 1.99 + function printDebug(msg) { if (gDebug) dump(msg); } 1.100 + 1.101 + var gExpectedEvents = []; 1.102 + var gRightWindow = null, gPopup = null; 1.103 + var gCurrentMouseX = 0, gCurrentMouseY = 0; 1.104 + var gAfterLoopExecution = 0; 1.105 + 1.106 + function testMouse(x, y, msg, elem, win, exp, flags, callback) { 1.107 + clearExpectedEvents(); 1.108 + var syntheticEvent = null; 1.109 + exp.forEach(function (expEv) { 1.110 + expEv.screenX = x; 1.111 + expEv.screenY = y; 1.112 + if (expEv.synthetic) { 1.113 + is(syntheticEvent, null, 1.114 + "Can't handle two synthetic events in a single testMouse call"); 1.115 + syntheticEvent = expEv; 1.116 + } 1.117 + gExpectedEvents.push(expEv); 1.118 + }); 1.119 + printDebug("sending event: " + x + ", " + y + " (" + msg + ")\n"); 1.120 + gCurrentMouseX = x; 1.121 + gCurrentMouseY = y; 1.122 + var utils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor). 1.123 + getInterface(Components.interfaces.nsIDOMWindowUtils); 1.124 + var callbackFunc = function() { 1.125 + clearExpectedEvents(); 1.126 + callback(); 1.127 + } 1.128 + if (syntheticEvent) { 1.129 + // Set up this listener before we sendNativeMouseEvent, just 1.130 + // in case that synchronously calls us. 1.131 + eventListenOnce(syntheticEvent.target, syntheticEvent.type, 1.132 + // Trigger callbackFunc async, so we're not assuming 1.133 + // anything about how our listener gets ordered with 1.134 + // others. 1.135 + function () { SimpleTest.executeSoon(callbackFunc) }); 1.136 + } 1.137 + utils.sendNativeMouseEvent(x, y, msg, flags || 0, elem); 1.138 + if (!syntheticEvent) { 1.139 + gAfterLoopExecution = setTimeout(callbackFunc, 0); 1.140 + } 1.141 + } 1.142 + 1.143 + function eventListenOnce(elem, name, callback) { 1.144 + elem.addEventListener(name, function(e) { 1.145 + elem.removeEventListener(name, arguments.callee, false); 1.146 + callback(e); 1.147 + }, false); 1.148 + } 1.149 + 1.150 + function focusAndThen(win, callback) { 1.151 + eventListenOnce(win, "focus", callback); 1.152 + printDebug("focusing a window\n"); 1.153 + win.focus(); 1.154 + } 1.155 + 1.156 + function eventToString(e) { 1.157 + return JSON.stringify({ 1.158 + type: e.type, target: e.target.nodeName, screenX: e.screenX, screenY: e.screenY 1.159 + }); 1.160 + } 1.161 + 1.162 + function clearExpectedEvents() { 1.163 + while (gExpectedEvents.length > 0) { 1.164 + var expectedEvent = gExpectedEvents.shift(); 1.165 + var errFun = expectedEvent.shouldFireButDoesnt ? todo : ok; 1.166 + errFun(false, "Didn't receive expected event: " + eventToString(expectedEvent)); 1.167 + } 1.168 + } 1.169 + 1.170 + var gEventNum = 0; 1.171 + 1.172 + function eventMonitor(e) { 1.173 + printDebug("got event: " + eventToString(e) + "\n"); 1.174 + processEvent(e); 1.175 + } 1.176 + 1.177 + function processEvent(e) { 1.178 + if (e.screenX != gCurrentMouseX || e.screenY != gCurrentMouseY) { 1.179 + todo(false, "Oh no! Received a stray event from a confused tracking area. Aborting test."); 1.180 + onTestsFinished(); 1.181 + return; 1.182 + } 1.183 + var expectedEvent = gExpectedEvents.shift(); 1.184 + if (!expectedEvent) { 1.185 + ok(false, "received event I didn't expect: " + eventToString(e)); 1.186 + return; 1.187 + } 1.188 + if (e.type != expectedEvent.type) { 1.189 + // Didn't get expectedEvent. 1.190 + var errFun = expectedEvent.shouldFireButDoesnt ? todo : ok; 1.191 + errFun(false, "Didn't receive expected event: " + eventToString(expectedEvent)); 1.192 + return processEvent(e); 1.193 + } 1.194 + gEventNum++; 1.195 + is(e.screenX, expectedEvent.screenX, gEventNum + " | wrong X coord for event " + eventToString(e)); 1.196 + is(e.screenY, expectedEvent.screenY, gEventNum + " | wrong Y coord for event " + eventToString(e)); 1.197 + is(e.target, expectedEvent.target, gEventNum + " | wrong target for event " + eventToString(e)); 1.198 + if (expectedEvent.firesButShouldnt) { 1.199 + todo(false, gEventNum + " | Got an event that should not have fired: " + eventToString(e)); 1.200 + } 1.201 + } 1.202 + 1.203 + function observe(elem, fun, add) { 1.204 + var addOrRemove = add ? "addEventListener" : "removeEventListener"; 1.205 + elem[addOrRemove]("mousemove", fun, false); 1.206 + elem[addOrRemove]("mouseover", fun, false); 1.207 + elem[addOrRemove]("mouseout", fun, false); 1.208 + elem[addOrRemove]("mousedown", fun, false); 1.209 + elem[addOrRemove]("mouseup", fun, false); 1.210 + elem[addOrRemove]("click", fun, false); 1.211 + } 1.212 + 1.213 + function start() { 1.214 + window.resizeTo(200, 200); 1.215 + window.moveTo(50, 50); 1.216 + gRightWindow = open(xulWin, '', 'chrome,screenX=300,screenY=50,width=200,height=200'); 1.217 + eventListenOnce(gRightWindow, "focus", function () { 1.218 + focusAndThen(window, runTests); 1.219 + }); 1.220 + gPopup = document.getElementById("popup"); 1.221 + } 1.222 + 1.223 + function runTests() { 1.224 + observe(window, eventMonitor, true); 1.225 + observe(gRightWindow, eventMonitor, true); 1.226 + var left = window, right = gRightWindow; 1.227 + var leftElem = document.getElementById("box"); 1.228 + var rightElem = gRightWindow.document.documentElement; 1.229 + var panel = document.getElementById("panel"); 1.230 + var tooltip = (function createTooltipInRightWindow() { 1.231 + var _tooltip = right.document.createElementNS(XUL_NS, "tooltip"); 1.232 + _tooltip.setAttribute("id", "tip"); 1.233 + _tooltip.setAttribute("width", "80"); 1.234 + _tooltip.setAttribute("height", "20"); 1.235 + right.document.documentElement.appendChild(_tooltip); 1.236 + return _tooltip; 1.237 + })(); 1.238 + var tests = [ 1.239 + 1.240 + // Part 1: Disallow click-through 1.241 + 1.242 + function blockClickThrough(callback) { 1.243 + document.documentElement.setAttribute("clickthrough", "never"); 1.244 + gRightWindow.document.documentElement.setAttribute("clickthrough", "never"); 1.245 + callback(); 1.246 + }, 1.247 + // Enter the left window, which is focused. 1.248 + [150, 150, NSMouseMoved, null, left, [ 1.249 + { type: "mouseover", target: leftElem }, 1.250 + { type: "mousemove", target: leftElem } 1.251 + ]], 1.252 + // Test that moving inside the window fires mousemove events. 1.253 + [170, 150, NSMouseMoved, null, left, [ 1.254 + { type: "mousemove", target: leftElem }, 1.255 + ]], 1.256 + // Leaving the window should fire a mouseout event... 1.257 + [170, 20, NSMouseMoved, null, left, [ 1.258 + { type: "mouseout", target: leftElem }, 1.259 + ]], 1.260 + // ... and entering a mouseover event. 1.261 + [170, 120, NSMouseMoved, null, left, [ 1.262 + { type: "mouseover", target: leftElem }, 1.263 + { type: "mousemove", target: leftElem }, 1.264 + ]], 1.265 + // Move over the right window, which is inactive. 1.266 + // Inactive windows shouldn't respond to mousemove events when clickthrough="never", 1.267 + // so we should only get a mouseout event, no mouseover event. 1.268 + [400, 150, NSMouseMoved, null, right, [ 1.269 + { type: "mouseout", target: leftElem }, 1.270 + ]], 1.271 + // Left-clicking while holding Cmd and middle clicking should work even 1.272 + // on inactive windows, but without making them active. 1.273 + [400, 150, NSLeftMouseDown, null, right, [ 1.274 + { type: "mousedown", target: rightElem }, 1.275 + ], NSCommandKeyMask], 1.276 + [400, 150, NSLeftMouseUp, null, right, [ 1.277 + { type: "mouseup", target: rightElem }, 1.278 + { type: "click", target: rightElem }, 1.279 + ], NSCommandKeyMask], 1.280 + [400, 150, NSOtherMouseDown, null, right, [ 1.281 + { type: "mousedown", target: rightElem }, 1.282 + ]], 1.283 + [400, 150, NSOtherMouseUp, null, right, [ 1.284 + { type: "mouseup", target: rightElem }, 1.285 + { type: "click", target: rightElem }, 1.286 + ]], 1.287 + // Clicking an inactive window should make it active and fire a mouseover 1.288 + // event. 1.289 + [400, 150, NSLeftMouseDown, null, right, [ 1.290 + { type: "mouseover", target: rightElem, synthetic: true }, 1.291 + ]], 1.292 + [400, 150, NSLeftMouseUp, null, right, [ 1.293 + ]], 1.294 + // Now it's focused, so we should get a mousedown event when clicking. 1.295 + [400, 150, NSLeftMouseDown, null, right, [ 1.296 + { type: "mousedown", target: rightElem }, 1.297 + ]], 1.298 + // Let's drag to the right without letting the button go. 1.299 + [410, 150, NSLeftMouseDragged, null, right, [ 1.300 + { type: "mousemove", target: rightElem }, 1.301 + ]], 1.302 + // Let go of the mouse. 1.303 + [410, 150, NSLeftMouseUp, null, right, [ 1.304 + { type: "mouseup", target: rightElem }, 1.305 + { type: "click", target: rightElem }, 1.306 + ]], 1.307 + // Move the mouse back over the left window, which is inactive. 1.308 + [150, 170, NSMouseMoved, null, left, [ 1.309 + { type: "mouseout", target: rightElem }, 1.310 + ]], 1.311 + // Now we're being sneaky. The left window is inactive, but *right*-clicks to it 1.312 + // should still get through. Test that. 1.313 + // Ideally we'd be bracketing that event with over and out events, too, but it 1.314 + // probably doesn't matter too much. 1.315 + [150, 170, NSRightMouseDown, null, left, [ 1.316 + { type: "mouseover", target: leftElem, shouldFireButDoesnt: true }, 1.317 + { type: "mousedown", target: leftElem }, 1.318 + { type: "mouseout", target: leftElem, shouldFireButDoesnt: true }, 1.319 + ]], 1.320 + // Let go of the mouse. 1.321 + [150, 170, NSRightMouseUp, null, left, [ 1.322 + { type: "mouseover", target: leftElem, shouldFireButDoesnt: true }, 1.323 + { type: "mouseup", target: leftElem }, 1.324 + { type: "click", target: leftElem }, 1.325 + { type: "mouseout", target: leftElem, shouldFireButDoesnt: true }, 1.326 + ]], 1.327 + // Right clicking hasn't focused it, so the window is still inactive. 1.328 + // Let's focus it; this time without the mouse, for variaton's sake. 1.329 + // Still, mouseout and mouseover events should fire. 1.330 + function raiseLeftWindow(callback) { 1.331 + clearExpectedEvents(); 1.332 + gExpectedEvents.push({ screenX: 150, screenY: 170, type: "mouseover", target: leftElem }); 1.333 + // We have to be a bit careful here. The synthetic mouse event may 1.334 + // not fire for a bit after we focus the left window. 1.335 + eventListenOnce(leftElem, "mouseover", function() { 1.336 + // Trigger callback async, so we're not assuming 1.337 + // anything about how our listener gets ordered with others. 1.338 + SimpleTest.executeSoon(callback); 1.339 + }); 1.340 + printDebug("focusing left window"); 1.341 + left.focus(); 1.342 + }, 1.343 + // It's active, so it should respond to mousemove events now. 1.344 + [150, 170, NSMouseMoved, null, left, [ 1.345 + { type: "mousemove", target: leftElem }, 1.346 + ]], 1.347 + // This was boring... let's introduce a popup. It will overlap both the left 1.348 + // and the right window. 1.349 + function openPopupInLeftWindow(callback) { 1.350 + eventListenOnce(gPopup, "popupshown", callback); 1.351 + gPopup.openPopupAtScreen(150, 50, true); 1.352 + }, 1.353 + // Move the mouse over the popup. 1.354 + [200, 80, NSMouseMoved, gPopup, left, [ 1.355 + { type: "mouseout", target: leftElem }, 1.356 + { type: "mouseover", target: gPopup }, 1.357 + { type: "mousemove", target: gPopup }, 1.358 + ]], 1.359 + // Move the mouse back over the left window outside the popup. 1.360 + [160, 170, NSMouseMoved, null, left, [ 1.361 + { type: "mouseout", target: gPopup }, 1.362 + { type: "mouseover", target: leftElem }, 1.363 + { type: "mousemove", target: leftElem }, 1.364 + ]], 1.365 + // Back over the popup... 1.366 + [190, 80, NSMouseMoved, gPopup, left, [ 1.367 + { type: "mouseout", target: leftElem }, 1.368 + { type: "mouseover", target: gPopup }, 1.369 + { type: "mousemove", target: gPopup }, 1.370 + ]], 1.371 + // ...and over into the right window. 1.372 + // It's inactive, so it shouldn't get mouseover events yet. 1.373 + [400, 170, NSMouseMoved, null, right, [ 1.374 + { type: "mouseout", target: gPopup }, 1.375 + ]], 1.376 + // Again, no mouse events please, even though a popup is open. (bug 425556) 1.377 + [400, 180, NSMouseMoved, null, right, [ 1.378 + ]], 1.379 + // Activate the right window with a click. 1.380 + // This will close the popup and make the mouse enter the right window. 1.381 + [400, 180, NSLeftMouseDown, null, right, [ 1.382 + { type: "mouseover", target: rightElem, synthetic: true }, 1.383 + ]], 1.384 + [400, 180, NSLeftMouseUp, null, right, [ 1.385 + ]], 1.386 + function verifyPopupClosed2(callback) { 1.387 + is(gPopup.popupBoxObject.popupState, "closed", "popup should have closed when clicking"); 1.388 + callback(); 1.389 + }, 1.390 + // Now the right window is active; click it again, just for fun. 1.391 + [400, 180, NSLeftMouseDown, null, right, [ 1.392 + { type: "mousedown", target: rightElem }, 1.393 + ]], 1.394 + [400, 180, NSLeftMouseUp, null, right, [ 1.395 + { type: "mouseup", target: rightElem }, 1.396 + { type: "click", target: rightElem }, 1.397 + ]], 1.398 + 1.399 + // Time for our next trick: a tooltip! 1.400 + // Install the tooltip, but don't show it yet. 1.401 + function setTooltip(callback) { 1.402 + rightElem.setAttribute("tooltip", "tip"); 1.403 + gExpectedEvents.push({ screenX: 410, screenY: 180, type: "mousemove", target: rightElem }); 1.404 + eventListenOnce(rightElem, "popupshown", callback); 1.405 + gCurrentMouseX = 410; 1.406 + gCurrentMouseY = 180; 1.407 + var utils = right.QueryInterface(Components.interfaces.nsIInterfaceRequestor). 1.408 + getInterface(Components.interfaces.nsIDOMWindowUtils); 1.409 + utils.sendNativeMouseEvent(410, 180, NSMouseMoved, 0, null); 1.410 + }, 1.411 + // Now the tooltip is visible. 1.412 + // Move the mouse a little to the right. 1.413 + [411, 180, NSMouseMoved, null, right, [ 1.414 + { type: "mousemove", target: rightElem }, 1.415 + ]], 1.416 + // Move another pixel. 1.417 + [412, 180, NSMouseMoved, null, right, [ 1.418 + { type: "mousemove", target: rightElem }, 1.419 + ]], 1.420 + // Move up and click to make the tooltip go away. 1.421 + [412, 80, NSMouseMoved, null, right, [ 1.422 + { type: "mousemove", target: rightElem }, 1.423 + ]], 1.424 + [412, 80, NSLeftMouseDown, null, right, [ 1.425 + { type: "mousedown", target: rightElem }, 1.426 + ]], 1.427 + [412, 80, NSLeftMouseUp, null, right, [ 1.428 + { type: "mouseup", target: rightElem }, 1.429 + { type: "click", target: rightElem }, 1.430 + ]], 1.431 + // OK, next round. Open a panel in the left window, which is inactive. 1.432 + function openPanel(callback) { 1.433 + eventListenOnce(panel, "popupshown", callback); 1.434 + panel.openPopupAtScreen(150, 150, false); 1.435 + }, 1.436 + // The panel is parented, so it will be z-ordered over its parent but 1.437 + // under the active window. 1.438 + // Now we move the mouse over the part where the panel rect intersects the 1.439 + // right window's rect. Since the panel is under the window, all the events 1.440 + // should target the right window. 1.441 + [390, 170, NSMouseMoved, null, right, [ 1.442 + { type: "mousemove", target: rightElem }, 1.443 + ]], 1.444 + [390, 171, NSMouseMoved, null, right, [ 1.445 + { type: "mousemove", target: rightElem }, 1.446 + ]], 1.447 + [391, 171, NSMouseMoved, null, right, [ 1.448 + { type: "mousemove", target: rightElem }, 1.449 + ]], 1.450 + // Now move off the right window, so that the mouse is directly over the 1.451 + // panel. 1.452 + [260, 170, NSMouseMoved, panel, left, [ 1.453 + { type: "mouseout", target: rightElem }, 1.454 + ]], 1.455 + [260, 171, NSMouseMoved, panel, left, [ 1.456 + ]], 1.457 + [261, 171, NSMouseMoved, panel, left, [ 1.458 + ]], 1.459 + // Let's be evil and click it. 1.460 + [261, 171, NSLeftMouseDown, panel, left, [ 1.461 + ]], 1.462 + [261, 171, NSLeftMouseUp, panel, left, [ 1.463 + ]], 1.464 + // This didn't focus the window, unfortunately, so let's do it ourselves. 1.465 + function raiseLeftWindowTakeTwo(callback) { 1.466 + focusAndThen(left, callback); 1.467 + }, 1.468 + // Now mouse events should get through to the panel (which is now over the 1.469 + // right window). 1.470 + [387, 170, NSMouseMoved, panel, left, [ 1.471 + { type: "mouseover", target: panel }, 1.472 + { type: "mousemove", target: panel }, 1.473 + ]], 1.474 + [387, 171, NSMouseMoved, panel, left, [ 1.475 + { type: "mousemove", target: panel }, 1.476 + ]], 1.477 + [388, 171, NSMouseMoved, panel, left, [ 1.478 + { type: "mousemove", target: panel }, 1.479 + ]], 1.480 + // Click the panel. 1.481 + [388, 171, NSLeftMouseDown, panel, left, [ 1.482 + { type: "mousedown", target: panel } 1.483 + ]], 1.484 + [388, 171, NSLeftMouseUp, panel, left, [ 1.485 + { type: "mouseup", target: panel }, 1.486 + { type: "click", target: panel }, 1.487 + ]], 1.488 + 1.489 + // Last test for this part: Hit testing in the Canyon of Nowhere - 1.490 + // the pixel row directly south of the panel, over the left window. 1.491 + // Before bug 515003 we wrongly thought the mouse wasn't over any window. 1.492 + [173, 200, NSMouseMoved, null, left, [ 1.493 + { type: "mouseout", target: panel }, 1.494 + { type: "mouseover", target: leftElem }, 1.495 + { type: "mousemove", target: leftElem }, 1.496 + ]], 1.497 + [173, 201, NSMouseMoved, null, left, [ 1.498 + { type: "mousemove", target: leftElem }, 1.499 + ]], 1.500 + 1.501 + // Part 2: Allow click-through 1.502 + 1.503 + function hideThatPanel(callback) { 1.504 + eventListenOnce(panel, "popuphidden", callback); 1.505 + panel.hidePopup(); 1.506 + }, 1.507 + function unblockClickThrough(callback) { 1.508 + document.documentElement.removeAttribute("clickthrough"); 1.509 + gRightWindow.document.documentElement.removeAttribute("clickthrough"); 1.510 + callback(); 1.511 + }, 1.512 + // Enter the left window, which is focused. 1.513 + [150, 150, NSMouseMoved, null, left, [ 1.514 + { type: "mousemove", target: leftElem } 1.515 + ]], 1.516 + // Test that moving inside the window fires mousemove events. 1.517 + [170, 150, NSMouseMoved, null, left, [ 1.518 + { type: "mousemove", target: leftElem }, 1.519 + ]], 1.520 + // Leaving the window should fire a mouseout event... 1.521 + [170, 20, NSMouseMoved, null, left, [ 1.522 + { type: "mouseout", target: leftElem }, 1.523 + ]], 1.524 + // ... and entering a mouseover event. 1.525 + [170, 120, NSMouseMoved, null, left, [ 1.526 + { type: "mouseover", target: leftElem }, 1.527 + { type: "mousemove", target: leftElem }, 1.528 + ]], 1.529 + // Move over the right window, which is inactive but still accepts 1.530 + // mouse events. 1.531 + [400, 150, NSMouseMoved, null, right, [ 1.532 + { type: "mouseout", target: leftElem }, 1.533 + { type: "mouseover", target: rightElem }, 1.534 + { type: "mousemove", target: rightElem }, 1.535 + ]], 1.536 + // Left-clicking while holding Cmd and middle clicking should work 1.537 + // on inactive windows, but without making them active. 1.538 + [400, 150, NSLeftMouseDown, null, right, [ 1.539 + { type: "mousedown", target: rightElem }, 1.540 + ], NSCommandKeyMask], 1.541 + [400, 150, NSLeftMouseUp, null, right, [ 1.542 + { type: "mouseup", target: rightElem }, 1.543 + { type: "click", target: rightElem }, 1.544 + ], NSCommandKeyMask], 1.545 + [400, 150, NSOtherMouseDown, null, right, [ 1.546 + { type: "mousedown", target: rightElem }, 1.547 + ]], 1.548 + [400, 150, NSOtherMouseUp, null, right, [ 1.549 + { type: "mouseup", target: rightElem }, 1.550 + { type: "click", target: rightElem }, 1.551 + ]], 1.552 + // Clicking an inactive window should make it active 1.553 + [400, 150, NSLeftMouseDown, null, right, [ 1.554 + { type: "mousedown", target: rightElem }, 1.555 + ]], 1.556 + [400, 150, NSLeftMouseUp, null, right, [ 1.557 + { type: "mouseup", target: rightElem }, 1.558 + { type: "click", target: rightElem }, 1.559 + ]], 1.560 + // Now it's focused. 1.561 + [401, 150, NSLeftMouseDown, null, right, [ 1.562 + { type: "mousedown", target: rightElem }, 1.563 + ]], 1.564 + // Let's drag to the right without letting the button go. 1.565 + [410, 150, NSLeftMouseDragged, null, right, [ 1.566 + { type: "mousemove", target: rightElem }, 1.567 + ]], 1.568 + // Let go of the mouse. 1.569 + [410, 150, NSLeftMouseUp, null, right, [ 1.570 + { type: "mouseup", target: rightElem }, 1.571 + { type: "click", target: rightElem }, 1.572 + ]], 1.573 + // Move the mouse back over the left window, which is inactive. 1.574 + [150, 170, NSMouseMoved, null, left, [ 1.575 + { type: "mouseout", target: rightElem }, 1.576 + { type: "mouseover", target: leftElem }, 1.577 + { type: "mousemove", target: leftElem }, 1.578 + ]], 1.579 + // Right-click it. 1.580 + [150, 170, NSRightMouseDown, null, left, [ 1.581 + { type: "mousedown", target: leftElem }, 1.582 + ]], 1.583 + // Let go of the mouse. 1.584 + [150, 170, NSRightMouseUp, null, left, [ 1.585 + { type: "mouseup", target: leftElem }, 1.586 + { type: "click", target: leftElem }, 1.587 + ]], 1.588 + // Right clicking hasn't focused it, so the window is still inactive. 1.589 + // Let's focus it; this time without the mouse, for variaton's sake. 1.590 + function raiseLeftWindow(callback) { 1.591 + clearExpectedEvents(); 1.592 + focusAndThen(left, function () { SimpleTest.executeSoon(callback); }); 1.593 + }, 1.594 + // It's active and should still respond to mousemove events. 1.595 + [150, 170, NSMouseMoved, null, left, [ 1.596 + { type: "mousemove", target: leftElem }, 1.597 + ]], 1.598 + 1.599 + // This was boring... let's introduce a popup. It will overlap both the left 1.600 + // and the right window. 1.601 + function openPopupInLeftWindow(callback) { 1.602 + eventListenOnce(gPopup, "popupshown", callback); 1.603 + gPopup.openPopupAtScreen(150, 50, true); 1.604 + }, 1.605 + // Move the mouse over the popup. 1.606 + [200, 80, NSMouseMoved, gPopup, left, [ 1.607 + { type: "mouseout", target: leftElem }, 1.608 + { type: "mouseover", target: gPopup }, 1.609 + { type: "mousemove", target: gPopup }, 1.610 + ]], 1.611 + // Move the mouse back over the left window outside the popup. 1.612 + [160, 170, NSMouseMoved, null, left, [ 1.613 + { type: "mouseout", target: gPopup }, 1.614 + { type: "mouseover", target: leftElem }, 1.615 + { type: "mousemove", target: leftElem }, 1.616 + ]], 1.617 + // Back over the popup... 1.618 + [190, 80, NSMouseMoved, gPopup, left, [ 1.619 + { type: "mouseout", target: leftElem }, 1.620 + { type: "mouseover", target: gPopup }, 1.621 + { type: "mousemove", target: gPopup }, 1.622 + ]], 1.623 + // ...and over into the right window. 1.624 + [400, 170, NSMouseMoved, null, right, [ 1.625 + { type: "mouseout", target: gPopup }, 1.626 + { type: "mouseover", target: rightElem }, 1.627 + { type: "mousemove", target: rightElem }, 1.628 + ]], 1.629 + [400, 180, NSMouseMoved, null, right, [ 1.630 + { type: "mousemove", target: rightElem }, 1.631 + ]], 1.632 + // Activate the right window with a click. 1.633 + [400, 180, NSLeftMouseDown, null, right, [ 1.634 + { type: "mousedown", target: rightElem }, 1.635 + ]], 1.636 + [400, 180, NSLeftMouseUp, null, right, [ 1.637 + { type: "mouseup", target: rightElem }, 1.638 + { type: "click", target: rightElem }, 1.639 + ]], 1.640 + function verifyPopupClosed2(callback) { 1.641 + is(gPopup.popupBoxObject.popupState, "closed", "popup should have closed when clicking"); 1.642 + callback(); 1.643 + }, 1.644 + // Now the right window is active; click it again, just for fun. 1.645 + [400, 180, NSLeftMouseDown, null, right, [ 1.646 + { type: "mousedown", target: rightElem }, 1.647 + ]], 1.648 + [400, 180, NSLeftMouseUp, null, right, [ 1.649 + { type: "mouseup", target: rightElem }, 1.650 + { type: "click", target: rightElem }, 1.651 + ]], 1.652 + 1.653 + // Time for our next trick: a tooltip! 1.654 + // Install the tooltip, but don't show it yet. 1.655 + function setTooltip2(callback) { 1.656 + rightElem.setAttribute("tooltip", "tip"); 1.657 + gExpectedEvents.push({ screenX: 410, screenY: 180, type: "mousemove", target: rightElem }); 1.658 + eventListenOnce(rightElem, "popupshown", callback); 1.659 + gCurrentMouseX = 410; 1.660 + gCurrentMouseY = 180; 1.661 + var utils = right.QueryInterface(Components.interfaces.nsIInterfaceRequestor). 1.662 + getInterface(Components.interfaces.nsIDOMWindowUtils); 1.663 + utils.sendNativeMouseEvent(410, 180, NSMouseMoved, 0, null); 1.664 + }, 1.665 + // Now the tooltip is visible. 1.666 + // Move the mouse a little to the right. 1.667 + [411, 180, NSMouseMoved, null, right, [ 1.668 + { type: "mousemove", target: rightElem }, 1.669 + ]], 1.670 + // Move another pixel. 1.671 + [412, 180, NSMouseMoved, null, right, [ 1.672 + { type: "mousemove", target: rightElem }, 1.673 + ]], 1.674 + // Move up and click to make the tooltip go away. 1.675 + [412, 80, NSMouseMoved, null, right, [ 1.676 + { type: "mousemove", target: rightElem }, 1.677 + ]], 1.678 + [412, 80, NSLeftMouseDown, null, right, [ 1.679 + { type: "mousedown", target: rightElem }, 1.680 + ]], 1.681 + [412, 80, NSLeftMouseUp, null, right, [ 1.682 + { type: "mouseup", target: rightElem }, 1.683 + { type: "click", target: rightElem }, 1.684 + ]], 1.685 + // OK, next round. Open a panel in the left window, which is inactive. 1.686 + function openPanel2(callback) { 1.687 + eventListenOnce(panel, "popupshown", callback); 1.688 + panel.openPopupAtScreen(150, 150, false); 1.689 + }, 1.690 + // The panel is parented, so it will be z-ordered over its parent but 1.691 + // under the active window. 1.692 + // Now we move the mouse over the part where the panel rect intersects the 1.693 + // right window's rect. Since the panel is under the window, all the events 1.694 + // should target the right window. 1.695 + [390, 170, NSMouseMoved, null, right, [ 1.696 + { type: "mousemove", target: rightElem }, 1.697 + ]], 1.698 + [390, 171, NSMouseMoved, null, right, [ 1.699 + { type: "mousemove", target: rightElem }, 1.700 + ]], 1.701 + [391, 171, NSMouseMoved, null, right, [ 1.702 + { type: "mousemove", target: rightElem }, 1.703 + ]], 1.704 + // Now move off the right window, so that the mouse is directly over the 1.705 + // panel. 1.706 + [260, 170, NSMouseMoved, panel, left, [ 1.707 + { type: "mouseout", target: rightElem }, 1.708 + { type: "mouseover", target: panel }, 1.709 + { type: "mousemove", target: panel }, 1.710 + ]], 1.711 + [260, 171, NSMouseMoved, panel, left, [ 1.712 + { type: "mousemove", target: panel }, 1.713 + ]], 1.714 + [261, 171, NSMouseMoved, panel, left, [ 1.715 + { type: "mousemove", target: panel }, 1.716 + ]], 1.717 + // Let's be evil and click it. 1.718 + [261, 171, NSLeftMouseDown, panel, left, [ 1.719 + { type: "mousedown", target: panel }, 1.720 + ]], 1.721 + [261, 171, NSLeftMouseUp, panel, left, [ 1.722 + { type: "mouseup", target: panel }, 1.723 + { type: "click", target: panel }, 1.724 + ]], 1.725 + // This didn't focus the window, unfortunately, so let's do it ourselves. 1.726 + function raiseLeftWindowTakeTwo(callback) { 1.727 + focusAndThen(left, callback); 1.728 + }, 1.729 + [387, 170, NSMouseMoved, panel, left, [ 1.730 + { type: "mousemove", target: panel }, 1.731 + ]], 1.732 + [387, 171, NSMouseMoved, panel, left, [ 1.733 + { type: "mousemove", target: panel }, 1.734 + ]], 1.735 + [388, 171, NSMouseMoved, panel, left, [ 1.736 + { type: "mousemove", target: panel }, 1.737 + ]], 1.738 + // Click the panel. 1.739 + [388, 171, NSLeftMouseDown, panel, left, [ 1.740 + { type: "mousedown", target: panel } 1.741 + ]], 1.742 + [388, 171, NSLeftMouseUp, panel, left, [ 1.743 + { type: "mouseup", target: panel }, 1.744 + { type: "click", target: panel }, 1.745 + ]], 1.746 + 1.747 + // Last test for today: Hit testing in the Canyon of Nowhere - 1.748 + // the pixel row directly south of the panel, over the left window. 1.749 + // Before bug 515003 we wrongly thought the mouse wasn't over any window. 1.750 + [173, 200, NSMouseMoved, null, left, [ 1.751 + { type: "mouseout", target: panel }, 1.752 + { type: "mouseover", target: leftElem }, 1.753 + { type: "mousemove", target: leftElem }, 1.754 + ]], 1.755 + [173, 201, NSMouseMoved, null, left, [ 1.756 + { type: "mousemove", target: leftElem }, 1.757 + ]], 1.758 + ]; 1.759 + function runNextTest() { 1.760 + if (!tests.length) 1.761 + return onTestsFinished(); 1.762 + 1.763 + var test = tests.shift(); 1.764 + if (typeof test == "function") 1.765 + return test(runNextTest); 1.766 + 1.767 + var [x, y, msg, elem, win, exp, flags] = test; 1.768 + testMouse(x, y, msg, elem, win, exp, flags, runNextTest); 1.769 + } 1.770 + runNextTest(); 1.771 + } 1.772 + 1.773 + SimpleTest.waitForFocus(start); 1.774 + 1.775 + ]]></script> 1.776 +</window>