1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/tests/mochitest/chrome/window_focus.xul Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1718 @@ 1.4 +<?xml version="1.0"?> 1.5 +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> 1.6 +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" 1.7 + type="text/css"?> 1.8 +<!-- 1.9 + This test checks focus in various ways 1.10 +--> 1.11 +<window id="outer-document" title="Focus Test" width="600" height="550" 1.12 + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> 1.13 + <script type="application/javascript" 1.14 + src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> 1.15 + <script type="application/javascript" 1.16 + src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> 1.17 + 1.18 +<body xmlns="http://www.w3.org/1999/xhtml"/> 1.19 + 1.20 + <script type="application/javascript"><![CDATA[ 1.21 + 1.22 +var fm = Components.classes["@mozilla.org/focus-manager;1"]. 1.23 + getService(Components.interfaces.nsIFocusManager); 1.24 + 1.25 +const kChildDocumentRootIndex = 13; 1.26 +const kBeforeTabboxIndex = 34; 1.27 +const kTabbableSteps = 38; 1.28 +const kFocusSteps = 26; 1.29 +const kNoFocusSteps = 7; 1.30 +const kOverflowElementIndex = 27; 1.31 + 1.32 +var gTestStarted = false; 1.33 +var gPartialTabbing = false; 1.34 +var gMoveToFocusFrame = false; 1.35 +var gLastFocus = null; 1.36 +var gLastFocusWindow = window; 1.37 +var gLastFocusMethod = -1; 1.38 +var gEvents = ""; 1.39 +var gExpectedEvents = ""; 1.40 +var gEventMatched = true; 1.41 +var gShowOutput = false; 1.42 +var gChildWindow = null; 1.43 + 1.44 +var gOldExpectedWindow = null; 1.45 +var gNewExpectedWindow = null; 1.46 + 1.47 +function is(l, r, n) { window.opener.wrappedJSObject.SimpleTest.is(l,r,n); } 1.48 +function ok(v, n) { window.opener.wrappedJSObject.SimpleTest.ok(v,n); } 1.49 + 1.50 +function initEvents(target) 1.51 +{ 1.52 + target.addEventListener("focus", eventOccured, true); 1.53 + target.addEventListener("blur", eventOccured, true); 1.54 + getTopWindow(target).addEventListener("activate", eventOccured, true); 1.55 + getTopWindow(target).addEventListener("deactivate", eventOccured, true); 1.56 +} 1.57 + 1.58 +function eventOccured(event) 1.59 +{ 1.60 + // iframes should never receive focus or blur events directly 1.61 + if (event.target instanceof Element && event.target.localName == "iframe") 1.62 + ok(false, "iframe " + event.type + "occured"); 1.63 + 1.64 + var id; 1.65 + if (gOldExpectedWindow && event.type == "blur") { 1.66 + if (event.target instanceof Window) 1.67 + id = "frame-" + gOldExpectedWindow.document.documentElement.id + "-window"; 1.68 + else if (event.target instanceof Document) 1.69 + id = "frame-" + gOldExpectedWindow.document.documentElement.id + "-document"; 1.70 + else 1.71 + id = event.originalTarget.id; 1.72 + } 1.73 + else if (gNewExpectedWindow && event.type == "focus") { 1.74 + if (event.target instanceof Window) 1.75 + id = "frame-" + gNewExpectedWindow.document.documentElement.id + "-window"; 1.76 + else if (event.target instanceof Document) 1.77 + id = "frame-" + gNewExpectedWindow.document.documentElement.id + "-document"; 1.78 + else 1.79 + id = event.originalTarget.id; 1.80 + } 1.81 + else if (event.type == "activate" || event.type == "deactivate") 1.82 + id = event.target.document.documentElement.id + "-window"; 1.83 + else if (event.target instanceof Window) 1.84 + id = (event.target == window) ? "outer-window" : "child-window"; 1.85 + else if (event.target instanceof Document) 1.86 + id = (event.target == document) ? "outer-document" : "child-document"; 1.87 + else 1.88 + id = event.originalTarget.id; 1.89 + 1.90 + if (gEvents) 1.91 + gEvents += " "; 1.92 + gEvents += event.type + ": " + id; 1.93 +} 1.94 + 1.95 +function expectFocusShift(callback, expectedWindow, expectedElement, focusChanged, testid) 1.96 +{ 1.97 + if (expectedWindow == null) 1.98 + expectedWindow = expectedElement ? 1.99 + expectedElement.ownerDocument.defaultView : 1.100 + gLastFocusWindow; 1.101 + 1.102 + var expectedEvents = ""; 1.103 + if (focusChanged) { 1.104 + var id; 1.105 + if (getTopWindow(gLastFocusWindow) != getTopWindow(expectedWindow)) { 1.106 + id = getTopWindow(gLastFocusWindow).document.documentElement.id; 1.107 + expectedEvents += "deactivate: " + id + "-window"; 1.108 + } 1.109 + 1.110 + if (gLastFocus && gLastFocus.id != "t" + kChildDocumentRootIndex && 1.111 + (!gOldExpectedWindow || gOldExpectedWindow.document.documentElement != gLastFocus)) { 1.112 + if (expectedEvents) 1.113 + expectedEvents += " "; 1.114 + if (!gOldExpectedWindow) 1.115 + expectedEvents += "commandupdate: cu "; 1.116 + expectedEvents += "blur: " + gLastFocus.id; 1.117 + } 1.118 + 1.119 + if (gLastFocusWindow && gLastFocusWindow != expectedWindow) { 1.120 + if (!gMoveToFocusFrame) { 1.121 + if (gOldExpectedWindow) 1.122 + id = "frame-" + gOldExpectedWindow.document.documentElement.id; 1.123 + else 1.124 + id = (gLastFocusWindow == window) ? "outer" : "child"; 1.125 + if (expectedEvents) 1.126 + expectedEvents += " "; 1.127 + expectedEvents += "blur: " + id + "-document " + 1.128 + "blur: " + id + "-window"; 1.129 + } 1.130 + } 1.131 + 1.132 + if (getTopWindow(gLastFocusWindow) != getTopWindow(expectedWindow)) { 1.133 + id = getTopWindow(expectedWindow).document.documentElement.id; 1.134 + if (expectedEvents) 1.135 + expectedEvents += " "; 1.136 + expectedEvents += "activate: " + id + "-window"; 1.137 + } 1.138 + 1.139 + if (expectedWindow && gLastFocusWindow != expectedWindow) { 1.140 + if (gNewExpectedWindow) 1.141 + id = "frame-" + gNewExpectedWindow.document.documentElement.id; 1.142 + else 1.143 + id = (expectedWindow == window) ? "outer" : "child"; 1.144 + if (expectedEvents) 1.145 + expectedEvents += " "; 1.146 + expectedEvents += "focus: " + id + "-document " + 1.147 + "focus: " + id + "-window"; 1.148 + } 1.149 + 1.150 + // for this test which fires a mouse event on a label, the document will 1.151 + // be focused first and then the label code will focus the related 1.152 + // control. This doesn't result in different focus events, but a command 1.153 + // update will occur for the document and then a secon command update will 1.154 + // occur when the control is focused. 1.155 + if (testid == "mouse on html label with content inside") 1.156 + expectedEvents += " commandupdate: cu"; 1.157 + 1.158 + if (expectedElement && 1.159 + (!gNewExpectedWindow || gNewExpectedWindow.document.documentElement != expectedElement)) { 1.160 + if (!gNewExpectedWindow) { 1.161 + if (expectedEvents) 1.162 + expectedEvents += " "; 1.163 + expectedEvents += "commandupdate: cu"; 1.164 + } 1.165 + if (expectedElement.id != "t" + kChildDocumentRootIndex) { 1.166 + if (expectedEvents) 1.167 + expectedEvents += " "; 1.168 + expectedEvents += "focus: " + expectedElement.id; 1.169 + } 1.170 + } 1.171 + else if (expectedWindow && gLastFocusWindow != expectedWindow && 1.172 + !expectedElement) { 1.173 + if (expectedEvents) 1.174 + expectedEvents += " "; 1.175 + expectedEvents += "commandupdate: cu"; 1.176 + } 1.177 + } 1.178 + 1.179 + gLastFocus = expectedElement; 1.180 + gLastFocusWindow = expectedWindow; 1.181 + 1.182 + callback(); 1.183 + 1.184 + compareEvents(expectedEvents, expectedWindow, expectedElement, testid); 1.185 +} 1.186 + 1.187 +function compareEvents(expectedEvents, expectedWindow, expectedElement, testid) 1.188 +{ 1.189 + if (!gShowOutput) { 1.190 + gEvents = ""; 1.191 + return; 1.192 + } 1.193 + 1.194 + is(gEvents, expectedEvents, testid + " events"); 1.195 + gEvents = ""; 1.196 + 1.197 + var doc; 1.198 + if (expectedWindow == window) 1.199 + doc = "outer-document"; 1.200 + else if (expectedWindow == gChildWindow) 1.201 + doc = "inner-document"; 1.202 + else if (gNewExpectedWindow) 1.203 + doc = gNewExpectedWindow.document.body ? gNewExpectedWindow.document.body.id : 1.204 + gNewExpectedWindow.document.documentElement.id; 1.205 + else 1.206 + doc = "other-document"; 1.207 + 1.208 + var focusedElement = fm.focusedElement; 1.209 + is(focusedElement ? focusedElement.id : "none", 1.210 + expectedElement ? expectedElement.id : "none", testid + " focusedElement"); 1.211 + is(fm.focusedWindow, expectedWindow, testid + " focusedWindow"); 1.212 + var focusedWindow = {}; 1.213 + is(fm.getFocusedElementForWindow(expectedWindow, false, focusedWindow), 1.214 + expectedElement, testid + " getFocusedElementForWindow"); 1.215 + is(focusedWindow.value, expectedWindow, testid + " getFocusedElementForWindow frame"); 1.216 + is(expectedWindow.document.hasFocus(), true, testid + " hasFocus"); 1.217 + is(expectedWindow.document.activeElement ? expectedWindow.document.activeElement.id : "none", 1.218 + expectedElement ? expectedElement.id : doc, testid + " activeElement"); 1.219 + var cdwindow = getTopWindow(expectedWindow); 1.220 + if (cdwindow.document.commandDispatcher) { 1.221 + is(cdwindow.document.commandDispatcher.focusedWindow, expectedWindow, testid + " commandDispatcher focusedWindow"); 1.222 + is(cdwindow.document.commandDispatcher.focusedElement, focusedElement, testid + " commandDispatcher focusedElement"); 1.223 + } 1.224 + 1.225 + if (gLastFocusMethod != -1) { 1.226 + is(fm.getLastFocusMethod(null), gLastFocusMethod, testid + " lastFocusMethod null"); 1.227 + is(fm.getLastFocusMethod(expectedWindow), gLastFocusMethod, testid + " lastFocusMethod window"); 1.228 + } 1.229 + 1.230 + // the parent should have the iframe focused 1.231 + if (doc == "inner-document") { 1.232 + is(document.hasFocus(), true, testid + " hasFocus"); 1.233 + is(fm.getFocusedElementForWindow(window, false, focusedWindow), 1.234 + $("childframe"), testid + " getFocusedElementForWindow for parent"); 1.235 + is(focusedWindow.value, window, testid + " getFocusedElementForWindow for parent frame"); 1.236 + is(fm.getFocusedElementForWindow(window, true, focusedWindow), 1.237 + expectedElement, testid + " getFocusedElementForWindow deep for parent"); 1.238 + is(focusedWindow.value, gChildWindow, testid + " getFocusedElementForWindow deep for parent frame"); 1.239 + is(document.activeElement.id, "childframe", testid + " activeElement for parent"); 1.240 + } 1.241 + 1.242 + // compare the selection for the child window. Skip mouse tests as the caret 1.243 + // is adjusted by the selection code for mouse clicks, and not the focus code. 1.244 + if (expectedWindow == window) { 1.245 + var selection = window.getSelection(); 1.246 + ok(selection.focusNode == null && selection.focusOffset == 0 && 1.247 + selection.anchorNode == null && selection.anchorOffset == 0, testid + " selection"); 1.248 + } 1.249 + else if ((expectedWindow == gChildWindow) && !testid.indexOf("mouse") == -1) { 1.250 + checkSelection(expectedElement, testid); 1.251 + } 1.252 +} 1.253 + 1.254 +function checkSelection(node, testid) 1.255 +{ 1.256 + var selection = gChildWindow.getSelection(); 1.257 + 1.258 + var range = gChildWindow.document.createRange(); 1.259 + range.selectNodeContents(node); 1.260 + if (!node.firstChild || node.localName == "input" || 1.261 + node.localName == "select" || node.localName == "button") { 1.262 + range.setStartBefore(node); 1.263 + range.setEndBefore(node); 1.264 + } 1.265 + 1.266 + if (node.firstChild) 1.267 + range.setEnd(range.startContainer, range.startOffset); 1.268 + 1.269 + is(selection.focusNode, range.startContainer, testid + " selection focusNode"); 1.270 + is(selection.focusOffset, range.startOffset, testid + " selection focusOffset"); 1.271 + is(selection.anchorNode, range.endContainer, testid + " selection anchorNode"); 1.272 + is(selection.anchorOffset, range.endOffset, testid + " selection anchorOffset"); 1.273 +} 1.274 + 1.275 +function getTopWindow(win) 1.276 +{ 1.277 + return win.QueryInterface(Components.interfaces.nsIInterfaceRequestor). 1.278 + getInterface(Components.interfaces.nsIWebNavigation). 1.279 + QueryInterface(Components.interfaces.nsIDocShellTreeItem).rootTreeItem. 1.280 + QueryInterface(Components.interfaces.nsIInterfaceRequestor). 1.281 + getInterface(Components.interfaces.nsIDOMWindow); 1.282 +} 1.283 + 1.284 +function mouseOnElement(element, expectedElement, focusChanged, testid) 1.285 +{ 1.286 + var expectedWindow = (element.ownerDocument.defaultView == gChildWindow) ? gChildWindow : window; 1.287 + // on Mac, form elements are not focused when clicking, except for lists and textboxes. 1.288 + var noFocusOnMouse = (navigator.platform.indexOf("Mac") == 0); 1.289 + if (noFocusOnMouse) { 1.290 + if (element.namespaceURI == "http://www.w3.org/1999/xhtml") { 1.291 + // links are special. They can be focused but show no focus ring 1.292 + if (element.localName == "a" || element.localName == "div" || 1.293 + element.localName == "select" || 1.294 + element.localName == "input" && (element.type == "text" || 1.295 + element.type == "password")) { 1.296 + noFocusOnMouse = false; 1.297 + } 1.298 + } 1.299 + else if (element.localName == "listbox") { 1.300 + noFocusOnMouse = false; 1.301 + } 1.302 + } 1.303 + 1.304 + if (noFocusOnMouse) { 1.305 + // no focus so the last focus method will be 0 1.306 + gLastFocusMethod = 0; 1.307 + expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView), 1.308 + expectedWindow, null, true, testid); 1.309 + gLastFocusMethod = fm.FLAG_BYMOUSE; 1.310 + } 1.311 + else { 1.312 + expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView), 1.313 + element.ownerDocument.defaultView, 1.314 + expectedElement, focusChanged, testid); 1.315 + } 1.316 +} 1.317 + 1.318 +function done() 1.319 +{ 1.320 + var opener = window.opener; 1.321 + window.close(); 1.322 + opener.wrappedJSObject.SimpleTest.finish(); 1.323 +} 1.324 + 1.325 +var pressTab = function () synthesizeKey("VK_TAB", { }); 1.326 + 1.327 +function setFocusTo(id, fwindow) 1.328 +{ 1.329 + gLastFocus = getById(id); 1.330 + gLastFocusWindow = fwindow; 1.331 + if (gLastFocus) 1.332 + gLastFocus.focus(); 1.333 + else 1.334 + fm.clearFocus(fwindow); 1.335 + gEvents = ""; 1.336 +} 1.337 + 1.338 +function getById(id) 1.339 +{ 1.340 + if (gNewExpectedWindow) 1.341 + return gNewExpectedWindow.document.getElementById(id); 1.342 + var element = $(id); 1.343 + if (!element) 1.344 + element = $("childframe").contentDocument.getElementById(id); 1.345 + return element; 1.346 +} 1.347 + 1.348 +function startTest() 1.349 +{ 1.350 + if (gTestStarted) 1.351 + return; 1.352 + gTestStarted = true; 1.353 + 1.354 + gChildWindow = $("childframe").contentWindow; 1.355 + gShowOutput = true; 1.356 + 1.357 + // synthesize a mousemove over the image to ensure that the imagemap data is 1.358 + // created. Otherwise, the special imagemap frames might not exist, and 1.359 + // won't be focusable. 1.360 + synthesizeMouse(getById("image"), 4, 4, { type: "mousemove" }, gChildWindow); 1.361 + 1.362 + initEvents(window); 1.363 + 1.364 + is(fm.activeWindow, window, "activeWindow"); 1.365 + is(gChildWindow.document.hasFocus(), false, " child document hasFocus"); 1.366 + 1.367 + // test to see if the Mac Full Keyboard Access setting is set. If t3 is 1.368 + // focused after tab is pressed, then it is set to textboxes and lists only. 1.369 + // Otherwise, all elements are in the tab order. 1.370 + pressTab(); 1.371 + 1.372 + if (fm.focusedElement.id == "t3") 1.373 + gPartialTabbing = true; 1.374 + else 1.375 + is(fm.focusedElement.id, "t1", "initial tab key"); 1.376 + 1.377 + is(fm.getLastFocusMethod(null), fm.FLAG_BYKEY, "last focus method null start"); 1.378 + is(fm.getLastFocusMethod(window), fm.FLAG_BYKEY, "last focus method window start"); 1.379 + 1.380 + fm.clearFocus(window); 1.381 + gEvents = ""; 1.382 + 1.383 + gLastFocusMethod = fm.FLAG_BYKEY; 1.384 + if (gPartialTabbing) { 1.385 + var partialTabList = ["t3", "t5", "t9", "t10", "t11", "t12", "t13", "t14", "t15", 1.386 + "t16", "t19", "t20", "t21", "t22", "t26", "t27", "t28", "t29", "t30"]; 1.387 + for (var idx = 0; idx < partialTabList.length; idx++) { 1.388 + expectFocusShift(pressTab, null, getById(partialTabList[idx]), true, "partial tab key " + partialTabList[idx]); 1.389 + } 1.390 + setFocusTo("last", window); 1.391 + expectFocusShift(pressTab, null, getById(partialTabList[0]), true, "partial tab key wrap to start"); 1.392 + expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), 1.393 + null, getById("last"), true, "partial shift tab key wrap to end"); 1.394 + for (var idx = partialTabList.length - 1; idx >= 0; idx--) { 1.395 + expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), 1.396 + null, getById(partialTabList[idx]), true, "partial tab key " + partialTabList[idx]); 1.397 + } 1.398 + } 1.399 + else { 1.400 + // TAB key 1.401 + for (var idx = 1; idx <= kTabbableSteps; idx++) { 1.402 + expectFocusShift(pressTab, null, getById("t" + idx), true, "tab key t" + idx); 1.403 + } 1.404 + 1.405 + // wrapping around at end with TAB key 1.406 + setFocusTo("last", window); 1.407 + expectFocusShift(pressTab, null, getById("t1"), true, "tab key wrap to start"); 1.408 + expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), 1.409 + null, getById("last"), true, "shift tab key wrap to end"); 1.410 + 1.411 + // Shift+TAB key 1.412 + setFocusTo("o5", window); 1.413 + for (idx = kTabbableSteps; idx > 0; idx--) { 1.414 + expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), 1.415 + null, getById("t" + idx), true, "shift tab key t" + idx); 1.416 + } 1.417 + } 1.418 + 1.419 + var t19 = getById("t19"); 1.420 + is(t19.selectionStart, 0, "input focused from tab key selectionStart"); 1.421 + is(t19.selectionEnd, 5, "input focused from tab key selectionEnd"); 1.422 + t19.setSelectionRange(0, 0); 1.423 + 1.424 + gLastFocusMethod = 0; 1.425 + var selectFired = false; 1.426 + function selectListener() { selectFired = true; } 1.427 + t19.addEventListener("select", selectListener, false); 1.428 + expectFocusShift(function() t19.select(), 1.429 + null, getById("t" + 19), true, "input.select()"); 1.430 + t19.removeEventListener("select", selectListener, false); 1.431 + ok(selectFired, "select event fires for input"); 1.432 + 1.433 + // mouse clicking 1.434 + gLastFocusMethod = fm.FLAG_BYMOUSE; 1.435 + for (idx = kTabbableSteps; idx >= 1; idx--) { 1.436 + // skip the document root and the overflow element 1.437 + if (idx == kChildDocumentRootIndex || idx == kOverflowElementIndex) 1.438 + continue; 1.439 + if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1)) 1.440 + continue; 1.441 + 1.442 + var element = getById("t" + idx); 1.443 + // skip area elements, as getBoundingClientRect doesn't return their actual coordinates 1.444 + if (element.localName == "area") 1.445 + continue; 1.446 + 1.447 + mouseOnElement(element, getById("t" + idx), true, "mouse on element t" + idx); 1.448 + var expectedWindow = (element.ownerDocument.defaultView == gChildWindow) ? gChildWindow : window; 1.449 + if (element.localName == "listbox" && expectedWindow == window && 1.450 + navigator.platform.indexOf("Mac") == 0) { 1.451 + // after focusing a listbox on Mac, clear the focus before continuing. 1.452 + setFocusTo(null, window); 1.453 + } 1.454 + } 1.455 + 1.456 + is(t19.selectionStart, 0, "input focused from mouse selectionStart"); 1.457 + is(t19.selectionEnd, 0, "input focused from mouse selectionEnd"); 1.458 + 1.459 + // mouse clicking on elements that are not tabbable 1.460 + for (idx = 1; idx <= kFocusSteps; idx++) { 1.461 + var element = getById("o" + (idx % 2 ? idx : idx - 1)); 1.462 + 1.463 + mouseOnElement(element, element, idx % 2, 1.464 + "mouse on non-tabbable element o" + idx); 1.465 + } 1.466 + 1.467 + // mouse clicking on elements that are not tabbable and have user-focus: none 1.468 + // or are not focusable for other reasons (for instance, being disabled) 1.469 + // These elements will clear the focus when clicked. 1.470 + for (idx = 1; idx <= kNoFocusSteps; idx++) { 1.471 + var element = getById("n" + idx); 1.472 + gLastFocusMethod = idx % 2 ? 0 : fm.FLAG_BYMOUSE; 1.473 + 1.474 + mouseOnElement(element, idx % 2 ? null: element, true, "mouse on unfocusable element n" + idx); 1.475 + } 1.476 + 1.477 + if (idx == kOverflowElementIndex) { 1.478 + gLastFocusMethod = fm.FLAG_BYMOUSE; 1.479 + var element = getById("t" + idx); 1.480 + expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView), 1.481 + window, null, true, "mouse on scrollable element"); 1.482 + } 1.483 + 1.484 + // focus() method 1.485 + gLastFocusMethod = 0; 1.486 + for (idx = kTabbableSteps; idx >= 1; idx--) { 1.487 + if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1)) 1.488 + continue; 1.489 + expectFocusShift(function () getById("t" + idx).focus(), 1.490 + null, getById("t" + idx), true, "focus method on element t" + idx); 1.491 + } 1.492 + 1.493 + $("t1").focus(); 1.494 + ok(gEvents === "", "focusing element that is already focused"); 1.495 + 1.496 + $("t2").blur(); 1.497 + $("t7").blur(); 1.498 + ok(gEvents === "", "blurring element that is not focused"); 1.499 + is(document.activeElement, $("t1"), "old element still focused after blur() on another element"); 1.500 + 1.501 + // focus() method on elements that are not tabbable 1.502 + for (idx = 1; idx <= kFocusSteps; idx++) { 1.503 + var expected = getById("o" + (idx % 2 ? idx : idx - 1)); 1.504 + expectFocusShift(function () getById("o" + idx).focus(), 1.505 + expected.ownerDocument.defaultView, 1.506 + expected, idx % 2, "focus method on non-tabbable element o" + idx); 1.507 + } 1.508 + 1.509 + // focus() method on elements that are not tabbable and have user-focus: none 1.510 + // or are not focusable for other reasons (for instance, being disabled) 1.511 + for (idx = 1; idx <= kNoFocusSteps; idx++) { 1.512 + var expected = getById("o" + (idx % 2 ? idx : idx - 1)); 1.513 + expectFocusShift(function () getById("o" + idx).focus(), 1.514 + expected.ownerDocument.defaultView, 1.515 + expected, idx % 2, "focus method on unfocusable element n" + idx); 1.516 + } 1.517 + 1.518 + // the focus() method on the legend element should focus the legend if it is 1.519 + // focusable, or the first element after the legend if it is not focusable. 1.520 + if (!gPartialTabbing) { 1.521 + gLastFocusMethod = fm.FLAG_BYMOVEFOCUS; 1.522 + var legend = getById("legend"); 1.523 + expectFocusShift(function () legend.focus(), 1.524 + null, getById("t28"), true, "focus method on unfocusable legend"); 1.525 + gLastFocusMethod = 0; 1.526 + legend.tabIndex = "0"; 1.527 + expectFocusShift(function () legend.focus(), 1.528 + null, getById("legend"), true, "focus method on focusable legend"); 1.529 + legend.tabIndex = "-1"; 1.530 + } 1.531 + 1.532 + var accessKeyDetails = (navigator.platform.indexOf("Mac") >= 0) ? 1.533 + { ctrlKey : true } : { altKey : true }; 1.534 + 1.535 + // test accesskeys 1.536 + var keys = ["t26", "t19", "t22", "t29", "t15", "t17", "n6", 1.537 + "t4", "o1", "o9", "n4"]; 1.538 + for (var k = 0; k < keys.length; k++) { 1.539 + var key = String.fromCharCode(65 + k); 1.540 + 1.541 + // accesskeys D and G are for labels so get redirected 1.542 + gLastFocusMethod = (key == "D" || key == "G") ? fm.FLAG_BYMOVEFOCUS : fm.FLAG_BYKEY; 1.543 + 1.544 + // on Windows and Linux, the shift key must be pressed for content area access keys 1.545 + // and on Mac, the alt key must be pressed for content area access keys 1.546 + var isContent = (getById(keys[k]).ownerDocument.defaultView == gChildWindow); 1.547 + if (navigator.platform.indexOf("Mac") == -1) { 1.548 + accessKeyDetails.shiftKey = isContent; 1.549 + } else { 1.550 + accessKeyDetails.altKey = isContent; 1.551 + } 1.552 + 1.553 + expectFocusShift(function () synthesizeKey(key, accessKeyDetails), 1.554 + null, getById(keys[k]), true, "accesskey " + key); 1.555 + } 1.556 + 1.557 + // clicking on the labels 1.558 + gLastFocusMethod = fm.FLAG_BYMOVEFOCUS; 1.559 + expectFocusShift(function () synthesizeMouse(getById("ad"), 2, 2, { }, gChildWindow), 1.560 + null, getById("t29"), true, "mouse on html label with content inside"); 1.561 + expectFocusShift(function () synthesizeMouse(getById("ag"), 2, 2, { }, gChildWindow), 1.562 + null, getById("n6"), true, "mouse on html label with for attribute"); 1.563 + gLastFocusMethod = 0; 1.564 + expectFocusShift(function () synthesizeMouse(getById("aj"), 2, 2, { }), 1.565 + null, getById("o9"), true, "mouse on xul label with content inside"); 1.566 + expectFocusShift(function () synthesizeMouse(getById("ak"), 2, 2, { }), 1.567 + null, getById("n4"), true, "mouse on xul label with control attribute"); 1.568 + 1.569 + // test accesskeys that shouldn't work 1.570 + k = "o".charCodeAt(0); 1.571 + while (k++ < "v".charCodeAt(0)) { 1.572 + var key = String.fromCharCode(k); 1.573 + expectFocusShift(function () synthesizeKey(key, accessKeyDetails), 1.574 + window, getById("n4"), false, "non accesskey " + key); 1.575 + } 1.576 + gLastFocusMethod = -1; 1.577 + 1.578 + // should focus the for element when using the focus method on a label as well 1.579 + expectFocusShift(function () getById("ad").focus(), 1.580 + null, getById("t29"), true, "mouse on html label using focus method"); 1.581 + 1.582 + // make sure that the text is selected when clicking a label associated with an input 1.583 + getById("ag").htmlFor = "t19"; 1.584 + expectFocusShift(function () synthesizeMouse(getById("ag"), 2, 2, { }, gChildWindow), 1.585 + null, getById("t19"), true, "mouse on html label with for attribute changed"); 1.586 + is(t19.selectionStart, 0, "input focused from label, selectionStart"); 1.587 + is(t19.selectionEnd, 5, "input focused from label, selectionEnd"); 1.588 + 1.589 + // switch to another panel in a tabbox and ensure that tabbing moves between 1.590 + // elements on the new panel. 1.591 + $("tabbox").selectedIndex = 1; 1.592 + expectFocusShift(function () getById("t" + kBeforeTabboxIndex).focus(), 1.593 + null, getById("t" + kBeforeTabboxIndex), true, "focus method on element before tabbox"); 1.594 + 1.595 + if (!gPartialTabbing) { 1.596 + expectFocusShift(pressTab, null, getById("tab2"), true, "focus method on tab"); 1.597 + expectFocusShift(pressTab, null, getById("htab1"), true, "tab key switch tabpanel 1"); 1.598 + expectFocusShift(pressTab, null, getById("htab2"), true, "tab key switch tabpanel 2"); 1.599 + expectFocusShift(pressTab, null, getById("t" + (kBeforeTabboxIndex + 4)), true, "tab key switch tabpanel 3"); 1.600 + } 1.601 + $("tabbox").selectedIndex = 0; 1.602 + 1.603 + // ---- the following checks when the focus changes during a blur or focus event ---- 1.604 + 1.605 + var o5 = $("o5"); 1.606 + var o9 = $("o9"); 1.607 + var t3 = $("t3"); 1.608 + var t17 = getById("t17"); 1.609 + var t19 = getById("t19"); 1.610 + var shiftFocusParentDocument = function() o9.focus(); 1.611 + var shiftFocusChildDocument = function() t17.focus(); 1.612 + 1.613 + var trapBlur = function (element, eventListener, blurFunction) 1.614 + { 1.615 + element.focus(); 1.616 + gEvents = ""; 1.617 + element.addEventListener("blur", eventListener, false); 1.618 + blurFunction(); 1.619 + element.removeEventListener("blur", eventListener, false); 1.620 + } 1.621 + 1.622 + var functions = [ 1.623 + function(element) element.focus(), 1.624 + function(element) synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView) 1.625 + ]; 1.626 + 1.627 + // first, check cases where the focus is adjusted during the blur event. Iterate twice, 1.628 + // once with the focus method and then focusing by mouse clicking 1.629 + for (var l = 0; l < 2; l++) { 1.630 + var adjustFocus = functions[l]; 1.631 + var mod = (l == 1) ? " with mouse" : ""; 1.632 + 1.633 + // an attempt is made to switch the focus from one element (o5) to another 1.634 + // element (t3) within the same document, yet the focus is shifted to a 1.635 + // third element (o9) in the same document during the blur event for the 1.636 + // first element. 1.637 + trapBlur(o5, shiftFocusParentDocument, function () adjustFocus(t3)); 1.638 + compareEvents("commandupdate: cu blur: o5 commandupdate: cu focus: o9", 1.639 + window, o9, "change focus to sibling during element blur, attempted sibling" + mod); 1.640 + 1.641 + // similar, but the third element (t17) is in a child document 1.642 + trapBlur(o9, shiftFocusChildDocument, function () adjustFocus(t3)); 1.643 + compareEvents("commandupdate: cu blur: o9 blur: outer-document blur: outer-window " + 1.644 + "focus: child-document focus: child-window commandupdate: cu focus: t17", 1.645 + gChildWindow, t17, "change focus to child document during element blur, attempted sibling" + mod); 1.646 + 1.647 + // similar, but an attempt to switch focus within the same document, but the 1.648 + // third element (t17) is in a parent document 1.649 + trapBlur(t17, shiftFocusParentDocument, function () adjustFocus(t19)); 1.650 + compareEvents("commandupdate: cu blur: t17 blur: child-document blur: child-window " + 1.651 + "focus: outer-document focus: outer-window commandupdate: cu focus: o9", 1.652 + window, o9, "change focus to parent document during element blur, attempted sibling" + mod); 1.653 + 1.654 + // similar, but blur is called instead of switching focus 1.655 + trapBlur(t3, shiftFocusParentDocument, function () t3.blur()); 1.656 + compareEvents("commandupdate: cu blur: t3 commandupdate: cu focus: o9", 1.657 + window, o9, "change focus to same document during clear focus" + mod); 1.658 + 1.659 + // check when an element in the same document is focused during the 1.660 + // element's blur event, but an attempt was made to focus an element in the 1.661 + // child document. In this case, the focus in the parent document should be 1.662 + // what was set during the blur event, but the actual focus should still 1.663 + // move to the child document. 1.664 + trapBlur(t3, shiftFocusParentDocument, function () adjustFocus(t17)); 1.665 + compareEvents("commandupdate: cu blur: t3 commandupdate: cu focus: o9 " + 1.666 + "blur: outer-document blur: outer-window " + 1.667 + "focus: child-document focus: child-window commandupdate: cu focus: t17", 1.668 + gChildWindow, t17, "change focus to sibling during element blur, attempted child" + mod); 1.669 + is(fm.getFocusedElementForWindow(window, false, {}), $("childframe"), 1.670 + "change focus to sibling during element blur, attempted child, focused in parent" + mod); 1.671 + 1.672 + // similar, but with a parent 1.673 + trapBlur(t19, shiftFocusChildDocument, function () adjustFocus(t3)); 1.674 + compareEvents("commandupdate: cu blur: t19 commandupdate: cu focus: t17 " + 1.675 + "blur: child-document blur: child-window " + 1.676 + "focus: outer-document focus: outer-window commandupdate: cu focus: t3", 1.677 + window, t3, "change focus to sibling during element blur, attempted parent" + mod); 1.678 + is(fm.getFocusedElementForWindow(gChildWindow, false, {}), t17, 1.679 + "change focus to sibling during element blur, attempted child, focused in child" + mod); 1.680 + 1.681 + // similar, with a child, but the blur event focuses a child element also 1.682 + trapBlur(t3, shiftFocusChildDocument, function () adjustFocus(t19)); 1.683 + compareEvents("commandupdate: cu blur: t3 blur: outer-document blur: outer-window " + 1.684 + "focus: child-document focus: child-window commandupdate: cu focus: t17", 1.685 + gChildWindow, t17, "change focus to child during element blur, attempted child" + mod); 1.686 + 1.687 + // similar, with a parent, where the blur event focuses a parent element also 1.688 + trapBlur(t17, shiftFocusParentDocument, function () adjustFocus(t3)); 1.689 + compareEvents("commandupdate: cu blur: t17 blur: child-document blur: child-window " + 1.690 + "focus: outer-document focus: outer-window commandupdate: cu focus: o9", 1.691 + window, o9, "change focus to parent during element blur, attempted parent" + mod); 1.692 + } 1.693 + 1.694 + var trapFocus = function (element, eventListener) 1.695 + { 1.696 + element.addEventListener("focus", eventListener, false); 1.697 + element.focus(); 1.698 + element.removeEventListener("focus", eventListener, false); 1.699 + } 1.700 + 1.701 + fm.clearFocus(window); 1.702 + gEvents = ""; 1.703 + 1.704 + // next, check cases where the focus is adjusted during the focus event 1.705 + 1.706 + // switch focus to an element in the same document 1.707 + trapFocus(o5, shiftFocusParentDocument); 1.708 + compareEvents("commandupdate: cu focus: o5 commandupdate: cu blur: o5 commandupdate: cu focus: o9", 1.709 + window, o9, "change focus to sibling during element focus"); 1.710 + 1.711 + // similar, but the new element (t17) is in a child document 1.712 + trapFocus(o5, shiftFocusChildDocument); 1.713 + compareEvents("commandupdate: cu blur: o9 " + 1.714 + "commandupdate: cu focus: o5 commandupdate: cu blur: o5 " + 1.715 + "blur: outer-document blur: outer-window " + 1.716 + "focus: child-document focus: child-window commandupdate: cu focus: t17", 1.717 + gChildWindow, t17, "change focus to child document during element focus"); 1.718 + 1.719 + // similar, but the new element (o9) is in a parent document. 1.720 + trapFocus(t19, shiftFocusParentDocument); 1.721 + compareEvents("commandupdate: cu blur: t17 " + 1.722 + "commandupdate: cu focus: t19 commandupdate: cu blur: t19 " + 1.723 + "blur: child-document blur: child-window " + 1.724 + "focus: outer-document focus: outer-window commandupdate: cu focus: o9", 1.725 + window, o9, "change focus to parent document during element focus"); 1.726 + 1.727 + // clear the focus during the focus event 1.728 + trapFocus(t3, function () fm.clearFocus(window)); 1.729 + compareEvents("commandupdate: cu blur: o9 commandupdate: cu focus: t3 commandupdate: cu blur: t3", 1.730 + window, null, "clear focus during focus event"); 1.731 + 1.732 + if (!gPartialTabbing) 1.733 + doCommandDispatcherTests(); 1.734 + 1.735 + testMoveFocus(); 1.736 + 1.737 + doRemoveTests(); 1.738 + 1.739 + // tests various focus manager apis for null checks 1.740 + var exh = false; 1.741 + try { 1.742 + fm.clearFocus(null); 1.743 + } 1.744 + catch (ex) { exh = true; } 1.745 + is(exh, true, "clearFocus with null window causes exception"); 1.746 + 1.747 + var exh = false; 1.748 + try { 1.749 + fm.getFocusedElementForWindow(null, false, focusedWindow); 1.750 + } 1.751 + catch (ex) { exh = true; } 1.752 + is(exh, true, "getFocusedElementForWindow with null window causes exception"); 1.753 + 1.754 + // just make sure that this doesn't crash 1.755 + fm.moveCaretToFocus(null); 1.756 + 1.757 + // ---- tests for the FLAG_NOSWITCHFRAME flag 1.758 + getById("o5").focus(); 1.759 + gLastFocusMethod = 0; 1.760 + gEvents = ""; 1.761 + // focus is being shifted in a child, so the focus should not change 1.762 + expectFocusShift(function () fm.setFocus(getById("t20"), fm.FLAG_NOSWITCHFRAME), 1.763 + window, getById("o5"), false, "no switch frame focus to child"); 1.764 + setFocusTo("t20", gChildWindow); 1.765 + 1.766 + // here, however, focus is being shifted in a parent, which will have to blur 1.767 + // the child, so the focus will always change 1.768 + expectFocusShift(function () fm.setFocus(getById("o5"), fm.FLAG_NOSWITCHFRAME), 1.769 + window, getById("o5"), true, "no switch frame focus to parent"); 1.770 + 1.771 + expectFocusShift(function () fm.setFocus(getById("t1"), fm.FLAG_NOSWITCHFRAME), 1.772 + window, getById("t1"), true, "no switch frame focus to same window"); 1.773 + 1.774 + // ---- tests for focus and scrolling into view ---- 1.775 + var inscroll = getById("inscroll"); 1.776 + inscroll.tabIndex = 0; 1.777 + is(inscroll.parentNode.scrollTop, 0, "scroll position before focus"); 1.778 + inscroll.focus(); 1.779 + ok(inscroll.parentNode.scrollTop > 5, "scroll position after focus"); 1.780 + inscroll.parentNode.scrollTop = 0; 1.781 + fm.setFocus(inscroll, fm.FLAG_NOSCROLL); 1.782 + is(inscroll.parentNode.scrollTop, 0, "scroll position after noscroll focus"); 1.783 + 1.784 + getById("t9").focus(); 1.785 + getById("inpopup1").focus(); 1.786 + is(fm.focusedElement, getById("t9"), "focus in closed popup"); 1.787 + 1.788 + // ---- tests to check if tabbing out of a textbox works 1.789 + 1.790 + setFocusTo("t1", window); 1.791 + 1.792 + var textbox1 = document.createElement("textbox"); 1.793 + $("innerbox").appendChild(textbox1); 1.794 + 1.795 + var textbox2 = document.createElement("textbox"); 1.796 + $("innerbox").appendChild(textbox2); 1.797 + 1.798 + gLastFocusMethod = 0; 1.799 + expectFocusShift(function () textbox2.focus(), 1.800 + null, textbox2.inputField, true, "focus on textbox"); 1.801 + gLastFocusMethod = fm.FLAG_BYKEY; 1.802 + expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), 1.803 + null, textbox1.inputField, true, "shift+tab on textbox"); 1.804 + 1.805 + textbox1.tabIndex = 2; 1.806 + textbox2.tabIndex = 2; 1.807 + gLastFocusMethod = 0; 1.808 + expectFocusShift(function () textbox2.focus(), 1.809 + null, textbox2.inputField, true, "focus on textbox with tabindex set"); 1.810 + gLastFocusMethod = fm.FLAG_BYKEY; 1.811 + expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), 1.812 + null, textbox1.inputField, true, "shift+tab on textbox with tabindex set"); 1.813 + 1.814 + // ---- test for bug 618907 which ensures that canceling the mousedown event still focuses the 1.815 + // right frame 1.816 + 1.817 + var childContentFrame = document.getElementById("ifa") 1.818 + childContentFrame.style.MozUserFocus = ""; 1.819 + 1.820 + var frab = childContentFrame.contentDocument.getElementById("fra-b"); 1.821 + var mouseDownListener = function(event) event.preventDefault(); 1.822 + frab.addEventListener("mousedown", mouseDownListener, false); 1.823 + 1.824 + var childElementToFocus = childContentFrame.contentDocument.getElementById("fra"); 1.825 + gLastFocus = childElementToFocus; 1.826 + gLastFocusWindow = childContentFrame.contentWindow; 1.827 + gLastFocus.focus(); 1.828 + gEvents = ""; 1.829 + 1.830 + setFocusTo("t1", window); 1.831 + 1.832 + gLastFocusMethod = -1; 1.833 + expectFocusShift(function () synthesizeMouse(frab, 5, 5, { }, childContentFrame.contentWindow), 1.834 + null, childElementToFocus, true, 1.835 + "mousedown event canceled - chrome to content"); 1.836 + 1.837 + frab.removeEventListener("mousedown", mouseDownListener, false); 1.838 + 1.839 + var t5 = getById("t5"); 1.840 + t5.addEventListener("mousedown", mouseDownListener, false); 1.841 + synthesizeMouse(t5, 10, 10, { }) 1.842 + t5.removeEventListener("mousedown", mouseDownListener, false); 1.843 + is(fm.focusedElement, childElementToFocus, 1.844 + "mousedown event cancelled - content to chrome - element"); 1.845 + is(fm.focusedWindow, childContentFrame.contentWindow, "mousedown event cancelled - content to chrome - window"); 1.846 + 1.847 + // ---- test to check that refocusing an element during a blur event doesn't succeed 1.848 + 1.849 + var t1 = getById("t1"); 1.850 + t1.addEventListener("blur", function() t1.focus(), true); 1.851 + t1.focus(); 1.852 + var t3 = getById("t3"); 1.853 + synthesizeMouse(t3, 2, 2, { }); 1.854 + is(fm.focusedElement, t3, "focus during blur"); 1.855 + 1.856 + setFocusTo("t9", window); 1.857 + gLastFocusMethod = -1; 1.858 + window.openDialog("focus_window2.xul", "_blank", "chrome", otherWindowFocused); 1.859 +} 1.860 + 1.861 +function doCommandDispatcherTests() 1.862 +{ 1.863 + var t19 = getById("t19"); 1.864 + t19.focus(); 1.865 + gLastFocusWindow = gChildWindow; 1.866 + gLastFocus = t19; 1.867 + gEvents = ""; 1.868 + 1.869 + expectFocusShift(function () document.commandDispatcher.focusedElement = getById("o9"), 1.870 + null, getById("o9"), true, "command dispatcher set focusedElement"); 1.871 + expectFocusShift(function () document.commandDispatcher.advanceFocus(), 1.872 + null, getById("o13"), true, "command dispatcher advanceFocus"); 1.873 + expectFocusShift(function () document.commandDispatcher.rewindFocus(), 1.874 + null, getById("o9"), true, "command dispatcher rewindFocus"); 1.875 + expectFocusShift(function () document.commandDispatcher.focusedElement = null, 1.876 + null, null, true, "command dispatcher set focusedElement to null"); 1.877 + expectFocusShift(function () document.commandDispatcher.focusedWindow = gChildWindow, 1.878 + null, getById("t19"), true, "command dispatcher set focusedElement to null"); 1.879 + expectFocusShift(function () document.commandDispatcher.focusedElement = null, 1.880 + gChildWindow, null, true, "command dispatcher set focusedElement to null in child"); 1.881 + expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(getById("t19")), 1.882 + null, getById("t20"), true, "command dispatcher advanceFocusIntoSubtree child"); 1.883 + expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(null), 1.884 + null, getById("t21"), true, "command dispatcher advanceFocusIntoSubtree null child"); 1.885 + expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(getById("o9").parentNode), 1.886 + null, getById("o9"), true, "command dispatcher advanceFocusIntoSubtree parent"); 1.887 +} 1.888 + 1.889 +function doRemoveTests() 1.890 +{ 1.891 + // next, some tests which remove elements 1.892 + var t19 = getById("t19"); 1.893 + t19.focus(); 1.894 + t19.parentNode.removeChild(t19); 1.895 + 1.896 + is(fm.focusedElement, null, "removed element focusedElement"); 1.897 + is(fm.focusedWindow, gChildWindow, "removed element focusedWindow"); 1.898 + is(gChildWindow.document.hasFocus(), true, "removed element hasFocus"); 1.899 + is(gChildWindow.document.activeElement, getById("inner-document"), "removed element activeElement"); 1.900 + 1.901 + getById("t15").focus(); 1.902 + var abs = getById("abs"); 1.903 + abs.parentNode.removeChild(abs); 1.904 + 1.905 + is(fm.focusedElement, null, "removed ancestor focusedElement"); 1.906 + is(fm.focusedWindow, gChildWindow, "removed ancestor focusedWindow"); 1.907 + is(gChildWindow.document.hasFocus(), true, "removed ancestor hasFocus"); 1.908 + is(gChildWindow.document.activeElement, getById("inner-document"), "removed ancestor activeElement"); 1.909 +} 1.910 + 1.911 +// tests for the FocusManager moveFocus method 1.912 +function testMoveFocus() 1.913 +{ 1.914 + setFocusTo("t6", window); 1.915 + 1.916 + // moving focus while an element is already focused 1.917 + var newFocus; 1.918 + gLastFocusMethod = fm.FLAG_BYMOVEFOCUS; 1.919 + var expectedFirst = getById(gPartialTabbing ? "t3" : "t1"); 1.920 + expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0), 1.921 + window, expectedFirst, true, "moveFocus to first null window null content"); 1.922 + is(newFocus, fm.focusedElement, "moveFocus to first null window null content return value"); 1.923 + 1.924 + expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_LAST, 0), 1.925 + window, getById("last"), true, "moveFocus to last null window null content"); 1.926 + is(newFocus, fm.focusedElement, "moveFocus to last null window null content return value"); 1.927 + 1.928 + gLastFocusMethod = 0; 1.929 + newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0); 1.930 + is(newFocus, null, "moveFocus to root null window null content return value"); 1.931 + is(fm.focusedWindow, window, "moveFocus to root null window null content focusedWindow"); 1.932 + is(fm.focusedElement, null, "moveFocus to root null window null content focusedElement"); 1.933 + 1.934 + // moving focus while no element is focused 1.935 + fm.clearFocus(window); 1.936 + gEvents = ""; 1.937 + gLastFocus = null; 1.938 + gLastFocusMethod = fm.FLAG_BYMOVEFOCUS; 1.939 + expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0), 1.940 + window, expectedFirst, true, "moveFocus to first null window null content no focus"); 1.941 + is(newFocus, fm.focusedElement, "moveFocus to first null window null content no focus return value"); 1.942 + fm.clearFocus(window); 1.943 + gEvents = ""; 1.944 + gLastFocus = null; 1.945 + expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_LAST, 0), 1.946 + window, getById("last"), true, "moveFocus to last null window null content no focus"); 1.947 + is(newFocus, fm.focusedElement, "moveFocus to last null window null content no focus return value"); 1.948 + fm.clearFocus(window); 1.949 + gEvents = ""; 1.950 + gLastFocusMethod = 0; 1.951 + newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0); 1.952 + is(newFocus, null, "moveFocus to root null window null content no focus return value"); 1.953 + is(fm.focusedWindow, window, "moveFocus to root null window null content no focus focusedWindow"); 1.954 + is(fm.focusedElement, null, "moveFocus to root null window null content no focus focusedElement"); 1.955 + 1.956 + // moving focus from a specified element 1.957 + setFocusTo("t6", window); 1.958 + gLastFocusMethod = fm.FLAG_BYMOVEFOCUS; 1.959 + expectFocusShift(function () newFocus = fm.moveFocus(null, getById("specialroot"), fm.MOVEFOCUS_FIRST, 0), 1.960 + window, getById("t3"), true, "moveFocus to first null window with content"); 1.961 +// XXXndeakin P3 this doesn't work 1.962 +// expectFocusShift(function () newFocus = fm.moveFocus(null, getById("specialroot"), fm.MOVEFOCUS_LAST, 0), 1.963 +// window, getById("o3"), true, "moveFocus to last null window with content"); 1.964 + 1.965 + // move focus to first in child window 1.966 + expectFocusShift(function () newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_FIRST, 0), 1.967 + gChildWindow, getById("t" + (kChildDocumentRootIndex + 1)), true, 1.968 + "moveFocus to first child window null content"); 1.969 + is(newFocus, getById("t" + (kChildDocumentRootIndex + 1)), 1.970 + "moveFocus to first child window null content return value"); 1.971 + 1.972 + // move focus to last in child window 1.973 + setFocusTo("t6", window); 1.974 + var expectedLast = getById(gPartialTabbing ? "t30" : "t" + (kBeforeTabboxIndex - 1)); 1.975 + expectFocusShift(function () newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_LAST, 0), 1.976 + gChildWindow, expectedLast, true, 1.977 + "moveFocus to last child window null content"); 1.978 + is(newFocus, getById(expectedLast), 1.979 + "moveFocus to last child window null content return value"); 1.980 + 1.981 + // move focus to root in child window 1.982 + setFocusTo("t6", window); 1.983 + var childroot = getById("t" + kChildDocumentRootIndex); 1.984 + gLastFocusMethod = 0; 1.985 + newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_ROOT, 0), 1.986 + is(newFocus, childroot, "moveFocus to root child window null content return value"); 1.987 + is(fm.focusedWindow, gChildWindow, "moveFocus to root child window null content focusedWindow"); 1.988 + is(fm.focusedElement, childroot, "moveFocus to root child window null content focusedElement"); 1.989 + 1.990 + // MOVEFOCUS_CARET tests 1.991 + getById("t20").focus(); 1.992 + gEvents = ""; 1.993 + 1.994 + var selection = gChildWindow.getSelection(); 1.995 + selection.removeAllRanges(); 1.996 + 1.997 + newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0); 1.998 + is(newFocus, null, "move caret when at document root"); 1.999 + is(fm.focusedElement, null, "move caret when at document root"); 1.1000 + 1.1001 + var node = getById("t16").firstChild; 1.1002 + var range = gChildWindow.document.createRange(); 1.1003 + range.setStart(node, 3); 1.1004 + range.setEnd(node, 3); 1.1005 + selection.addRange(range); 1.1006 + 1.1007 + newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0); 1.1008 + is(newFocus, null, "move caret to non-link return value"); 1.1009 + is(fm.focusedElement, null, "move caret to non-link"); 1.1010 + 1.1011 + var t25 = getById("t25"); 1.1012 + var node = t25.firstChild; 1.1013 + range.setStart(node, 1); 1.1014 + range.setEnd(node, 1); 1.1015 + newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0); 1.1016 + 1.1017 + is(newFocus, t25, "move caret to link return value"); 1.1018 + is(fm.focusedElement, t25, "move caret to link focusedElement"); 1.1019 + 1.1020 + // enable caret browsing temporarily to test caret movement 1.1021 + var prefs = Components.classes["@mozilla.org/preferences-service;1"]. 1.1022 + getService(Components.interfaces.nsIPrefBranch); 1.1023 + prefs.setBoolPref("accessibility.browsewithcaret", true); 1.1024 + 1.1025 + synthesizeKey("VK_LEFT", { }, gChildWindow); 1.1026 + synthesizeKey("VK_LEFT", { }, gChildWindow); 1.1027 + is(fm.focusedElement, null, "move caret away from link"); 1.1028 + 1.1029 + synthesizeKey("VK_LEFT", { }, gChildWindow); 1.1030 + is(fm.focusedElement, getById("t24"), "move caret away onto link"); 1.1031 + 1.1032 + prefs.setBoolPref("accessibility.browsewithcaret", false); 1.1033 + 1.1034 + // cases where focus in on a content node with no frame 1.1035 + 1.1036 + if (!gPartialTabbing) { 1.1037 + getById("t24").blur(); 1.1038 + gEvents = ""; 1.1039 + gLastFocus = null; 1.1040 + gLastFocusWindow = gChildWindow; 1.1041 + gLastFocusMethod = fm.FLAG_BYKEY; 1.1042 + 1.1043 + selection.selectAllChildren(getById("hiddenspan")); 1.1044 + expectFocusShift(function () synthesizeKey("VK_TAB", { }), 1.1045 + gChildWindow, getById("t26"), true, "tab with selection on hidden content"); 1.1046 + 1.1047 + setFocusTo($("o15"), window); 1.1048 + $("o15").hidden = true; 1.1049 + document.documentElement.getBoundingClientRect(); // flush after hiding 1.1050 + expectFocusShift(function () synthesizeKey("VK_TAB", { }), 1.1051 + window, $("o17"), true, "tab with focus on hidden content"); 1.1052 + 1.1053 + $("o17").hidden = true; 1.1054 + document.documentElement.getBoundingClientRect(); 1.1055 + expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }), 1.1056 + window, $("o13"), true, "shift+tab with focus on hidden content"); 1.1057 + } 1.1058 + 1.1059 + // cases with selection in an <input> 1.1060 + 1.1061 + var t19 = getById("t19"); 1.1062 + t19.setSelectionRange(0, 0); 1.1063 + setFocusTo("t18", gChildWindow); 1.1064 + 1.1065 + gLastFocusMethod = fm.FLAG_BYMOVEFOCUS; 1.1066 + expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, 0), 1.1067 + gChildWindow, t19, true, "moveFocus to next textbox"); 1.1068 + is(t19.selectionStart, 0, "input focused after moveFocus selectionStart"); 1.1069 + is(t19.selectionEnd, 5, "input focused after moveFocus selectionEnd"); 1.1070 + 1.1071 + t19.setSelectionRange(0, 0); 1.1072 + setFocusTo("t18", gChildWindow); 1.1073 + gLastFocusMethod = fm.FLAG_BYKEY; 1.1074 + expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, fm.FLAG_BYKEY), 1.1075 + gChildWindow, t19, true, "moveFocus to next textbox by key"); 1.1076 + is(t19.selectionStart, 0, "input focused after moveFocus by key selectionStart"); 1.1077 + is(t19.selectionEnd, 5, "input focused after moveFocus by key selectionEnd"); 1.1078 +} 1.1079 + 1.1080 +function otherWindowFocused(otherWindow) 1.1081 +{ 1.1082 + var expectedElement = getById("t9"); 1.1083 + 1.1084 + is(fm.activeWindow, otherWindow, "other activeWindow"); 1.1085 + is(fm.focusedWindow, otherWindow, "other focusedWindow"); 1.1086 + is(window.document.hasFocus(), false, "when lowered document hasFocus"); 1.1087 + var focusedWindow = {}; 1.1088 + is(fm.getFocusedElementForWindow(window, false, focusedWindow), 1.1089 + expectedElement, "when lowered getFocusedElementForWindow"); 1.1090 + is(focusedWindow.value, window, "when lowered getFocusedElementForWindow frame"); 1.1091 + is(document.activeElement.id, expectedElement.id, "when lowered activeElement"); 1.1092 + is(window.document.commandDispatcher.focusedWindow, window, " commandDispatcher in other window focusedWindow"); 1.1093 + is(window.document.commandDispatcher.focusedElement, expectedElement, " commandDispatcher in other window focusedElement"); 1.1094 + 1.1095 + compareEvents("deactivate: outer-document-window blur: t9 blur: outer-document blur: outer-window", 1.1096 + otherWindow, null, "other window opened"); 1.1097 + 1.1098 + otherWindow.document.getElementById("other").focus(); 1.1099 + 1.1100 + for (var idx = kTabbableSteps; idx >= 1; idx--) { 1.1101 + expectedElement = getById("t" + idx); 1.1102 + if (!expectedElement) // skip elements that were removed in doRemoveTests() 1.1103 + continue; 1.1104 + if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1)) 1.1105 + continue; 1.1106 + 1.1107 + expectedElement.focus(); 1.1108 + 1.1109 + is(fm.focusedElement.id, "other", "when lowered focusedElement t" + idx); 1.1110 + is(fm.focusedWindow, otherWindow, "when lowered focusedWindow t" + idx); 1.1111 + 1.1112 + var checkWindow = expectedElement.ownerDocument.defaultView; 1.1113 + is(fm.getFocusedElementForWindow(checkWindow, false, {}).id, expectedElement.id, 1.1114 + "when lowered getFocusedElementForWindow t" + idx); 1.1115 + is(checkWindow.document.activeElement.id, expectedElement.id, "when lowered activeElement t" + idx); 1.1116 + if (checkWindow != window) { 1.1117 + is(fm.getFocusedElementForWindow(window, false, {}), $("childframe"), 1.1118 + "when lowered parent getFocusedElementForWindow t" + idx); 1.1119 + is(document.activeElement.id, "childframe", 1.1120 + "when lowered parent activeElement t" + idx); 1.1121 + } 1.1122 + } 1.1123 + 1.1124 + gEvents = gEvents.replace(/commandupdate: cu\s?/g, ""); 1.1125 + is(gEvents, "", "when lowered no events fired"); 1.1126 + 1.1127 + var other = otherWindow.document.getElementById("other"); 1.1128 + other.focus(); 1.1129 + is(fm.focusedElement, other, "focus method in second window"); 1.1130 + 1.1131 + otherWindow.close(); 1.1132 + 1.1133 + getById("n2").focus(); 1.1134 + 1.1135 + // next, check modal dialogs 1.1136 + // XXXndeakin Bug 621399 - the modal dialog test as well as later tests sometime fail 1.1137 + // on Windows 8 so just end the test here. 1.1138 + if (navigator.userAgent.indexOf("Windows NT 6.2") >= 0) { 1.1139 + done(); 1.1140 + } 1.1141 + else { 1.1142 + window.openDialog("focus_window2.xul", "_blank", "chrome,modal", modalWindowOpened); 1.1143 + } 1.1144 +} 1.1145 + 1.1146 +function modalWindowOpened(modalWindow) 1.1147 +{ 1.1148 + var elem = modalWindow.document.getElementById("other"); 1.1149 + if (gPartialTabbing) 1.1150 + elem.focus(); 1.1151 + else 1.1152 + synthesizeKey("VK_TAB", { }, modalWindow); 1.1153 + is(fm.activeWindow, modalWindow, "modal activeWindow"); 1.1154 + is(fm.focusedElement, elem, "modal focusedElement"); 1.1155 + 1.1156 + modalWindow.close(); 1.1157 + SimpleTest.waitForFocus(modalWindowClosed); 1.1158 +} 1.1159 + 1.1160 +function modalWindowClosed() 1.1161 +{ 1.1162 + is(fm.activeWindow, window, "modal window closed activeWindow"); 1.1163 + is(fm.focusedElement, getById("n2"), "modal window closed focusedElement"); 1.1164 + 1.1165 + window.open("focus_frameset.html", "_blank", "width=400,height=400,toolbar=no"); 1.1166 +} 1.1167 + 1.1168 +function framesetWindowLoaded(framesetWindow) 1.1169 +{ 1.1170 + gLastFocus = null; 1.1171 + gLastFocusWindow = framesetWindow; 1.1172 + gEvents = ""; 1.1173 + 1.1174 + is(fm.activeWindow, getTopWindow(framesetWindow), "frameset window active"); 1.1175 + gOldExpectedWindow = getTopWindow(framesetWindow); 1.1176 + 1.1177 + gMoveToFocusFrame = true; 1.1178 + for (var idx = 1; idx <= 8; idx++) { 1.1179 + gNewExpectedWindow = framesetWindow.frames[(idx - 1) >> 1]; 1.1180 + if (idx % 2) 1.1181 + initEvents(gNewExpectedWindow); 1.1182 + expectFocusShift(function () synthesizeKey("VK_TAB", { }, framesetWindow), 1.1183 + gNewExpectedWindow, getById("f" + idx), true, "frameset tab key f" + idx); 1.1184 + gMoveToFocusFrame = false; 1.1185 + gOldExpectedWindow = gNewExpectedWindow; 1.1186 + } 1.1187 + 1.1188 + gNewExpectedWindow = framesetWindow.frames[0]; 1.1189 + expectFocusShift(function () synthesizeKey("VK_TAB", { }, framesetWindow), 1.1190 + gNewExpectedWindow, getById("f1"), true, "frameset tab key wrap to start"); 1.1191 + gOldExpectedWindow = gNewExpectedWindow; 1.1192 + gNewExpectedWindow = framesetWindow.frames[3]; 1.1193 + expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }, framesetWindow), 1.1194 + gNewExpectedWindow, getById("f8"), true, "frameset shift tab key wrap to end"); 1.1195 + 1.1196 + for (idx = 7; idx >= 1; idx--) { 1.1197 + gOldExpectedWindow = gNewExpectedWindow; 1.1198 + gNewExpectedWindow = framesetWindow.frames[(idx - 1) >> 1]; 1.1199 + expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }, framesetWindow), 1.1200 + gNewExpectedWindow, getById("f" + idx), true, "frameset shift tab key f" + idx); 1.1201 + } 1.1202 + 1.1203 + // document shifting 1.1204 + // XXXndeakin P3 ctrl+tab doesn't seem to be testable currently for some reason 1.1205 + gNewExpectedWindow = framesetWindow.frames[1]; 1.1206 + expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow), 1.1207 + gNewExpectedWindow, getById("f3"), true, "switch document forward with f6"); 1.1208 + gOldExpectedWindow = gNewExpectedWindow; 1.1209 + gNewExpectedWindow = framesetWindow.frames[2]; 1.1210 + expectFocusShift(function () synthesizeKey("VK_F6", { }, framesetWindow), 1.1211 + gNewExpectedWindow, getById("f5"), true, "switch document forward with ctrl+tab"); 1.1212 + gOldExpectedWindow = gNewExpectedWindow; 1.1213 + gNewExpectedWindow = framesetWindow.frames[3]; 1.1214 + expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow), 1.1215 + gNewExpectedWindow, getById("f7"), true, "switch document forward with ctrl+f6"); 1.1216 + gOldExpectedWindow = gNewExpectedWindow; 1.1217 + gNewExpectedWindow = framesetWindow.frames[0]; 1.1218 + expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow), 1.1219 + gNewExpectedWindow, getById("f1"), true, "switch document forward and wrap"); 1.1220 + 1.1221 +// going backwards by document and wrapping doesn't currently work, but didn't work 1.1222 +// before the focus reworking either 1.1223 + 1.1224 +/* 1.1225 + gOldExpectedWindow = gNewExpectedWindow; 1.1226 + gNewExpectedWindow = framesetWindow.frames[3]; 1.1227 + expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow), 1.1228 + gNewExpectedWindow, getById("f7"), true, "switch document backward and wrap"); 1.1229 + */ 1.1230 + 1.1231 + fm.moveFocus(framesetWindow.frames[3], null, fm.MOVEFOCUS_ROOT, 0); 1.1232 + gEvents = ""; 1.1233 + 1.1234 + gOldExpectedWindow = gNewExpectedWindow; 1.1235 + gNewExpectedWindow = framesetWindow.frames[2]; 1.1236 + expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow), 1.1237 + gNewExpectedWindow, getById("f5"), true, "switch document backward with f6"); 1.1238 + gOldExpectedWindow = gNewExpectedWindow; 1.1239 + gNewExpectedWindow = framesetWindow.frames[1]; 1.1240 + expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow), 1.1241 + gNewExpectedWindow, getById("f3"), true, "switch document backward with ctrl+tab"); 1.1242 + gOldExpectedWindow = gNewExpectedWindow; 1.1243 + gNewExpectedWindow = framesetWindow.frames[0]; 1.1244 + expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow), 1.1245 + gNewExpectedWindow, getById("f1"), true, "switch document backward with ctrl+f6"); 1.1246 + 1.1247 + // skip the window switching tests for now on Linux, as raising and lowering 1.1248 + // a window is asynchronous there 1.1249 + if (navigator.platform.indexOf("Linux") == -1) { 1.1250 + window.openDialog("focus_window2.xul", "_blank", "chrome", switchWindowTest, framesetWindow); 1.1251 + } 1.1252 + else { 1.1253 + gOldExpectedWindow = null; 1.1254 + gNewExpectedWindow = null; 1.1255 + framesetWindow.close(); 1.1256 + SimpleTest.waitForFocus(doWindowNoRootTest); 1.1257 + } 1.1258 +} 1.1259 + 1.1260 +// test switching between two windows 1.1261 +function switchWindowTest(otherWindow, framesetWindow) 1.1262 +{ 1.1263 + initEvents(otherWindow); 1.1264 + var otherElement = otherWindow.document.getElementById("other"); 1.1265 + otherElement.focus(); 1.1266 + 1.1267 + framesetWindow.frames[1].document.getElementById("f4").focus(); 1.1268 + 1.1269 + is(fm.focusedElement, otherElement, "focus after inactive window focus"); 1.1270 + 1.1271 + gLastFocus = otherElement; 1.1272 + gLastFocusWindow = otherWindow; 1.1273 + gEvents = ""; 1.1274 + gOldExpectedWindow = otherWindow; 1.1275 + gNewExpectedWindow = framesetWindow.frames[1]; 1.1276 + 1.1277 + expectFocusShift(function () gNewExpectedWindow.focus(), 1.1278 + gNewExpectedWindow, getById("f4"), true, "switch to frame in another window"); 1.1279 + is(fm.getFocusedElementForWindow(otherWindow, false, {}).id, "other", "inactive window has focused element"); 1.1280 + 1.1281 + gOldExpectedWindow = framesetWindow.frames[1]; 1.1282 + gNewExpectedWindow = otherWindow; 1.1283 + expectFocusShift(function () otherWindow.focus(), 1.1284 + gNewExpectedWindow, getById("other"), true, "switch to another window"); 1.1285 + 1.1286 + var exh = false; 1.1287 + try { 1.1288 + fm.activeWindow = framesetWindow.frames[0]; 1.1289 + } 1.1290 + catch (ex) { exh = true; } 1.1291 + is(exh, true, "activeWindow set to non top-level window"); 1.1292 + 1.1293 + exh = false; 1.1294 + try { 1.1295 + fm.activeWindow = null; 1.1296 + } 1.1297 + catch (ex) { exh = true; } 1.1298 + is(exh, true, "activeWindow set to null"); 1.1299 + is(fm.activeWindow, otherWindow, "window not changed when activeWindow set to null"); 1.1300 + 1.1301 + var topWindow = getTopWindow(framesetWindow); 1.1302 + 1.1303 + ok(topWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"), 1.1304 + "getControllerForCommand for focused window set"); 1.1305 + ok(otherWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"), 1.1306 + "getControllerForCommand for non-focused window set"); 1.1307 + ok(topWindow.document.commandDispatcher.getControllerForCommand("cmd_copy") != 1.1308 + otherWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"), 1.1309 + "getControllerForCommand for two windows different"); 1.1310 + ok(topWindow.document.commandDispatcher.getControllers() != 1.1311 + otherWindow.document.commandDispatcher.getControllers(), 1.1312 + "getControllers for two windows different"); 1.1313 + 1.1314 + gOldExpectedWindow = otherWindow; 1.1315 + gNewExpectedWindow = framesetWindow.frames[1]; 1.1316 + expectFocusShift(function () fm.activeWindow = topWindow, 1.1317 + gNewExpectedWindow, getById("f4"), true, "switch to frame activeWindow"); 1.1318 + 1.1319 + fm.clearFocus(otherWindow); 1.1320 + gOldExpectedWindow = gNewExpectedWindow; 1.1321 + gNewExpectedWindow = otherWindow; 1.1322 + expectFocusShift(function () fm.setFocus(otherElement, fm.FLAG_RAISE), 1.1323 + gNewExpectedWindow, getById("other"), true, "switch to window with raise"); 1.1324 + 1.1325 + getTopWindow(framesetWindow).document.commandDispatcher.focusedWindow = gOldExpectedWindow; 1.1326 + is(fm.activeWindow, gNewExpectedWindow, "setting commandDispatcher focusedWindow doesn't raise window"); 1.1327 + 1.1328 + fm.moveFocus(otherWindow, null, fm.MOVEFOCUS_FORWARD, 0); 1.1329 + var otherTextbox = otherWindow.document.getElementById("other-textbox"); 1.1330 + otherTextbox.setSelectionRange(2, 3); 1.1331 + fm.activeWindow = topWindow; 1.1332 + fm.activeWindow = otherWindow; 1.1333 + is(otherTextbox.selectionStart, 2, "selectionStart after textbox focus and window raise"); 1.1334 + is(otherTextbox.selectionEnd, 3, "selectionEnd after textbox focus and window raise"); 1.1335 + is(fm.getLastFocusMethod(null), fm.FLAG_BYMOVEFOCUS, "last focus method after textbox focus and window raise"); 1.1336 + 1.1337 + fm.clearFocus(otherWindow); 1.1338 + 1.1339 + // test to ensure that a synthetic event works 1.1340 + var synevent = document.createEvent("Event"); 1.1341 + synevent.initEvent("focus", false, false); 1.1342 + otherTextbox.inputField.dispatchEvent(synevent); 1.1343 + is(synevent.type, "focus", "event.type after synthetic focus event"); 1.1344 + is(synevent.target, otherTextbox, "event.target after synthetic focus event"); 1.1345 + is(fm.focusedElement, null, "focusedElement after synthetic focus event"); 1.1346 + is(otherWindow.document.activeElement, otherWindow.document.documentElement, 1.1347 + "document.activeElement after synthetic focus event"); 1.1348 + 1.1349 + // check accessing a focus event after the event has finishing firing 1.1350 + function continueTest(event) { 1.1351 + is(event.type, "focus", "event.type after accessing focus event in timeout"); 1.1352 + is(event.target, otherTextbox, "event.target after accessing focus event in timeout"); 1.1353 + 1.1354 + gOldExpectedWindow = null; 1.1355 + gNewExpectedWindow = null; 1.1356 + otherWindow.close(); 1.1357 + framesetWindow.close(); 1.1358 + 1.1359 + SimpleTest.waitForFocus(doWindowNoRootTest); 1.1360 + } 1.1361 + 1.1362 + function textboxFocused(event) { 1.1363 + otherTextbox.removeEventListener("focus", textboxFocused, true); 1.1364 + setTimeout(continueTest, 0, event); 1.1365 + } 1.1366 + 1.1367 + otherTextbox.addEventListener("focus", textboxFocused, true); 1.1368 + otherTextbox.focus(); 1.1369 +} 1.1370 + 1.1371 +// open a window with no root element 1.1372 +var noRootWindow = null; 1.1373 +function doWindowNoRootTest() 1.1374 +{ 1.1375 + var data = "data:application/vnd.mozilla.xul+xml," + unescape( 1.1376 + "<window onfocus='dostuff()' xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" + 1.1377 + " style='-moz-user-focus: normal;'>" + 1.1378 + "<script>function dostuff() { setTimeout(function() { " + 1.1379 + "document.documentElement.focus(); document.removeChild(document.documentElement);" + 1.1380 + "window.opener.focus(); }, 100); }</script></window>"); 1.1381 + 1.1382 + addEventListener("focus", doFrameSwitchingTests, true); 1.1383 + noRootWindow = window.open(data, "_blank", "chrome,width=100,height=100"); 1.1384 +} 1.1385 + 1.1386 +// these tests check when focus is moved between a tree of frames to ensure 1.1387 +// that the focus is in the right place at each event step. 1.1388 +function doFrameSwitchingTests() 1.1389 +{ 1.1390 + removeEventListener("focus", doFrameSwitchingTests, true); 1.1391 + noRootWindow.close(); 1.1392 + 1.1393 + var framea = document.getElementById("ifa"); 1.1394 + var frameb = document.getElementById("ifb"); 1.1395 + framea.style.MozUserFocus = ""; 1.1396 + frameb.style.MozUserFocus = ""; 1.1397 + 1.1398 + window.removeEventListener("focus", eventOccured, true); 1.1399 + window.removeEventListener("blur", eventOccured, true); 1.1400 + 1.1401 + var inputa = framea.contentDocument.body.firstChild; 1.1402 + inputa.focus(); 1.1403 + 1.1404 + addFrameSwitchingListeners(framea); 1.1405 + addFrameSwitchingListeners(frameb); 1.1406 + var framec = framea.contentDocument.body.lastChild; 1.1407 + addFrameSwitchingListeners(framec); 1.1408 + 1.1409 + var framed = framec.contentDocument.body.lastChild; 1.1410 + addFrameSwitchingListeners(framed); 1.1411 + 1.1412 + var inputc = framec.contentDocument.body.firstChild; 1.1413 + 1.1414 + var expectedMainWindowFocus = framea; 1.1415 + 1.1416 + // An element in the immediate parent frame is focused. Focus an element in 1.1417 + // the child. The child should be focused and the parent's current focus should 1.1418 + // be the child iframe. 1.1419 + gEventMatched = true; 1.1420 + is(fm.getFocusedElementForWindow(window, false, {}), expectedMainWindowFocus, 1.1421 + "parent of framea has iframe focused"); 1.1422 + gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea], 1.1423 + [framea.contentDocument, "blur", null, null, window, framea], 1.1424 + [framea.contentWindow, "blur", null, null, window, framea], 1.1425 + [framec.contentDocument, "focus", null, framec.contentWindow, window, framea], 1.1426 + [framec.contentWindow, "focus", null, framec.contentWindow, window, framea], 1.1427 + [inputc, "focus", inputc, framec.contentWindow, window, framea]]; 1.1428 + inputc.focus(); 1.1429 + ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from parent input to child input" + gExpectedEvents); 1.1430 + 1.1431 + // An element in a child is focused. Focus an element in the immediate 1.1432 + // parent. 1.1433 + gEventMatched = true; 1.1434 + gExpectedEvents = [[inputc, "blur", null, framec.contentWindow, window, framea], 1.1435 + [framec.contentDocument, "blur", null, null, window, framea], 1.1436 + [framec.contentWindow, "blur", null, null, window, framea], 1.1437 + [framea.contentDocument, "focus", null, framea.contentWindow, window, framea], 1.1438 + [framea.contentWindow, "focus", null, framea.contentWindow, window, framea], 1.1439 + [inputa, "focus", inputa, framea.contentWindow, window, framea]]; 1.1440 + inputa.focus(); 1.1441 + ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to parent input"); 1.1442 + 1.1443 + // An element in a frame is focused. Focus an element in a sibling frame. 1.1444 + // The common ancestor of the two frames should have its focused node 1.1445 + // cleared after the element is blurred. 1.1446 + var inputb = frameb.contentDocument.body.firstChild; 1.1447 + 1.1448 + gEventMatched = true; 1.1449 + gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea], 1.1450 + [framea.contentDocument, "blur", null, null, window, null], 1.1451 + [framea.contentWindow, "blur", null, null, window, null], 1.1452 + [frameb.contentDocument, "focus", null, frameb.contentWindow, window, frameb], 1.1453 + [frameb.contentWindow, "focus", null, frameb.contentWindow, window, frameb], 1.1454 + [inputb, "focus", inputb, frameb.contentWindow, window, frameb]]; 1.1455 + inputb.focus(); 1.1456 + ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from input to sibling frame"); 1.1457 + is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), inputa, 1.1458 + "blurred frame still has input as focus"); 1.1459 + 1.1460 + // focus a descendant in a sibling 1.1461 + var inputd = framed.contentDocument.body.firstChild; 1.1462 + gEventMatched = true; 1.1463 + gExpectedEvents = [[inputb, "blur", null, frameb.contentWindow, window, frameb], 1.1464 + [frameb.contentDocument, "blur", null, null, window, null], 1.1465 + [frameb.contentWindow, "blur", null, null, window, null], 1.1466 + [framed.contentDocument, "focus", null, framed.contentWindow, window, framea], 1.1467 + [framed.contentWindow, "focus", null, framed.contentWindow, window, framea], 1.1468 + [inputd, "focus", inputd, framed.contentWindow, window, framea]]; 1.1469 + inputd.focus(); 1.1470 + ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from input to sibling descendant"); 1.1471 + is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec, 1.1472 + "sibling parent focus has shifted to frame"); 1.1473 + 1.1474 + // focus an ancestor 1.1475 + gEventMatched = true; 1.1476 + gExpectedEvents = [[inputd, "blur", null, framed.contentWindow, window, framea], 1.1477 + [framed.contentDocument, "blur", null, null, window, framea], 1.1478 + [framed.contentWindow, "blur", null, null, window, framea], 1.1479 + [framea.contentDocument, "focus", null, framea.contentWindow, window, framea], 1.1480 + [framea.contentWindow, "focus", null, framea.contentWindow, window, framea], 1.1481 + [inputa, "focus", inputa, framea.contentWindow, window, framea]]; 1.1482 + inputa.focus(); 1.1483 + ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to ancestor"); 1.1484 + 1.1485 + // focus a descendant 1.1486 + gEventMatched = true; 1.1487 + gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea], 1.1488 + [framea.contentDocument, "blur", null, null, window, framea], 1.1489 + [framea.contentWindow, "blur", null, null, window, framea], 1.1490 + [framed.contentDocument, "focus", null, framed.contentWindow, window, framea], 1.1491 + [framed.contentWindow, "focus", null, framed.contentWindow, window, framea], 1.1492 + [inputd, "focus", inputd, framed.contentWindow, window, framea]]; 1.1493 + inputd.focus(); 1.1494 + ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to ancestor"); 1.1495 + is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec, 1.1496 + "parent focus has shifted to frame"); 1.1497 + 1.1498 + // focus a sibling frame by setting focusedWindow 1.1499 + gEventMatched = true; 1.1500 + gExpectedEvents = [[inputd, "blur", null, framed.contentWindow, window, framea], 1.1501 + [framed.contentDocument, "blur", null, null, window, null], 1.1502 + [framed.contentWindow, "blur", null, null, window, null], 1.1503 + [frameb.contentDocument, "focus", null, frameb.contentWindow, window, frameb], 1.1504 + [frameb.contentWindow, "focus", null, frameb.contentWindow, window, frameb], 1.1505 + [inputb, "focus", inputb, frameb.contentWindow, window, frameb]]; 1.1506 + fm.focusedWindow = frameb.contentWindow; 1.1507 + ok(gEventMatched && gExpectedEvents.length == 0, "frame switch using focusedWindow"); 1.1508 + 1.1509 + // clear the focus in an unfocused frame 1.1510 + gEventMatched = true; 1.1511 + gExpectedEvents = []; 1.1512 + fm.clearFocus(framec.contentWindow); 1.1513 + ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in unfocused frame"); 1.1514 + 1.1515 + // focus a sibling frame by setting focusedWindow when no element is focused in that frame 1.1516 + gEventMatched = true; 1.1517 + gExpectedEvents = [[inputb, "blur", null, frameb.contentWindow, window, frameb], 1.1518 + [frameb.contentDocument, "blur", null, null, window, null], 1.1519 + [frameb.contentWindow, "blur", null, null, window, null], 1.1520 + [framec.contentDocument, "focus", null, framec.contentWindow, window, framea], 1.1521 + [framec.contentWindow, "focus", null, framec.contentWindow, window, framea]]; 1.1522 + fm.focusedWindow = framec.contentWindow; 1.1523 + ok(gEventMatched && gExpectedEvents.length == 0, "frame switch using focusedWindow with no element focused"); 1.1524 + is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec, 1.1525 + "parent focus has shifted to frame using focusedWindow"); 1.1526 + 1.1527 + // focus the parent frame by setting focusedWindow. This should have no effect. 1.1528 + gEventMatched = true; 1.1529 + gExpectedEvents = []; 1.1530 + fm.focusedWindow = framea.contentWindow; 1.1531 + ok(gEventMatched && gExpectedEvents.length == 0, "frame switch to parent using focusedWindow"); 1.1532 + 1.1533 + // clear the focus in the parent frame 1.1534 + gEventMatched = true; 1.1535 + gExpectedEvents = [[framec.contentDocument, "blur", null, null, window, framea], 1.1536 + [framec.contentWindow, "blur", null, null, window, framea], 1.1537 + [framea.contentDocument, "focus", null, framea.contentWindow, window, framea], 1.1538 + [framea.contentWindow, "focus", null, framea.contentWindow, window, framea]]; 1.1539 + fm.clearFocus(framea.contentWindow); 1.1540 + ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in parent frame"); 1.1541 + 1.1542 + // clear the focus in an unfocused child frame 1.1543 + gEventMatched = true; 1.1544 + gExpectedEvents = []; 1.1545 + fm.clearFocus(framed.contentWindow); 1.1546 + ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in unfocused child frame"); 1.1547 + 1.1548 + var exh = false; 1.1549 + try { 1.1550 + fm.focusedWindow = null; 1.1551 + } 1.1552 + catch (ex) { exh = true; } 1.1553 + is(exh, true, "focusedWindow set to null"); 1.1554 + is(fm.focusedWindow, framea.contentWindow, "window not changed when focusedWindow set to null"); 1.1555 + 1.1556 + doFrameHistoryTests() 1.1557 +} 1.1558 + 1.1559 +function doFrameHistoryTests() 1.1560 +{ 1.1561 + var t20 = getById("t20"); 1.1562 + t20.focus(); 1.1563 + 1.1564 + gChildWindow.addEventListener("focus", 1.1565 + function(event) { 1.1566 + if (event.target == t20) { 1.1567 + is(fm.focusedElement, t20, "focus restored after history back"); done(); 1.1568 + } 1.1569 + }, true); 1.1570 + 1.1571 + // make sure that loading a new page and then going back maintains the focus 1.1572 + gChildWindow.location = "data:text/html,<script>window.onload=function() {setTimeout(function () {window.back();}, 0);}</script>"; 1.1573 +} 1.1574 + 1.1575 +function addFrameSwitchingListeners(frame) 1.1576 +{ 1.1577 + frame.contentWindow.addEventListener("focus", frameSwitchingEventOccured, false); 1.1578 + frame.contentWindow.addEventListener("blur", frameSwitchingEventOccured, false); 1.1579 + frame.contentDocument.addEventListener("focus", frameSwitchingEventOccured, false); 1.1580 + frame.contentDocument.addEventListener("blur", frameSwitchingEventOccured, false); 1.1581 + 1.1582 + var node = frame.contentDocument.body.firstChild; 1.1583 + node.addEventListener("focus", frameSwitchingEventOccured, false); 1.1584 + node.addEventListener("blur", frameSwitchingEventOccured, false); 1.1585 +} 1.1586 + 1.1587 +function frameSwitchingEventOccured(event) 1.1588 +{ 1.1589 + if (!gExpectedEvents.length) { 1.1590 + gEventMatched = false; 1.1591 + return; 1.1592 + } 1.1593 + 1.1594 + try { 1.1595 + var events = gExpectedEvents.shift(); 1.1596 + is(event.target, events[0], "event target"); 1.1597 + is(event.type, events[1], "event type"); 1.1598 + is(fm.focusedElement, events[2], "focused element"); 1.1599 + is(fm.focusedWindow, events[3], "focused frame"); 1.1600 + if (events[4]) 1.1601 + is(fm.getFocusedElementForWindow(events[4], false, {}), events[5], "focused element in frame"); 1.1602 + 1.1603 + if (gEventMatched && event.target == events[0] && event.type == events[1] && 1.1604 + fm.focusedElement == events[2] && fm.focusedWindow == events[3]) { 1.1605 + if (!events[4] || fm.getFocusedElementForWindow(events[4], false, {}) == events[5]) 1.1606 + return; 1.1607 + } 1.1608 + } catch (ex) { ok(ex, "exception"); } 1.1609 + 1.1610 + gEventMatched = false; 1.1611 +} 1.1612 + 1.1613 +SimpleTest.waitForExplicitFinish(); 1.1614 +SimpleTest.waitForFocus(startTest); 1.1615 + 1.1616 +]]> 1.1617 +</script> 1.1618 + 1.1619 +<commandset id="cu" 1.1620 + commandupdater="true" 1.1621 + events="focus" 1.1622 + oncommandupdate="eventOccured(event)"/> 1.1623 + 1.1624 +<!-- 1.1625 + The elements with ids starting with t are focusable and in the taborder. 1.1626 + The elements with ids starting with o are: 1.1627 + odd numbered ids - focusable but not part of the tab order 1.1628 + even numbered ids - not focusable with -moz-user-focus: ignore or disabled 1.1629 + The elements with ids starting with n are: 1.1630 + odd numbered ids - not focusable with -moz-user-focus: none 1.1631 + even numbered ids - focusable but not part of the tab order 1.1632 + --> 1.1633 +<vbox id="buttonbox"> 1.1634 +<hbox id="innerbox"> 1.1635 + <button id="t4" accesskey="h" label="no tabindex"/> 1.1636 + <button id="o1" accesskey="i" label="tabindex = -1" tabindex="-1"/> 1.1637 + <listbox id="t5" label="tabindex = 0" tabindex="0" rows="1"> 1.1638 + <listitem/> 1.1639 + </listbox> 1.1640 + <button id="t1" label="tabindex = 2" tabindex="2"/> 1.1641 +</hbox> 1.1642 +<hbox> 1.1643 + <button id="o2" accesskey="o" style="-moz-user-focus: ignore;" label="no tabindex"/> 1.1644 + <button id="o4" style="-moz-user-focus: ignore;" label="tabindex = -1" tabindex="-1"/> 1.1645 + <button id="t6" style="-moz-user-focus: ignore;" label="tabindex = 0" tabindex="0"/> 1.1646 + <button id="t2" style="-moz-user-focus: ignore;" label="tabindex = 2" tabindex="2"/> 1.1647 +</hbox> 1.1648 +<hbox id="specialroot"> 1.1649 + <button id="t7" style="-moz-user-focus: normal;" label="no tabindex"/> 1.1650 + <button id="o3" style="-moz-user-focus: normal;" label="tabindex = -1" tabindex="-1"/> 1.1651 + <button id="t8" style="-moz-user-focus: normal;" label="tabindex = 0" tabindex="0"/> 1.1652 + <listbox id="t3" style="-moz-user-focus: normal;" label="tabindex = 2" tabindex="2" rows="1"> 1.1653 + <listitem/> 1.1654 + </listbox> 1.1655 +</hbox> 1.1656 +<hbox> 1.1657 + <button accesskey="p" style="display: none;"/> <button accesskey="q" style="visibility: collapse;"/> 1.1658 + <button style="display: none;" tabindex="2"/> <button style="visibility: collapse;" tabindex="2"/> 1.1659 +</hbox> 1.1660 +<hbox> 1.1661 + <button id="o20" accesskey="s" label="no tabindex" disabled="true"/> 1.1662 + <button id="o22" label="tabindex = -1" tabindex="-1" disabled="true"/> 1.1663 + <button id="o24" label="tabindex = 0" tabindex="0" disabled="true"/> 1.1664 + <button id="o26" label="tabindex = 2" tabindex="2" disabled="true"/> 1.1665 +</hbox> 1.1666 +</vbox> 1.1667 +<vbox> 1.1668 +<hbox> 1.1669 + <dropmarker id="o6" value="no tabindex"/> 1.1670 + <dropmarker id="o8" value="tabindex = -1" tabindex="-1"/> 1.1671 + <dropmarker id="o10" value="tabindex = 0" tabindex="0"/> 1.1672 + <dropmarker id="o12" value="tabindex = 2" tabindex="2"/> 1.1673 + <dropmarker id="t9" accesskey="r" style="-moz-user-focus: normal;" value="no tabindex" /> 1.1674 + <dropmarker id="t10" style="-moz-user-focus: normal;" value="tabindex = -1" tabindex="-1" /> 1.1675 + <dropmarker id="t11" style="-moz-user-focus: normal;" value="tabindex = 0" tabindex="0" /> 1.1676 + <dropmarker id="t12" style="-moz-user-focus: normal;" value="tabindex = 2" tabindex="2" /> 1.1677 + <dropmarker id="o14" style="-moz-user-focus: ignore;" value="no tabindex"/> 1.1678 + <dropmarker id="o16" style="-moz-user-focus: ignore;" value="tabindex = -1" tabindex="-1"/> 1.1679 + <dropmarker id="n1" style="-moz-user-focus: none;" value="tabindex = 0" tabindex="0"/> 1.1680 + <dropmarker id="n3" style="-moz-user-focus: none;" value="tabindex = 2" tabindex="2"/> 1.1681 +</hbox> 1.1682 +</vbox> 1.1683 +<browser id="childframe" type="content" src="child_focus_frame.html" width="300" height="195"/> 1.1684 +<button id="t34"/> 1.1685 +<tabbox id="tabbox"> 1.1686 + <tabs><tab id="t35" label="One"/><tab id="tab2" label="Two"/></tabs> 1.1687 + <tabpanels> 1.1688 + <tabpanel> 1.1689 + <checkbox id="t36"/> 1.1690 + <button id="t37"/> 1.1691 + </tabpanel> 1.1692 + <tabpanel> 1.1693 + <checkbox id="htab1"/> 1.1694 + <button id="nohtab2" tabindex="7"/> 1.1695 + <checkbox id="htab2" tabindex="0"/> 1.1696 + </tabpanel> 1.1697 + </tabpanels> 1.1698 +</tabbox> 1.1699 +<hbox> 1.1700 +<panel> 1.1701 + <button id="inpopup1" label="One"/> 1.1702 + <textbox label="Two"/> 1.1703 +</panel> 1.1704 +<description label="o" accesskey="v"/> 1.1705 +<button id="t38"/> 1.1706 +<!-- The 't' element tests end here so it doesn't matter that these elements are tabbable --> 1.1707 +<label id="aj" value="j" accesskey="j" control="o9"/> 1.1708 +<label id="ak" accesskey="k" control="n4">k</label> 1.1709 +<checkbox id="o5"/><checkbox id="o7"/><hbox><checkbox id="o9"/></hbox> 1.1710 +<checkbox id="o13"/><checkbox id="o15"/><checkbox id="o17"/><checkbox id="o19"/><checkbox id="o21"/><checkbox id="o23"/><checkbox id="o25"/> 1.1711 +<checkbox id="n2"/><checkbox id="n4"/> 1.1712 +<listbox id="last" width="20" rows="1"/> 1.1713 + 1.1714 +<iframe id="ifa" width="40" height="60" style="-moz-user-focus: ignore;" type="content" 1.1715 + src="data:text/html,<input id=fra size='2'><input id='fra-b' size='2'> 1.1716 + <iframe src='data:text/html,<input id=frc><iframe src="data:text/html,<input id=frd>"></iframe>'></iframe>"/> 1.1717 +<iframe id="ifb" width="20" height="20" style="-moz-user-focus: ignore;" 1.1718 + src="data:text/html,<input id=frd></iframe>"/> 1.1719 + 1.1720 +</hbox> 1.1721 +</window>