dom/tests/mochitest/chrome/window_focus.xul

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

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

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

     1 <?xml version="1.0"?>
     2 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
     3 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
     4                  type="text/css"?>
     5 <!--
     6  This test checks focus in various ways
     7 -->
     8 <window id="outer-document" title="Focus Test" width="600" height="550"
     9         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    10   <script type="application/javascript"
    11           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
    12   <script type="application/javascript"
    13           src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
    15 <body xmlns="http://www.w3.org/1999/xhtml"/>
    17   <script type="application/javascript"><![CDATA[
    19 var fm = Components.classes["@mozilla.org/focus-manager;1"].
    20            getService(Components.interfaces.nsIFocusManager);
    22 const kChildDocumentRootIndex = 13;
    23 const kBeforeTabboxIndex = 34;
    24 const kTabbableSteps = 38;
    25 const kFocusSteps = 26;
    26 const kNoFocusSteps = 7;
    27 const kOverflowElementIndex = 27;
    29 var gTestStarted = false;
    30 var gPartialTabbing = false;
    31 var gMoveToFocusFrame = false;
    32 var gLastFocus = null;
    33 var gLastFocusWindow = window;
    34 var gLastFocusMethod = -1;
    35 var gEvents = "";
    36 var gExpectedEvents = "";
    37 var gEventMatched = true;
    38 var gShowOutput = false;
    39 var gChildWindow = null;
    41 var gOldExpectedWindow = null;
    42 var gNewExpectedWindow = null;
    44 function is(l, r, n) { window.opener.wrappedJSObject.SimpleTest.is(l,r,n); }
    45 function ok(v, n) { window.opener.wrappedJSObject.SimpleTest.ok(v,n); }
    47 function initEvents(target)
    48 {
    49   target.addEventListener("focus", eventOccured, true);
    50   target.addEventListener("blur", eventOccured, true);
    51   getTopWindow(target).addEventListener("activate", eventOccured, true);
    52   getTopWindow(target).addEventListener("deactivate", eventOccured, true);
    53 }
    55 function eventOccured(event)
    56 {
    57   // iframes should never receive focus or blur events directly
    58   if (event.target instanceof Element && event.target.localName == "iframe")
    59     ok(false, "iframe " + event.type + "occured");
    61   var id;
    62   if (gOldExpectedWindow && event.type == "blur") {
    63     if (event.target instanceof Window)
    64       id = "frame-" + gOldExpectedWindow.document.documentElement.id + "-window";
    65     else if (event.target instanceof Document)
    66       id = "frame-" + gOldExpectedWindow.document.documentElement.id + "-document";
    67     else
    68       id = event.originalTarget.id;
    69   }
    70   else if (gNewExpectedWindow && event.type == "focus") {
    71     if (event.target instanceof Window)
    72       id = "frame-" + gNewExpectedWindow.document.documentElement.id + "-window";
    73     else if (event.target instanceof Document)
    74       id = "frame-" + gNewExpectedWindow.document.documentElement.id + "-document";
    75     else
    76       id = event.originalTarget.id;
    77   }
    78   else if (event.type == "activate" || event.type == "deactivate")
    79     id = event.target.document.documentElement.id + "-window";
    80   else if (event.target instanceof Window)
    81     id = (event.target == window) ? "outer-window" : "child-window";
    82   else if (event.target instanceof Document)
    83     id = (event.target == document) ? "outer-document" : "child-document";
    84   else
    85     id = event.originalTarget.id;
    87   if (gEvents)
    88     gEvents += " ";
    89   gEvents += event.type + ": " + id;
    90 }
    92 function expectFocusShift(callback, expectedWindow, expectedElement, focusChanged, testid)
    93 {
    94   if (expectedWindow == null)
    95     expectedWindow = expectedElement ?
    96                      expectedElement.ownerDocument.defaultView :
    97                      gLastFocusWindow;
    99   var expectedEvents = "";
   100   if (focusChanged) {
   101     var id;
   102     if (getTopWindow(gLastFocusWindow) != getTopWindow(expectedWindow)) {
   103       id = getTopWindow(gLastFocusWindow).document.documentElement.id;
   104       expectedEvents += "deactivate: " + id + "-window";
   105     }
   107     if (gLastFocus && gLastFocus.id != "t" + kChildDocumentRootIndex &&
   108         (!gOldExpectedWindow || gOldExpectedWindow.document.documentElement != gLastFocus)) {
   109       if (expectedEvents)
   110         expectedEvents += " ";
   111       if (!gOldExpectedWindow)
   112         expectedEvents += "commandupdate: cu ";
   113       expectedEvents += "blur: " + gLastFocus.id;
   114     }
   116     if (gLastFocusWindow && gLastFocusWindow != expectedWindow) {
   117       if (!gMoveToFocusFrame) {
   118         if (gOldExpectedWindow)
   119           id = "frame-" + gOldExpectedWindow.document.documentElement.id;
   120         else
   121           id = (gLastFocusWindow == window) ? "outer" : "child";
   122         if (expectedEvents)
   123           expectedEvents += " ";
   124         expectedEvents += "blur: " + id + "-document " +
   125                           "blur: " + id + "-window";
   126       }
   127     }
   129     if (getTopWindow(gLastFocusWindow) != getTopWindow(expectedWindow)) {
   130       id = getTopWindow(expectedWindow).document.documentElement.id;
   131       if (expectedEvents)
   132         expectedEvents += " ";
   133       expectedEvents += "activate: " + id + "-window";
   134     }
   136     if (expectedWindow && gLastFocusWindow != expectedWindow) {
   137       if (gNewExpectedWindow)
   138         id = "frame-" + gNewExpectedWindow.document.documentElement.id;
   139       else
   140         id = (expectedWindow == window) ? "outer" : "child";
   141       if (expectedEvents)
   142         expectedEvents += " ";
   143       expectedEvents += "focus: " + id + "-document " +
   144                         "focus: " + id + "-window";
   145     }
   147     // for this test which fires a mouse event on a label, the document will
   148     // be focused first and then the label code will focus the related
   149     // control. This doesn't result in different focus events, but a command
   150     // update will occur for the document and then a secon command update will
   151     // occur when the control is focused.
   152     if (testid == "mouse on html label with content inside")
   153       expectedEvents += " commandupdate: cu";
   155     if (expectedElement &&
   156         (!gNewExpectedWindow || gNewExpectedWindow.document.documentElement != expectedElement)) {
   157       if (!gNewExpectedWindow) {
   158         if (expectedEvents)
   159           expectedEvents += " ";
   160         expectedEvents += "commandupdate: cu";
   161       }
   162       if (expectedElement.id != "t" + kChildDocumentRootIndex) {
   163         if (expectedEvents)
   164           expectedEvents += " ";
   165         expectedEvents += "focus: " + expectedElement.id;
   166       }
   167     }
   168     else if (expectedWindow && gLastFocusWindow != expectedWindow &&
   169              !expectedElement) {
   170       if (expectedEvents)
   171         expectedEvents += " ";
   172       expectedEvents += "commandupdate: cu";
   173     }
   174   }
   176   gLastFocus = expectedElement;
   177   gLastFocusWindow = expectedWindow;
   179   callback();
   181   compareEvents(expectedEvents, expectedWindow, expectedElement, testid);
   182 }
   184 function compareEvents(expectedEvents, expectedWindow, expectedElement, testid)
   185 {
   186   if (!gShowOutput) {
   187     gEvents = "";
   188     return;
   189   }
   191   is(gEvents, expectedEvents, testid + " events");
   192   gEvents = "";
   194   var doc;
   195   if (expectedWindow == window)
   196     doc = "outer-document";
   197   else if (expectedWindow == gChildWindow)
   198     doc = "inner-document";
   199   else if (gNewExpectedWindow)
   200     doc = gNewExpectedWindow.document.body ? gNewExpectedWindow.document.body.id :
   201                                              gNewExpectedWindow.document.documentElement.id;
   202   else
   203     doc = "other-document";
   205   var focusedElement = fm.focusedElement;
   206   is(focusedElement ? focusedElement.id : "none",
   207      expectedElement ? expectedElement.id : "none", testid + " focusedElement");
   208   is(fm.focusedWindow, expectedWindow, testid + " focusedWindow");
   209   var focusedWindow = {};
   210   is(fm.getFocusedElementForWindow(expectedWindow, false, focusedWindow),
   211      expectedElement, testid + " getFocusedElementForWindow");
   212   is(focusedWindow.value, expectedWindow, testid + " getFocusedElementForWindow frame");
   213   is(expectedWindow.document.hasFocus(), true, testid + " hasFocus");
   214   is(expectedWindow.document.activeElement ? expectedWindow.document.activeElement.id : "none",
   215      expectedElement ? expectedElement.id : doc, testid + " activeElement");
   216   var cdwindow = getTopWindow(expectedWindow);
   217   if (cdwindow.document.commandDispatcher) {
   218     is(cdwindow.document.commandDispatcher.focusedWindow, expectedWindow, testid + " commandDispatcher focusedWindow");
   219     is(cdwindow.document.commandDispatcher.focusedElement, focusedElement, testid + " commandDispatcher focusedElement");
   220   }
   222   if (gLastFocusMethod != -1) {
   223     is(fm.getLastFocusMethod(null), gLastFocusMethod, testid + " lastFocusMethod null");
   224     is(fm.getLastFocusMethod(expectedWindow), gLastFocusMethod, testid + " lastFocusMethod window");
   225   }
   227   // the parent should have the iframe focused
   228   if (doc == "inner-document") {
   229     is(document.hasFocus(), true, testid + " hasFocus");
   230     is(fm.getFocusedElementForWindow(window, false, focusedWindow),
   231        $("childframe"), testid + " getFocusedElementForWindow for parent");
   232     is(focusedWindow.value, window, testid + " getFocusedElementForWindow for parent frame");
   233     is(fm.getFocusedElementForWindow(window, true, focusedWindow),
   234        expectedElement, testid + " getFocusedElementForWindow deep for parent");
   235     is(focusedWindow.value, gChildWindow, testid + " getFocusedElementForWindow deep for parent frame");
   236     is(document.activeElement.id, "childframe", testid + " activeElement for parent");
   237   }
   239   // compare the selection for the child window. Skip mouse tests as the caret
   240   // is adjusted by the selection code for mouse clicks, and not the focus code.
   241   if (expectedWindow == window) {
   242     var selection = window.getSelection();
   243     ok(selection.focusNode == null && selection.focusOffset == 0 &&
   244        selection.anchorNode == null && selection.anchorOffset == 0, testid + " selection");
   245   }
   246   else if ((expectedWindow == gChildWindow) && !testid.indexOf("mouse") == -1) {
   247     checkSelection(expectedElement, testid);
   248   }
   249 }
   251 function checkSelection(node, testid)
   252 {
   253   var selection = gChildWindow.getSelection();
   255   var range = gChildWindow.document.createRange();
   256   range.selectNodeContents(node);
   257   if (!node.firstChild || node.localName == "input" ||
   258        node.localName == "select" || node.localName == "button") {
   259     range.setStartBefore(node);
   260     range.setEndBefore(node);
   261   }
   263   if (node.firstChild)
   264     range.setEnd(range.startContainer, range.startOffset);
   266   is(selection.focusNode, range.startContainer, testid + " selection focusNode");
   267   is(selection.focusOffset, range.startOffset, testid + " selection focusOffset");
   268   is(selection.anchorNode, range.endContainer, testid + " selection anchorNode");
   269   is(selection.anchorOffset, range.endOffset, testid + " selection anchorOffset");
   270 }
   272 function getTopWindow(win)
   273 {
   274   return win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
   275              getInterface(Components.interfaces.nsIWebNavigation).
   276              QueryInterface(Components.interfaces.nsIDocShellTreeItem).rootTreeItem.
   277              QueryInterface(Components.interfaces.nsIInterfaceRequestor).
   278              getInterface(Components.interfaces.nsIDOMWindow);
   279 }
   281 function mouseOnElement(element, expectedElement, focusChanged, testid)
   282 {
   283   var expectedWindow = (element.ownerDocument.defaultView == gChildWindow) ? gChildWindow : window;
   284   // on Mac, form elements are not focused when clicking, except for lists and textboxes.
   285   var noFocusOnMouse = (navigator.platform.indexOf("Mac") == 0);
   286   if (noFocusOnMouse) {
   287     if (element.namespaceURI == "http://www.w3.org/1999/xhtml") {
   288       // links are special. They can be focused but show no focus ring
   289       if (element.localName == "a" || element.localName == "div" ||
   290           element.localName == "select" ||
   291           element.localName == "input" && (element.type == "text" ||
   292                                            element.type == "password")) {
   293         noFocusOnMouse = false;
   294       }
   295     }
   296     else if (element.localName == "listbox") {
   297       noFocusOnMouse = false;
   298     }
   299   }
   301   if (noFocusOnMouse) {
   302     // no focus so the last focus method will be 0
   303     gLastFocusMethod = 0;
   304     expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView),
   305                      expectedWindow, null, true, testid);
   306     gLastFocusMethod = fm.FLAG_BYMOUSE;
   307   }
   308   else {
   309     expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView),
   310                      element.ownerDocument.defaultView,
   311                      expectedElement, focusChanged, testid);
   312   }
   313 }
   315 function done()
   316 {
   317   var opener = window.opener;
   318   window.close();
   319   opener.wrappedJSObject.SimpleTest.finish();
   320 }
   322 var pressTab = function () synthesizeKey("VK_TAB", { });
   324 function setFocusTo(id, fwindow)
   325 {
   326   gLastFocus = getById(id);
   327   gLastFocusWindow = fwindow;
   328   if (gLastFocus)
   329     gLastFocus.focus();
   330   else
   331     fm.clearFocus(fwindow);
   332   gEvents = "";
   333 }
   335 function getById(id)
   336 {
   337   if (gNewExpectedWindow)
   338     return gNewExpectedWindow.document.getElementById(id);
   339   var element = $(id);
   340   if (!element)
   341     element = $("childframe").contentDocument.getElementById(id);
   342   return element;
   343 }
   345 function startTest()
   346 {
   347   if (gTestStarted)
   348     return;
   349   gTestStarted = true;
   351   gChildWindow = $("childframe").contentWindow;
   352   gShowOutput = true;
   354   // synthesize a mousemove over the image to ensure that the imagemap data is
   355   // created. Otherwise, the special imagemap frames might not exist, and
   356   // won't be focusable.
   357   synthesizeMouse(getById("image"), 4, 4, { type: "mousemove" }, gChildWindow);
   359   initEvents(window);
   361   is(fm.activeWindow, window, "activeWindow");
   362   is(gChildWindow.document.hasFocus(), false, " child document hasFocus");
   364   // test to see if the Mac Full Keyboard Access setting is set. If t3 is
   365   // focused after tab is pressed, then it is set to textboxes and lists only.
   366   // Otherwise, all elements are in the tab order.
   367   pressTab();
   369   if (fm.focusedElement.id == "t3")
   370     gPartialTabbing = true;
   371   else
   372     is(fm.focusedElement.id, "t1", "initial tab key");
   374   is(fm.getLastFocusMethod(null), fm.FLAG_BYKEY, "last focus method null start");
   375   is(fm.getLastFocusMethod(window), fm.FLAG_BYKEY, "last focus method window start");
   377   fm.clearFocus(window);
   378   gEvents = "";
   380   gLastFocusMethod = fm.FLAG_BYKEY;
   381   if (gPartialTabbing) {
   382     var partialTabList = ["t3", "t5", "t9", "t10", "t11", "t12", "t13", "t14", "t15",
   383                           "t16", "t19", "t20", "t21", "t22", "t26", "t27", "t28", "t29", "t30"];
   384     for (var idx = 0; idx < partialTabList.length; idx++) {
   385       expectFocusShift(pressTab, null, getById(partialTabList[idx]), true, "partial tab key " + partialTabList[idx]);
   386     }
   387     setFocusTo("last", window);
   388     expectFocusShift(pressTab, null, getById(partialTabList[0]), true, "partial tab key wrap to start");
   389     expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
   390                      null, getById("last"), true, "partial shift tab key wrap to end");
   391     for (var idx = partialTabList.length - 1; idx >= 0; idx--) {
   392       expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
   393                        null, getById(partialTabList[idx]), true, "partial tab key " + partialTabList[idx]);
   394     }
   395   }
   396   else {
   397     // TAB key
   398     for (var idx = 1; idx <= kTabbableSteps; idx++) {
   399       expectFocusShift(pressTab, null, getById("t" + idx), true, "tab key t" + idx);
   400     }
   402     // wrapping around at end with TAB key
   403     setFocusTo("last", window);
   404     expectFocusShift(pressTab, null, getById("t1"), true, "tab key wrap to start");
   405     expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
   406                      null, getById("last"), true, "shift tab key wrap to end");
   408     // Shift+TAB key
   409     setFocusTo("o5", window);
   410     for (idx = kTabbableSteps; idx > 0; idx--) {
   411       expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
   412                        null, getById("t" + idx), true, "shift tab key t" + idx);
   413     }
   414   }
   416   var t19 = getById("t19");
   417   is(t19.selectionStart, 0, "input focused from tab key selectionStart");
   418   is(t19.selectionEnd, 5, "input focused from tab key selectionEnd");
   419   t19.setSelectionRange(0, 0);
   421   gLastFocusMethod = 0;
   422   var selectFired = false;
   423   function selectListener() { selectFired = true; }
   424   t19.addEventListener("select", selectListener, false); 
   425   expectFocusShift(function() t19.select(),
   426                    null, getById("t" + 19), true, "input.select()");
   427   t19.removeEventListener("select", selectListener, false); 
   428   ok(selectFired, "select event fires for input");
   430   // mouse clicking
   431   gLastFocusMethod = fm.FLAG_BYMOUSE;
   432   for (idx = kTabbableSteps; idx >= 1; idx--) {
   433     // skip the document root and the overflow element
   434     if (idx == kChildDocumentRootIndex || idx == kOverflowElementIndex)
   435       continue;
   436     if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1))
   437       continue;
   439     var element = getById("t" + idx);
   440     // skip area elements, as getBoundingClientRect doesn't return their actual coordinates
   441     if (element.localName == "area")
   442       continue;
   444     mouseOnElement(element, getById("t" + idx), true, "mouse on element t" + idx);
   445     var expectedWindow = (element.ownerDocument.defaultView == gChildWindow) ? gChildWindow : window;
   446     if (element.localName == "listbox" && expectedWindow == window &&
   447         navigator.platform.indexOf("Mac") == 0) {
   448       // after focusing a listbox on Mac, clear the focus before continuing.
   449       setFocusTo(null, window);
   450     }
   451   }
   453   is(t19.selectionStart, 0, "input focused from mouse selectionStart");
   454   is(t19.selectionEnd, 0, "input focused from mouse selectionEnd");
   456   // mouse clicking on elements that are not tabbable 
   457   for (idx = 1; idx <= kFocusSteps; idx++) {
   458     var element = getById("o" + (idx % 2 ? idx : idx - 1));
   460     mouseOnElement(element, element, idx % 2,
   461                    "mouse on non-tabbable element o" + idx);
   462   }
   464   // mouse clicking on elements that are not tabbable and have user-focus: none
   465   // or are not focusable for other reasons (for instance, being disabled)
   466   // These elements will clear the focus when clicked.
   467   for (idx = 1; idx <= kNoFocusSteps; idx++) {
   468     var element = getById("n" + idx);
   469     gLastFocusMethod = idx % 2 ? 0 : fm.FLAG_BYMOUSE;
   471     mouseOnElement(element, idx % 2 ? null: element, true, "mouse on unfocusable element n" + idx);
   472   }
   474   if (idx == kOverflowElementIndex) {
   475     gLastFocusMethod = fm.FLAG_BYMOUSE;
   476     var element = getById("t" + idx);
   477     expectFocusShift(function () synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView),
   478                      window, null, true, "mouse on scrollable element");
   479   }
   481   // focus() method
   482   gLastFocusMethod = 0;
   483   for (idx = kTabbableSteps; idx >= 1; idx--) {
   484     if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1))
   485       continue;
   486     expectFocusShift(function () getById("t" + idx).focus(),
   487                      null, getById("t" + idx), true, "focus method on element t" + idx);
   488   }
   490   $("t1").focus();
   491   ok(gEvents === "", "focusing element that is already focused");
   493   $("t2").blur();
   494   $("t7").blur();
   495   ok(gEvents === "", "blurring element that is not focused");
   496   is(document.activeElement, $("t1"), "old element still focused after blur() on another element");
   498   // focus() method on elements that are not tabbable 
   499   for (idx = 1; idx <= kFocusSteps; idx++) {
   500     var expected = getById("o" + (idx % 2 ? idx : idx - 1));
   501     expectFocusShift(function () getById("o" + idx).focus(),
   502                      expected.ownerDocument.defaultView,
   503                      expected, idx % 2, "focus method on non-tabbable element o" + idx);
   504   }
   506   // focus() method on elements that are not tabbable and have user-focus: none
   507   // or are not focusable for other reasons (for instance, being disabled)
   508   for (idx = 1; idx <= kNoFocusSteps; idx++) {
   509     var expected = getById("o" + (idx % 2 ? idx : idx - 1));
   510     expectFocusShift(function () getById("o" + idx).focus(),
   511                      expected.ownerDocument.defaultView,
   512                      expected, idx % 2, "focus method on unfocusable element n" + idx);
   513   }
   515   // the focus() method on the legend element should focus the legend if it is
   516   // focusable, or the first element after the legend if it is not focusable.
   517   if (!gPartialTabbing) {
   518     gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
   519     var legend = getById("legend");
   520     expectFocusShift(function () legend.focus(),
   521                      null, getById("t28"), true, "focus method on unfocusable legend");
   522     gLastFocusMethod = 0;
   523     legend.tabIndex = "0";
   524     expectFocusShift(function () legend.focus(),
   525                      null, getById("legend"), true, "focus method on focusable legend");
   526     legend.tabIndex = "-1";
   527   }
   529   var accessKeyDetails = (navigator.platform.indexOf("Mac") >= 0) ?
   530                          { ctrlKey : true } : { altKey : true };
   532   // test accesskeys
   533   var keys = ["t26", "t19", "t22", "t29", "t15", "t17", "n6",
   534               "t4", "o1", "o9", "n4"];
   535   for (var k = 0; k < keys.length; k++) {
   536     var key = String.fromCharCode(65 + k);
   538     // accesskeys D and G are for labels so get redirected
   539     gLastFocusMethod = (key == "D" || key == "G") ? fm.FLAG_BYMOVEFOCUS : fm.FLAG_BYKEY;
   541     // on Windows and Linux, the shift key must be pressed for content area access keys
   542     // and on Mac, the alt key must be pressed for content area access keys
   543     var isContent = (getById(keys[k]).ownerDocument.defaultView == gChildWindow);
   544     if (navigator.platform.indexOf("Mac") == -1) {
   545       accessKeyDetails.shiftKey = isContent;
   546     } else {
   547       accessKeyDetails.altKey = isContent;
   548     }
   550     expectFocusShift(function () synthesizeKey(key, accessKeyDetails),
   551                      null, getById(keys[k]), true, "accesskey " + key);
   552   }
   554   // clicking on the labels
   555   gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
   556   expectFocusShift(function () synthesizeMouse(getById("ad"), 2, 2, { }, gChildWindow),
   557                    null, getById("t29"), true, "mouse on html label with content inside");
   558   expectFocusShift(function () synthesizeMouse(getById("ag"), 2, 2, { }, gChildWindow),
   559                    null, getById("n6"), true, "mouse on html label with for attribute");
   560   gLastFocusMethod = 0;
   561   expectFocusShift(function () synthesizeMouse(getById("aj"), 2, 2, { }),
   562                    null, getById("o9"), true, "mouse on xul label with content inside");
   563   expectFocusShift(function () synthesizeMouse(getById("ak"), 2, 2, { }),
   564                    null, getById("n4"), true, "mouse on xul label with control attribute");
   566   // test accesskeys that shouldn't work
   567   k = "o".charCodeAt(0);
   568   while (k++ < "v".charCodeAt(0)) {
   569     var key = String.fromCharCode(k);
   570     expectFocusShift(function () synthesizeKey(key, accessKeyDetails),
   571                      window, getById("n4"), false, "non accesskey " + key);
   572   }
   573   gLastFocusMethod = -1;
   575   // should focus the for element when using the focus method on a label as well
   576   expectFocusShift(function () getById("ad").focus(),
   577                    null, getById("t29"), true, "mouse on html label using focus method");
   579   // make sure that the text is selected when clicking a label associated with an input
   580   getById("ag").htmlFor = "t19";
   581   expectFocusShift(function () synthesizeMouse(getById("ag"), 2, 2, { }, gChildWindow),
   582                    null, getById("t19"), true, "mouse on html label with for attribute changed");
   583   is(t19.selectionStart, 0, "input focused from label, selectionStart");
   584   is(t19.selectionEnd, 5, "input focused from label, selectionEnd");
   586   // switch to another panel in a tabbox and ensure that tabbing moves between
   587   // elements on the new panel.
   588   $("tabbox").selectedIndex = 1;
   589   expectFocusShift(function () getById("t" + kBeforeTabboxIndex).focus(),
   590                    null, getById("t" + kBeforeTabboxIndex), true, "focus method on element before tabbox");
   592   if (!gPartialTabbing) {
   593     expectFocusShift(pressTab, null, getById("tab2"), true, "focus method on tab");
   594     expectFocusShift(pressTab, null, getById("htab1"), true, "tab key switch tabpanel 1");
   595     expectFocusShift(pressTab, null, getById("htab2"), true, "tab key switch tabpanel 2");
   596     expectFocusShift(pressTab, null, getById("t" + (kBeforeTabboxIndex + 4)), true, "tab key switch tabpanel 3");
   597   }
   598   $("tabbox").selectedIndex = 0;
   600   // ---- the following checks when the focus changes during a blur or focus event ----
   602   var o5 = $("o5");
   603   var o9 = $("o9");
   604   var t3 = $("t3");
   605   var t17 = getById("t17");
   606   var t19 = getById("t19");
   607   var shiftFocusParentDocument = function() o9.focus();
   608   var shiftFocusChildDocument = function() t17.focus();
   610   var trapBlur = function (element, eventListener, blurFunction)
   611   {
   612     element.focus();
   613     gEvents = "";
   614     element.addEventListener("blur", eventListener, false);
   615     blurFunction();
   616     element.removeEventListener("blur", eventListener, false);
   617   }
   619   var functions = [
   620     function(element) element.focus(),
   621     function(element) synthesizeMouse(element, 4, 4, { }, element.ownerDocument.defaultView)
   622   ];
   624   // first, check cases where the focus is adjusted during the blur event. Iterate twice,
   625   // once with the focus method and then focusing by mouse clicking
   626   for  (var l = 0; l < 2; l++) {
   627     var adjustFocus = functions[l];
   628     var mod = (l == 1) ? " with mouse" : "";
   630     // an attempt is made to switch the focus from one element (o5) to another
   631     // element (t3) within the same document, yet the focus is shifted to a
   632     // third element (o9) in the same document during the blur event for the
   633     // first element.
   634     trapBlur(o5, shiftFocusParentDocument, function () adjustFocus(t3));
   635     compareEvents("commandupdate: cu blur: o5 commandupdate: cu focus: o9",
   636                   window, o9, "change focus to sibling during element blur, attempted sibling" + mod);
   638     // similar, but the third element (t17) is in a child document
   639     trapBlur(o9, shiftFocusChildDocument, function () adjustFocus(t3));
   640     compareEvents("commandupdate: cu blur: o9 blur: outer-document blur: outer-window " +
   641                   "focus: child-document focus: child-window commandupdate: cu focus: t17",
   642                   gChildWindow, t17, "change focus to child document during element blur, attempted sibling" + mod);
   644     // similar, but an attempt to switch focus within the same document, but the
   645     // third element (t17) is in a parent document
   646     trapBlur(t17, shiftFocusParentDocument, function () adjustFocus(t19));
   647     compareEvents("commandupdate: cu blur: t17 blur: child-document blur: child-window " +
   648                   "focus: outer-document focus: outer-window commandupdate: cu focus: o9",
   649                   window, o9, "change focus to parent document during element blur, attempted sibling" + mod);
   651     // similar, but blur is called instead of switching focus
   652     trapBlur(t3, shiftFocusParentDocument, function () t3.blur());
   653     compareEvents("commandupdate: cu blur: t3 commandupdate: cu focus: o9",
   654                   window, o9, "change focus to same document during clear focus" + mod);
   656     // check when an element in the same document is focused during the
   657     // element's blur event, but an attempt was made to focus an element in the
   658     // child document. In this case, the focus in the parent document should be
   659     // what was set during the blur event, but the actual focus should still
   660     // move to the child document.
   661     trapBlur(t3, shiftFocusParentDocument, function () adjustFocus(t17));
   662     compareEvents("commandupdate: cu blur: t3 commandupdate: cu focus: o9 " +
   663                   "blur: outer-document blur: outer-window " +
   664                   "focus: child-document focus: child-window commandupdate: cu focus: t17",
   665                   gChildWindow, t17, "change focus to sibling during element blur, attempted child" + mod);
   666     is(fm.getFocusedElementForWindow(window, false, {}), $("childframe"),
   667        "change focus to sibling during element blur, attempted child, focused in parent" + mod);
   669     // similar, but with a parent
   670     trapBlur(t19, shiftFocusChildDocument, function () adjustFocus(t3));
   671     compareEvents("commandupdate: cu blur: t19 commandupdate: cu focus: t17 " +
   672                   "blur: child-document blur: child-window " +
   673                   "focus: outer-document focus: outer-window commandupdate: cu focus: t3",
   674                   window, t3, "change focus to sibling during element blur, attempted parent" + mod);
   675     is(fm.getFocusedElementForWindow(gChildWindow, false, {}), t17,
   676        "change focus to sibling during element blur, attempted child, focused in child" + mod);
   678     // similar, with a child, but the blur event focuses a child element also
   679     trapBlur(t3, shiftFocusChildDocument, function () adjustFocus(t19));
   680     compareEvents("commandupdate: cu blur: t3 blur: outer-document blur: outer-window " +
   681                   "focus: child-document focus: child-window commandupdate: cu focus: t17",
   682                   gChildWindow, t17, "change focus to child during element blur, attempted child" + mod);
   684     // similar, with a parent, where the blur event focuses a parent element also
   685     trapBlur(t17, shiftFocusParentDocument, function () adjustFocus(t3));
   686     compareEvents("commandupdate: cu blur: t17 blur: child-document blur: child-window " +
   687                   "focus: outer-document focus: outer-window commandupdate: cu focus: o9",
   688                   window, o9, "change focus to parent during element blur, attempted parent" + mod);
   689   }
   691   var trapFocus = function (element, eventListener)
   692   {
   693     element.addEventListener("focus", eventListener, false);
   694     element.focus();
   695     element.removeEventListener("focus", eventListener, false);
   696   }
   698   fm.clearFocus(window);
   699   gEvents = "";
   701   // next, check cases where the focus is adjusted during the focus event
   703   // switch focus to an element in the same document  
   704   trapFocus(o5, shiftFocusParentDocument);
   705   compareEvents("commandupdate: cu focus: o5 commandupdate: cu blur: o5 commandupdate: cu focus: o9",
   706                 window, o9, "change focus to sibling during element focus");
   708   // similar, but the new element (t17) is in a child document
   709   trapFocus(o5, shiftFocusChildDocument);
   710   compareEvents("commandupdate: cu blur: o9 " +
   711                 "commandupdate: cu focus: o5 commandupdate: cu blur: o5 " +
   712                 "blur: outer-document blur: outer-window " +
   713                 "focus: child-document focus: child-window commandupdate: cu focus: t17",
   714                 gChildWindow, t17, "change focus to child document during element focus");
   716   // similar, but the new element (o9) is in a parent document.
   717   trapFocus(t19, shiftFocusParentDocument);
   718   compareEvents("commandupdate: cu blur: t17 " +
   719                 "commandupdate: cu focus: t19 commandupdate: cu blur: t19 " +
   720                 "blur: child-document blur: child-window " +
   721                 "focus: outer-document focus: outer-window commandupdate: cu focus: o9",
   722                 window, o9, "change focus to parent document during element focus");
   724   // clear the focus during the focus event
   725   trapFocus(t3, function () fm.clearFocus(window));
   726   compareEvents("commandupdate: cu blur: o9 commandupdate: cu focus: t3 commandupdate: cu blur: t3",
   727                 window, null, "clear focus during focus event");
   729   if (!gPartialTabbing)
   730     doCommandDispatcherTests();
   732   testMoveFocus();
   734   doRemoveTests();
   736   // tests various focus manager apis for null checks
   737   var exh = false;
   738   try {
   739     fm.clearFocus(null);
   740   }
   741   catch (ex) { exh = true; }
   742   is(exh, true, "clearFocus with null window causes exception");
   744   var exh = false;
   745   try {
   746     fm.getFocusedElementForWindow(null, false, focusedWindow);
   747   }
   748   catch (ex) { exh = true; }
   749   is(exh, true, "getFocusedElementForWindow with null window causes exception");
   751   // just make sure that this doesn't crash
   752   fm.moveCaretToFocus(null);
   754   // ---- tests for the FLAG_NOSWITCHFRAME flag
   755   getById("o5").focus();
   756   gLastFocusMethod = 0;
   757   gEvents = "";
   758   // focus is being shifted in a child, so the focus should not change
   759   expectFocusShift(function () fm.setFocus(getById("t20"), fm.FLAG_NOSWITCHFRAME),
   760                    window, getById("o5"), false, "no switch frame focus to child");
   761   setFocusTo("t20", gChildWindow);
   763   // here, however, focus is being shifted in a parent, which will have to blur
   764   // the child, so the focus will always change
   765   expectFocusShift(function () fm.setFocus(getById("o5"), fm.FLAG_NOSWITCHFRAME),
   766                    window, getById("o5"), true, "no switch frame focus to parent");
   768   expectFocusShift(function () fm.setFocus(getById("t1"), fm.FLAG_NOSWITCHFRAME),
   769                    window, getById("t1"), true, "no switch frame focus to same window");
   771   // ---- tests for focus and scrolling into view ----
   772   var inscroll = getById("inscroll");
   773   inscroll.tabIndex = 0;
   774   is(inscroll.parentNode.scrollTop, 0, "scroll position before focus");
   775   inscroll.focus();
   776   ok(inscroll.parentNode.scrollTop > 5, "scroll position after focus");
   777   inscroll.parentNode.scrollTop = 0;
   778   fm.setFocus(inscroll, fm.FLAG_NOSCROLL);
   779   is(inscroll.parentNode.scrollTop, 0, "scroll position after noscroll focus");
   781   getById("t9").focus();
   782   getById("inpopup1").focus();
   783   is(fm.focusedElement, getById("t9"), "focus in closed popup");
   785   // ---- tests to check if tabbing out of a textbox works
   787   setFocusTo("t1", window);
   789   var textbox1 = document.createElement("textbox");
   790   $("innerbox").appendChild(textbox1);
   792   var textbox2 = document.createElement("textbox");
   793   $("innerbox").appendChild(textbox2);
   795   gLastFocusMethod = 0;
   796   expectFocusShift(function () textbox2.focus(),
   797                    null, textbox2.inputField, true, "focus on textbox");
   798   gLastFocusMethod = fm.FLAG_BYKEY;
   799   expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
   800                    null, textbox1.inputField, true, "shift+tab on textbox");
   802   textbox1.tabIndex = 2;
   803   textbox2.tabIndex = 2;
   804   gLastFocusMethod = 0;
   805   expectFocusShift(function () textbox2.focus(),
   806                    null, textbox2.inputField, true, "focus on textbox with tabindex set");
   807   gLastFocusMethod = fm.FLAG_BYKEY;
   808   expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
   809                    null, textbox1.inputField, true, "shift+tab on textbox with tabindex set");
   811   // ---- test for bug 618907 which ensures that canceling the mousedown event still focuses the
   812   //      right frame
   814   var childContentFrame = document.getElementById("ifa")
   815   childContentFrame.style.MozUserFocus = "";
   817   var frab = childContentFrame.contentDocument.getElementById("fra-b");
   818   var mouseDownListener = function(event) event.preventDefault();
   819   frab.addEventListener("mousedown", mouseDownListener, false);
   821   var childElementToFocus = childContentFrame.contentDocument.getElementById("fra");
   822   gLastFocus = childElementToFocus;
   823   gLastFocusWindow = childContentFrame.contentWindow;
   824   gLastFocus.focus();
   825   gEvents = "";
   827   setFocusTo("t1", window);
   829   gLastFocusMethod = -1;
   830   expectFocusShift(function () synthesizeMouse(frab, 5, 5, { }, childContentFrame.contentWindow),
   831                    null, childElementToFocus, true,
   832                    "mousedown event canceled - chrome to content");
   834   frab.removeEventListener("mousedown", mouseDownListener, false);
   836   var t5 = getById("t5");
   837   t5.addEventListener("mousedown", mouseDownListener, false);
   838   synthesizeMouse(t5, 10, 10, { })
   839   t5.removeEventListener("mousedown", mouseDownListener, false);
   840   is(fm.focusedElement, childElementToFocus,
   841      "mousedown event cancelled - content to chrome - element");
   842   is(fm.focusedWindow, childContentFrame.contentWindow, "mousedown event cancelled - content to chrome - window");
   844   // ---- test to check that refocusing an element during a blur event doesn't succeed
   846   var t1 = getById("t1");
   847   t1.addEventListener("blur", function() t1.focus(), true);
   848   t1.focus();
   849   var t3 = getById("t3");
   850   synthesizeMouse(t3, 2, 2, { });
   851   is(fm.focusedElement, t3, "focus during blur");
   853   setFocusTo("t9", window);
   854   gLastFocusMethod = -1;
   855   window.openDialog("focus_window2.xul", "_blank", "chrome", otherWindowFocused);
   856 }
   858 function doCommandDispatcherTests()
   859 {
   860   var t19 = getById("t19");
   861   t19.focus();
   862   gLastFocusWindow = gChildWindow;
   863   gLastFocus = t19;
   864   gEvents = "";
   866   expectFocusShift(function () document.commandDispatcher.focusedElement = getById("o9"),
   867                    null, getById("o9"), true, "command dispatcher set focusedElement");
   868   expectFocusShift(function () document.commandDispatcher.advanceFocus(),
   869                    null, getById("o13"), true, "command dispatcher advanceFocus");
   870   expectFocusShift(function () document.commandDispatcher.rewindFocus(),
   871                    null, getById("o9"), true, "command dispatcher rewindFocus");
   872   expectFocusShift(function () document.commandDispatcher.focusedElement = null,
   873                    null, null, true, "command dispatcher set focusedElement to null");
   874   expectFocusShift(function () document.commandDispatcher.focusedWindow = gChildWindow,
   875                    null, getById("t19"), true, "command dispatcher set focusedElement to null");
   876   expectFocusShift(function () document.commandDispatcher.focusedElement = null,
   877                    gChildWindow, null, true, "command dispatcher set focusedElement to null in child");
   878   expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(getById("t19")),
   879                    null, getById("t20"), true, "command dispatcher advanceFocusIntoSubtree child");
   880   expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(null),
   881                    null, getById("t21"), true, "command dispatcher advanceFocusIntoSubtree null child");
   882   expectFocusShift(function () document.commandDispatcher.advanceFocusIntoSubtree(getById("o9").parentNode),
   883                    null, getById("o9"), true, "command dispatcher advanceFocusIntoSubtree parent");
   884 }
   886 function doRemoveTests()
   887 {
   888   // next, some tests which remove elements
   889   var t19 = getById("t19");
   890   t19.focus();
   891   t19.parentNode.removeChild(t19);
   893   is(fm.focusedElement, null, "removed element focusedElement");
   894   is(fm.focusedWindow, gChildWindow, "removed element focusedWindow");
   895   is(gChildWindow.document.hasFocus(), true, "removed element hasFocus");
   896   is(gChildWindow.document.activeElement, getById("inner-document"), "removed element activeElement");
   898   getById("t15").focus();
   899   var abs = getById("abs");
   900   abs.parentNode.removeChild(abs);
   902   is(fm.focusedElement, null, "removed ancestor focusedElement");
   903   is(fm.focusedWindow, gChildWindow, "removed ancestor focusedWindow");
   904   is(gChildWindow.document.hasFocus(), true, "removed ancestor hasFocus");
   905   is(gChildWindow.document.activeElement, getById("inner-document"), "removed ancestor activeElement");
   906 }
   908 // tests for the FocusManager moveFocus method
   909 function testMoveFocus()
   910 {
   911   setFocusTo("t6", window);
   913   // moving focus while an element is already focused
   914   var newFocus;
   915   gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
   916   var expectedFirst = getById(gPartialTabbing ? "t3" : "t1");
   917   expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0),
   918                    window, expectedFirst, true, "moveFocus to first null window null content");
   919   is(newFocus, fm.focusedElement, "moveFocus to first null window null content return value");
   921   expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_LAST, 0),
   922                    window, getById("last"), true, "moveFocus to last null window null content");
   923   is(newFocus, fm.focusedElement, "moveFocus to last null window null content return value");
   925   gLastFocusMethod = 0;
   926   newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0);
   927   is(newFocus, null, "moveFocus to root null window null content return value");
   928   is(fm.focusedWindow, window, "moveFocus to root null window null content focusedWindow");
   929   is(fm.focusedElement, null, "moveFocus to root null window null content focusedElement");
   931   // moving focus while no element is focused
   932   fm.clearFocus(window);
   933   gEvents = "";
   934   gLastFocus = null;
   935   gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
   936   expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0),
   937                    window, expectedFirst, true, "moveFocus to first null window null content no focus");
   938   is(newFocus, fm.focusedElement, "moveFocus to first null window null content no focus return value");
   939   fm.clearFocus(window);
   940   gEvents = "";
   941   gLastFocus = null;
   942   expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_LAST, 0),
   943                    window, getById("last"), true, "moveFocus to last null window null content no focus");
   944   is(newFocus, fm.focusedElement, "moveFocus to last null window null content no focus return value");
   945   fm.clearFocus(window);
   946   gEvents = "";
   947   gLastFocusMethod = 0;
   948   newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0);
   949   is(newFocus, null, "moveFocus to root null window null content no focus return value");
   950   is(fm.focusedWindow, window, "moveFocus to root null window null content no focus focusedWindow");
   951   is(fm.focusedElement, null, "moveFocus to root null window null content no focus focusedElement");
   953   // moving focus from a specified element
   954   setFocusTo("t6", window);
   955   gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
   956   expectFocusShift(function () newFocus = fm.moveFocus(null, getById("specialroot"), fm.MOVEFOCUS_FIRST, 0),
   957                    window, getById("t3"), true, "moveFocus to first null window with content");
   958 // XXXndeakin P3 this doesn't work
   959 //  expectFocusShift(function () newFocus = fm.moveFocus(null, getById("specialroot"), fm.MOVEFOCUS_LAST, 0),
   960 //                   window, getById("o3"), true, "moveFocus to last null window with content");
   962   // move focus to first in child window
   963   expectFocusShift(function () newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_FIRST, 0),
   964                    gChildWindow, getById("t" + (kChildDocumentRootIndex + 1)), true,
   965                    "moveFocus to first child window null content");
   966   is(newFocus, getById("t" + (kChildDocumentRootIndex + 1)),
   967      "moveFocus to first child window null content return value");
   969   // move focus to last in child window
   970   setFocusTo("t6", window);
   971   var expectedLast = getById(gPartialTabbing ? "t30" : "t" + (kBeforeTabboxIndex - 1));
   972   expectFocusShift(function () newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_LAST, 0),
   973                    gChildWindow, expectedLast, true,
   974                    "moveFocus to last child window null content");
   975   is(newFocus, getById(expectedLast),
   976      "moveFocus to last child window null content return value");
   978   // move focus to root in child window
   979   setFocusTo("t6", window);
   980   var childroot = getById("t" + kChildDocumentRootIndex);
   981   gLastFocusMethod = 0;
   982   newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_ROOT, 0),
   983   is(newFocus, childroot, "moveFocus to root child window null content return value");
   984   is(fm.focusedWindow, gChildWindow, "moveFocus to root child window null content focusedWindow");
   985   is(fm.focusedElement, childroot, "moveFocus to root child window null content focusedElement");
   987   // MOVEFOCUS_CARET tests
   988   getById("t20").focus();
   989   gEvents = "";
   991   var selection = gChildWindow.getSelection();
   992   selection.removeAllRanges();
   994   newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0);
   995   is(newFocus, null, "move caret when at document root");
   996   is(fm.focusedElement, null, "move caret when at document root");
   998   var node = getById("t16").firstChild;
   999   var range = gChildWindow.document.createRange();
  1000   range.setStart(node, 3);
  1001   range.setEnd(node, 3);
  1002   selection.addRange(range);
  1004   newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0);
  1005   is(newFocus, null, "move caret to non-link return value");
  1006   is(fm.focusedElement, null, "move caret to non-link");
  1008   var t25 = getById("t25");
  1009   var node = t25.firstChild;
  1010   range.setStart(node, 1);
  1011   range.setEnd(node, 1);
  1012   newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_CARET, 0);
  1014   is(newFocus, t25, "move caret to link return value");
  1015   is(fm.focusedElement, t25, "move caret to link focusedElement");
  1017   // enable caret browsing temporarily to test caret movement
  1018   var prefs = Components.classes["@mozilla.org/preferences-service;1"].
  1019                 getService(Components.interfaces.nsIPrefBranch);
  1020   prefs.setBoolPref("accessibility.browsewithcaret", true);
  1022   synthesizeKey("VK_LEFT", { }, gChildWindow);
  1023   synthesizeKey("VK_LEFT", { }, gChildWindow);
  1024   is(fm.focusedElement, null, "move caret away from link");
  1026   synthesizeKey("VK_LEFT", { }, gChildWindow);
  1027   is(fm.focusedElement, getById("t24"), "move caret away onto link");
  1029   prefs.setBoolPref("accessibility.browsewithcaret", false);
  1031   // cases where focus in on a content node with no frame
  1033   if (!gPartialTabbing) {
  1034     getById("t24").blur();
  1035     gEvents = "";
  1036     gLastFocus = null;
  1037     gLastFocusWindow = gChildWindow;
  1038     gLastFocusMethod = fm.FLAG_BYKEY;
  1040     selection.selectAllChildren(getById("hiddenspan"));
  1041     expectFocusShift(function () synthesizeKey("VK_TAB", { }),
  1042                      gChildWindow, getById("t26"), true, "tab with selection on hidden content");
  1044     setFocusTo($("o15"), window);
  1045     $("o15").hidden = true;
  1046     document.documentElement.getBoundingClientRect(); // flush after hiding
  1047     expectFocusShift(function () synthesizeKey("VK_TAB", { }),
  1048                      window, $("o17"), true, "tab with focus on hidden content");
  1050     $("o17").hidden = true;
  1051     document.documentElement.getBoundingClientRect();
  1052     expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
  1053                      window, $("o13"), true, "shift+tab with focus on hidden content");
  1056   // cases with selection in an <input>
  1058   var t19 = getById("t19");
  1059   t19.setSelectionRange(0, 0);
  1060   setFocusTo("t18", gChildWindow);
  1062   gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
  1063   expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, 0),
  1064                    gChildWindow, t19, true, "moveFocus to next textbox");
  1065   is(t19.selectionStart, 0, "input focused after moveFocus selectionStart");
  1066   is(t19.selectionEnd, 5, "input focused after moveFocus selectionEnd");
  1068   t19.setSelectionRange(0, 0);
  1069   setFocusTo("t18", gChildWindow);
  1070   gLastFocusMethod = fm.FLAG_BYKEY;
  1071   expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, fm.FLAG_BYKEY),
  1072                    gChildWindow, t19, true, "moveFocus to next textbox by key");
  1073   is(t19.selectionStart, 0, "input focused after moveFocus by key selectionStart");
  1074   is(t19.selectionEnd, 5, "input focused after moveFocus by key selectionEnd");
  1077 function otherWindowFocused(otherWindow)
  1079   var expectedElement = getById("t9");
  1081   is(fm.activeWindow, otherWindow, "other activeWindow");
  1082   is(fm.focusedWindow, otherWindow, "other focusedWindow");
  1083   is(window.document.hasFocus(), false, "when lowered document hasFocus");
  1084   var focusedWindow = {};
  1085   is(fm.getFocusedElementForWindow(window, false, focusedWindow),
  1086      expectedElement, "when lowered getFocusedElementForWindow");
  1087   is(focusedWindow.value, window, "when lowered getFocusedElementForWindow frame");
  1088   is(document.activeElement.id, expectedElement.id, "when lowered activeElement");
  1089   is(window.document.commandDispatcher.focusedWindow, window, " commandDispatcher in other window focusedWindow");
  1090   is(window.document.commandDispatcher.focusedElement, expectedElement, " commandDispatcher in other window focusedElement");
  1092   compareEvents("deactivate: outer-document-window blur: t9 blur: outer-document blur: outer-window",
  1093                 otherWindow, null, "other window opened");
  1095   otherWindow.document.getElementById("other").focus();
  1097   for (var idx = kTabbableSteps; idx >= 1; idx--) {
  1098     expectedElement = getById("t" + idx);
  1099     if (!expectedElement) // skip elements that were removed in doRemoveTests()
  1100       continue;
  1101     if ((navigator.platform.indexOf("Mac") == 0) && (idx == kBeforeTabboxIndex + 1))
  1102       continue;
  1104     expectedElement.focus();
  1106     is(fm.focusedElement.id, "other", "when lowered focusedElement t" + idx);
  1107     is(fm.focusedWindow, otherWindow, "when lowered focusedWindow t" + idx);
  1109     var checkWindow = expectedElement.ownerDocument.defaultView;
  1110     is(fm.getFocusedElementForWindow(checkWindow, false, {}).id, expectedElement.id,
  1111        "when lowered getFocusedElementForWindow t" + idx);
  1112     is(checkWindow.document.activeElement.id, expectedElement.id, "when lowered activeElement t" + idx);
  1113     if (checkWindow != window) {
  1114       is(fm.getFocusedElementForWindow(window, false, {}), $("childframe"),
  1115          "when lowered parent getFocusedElementForWindow t" + idx);
  1116       is(document.activeElement.id, "childframe",
  1117          "when lowered parent activeElement t" + idx);
  1121   gEvents = gEvents.replace(/commandupdate: cu\s?/g, "");
  1122   is(gEvents, "", "when lowered no events fired");
  1124   var other = otherWindow.document.getElementById("other");
  1125   other.focus();
  1126   is(fm.focusedElement, other, "focus method in second window");
  1128   otherWindow.close();
  1130   getById("n2").focus();
  1132   // next, check modal dialogs
  1133   // XXXndeakin Bug 621399 - the modal dialog test as well as later tests sometime fail
  1134   // on Windows 8 so just end the test here.
  1135   if (navigator.userAgent.indexOf("Windows NT 6.2") >= 0) {
  1136     done();
  1138   else {
  1139     window.openDialog("focus_window2.xul", "_blank", "chrome,modal", modalWindowOpened);
  1143 function modalWindowOpened(modalWindow)
  1145   var elem = modalWindow.document.getElementById("other");
  1146   if (gPartialTabbing)
  1147     elem.focus();
  1148   else
  1149     synthesizeKey("VK_TAB", { }, modalWindow);
  1150   is(fm.activeWindow, modalWindow, "modal activeWindow");
  1151   is(fm.focusedElement, elem, "modal focusedElement");
  1153   modalWindow.close();
  1154   SimpleTest.waitForFocus(modalWindowClosed);
  1157 function modalWindowClosed()
  1159   is(fm.activeWindow, window, "modal window closed activeWindow");
  1160   is(fm.focusedElement, getById("n2"), "modal window closed focusedElement");
  1162   window.open("focus_frameset.html", "_blank", "width=400,height=400,toolbar=no");
  1165 function framesetWindowLoaded(framesetWindow)
  1167   gLastFocus = null;
  1168   gLastFocusWindow = framesetWindow;
  1169   gEvents = "";
  1171   is(fm.activeWindow, getTopWindow(framesetWindow), "frameset window active");
  1172   gOldExpectedWindow = getTopWindow(framesetWindow);
  1174   gMoveToFocusFrame = true;
  1175   for (var idx = 1; idx <= 8; idx++) {
  1176     gNewExpectedWindow = framesetWindow.frames[(idx - 1) >> 1];
  1177     if (idx % 2)
  1178       initEvents(gNewExpectedWindow);
  1179     expectFocusShift(function () synthesizeKey("VK_TAB", { }, framesetWindow),
  1180                      gNewExpectedWindow, getById("f" + idx), true, "frameset tab key f" + idx);
  1181     gMoveToFocusFrame = false;
  1182     gOldExpectedWindow = gNewExpectedWindow;
  1185   gNewExpectedWindow = framesetWindow.frames[0];
  1186   expectFocusShift(function () synthesizeKey("VK_TAB", { }, framesetWindow),
  1187                    gNewExpectedWindow, getById("f1"), true, "frameset tab key wrap to start");
  1188   gOldExpectedWindow = gNewExpectedWindow;
  1189   gNewExpectedWindow = framesetWindow.frames[3];
  1190   expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }, framesetWindow),
  1191                    gNewExpectedWindow, getById("f8"), true, "frameset shift tab key wrap to end");
  1193   for (idx = 7; idx >= 1; idx--) {
  1194     gOldExpectedWindow = gNewExpectedWindow;
  1195     gNewExpectedWindow = framesetWindow.frames[(idx - 1) >> 1];
  1196     expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }, framesetWindow),
  1197                      gNewExpectedWindow, getById("f" + idx), true, "frameset shift tab key f" + idx);
  1200   // document shifting
  1201   // XXXndeakin P3 ctrl+tab doesn't seem to be testable currently for some reason
  1202   gNewExpectedWindow = framesetWindow.frames[1];
  1203   expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow),
  1204                    gNewExpectedWindow, getById("f3"), true, "switch document forward with f6");
  1205   gOldExpectedWindow = gNewExpectedWindow;
  1206   gNewExpectedWindow = framesetWindow.frames[2];
  1207   expectFocusShift(function () synthesizeKey("VK_F6", { }, framesetWindow),
  1208                    gNewExpectedWindow, getById("f5"), true, "switch document forward with ctrl+tab");
  1209   gOldExpectedWindow = gNewExpectedWindow;
  1210   gNewExpectedWindow = framesetWindow.frames[3];
  1211   expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow),
  1212                    gNewExpectedWindow, getById("f7"), true, "switch document forward with ctrl+f6");
  1213   gOldExpectedWindow = gNewExpectedWindow;
  1214   gNewExpectedWindow = framesetWindow.frames[0];
  1215   expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true }, framesetWindow),
  1216                    gNewExpectedWindow, getById("f1"), true, "switch document forward and wrap");
  1218 // going backwards by document and wrapping doesn't currently work, but didn't work
  1219 // before the focus reworking either
  1221 /*
  1222   gOldExpectedWindow = gNewExpectedWindow;
  1223   gNewExpectedWindow = framesetWindow.frames[3];
  1224   expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow),
  1225                    gNewExpectedWindow, getById("f7"), true, "switch document backward and wrap");
  1226  */
  1228   fm.moveFocus(framesetWindow.frames[3], null, fm.MOVEFOCUS_ROOT, 0);
  1229   gEvents = "";
  1231   gOldExpectedWindow = gNewExpectedWindow;
  1232   gNewExpectedWindow = framesetWindow.frames[2];
  1233   expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow),
  1234                    gNewExpectedWindow, getById("f5"), true, "switch document backward with f6");
  1235   gOldExpectedWindow = gNewExpectedWindow;
  1236   gNewExpectedWindow = framesetWindow.frames[1];
  1237   expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow),
  1238                    gNewExpectedWindow, getById("f3"), true, "switch document backward with ctrl+tab");
  1239   gOldExpectedWindow = gNewExpectedWindow;
  1240   gNewExpectedWindow = framesetWindow.frames[0];
  1241   expectFocusShift(function () synthesizeKey("VK_F6", { ctrlKey: true, shiftKey: true }, framesetWindow),
  1242                    gNewExpectedWindow, getById("f1"), true, "switch document backward with ctrl+f6");
  1244   // skip the window switching tests for now on Linux, as raising and lowering
  1245   // a window is asynchronous there
  1246   if (navigator.platform.indexOf("Linux") == -1) {
  1247     window.openDialog("focus_window2.xul", "_blank", "chrome", switchWindowTest, framesetWindow);
  1249   else {
  1250     gOldExpectedWindow = null;
  1251     gNewExpectedWindow = null;
  1252     framesetWindow.close();
  1253     SimpleTest.waitForFocus(doWindowNoRootTest);
  1257 // test switching between two windows
  1258 function switchWindowTest(otherWindow, framesetWindow)
  1260   initEvents(otherWindow);
  1261   var otherElement = otherWindow.document.getElementById("other");
  1262   otherElement.focus();
  1264   framesetWindow.frames[1].document.getElementById("f4").focus();
  1266   is(fm.focusedElement, otherElement, "focus after inactive window focus");
  1268   gLastFocus = otherElement;
  1269   gLastFocusWindow = otherWindow;
  1270   gEvents = "";
  1271   gOldExpectedWindow = otherWindow;
  1272   gNewExpectedWindow = framesetWindow.frames[1];
  1274   expectFocusShift(function () gNewExpectedWindow.focus(),
  1275                    gNewExpectedWindow, getById("f4"), true, "switch to frame in another window");
  1276   is(fm.getFocusedElementForWindow(otherWindow, false, {}).id, "other", "inactive window has focused element");
  1278   gOldExpectedWindow = framesetWindow.frames[1];
  1279   gNewExpectedWindow = otherWindow;
  1280   expectFocusShift(function () otherWindow.focus(),
  1281                    gNewExpectedWindow, getById("other"), true, "switch to another window");
  1283   var exh = false;
  1284   try {
  1285     fm.activeWindow = framesetWindow.frames[0];
  1287   catch (ex) { exh = true; }
  1288   is(exh, true, "activeWindow set to non top-level window");
  1290   exh = false;
  1291   try {
  1292     fm.activeWindow = null;
  1294   catch (ex) { exh = true; }
  1295   is(exh, true, "activeWindow set to null");
  1296   is(fm.activeWindow, otherWindow, "window not changed when activeWindow set to null");
  1298   var topWindow = getTopWindow(framesetWindow);
  1300   ok(topWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"),
  1301      "getControllerForCommand for focused window set");
  1302   ok(otherWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"),
  1303      "getControllerForCommand for non-focused window set");
  1304   ok(topWindow.document.commandDispatcher.getControllerForCommand("cmd_copy") !=
  1305      otherWindow.document.commandDispatcher.getControllerForCommand("cmd_copy"),
  1306      "getControllerForCommand for two windows different");
  1307   ok(topWindow.document.commandDispatcher.getControllers() !=
  1308      otherWindow.document.commandDispatcher.getControllers(),
  1309      "getControllers for two windows different");
  1311   gOldExpectedWindow = otherWindow;
  1312   gNewExpectedWindow = framesetWindow.frames[1];
  1313   expectFocusShift(function () fm.activeWindow = topWindow,
  1314                    gNewExpectedWindow, getById("f4"), true, "switch to frame activeWindow");
  1316   fm.clearFocus(otherWindow);
  1317   gOldExpectedWindow = gNewExpectedWindow;
  1318   gNewExpectedWindow = otherWindow;
  1319   expectFocusShift(function () fm.setFocus(otherElement, fm.FLAG_RAISE),
  1320                    gNewExpectedWindow, getById("other"), true, "switch to window with raise");
  1322   getTopWindow(framesetWindow).document.commandDispatcher.focusedWindow = gOldExpectedWindow;
  1323   is(fm.activeWindow, gNewExpectedWindow, "setting commandDispatcher focusedWindow doesn't raise window");
  1325   fm.moveFocus(otherWindow, null, fm.MOVEFOCUS_FORWARD, 0);
  1326   var otherTextbox = otherWindow.document.getElementById("other-textbox");
  1327   otherTextbox.setSelectionRange(2, 3);
  1328   fm.activeWindow = topWindow;
  1329   fm.activeWindow = otherWindow;
  1330   is(otherTextbox.selectionStart, 2, "selectionStart after textbox focus and window raise");
  1331   is(otherTextbox.selectionEnd, 3, "selectionEnd after textbox focus and window raise");
  1332   is(fm.getLastFocusMethod(null), fm.FLAG_BYMOVEFOCUS, "last focus method after textbox focus and window raise");
  1334   fm.clearFocus(otherWindow);
  1336   // test to ensure that a synthetic event works
  1337   var synevent = document.createEvent("Event");
  1338   synevent.initEvent("focus", false, false);
  1339   otherTextbox.inputField.dispatchEvent(synevent);
  1340   is(synevent.type, "focus", "event.type after synthetic focus event");
  1341   is(synevent.target, otherTextbox, "event.target after synthetic focus event");
  1342   is(fm.focusedElement, null, "focusedElement after synthetic focus event");
  1343   is(otherWindow.document.activeElement, otherWindow.document.documentElement,
  1344      "document.activeElement after synthetic focus event");
  1346   // check accessing a focus event after the event has finishing firing
  1347   function continueTest(event) {
  1348     is(event.type, "focus", "event.type after accessing focus event in timeout");
  1349     is(event.target, otherTextbox, "event.target after accessing focus event in timeout");
  1351     gOldExpectedWindow = null;
  1352     gNewExpectedWindow = null;
  1353     otherWindow.close();
  1354     framesetWindow.close();
  1356     SimpleTest.waitForFocus(doWindowNoRootTest);
  1359   function textboxFocused(event) {
  1360     otherTextbox.removeEventListener("focus", textboxFocused, true);
  1361     setTimeout(continueTest, 0, event);
  1364   otherTextbox.addEventListener("focus", textboxFocused, true);
  1365   otherTextbox.focus();
  1368 // open a window with no root element
  1369 var noRootWindow = null;
  1370 function doWindowNoRootTest()
  1372   var data = "data:application/vnd.mozilla.xul+xml," + unescape(
  1373              "<window onfocus='dostuff()' xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
  1374              "        style='-moz-user-focus: normal;'>" +
  1375              "<script>function dostuff() { setTimeout(function() { " +
  1376              "document.documentElement.focus(); document.removeChild(document.documentElement);" +
  1377              "window.opener.focus(); }, 100); }</script></window>");
  1379   addEventListener("focus", doFrameSwitchingTests, true);
  1380   noRootWindow = window.open(data, "_blank", "chrome,width=100,height=100");
  1383 // these tests check when focus is moved between a tree of frames to ensure
  1384 // that the focus is in the right place at each event step.
  1385 function doFrameSwitchingTests()
  1387   removeEventListener("focus", doFrameSwitchingTests, true);
  1388   noRootWindow.close();
  1390   var framea = document.getElementById("ifa");
  1391   var frameb = document.getElementById("ifb");
  1392   framea.style.MozUserFocus = "";
  1393   frameb.style.MozUserFocus = "";
  1395   window.removeEventListener("focus", eventOccured, true);
  1396   window.removeEventListener("blur", eventOccured, true);
  1398   var inputa = framea.contentDocument.body.firstChild;
  1399   inputa.focus();
  1401   addFrameSwitchingListeners(framea);
  1402   addFrameSwitchingListeners(frameb);
  1403   var framec = framea.contentDocument.body.lastChild;
  1404   addFrameSwitchingListeners(framec);
  1406   var framed = framec.contentDocument.body.lastChild;
  1407   addFrameSwitchingListeners(framed);
  1409   var inputc = framec.contentDocument.body.firstChild;
  1411   var expectedMainWindowFocus = framea;
  1413   // An element in the immediate parent frame is focused. Focus an element in
  1414   // the child. The child should be focused and the parent's current focus should
  1415   // be the child iframe.
  1416   gEventMatched = true;
  1417   is(fm.getFocusedElementForWindow(window, false, {}), expectedMainWindowFocus,
  1418      "parent of framea has iframe focused");
  1419   gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea],
  1420                      [framea.contentDocument, "blur", null, null, window, framea],
  1421                      [framea.contentWindow, "blur", null, null, window, framea],
  1422                      [framec.contentDocument, "focus", null, framec.contentWindow, window, framea],
  1423                      [framec.contentWindow, "focus", null, framec.contentWindow, window, framea],
  1424                      [inputc, "focus", inputc, framec.contentWindow, window, framea]];
  1425   inputc.focus();
  1426   ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from parent input to child input" + gExpectedEvents);
  1428   // An element in a child is focused. Focus an element in the immediate
  1429   // parent.
  1430   gEventMatched = true;
  1431   gExpectedEvents = [[inputc, "blur", null, framec.contentWindow, window, framea],
  1432                      [framec.contentDocument, "blur", null, null, window, framea],
  1433                      [framec.contentWindow, "blur", null, null, window, framea],
  1434                      [framea.contentDocument, "focus", null, framea.contentWindow, window, framea],
  1435                      [framea.contentWindow, "focus", null, framea.contentWindow, window, framea],
  1436                      [inputa, "focus", inputa, framea.contentWindow, window, framea]];
  1437   inputa.focus();
  1438   ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to parent input");
  1440   // An element in a frame is focused. Focus an element in a sibling frame.
  1441   // The common ancestor of the two frames should have its focused node
  1442   // cleared after the element is blurred.
  1443   var inputb = frameb.contentDocument.body.firstChild;
  1445   gEventMatched = true;
  1446   gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea],
  1447                      [framea.contentDocument, "blur", null, null, window, null],
  1448                      [framea.contentWindow, "blur", null, null, window, null],
  1449                      [frameb.contentDocument, "focus", null, frameb.contentWindow, window, frameb],
  1450                      [frameb.contentWindow, "focus", null, frameb.contentWindow, window, frameb],
  1451                      [inputb, "focus", inputb, frameb.contentWindow, window, frameb]];
  1452   inputb.focus();
  1453   ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from input to sibling frame");
  1454   is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), inputa, 
  1455      "blurred frame still has input as focus");
  1457   // focus a descendant in a sibling
  1458   var inputd = framed.contentDocument.body.firstChild;
  1459   gEventMatched = true;
  1460   gExpectedEvents = [[inputb, "blur", null, frameb.contentWindow, window, frameb],
  1461                      [frameb.contentDocument, "blur", null, null, window, null],
  1462                      [frameb.contentWindow, "blur", null, null, window, null],
  1463                      [framed.contentDocument, "focus", null, framed.contentWindow, window, framea],
  1464                      [framed.contentWindow, "focus", null, framed.contentWindow, window, framea],
  1465                      [inputd, "focus", inputd, framed.contentWindow, window, framea]];
  1466   inputd.focus();
  1467   ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from input to sibling descendant");
  1468   is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec,
  1469      "sibling parent focus has shifted to frame");
  1471   // focus an ancestor
  1472   gEventMatched = true;
  1473   gExpectedEvents = [[inputd, "blur", null, framed.contentWindow, window, framea],
  1474                      [framed.contentDocument, "blur", null, null, window, framea],
  1475                      [framed.contentWindow, "blur", null, null, window, framea],
  1476                      [framea.contentDocument, "focus", null, framea.contentWindow, window, framea],
  1477                      [framea.contentWindow, "focus", null, framea.contentWindow, window, framea],
  1478                      [inputa, "focus", inputa, framea.contentWindow, window, framea]];
  1479   inputa.focus();
  1480   ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to ancestor");
  1482   // focus a descendant
  1483   gEventMatched = true;
  1484   gExpectedEvents = [[inputa, "blur", null, framea.contentWindow, window, framea],
  1485                      [framea.contentDocument, "blur", null, null, window, framea],
  1486                      [framea.contentWindow, "blur", null, null, window, framea],
  1487                      [framed.contentDocument, "focus", null, framed.contentWindow, window, framea],
  1488                      [framed.contentWindow, "focus", null, framed.contentWindow, window, framea],
  1489                      [inputd, "focus", inputd, framed.contentWindow, window, framea]];
  1490   inputd.focus();
  1491   ok(gEventMatched && gExpectedEvents.length == 0, "frame switch from child input to ancestor");
  1492   is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec,
  1493      "parent focus has shifted to frame");
  1495   // focus a sibling frame by setting focusedWindow
  1496   gEventMatched = true;
  1497   gExpectedEvents = [[inputd, "blur", null, framed.contentWindow, window, framea],
  1498                      [framed.contentDocument, "blur", null, null, window, null],
  1499                      [framed.contentWindow, "blur", null, null, window, null],
  1500                      [frameb.contentDocument, "focus", null, frameb.contentWindow, window, frameb],
  1501                      [frameb.contentWindow, "focus", null, frameb.contentWindow, window, frameb],
  1502                      [inputb, "focus", inputb, frameb.contentWindow, window, frameb]];
  1503   fm.focusedWindow = frameb.contentWindow;
  1504   ok(gEventMatched && gExpectedEvents.length == 0, "frame switch using focusedWindow");
  1506   // clear the focus in an unfocused frame
  1507   gEventMatched = true;
  1508   gExpectedEvents = [];
  1509   fm.clearFocus(framec.contentWindow);
  1510   ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in unfocused frame");
  1512   // focus a sibling frame by setting focusedWindow when no element is focused in that frame
  1513   gEventMatched = true;
  1514   gExpectedEvents = [[inputb, "blur", null, frameb.contentWindow, window, frameb],
  1515                      [frameb.contentDocument, "blur", null, null, window, null],
  1516                      [frameb.contentWindow, "blur", null, null, window, null],
  1517                      [framec.contentDocument, "focus", null, framec.contentWindow, window, framea],
  1518                      [framec.contentWindow, "focus", null, framec.contentWindow, window, framea]];
  1519   fm.focusedWindow = framec.contentWindow;
  1520   ok(gEventMatched && gExpectedEvents.length == 0, "frame switch using focusedWindow with no element focused");
  1521   is(fm.getFocusedElementForWindow(framea.contentWindow, false, {}), framec,
  1522      "parent focus has shifted to frame using focusedWindow");
  1524   // focus the parent frame by setting focusedWindow. This should have no effect.
  1525   gEventMatched = true;
  1526   gExpectedEvents = [];
  1527   fm.focusedWindow = framea.contentWindow;
  1528   ok(gEventMatched && gExpectedEvents.length == 0, "frame switch to parent using focusedWindow");
  1530   // clear the focus in the parent frame
  1531   gEventMatched = true;
  1532   gExpectedEvents = [[framec.contentDocument, "blur", null, null, window, framea],
  1533                      [framec.contentWindow, "blur", null, null, window, framea],
  1534                      [framea.contentDocument, "focus", null, framea.contentWindow, window, framea],
  1535                      [framea.contentWindow, "focus", null, framea.contentWindow, window, framea]];
  1536   fm.clearFocus(framea.contentWindow);
  1537   ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in parent frame");
  1539   // clear the focus in an unfocused child frame
  1540   gEventMatched = true;
  1541   gExpectedEvents = [];
  1542   fm.clearFocus(framed.contentWindow);
  1543   ok(gEventMatched && gExpectedEvents.length == 0, "clearFocus in unfocused child frame");
  1545   var exh = false;
  1546   try {
  1547     fm.focusedWindow = null;
  1549   catch (ex) { exh = true; }
  1550   is(exh, true, "focusedWindow set to null");
  1551   is(fm.focusedWindow, framea.contentWindow, "window not changed when focusedWindow set to null");
  1553   doFrameHistoryTests()
  1556 function doFrameHistoryTests()
  1558   var t20 = getById("t20");
  1559   t20.focus();
  1561   gChildWindow.addEventListener("focus",
  1562     function(event) {
  1563       if (event.target == t20) {
  1564         is(fm.focusedElement, t20, "focus restored after history back"); done();
  1566   }, true);
  1568   // make sure that loading a new page and then going back maintains the focus
  1569   gChildWindow.location = "data:text/html,<script>window.onload=function() {setTimeout(function () {window.back();}, 0);}</script>";
  1572 function addFrameSwitchingListeners(frame)
  1574   frame.contentWindow.addEventListener("focus", frameSwitchingEventOccured, false);
  1575   frame.contentWindow.addEventListener("blur", frameSwitchingEventOccured, false);
  1576   frame.contentDocument.addEventListener("focus", frameSwitchingEventOccured, false);
  1577   frame.contentDocument.addEventListener("blur", frameSwitchingEventOccured, false);
  1579   var node = frame.contentDocument.body.firstChild;
  1580   node.addEventListener("focus", frameSwitchingEventOccured, false);
  1581   node.addEventListener("blur", frameSwitchingEventOccured, false);
  1584 function frameSwitchingEventOccured(event)
  1586   if (!gExpectedEvents.length) {
  1587     gEventMatched = false;
  1588     return;
  1591   try {
  1592     var events = gExpectedEvents.shift();
  1593     is(event.target, events[0], "event target");
  1594     is(event.type, events[1], "event type");
  1595     is(fm.focusedElement, events[2], "focused element");
  1596     is(fm.focusedWindow, events[3], "focused frame");
  1597     if (events[4])
  1598       is(fm.getFocusedElementForWindow(events[4], false, {}), events[5], "focused element in frame");
  1600     if (gEventMatched && event.target == events[0] && event.type == events[1] &&
  1601         fm.focusedElement == events[2] && fm.focusedWindow == events[3]) {
  1602       if (!events[4] || fm.getFocusedElementForWindow(events[4], false, {}) == events[5])
  1603         return;
  1605   } catch (ex) { ok(ex, "exception"); }
  1607   gEventMatched = false;
  1610 SimpleTest.waitForExplicitFinish();
  1611 SimpleTest.waitForFocus(startTest);
  1613 ]]>
  1614 </script>
  1616 <commandset id="cu"
  1617             commandupdater="true"
  1618             events="focus"
  1619             oncommandupdate="eventOccured(event)"/>
  1621 <!--
  1622  The elements with ids starting with t are focusable and in the taborder.
  1623  The elements with ids starting with o are:
  1624    odd numbered ids - focusable but not part of the tab order
  1625    even numbered ids - not focusable with -moz-user-focus: ignore or disabled
  1626  The elements with ids starting with n are:
  1627    odd numbered ids - not focusable with -moz-user-focus: none
  1628    even numbered ids - focusable but not part of the tab order
  1629  -->
  1630 <vbox id="buttonbox">
  1631 <hbox id="innerbox">
  1632   <button id="t4" accesskey="h" label="no tabindex"/>
  1633   <button id="o1" accesskey="i" label="tabindex = -1" tabindex="-1"/>
  1634   <listbox id="t5" label="tabindex = 0" tabindex="0" rows="1">
  1635     <listitem/>
  1636   </listbox>
  1637   <button id="t1" label="tabindex = 2" tabindex="2"/>
  1638 </hbox>
  1639 <hbox>
  1640   <button id="o2" accesskey="o" style="-moz-user-focus: ignore;" label="no tabindex"/>
  1641   <button id="o4" style="-moz-user-focus: ignore;" label="tabindex = -1" tabindex="-1"/>
  1642   <button id="t6" style="-moz-user-focus: ignore;" label="tabindex = 0" tabindex="0"/>
  1643   <button id="t2" style="-moz-user-focus: ignore;" label="tabindex = 2" tabindex="2"/>
  1644 </hbox>
  1645 <hbox id="specialroot">
  1646   <button id="t7" style="-moz-user-focus: normal;" label="no tabindex"/>
  1647   <button id="o3" style="-moz-user-focus: normal;" label="tabindex = -1" tabindex="-1"/>
  1648   <button id="t8" style="-moz-user-focus: normal;" label="tabindex = 0" tabindex="0"/>
  1649   <listbox id="t3" style="-moz-user-focus: normal;" label="tabindex = 2" tabindex="2" rows="1">
  1650     <listitem/>
  1651   </listbox>
  1652 </hbox>
  1653 <hbox>
  1654   <button accesskey="p" style="display: none;"/> <button accesskey="q" style="visibility: collapse;"/>
  1655   <button style="display: none;" tabindex="2"/> <button style="visibility: collapse;" tabindex="2"/>
  1656 </hbox>
  1657 <hbox>
  1658   <button id="o20" accesskey="s" label="no tabindex" disabled="true"/>
  1659   <button id="o22" label="tabindex = -1" tabindex="-1" disabled="true"/>
  1660   <button id="o24" label="tabindex = 0" tabindex="0" disabled="true"/>
  1661   <button id="o26" label="tabindex = 2" tabindex="2" disabled="true"/>
  1662 </hbox>
  1663 </vbox>
  1664 <vbox>
  1665 <hbox>
  1666   <dropmarker id="o6" value="no tabindex"/>
  1667   <dropmarker id="o8" value="tabindex = -1" tabindex="-1"/>
  1668   <dropmarker id="o10" value="tabindex = 0" tabindex="0"/>
  1669   <dropmarker id="o12" value="tabindex = 2" tabindex="2"/>
  1670   <dropmarker id="t9" accesskey="r" style="-moz-user-focus: normal;" value="no tabindex" />
  1671   <dropmarker id="t10" style="-moz-user-focus: normal;" value="tabindex = -1" tabindex="-1" />
  1672   <dropmarker id="t11" style="-moz-user-focus: normal;" value="tabindex = 0" tabindex="0" />
  1673   <dropmarker id="t12" style="-moz-user-focus: normal;" value="tabindex = 2" tabindex="2" />
  1674   <dropmarker id="o14" style="-moz-user-focus: ignore;" value="no tabindex"/>
  1675   <dropmarker id="o16" style="-moz-user-focus: ignore;" value="tabindex = -1" tabindex="-1"/>
  1676   <dropmarker id="n1" style="-moz-user-focus: none;" value="tabindex = 0" tabindex="0"/>
  1677   <dropmarker id="n3" style="-moz-user-focus: none;" value="tabindex = 2" tabindex="2"/>
  1678 </hbox>
  1679 </vbox>
  1680 <browser id="childframe" type="content" src="child_focus_frame.html" width="300" height="195"/>
  1681 <button id="t34"/>
  1682 <tabbox id="tabbox">
  1683   <tabs><tab id="t35" label="One"/><tab id="tab2" label="Two"/></tabs>
  1684   <tabpanels>
  1685     <tabpanel>
  1686       <checkbox id="t36"/>
  1687       <button id="t37"/>
  1688     </tabpanel>
  1689     <tabpanel>
  1690       <checkbox id="htab1"/>
  1691       <button id="nohtab2" tabindex="7"/>
  1692       <checkbox id="htab2" tabindex="0"/>
  1693     </tabpanel>
  1694   </tabpanels>
  1695 </tabbox>
  1696 <hbox>
  1697 <panel>
  1698   <button id="inpopup1" label="One"/>
  1699   <textbox label="Two"/>
  1700 </panel>
  1701 <description label="o" accesskey="v"/>
  1702 <button id="t38"/>
  1703 <!-- The 't' element tests end here so it doesn't matter that these elements are tabbable -->
  1704 <label id="aj" value="j" accesskey="j" control="o9"/>
  1705 <label id="ak" accesskey="k" control="n4">k</label>
  1706 <checkbox id="o5"/><checkbox id="o7"/><hbox><checkbox id="o9"/></hbox>
  1707 <checkbox id="o13"/><checkbox id="o15"/><checkbox id="o17"/><checkbox id="o19"/><checkbox id="o21"/><checkbox id="o23"/><checkbox id="o25"/>
  1708 <checkbox id="n2"/><checkbox id="n4"/>
  1709 <listbox id="last" width="20" rows="1"/>
  1711 <iframe id="ifa" width="40" height="60" style="-moz-user-focus: ignore;" type="content"
  1712         src="data:text/html,&lt;input id=fra size='2'&gt;&lt;input id='fra-b' size='2'&gt;
  1713         &lt;iframe src='data:text/html,&lt;input id=frc&gt;&lt;iframe src=&quot;data:text/html,&lt;input id=frd&gt;&quot;&gt;&lt;/iframe&gt;'&gt;&lt;/iframe&gt;"/>
  1714 <iframe id="ifb" width="20" height="20" style="-moz-user-focus: ignore;"
  1715         src="data:text/html,&lt;input id=frd&gt;&lt;/iframe&gt;"/>
  1717 </hbox>
  1718 </window>

mercurial