Bug 685191, don't fire an extra DOMMenuItemActive event when switching menus on a menubar, r=neil

This commit is contained in:
Neil Deakin 2013-01-11 15:21:48 -05:00
Родитель 0949ef2b93
Коммит 6869e9de64
5 изменённых файлов: 122 добавлений и 774 удалений

Просмотреть файл

@ -61,8 +61,11 @@ public:
// Non-interface helpers
void
SetStayActive(bool aStayActive) { mStayActive = aStayActive; }
// The 'stay active' flag is set when navigating from one top-level menu
// to another, to prevent the menubar from deactivating and submenus from
// firing extra DOMMenuItemActive events.
bool GetStayActive() { return mStayActive; }
void SetStayActive(bool aStayActive) { mStayActive = aStayActive; }
// Called when a menu on the menu bar is clicked on. Returns a menu if one
// needs to be closed.

Просмотреть файл

@ -577,6 +577,22 @@ nsMenuFrame::PopupClosed(bool aDeselectMenu)
// becoming active again.
nsMenuFrame *current = mMenuParent->GetCurrentMenuItem();
if (current) {
// However, if the menu is a descendant on a menubar, and the menubar
// has the 'stay active' flag set, it means that the menubar is switching
// to another toplevel menu entirely (for example from Edit to View), so
// don't fire the DOMMenuItemActive event or else we'll send extraneous
// events for submenus. nsMenuBarFrame::ChangeMenuItem has already deselected
// the old menu, so it doesn't need to happen again here, and the new
// menu can be selected right away.
nsIFrame* parent = current;
while (parent) {
nsMenuBarFrame* menubar = do_QueryFrame(parent);
if (menubar && menubar->GetStayActive())
return;
parent = parent->GetParent();
}
nsCOMPtr<nsIRunnable> event =
new nsMenuActivateEvent(current->GetContent(),
PresContext(), true);

Просмотреть файл

@ -49,15 +49,10 @@ MOCHITEST_CHROME_FILES = \
test_editor_currentURI.xul \
$(NULL)
ifeq (gtk2,$(MOZ_WIDGET_TOOLKIT))
MOCHITEST_FILES += test_menubar_gtk.xul \
window_menubar_gtk.xul
else
ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
MOCHITEST_FILES += test_menubar.xul \
window_menubar.xul
endif
endif
libs:: $(_CHROME_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)/../chrome

Просмотреть файл

@ -91,6 +91,30 @@ window.opener.SimpleTest.waitForFocus(function () {
startPopupTests(popupTests);
}, window);
// On Linux, the first menu opens when F10 is pressed, but on other platforms
// the menubar is focused but no menu is opened. This means that different events
// fire.
function pressF10Events()
{
return navigator.platform.indexOf("Linux") >= 0 ?
[ "DOMMenuBarActive menubar", "popupshowing filepopup", "DOMMenuItemActive item1", "popupshown filepopup"] :
[ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ];
}
function closeAfterF10Events(extraInactive)
{
if (navigator.platform.indexOf("Linux") >= 0) {
var events = [ "popuphiding filepopup", "popuphidden filepopup", "DOMMenuItemInactive item1",
"DOMMenuInactive filepopup", "DOMMenuBarInactive menubar",
"DOMMenuItemInactive filemenu" ];
if (extraInactive)
events.push("DOMMenuItemInactive filemenu");
return events;
}
return [ "DOMMenuBarInactive menubar", "DOMMenuItemInactive filemenu" ];
}
var popupTests = [
{
testname: "press on menu",
@ -251,7 +275,7 @@ var popupTests = [
// open the submenu with the enter key
testname: "open submenu with enter",
events: function() {
// on Windows, the disabled 'navigation' item can stll be highlihted
// on Windows, the disabled 'navigation' item can stll be highlighted
if (navigator.platform.indexOf("Win") == 0)
return [ "popupshowing toolbarpopup", "DOMMenuItemActive navigation",
"popupshown toolbarpopup" ];
@ -283,9 +307,56 @@ var popupTests = [
checkClosed("toolbar", testname);
},
},
{
// open the submenu with the enter key again
testname: "open submenu with enter again",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: function() {
// on Windows, the disabled 'navigation' item can stll be highlighted
if (navigator.platform.indexOf("Win") == 0)
return [ "popupshowing toolbarpopup", "DOMMenuItemActive navigation",
"popupshown toolbarpopup" ];
else
return [ "popupshowing toolbarpopup", "popupshown toolbarpopup" ];
},
test: function() { sendKey("ENTER"); },
result: function(testname) {
checkOpen("viewmenu", testname);
checkOpen("toolbar", testname);
},
},
{
// while a submenu is open, switch to the next toplevel menu with the cursor right key
testname: "while a submenu is open, switch to the next menu with the cursor right",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "DOMMenuItemInactive viewmenu", "DOMMenuItemActive helpmenu",
"popuphiding toolbarpopup", "popuphidden toolbarpopup",
"popuphiding viewpopup", "popuphidden viewpopup",
"popupshowing helppopup", "DOMMenuItemInactive navigation",
"DOMMenuInactive toolbarpopup", "DOMMenuItemInactive toolbar",
"DOMMenuInactive viewpopup", "DOMMenuItemActive contents",
"popupshown helppopup" ],
test: function() { sendKey("RIGHT"); },
result: function(testname) {
checkOpen("helpmenu", testname);
checkClosed("toolbar", testname);
checkClosed("viewmenu", testname);
}
},
{
// close the main menu with the escape key
testname: "close menubar menu with escape",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "popuphiding helppopup", "popuphidden helppopup",
"DOMMenuItemInactive contents", "DOMMenuInactive helppopup",
"DOMMenuBarInactive menubar", "DOMMenuItemInactive helpmenu" ],
test: function() { sendKey("ESCAPE"); },
result: function(testname) { checkClosed("viewmenu", testname); },
},
{
// close the main menu with the escape key
testname: "close menubar menu with escape",
condition: function() { return (navigator.platform.indexOf("Win") != 0) },
events: [ "popuphiding viewpopup", "popuphidden viewpopup",
"DOMMenuItemInactive toolbar", "DOMMenuInactive viewpopup",
"DOMMenuBarInactive menubar",
@ -407,25 +478,37 @@ var popupTests = [
result: function(testname) { checkClosed("helpmenu", testname); }
},
{
// pressing F10 should highlight the first menu but not open it
// pressing F10 should highlight the first menu. On Linux, the menu is opened.
testname: "F10 to activate menubar",
events: [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ],
events: pressF10Events(),
test: function() { sendKey("F10"); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, true, testname + " openedWithKey");
checkClosed("filemenu", testname);
if (navigator.platform.indexOf("Linux") >= 0)
checkOpen("filemenu", testname);
else
checkClosed("filemenu", testname);
},
},
{
// pressing cursor down should open a menu
// pressing cursor left then down should open a menu
testname: "cursor down on menu",
events: [
"popupshowing helppopup",
"DOMMenuItemInactive filemenu", "DOMMenuItemActive helpmenu",
// This is in a different order than the
// "accelerator on active menubar" because menus opened from a
// shortcut key are fired asynchronously
"DOMMenuItemActive contents", "popupshown helppopup" ],
events: (navigator.platform.indexOf("Linux") >= 0) ?
[ "DOMMenuItemInactive filemenu", "DOMMenuItemActive helpmenu",
// This is in a different order than the
// "accelerator on active menubar" because menus opened from a
// shortcut key are fired asynchronously
"popuphiding filepopup", "popuphidden filepopup",
"popupshowing helppopup", "DOMMenuItemInactive item1",
"DOMMenuItemActive item2", "DOMMenuItemInactive item2",
"DOMMenuInactive filepopup", "DOMMenuItemActive contents",
"popupshown helppopup" ] :
[ "popupshowing helppopup", "DOMMenuItemInactive filemenu",
"DOMMenuItemActive helpmenu",
// This is in a different order than the
// "accelerator on active menubar" because menus opened from a
// shortcut key are fired asynchronously
"DOMMenuItemActive contents", "popupshown helppopup" ],
test: function() { sendKey("LEFT"); sendKey("DOWN"); },
result: function(testname) {
is(document.getElementById("helpmenu").openedWithKey, true, testname + " openedWithKey");
@ -576,12 +659,12 @@ var popupTests = [
},
{
testname: "F10 to activate menubar for tab deactivation",
events: [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ],
events: pressF10Events(true) ,
test: function() { sendKey("F10"); },
},
{
testname: "Deactivate menubar with tab key",
events: [ "DOMMenuBarInactive menubar", "DOMMenuItemInactive filemenu" ],
events: closeAfterF10Events(true),
test: function() { sendKey("TAB"); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
@ -589,12 +672,12 @@ var popupTests = [
},
{
testname: "F10 to activate menubar for escape deactivation",
events: [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ],
events: pressF10Events(),
test: function() { sendKey("F10"); },
},
{
testname: "Deactivate menubar with escape key",
events: [ "DOMMenuBarInactive menubar", "DOMMenuItemInactive filemenu" ],
events: closeAfterF10Events(false),
test: function() { sendKey("ESCAPE"); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
@ -602,12 +685,12 @@ var popupTests = [
},
{
testname: "F10 to activate menubar for f10 deactivation",
events: [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ],
events: pressF10Events(),
test: function() { sendKey("F10"); },
},
{
testname: "Deactivate menubar with f10 key",
events: [ "DOMMenuBarInactive menubar", "DOMMenuItemInactive filemenu" ],
events: closeAfterF10Events(true),
test: function() { sendKey("F10"); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");

Просмотреть файл

@ -1,749 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<!-- the condition in the focus event handler is because pressing Tab
unfocuses and refocuses the window on Windows -->
<window title="Popup Tests"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<title>Popup Tests</title>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript" src="popup_shared.js"></script>
<!--
Need to investigate these tests a bit more. Some of the accessibility events
are firing multiple times or in different orders in different circumstances.
Note that this was also the case before bug 279703.
-->
<hbox style="margin-left: 275px; margin-top: 275px;">
<menubar id="menubar">
<menu id="filemenu" label="File" accesskey="F">
<menupopup id="filepopup">
<menuitem id="item1" label="Open" accesskey="O"/>
<menuitem id="item2" label="Save" accesskey="S"/>
<menuitem id="item3" label="Close" accesskey="C"/>
</menupopup>
</menu>
<menu id="secretmenu" label="Secret Menu" accesskey="S" disabled="true">
<menupopup>
<menuitem label="Secret Command" accesskey="S"/>
</menupopup>
</menu>
<menu id="editmenu" label="Edit" accesskey="E">
<menupopup id="editpopup">
<menuitem id="cut" label="Cut" accesskey="t" disabled="true"/>
<menuitem id="copy" label="Copy" accesskey="C"/>
<menuitem id="paste" label="Paste" accesskey="P"/>
</menupopup>
</menu>
<menu id="viewmenu" label="View" accesskey="V">
<menupopup id="viewpopup">
<menu id="toolbar" label="Toolbar" accesskey="T">
<menupopup id="toolbarpopup">
<menuitem id="navigation" label="Navigation" accesskey="N" disabled="true"/>
<menuitem label="Bookmarks" accesskey="B" disabled="true"/>
</menupopup>
</menu>
<menuitem label="Status Bar" accesskey="S"/>
<menu label="Sidebar" accesskey="d">
<menupopup>
<menuitem label="Bookmarks" accesskey="B"/>
<menuitem label="History" accesskey="H"/>
</menupopup>
</menu>
</menupopup>
</menu>
<menu id="helpmenu" label="Help" accesskey="H">
<menupopup id="helppopup" >
<label value="Unselectable"/>
<menuitem id="contents" label="Contents" accesskey="C"/>
<menuitem label="More Info" accesskey="I"/>
<menuitem id="amenu" label="A Menu" accesskey="M"/>
<menuitem label="Another Menu"/>
<menuitem id="one" label="One"/>
<menu id="only" label="Only Menu">
<menupopup>
<menuitem label="Test Submenu"/>
</menupopup>
</menu>
<menuitem label="Second Menu"/>
<menuitem id="other" disabled="true" label="Other Menu"/>
<menuitem id="third" label="Third Menu"/>
<menuitem label="One Other Menu"/>
<label value="Unselectable"/>
<menuitem id="about" label="About" accesskey="A"/>
</menupopup>
</menu>
</menubar>
</hbox>
<script class="testbody" type="application/javascript">
<![CDATA[
window.opener.SimpleTest.waitForFocus(function () {
gFilePopup = document.getElementById("filepopup");
var filemenu = document.getElementById("filemenu");
filemenu.focus();
is(filemenu.openedWithKey, false, "initial openedWithKey");
startPopupTests(popupTests);
}, window);
var popupTests = [
{
testname: "press on menu",
events: [ "popupshowing filepopup", "DOMMenuBarActive menubar",
"DOMMenuItemActive filemenu", "popupshown filepopup" ],
test: function() { synthesizeMouse(document.getElementById("filemenu"), 8, 8, { }); },
result: function (testname) {
checkActive(gFilePopup, "", testname);
checkOpen("filemenu", testname);
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
// check that pressing cursor down while there is no selection
// highlights the first item
testname: "cursor down no selection",
events: [ "DOMMenuItemActive item1" ],
test: function() { sendKey("DOWN"); },
result: function(testname) { checkActive(gFilePopup, "item1", testname); }
},
{
// check that pressing cursor up wraps and highlights the last item
testname: "cursor up wrap",
events: [ "DOMMenuItemInactive item1", "DOMMenuItemActive item3" ],
test: function() { sendKey("UP"); },
result: function(testname) { checkActive(gFilePopup, "item3", testname); }
},
{
// check that pressing cursor down wraps and highlights the first item
testname: "cursor down wrap",
events: [ "DOMMenuItemInactive item3", "DOMMenuItemActive item1" ],
test: function() { sendKey("DOWN"); },
result: function(testname) { checkActive(gFilePopup, "item1", testname); }
},
{
// check that pressing cursor down highlights the second item
testname: "cursor down",
events: [ "DOMMenuItemInactive item1", "DOMMenuItemActive item2" ],
test: function() { sendKey("DOWN"); },
result: function(testname) { checkActive(gFilePopup, "item2", testname); }
},
{
// check that pressing cursor up highlights the second item
testname: "cursor up",
events: [ "DOMMenuItemInactive item2", "DOMMenuItemActive item1" ],
test: function() { sendKey("UP"); },
result: function(testname) { checkActive(gFilePopup, "item1", testname); }
},
{
// cursor right should skip the disabled menu and move to the edit menu
testname: "cursor right skip disabled",
events: function() {
var elist = [
// the file menu gets deactivated, the file menu gets hidden, then
// the edit menu is activated
"DOMMenuItemInactive filemenu", "DOMMenuItemActive editmenu",
"popuphiding filepopup", "popuphidden filepopup",
// the popupshowing event gets fired when showing the edit menu.
// The item from the file menu doesn't get deactivated until the
// next item needs to be selected
"popupshowing editpopup", "DOMMenuItemInactive item1",
// not sure why the menu inactivated event is firing so late
"DOMMenuInactive filepopup"
];
// finally, the first item is activated and popupshown is fired.
// On Windows, don't skip disabled items.
if (navigator.platform.indexOf("Win") == 0)
elist.push("DOMMenuItemActive cut");
else
elist.push("DOMMenuItemActive copy");
elist.push("popupshown editpopup");
return elist;
},
test: function() { sendKey("RIGHT"); },
result: function(testname) {
var expected = (navigator.platform.indexOf("Win") == 0) ? "cut" : "copy";
checkActive(document.getElementById("editpopup"), expected, testname);
checkClosed("filemenu", testname);
checkOpen("editmenu", testname);
is(document.getElementById("editmenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
// on Windows, a disabled item is selected, so pressing ENTER should close
// the menu but not fire a command event
testname: "enter on disabled",
events: function() {
if (navigator.platform.indexOf("Win") == 0)
return [ "popuphiding editpopup", "popuphidden editpopup",
"DOMMenuItemInactive cut", "DOMMenuInactive editpopup",
"DOMMenuBarInactive menubar",
"DOMMenuItemInactive editmenu", "DOMMenuItemInactive editmenu" ];
else
return [ "DOMMenuItemInactive copy", "DOMMenuInactive editpopup",
"DOMMenuBarInactive menubar",
"DOMMenuItemInactive editmenu", "DOMMenuItemInactive editmenu",
"command copy", "popuphiding editpopup", "popuphidden editpopup",
"DOMMenuItemInactive copy" ];
},
test: function() { sendKey("ENTER"); },
result: function(testname) {
checkClosed("editmenu", testname);
is(document.getElementById("editmenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
// pressing Alt + a key should open the corresponding menu
testname: "open with accelerator",
events: function() {
return [ "DOMMenuBarActive menubar",
"popupshowing viewpopup", "DOMMenuItemActive viewmenu",
"DOMMenuItemActive toolbar", "popupshown viewpopup" ];
},
test: function() { synthesizeKey("V", { altKey: true }); },
result: function(testname) {
checkOpen("viewmenu", testname);
is(document.getElementById("viewmenu").openedWithKey, true, testname + " openedWithKey");
}
},
{
// open the submenu with the cursor right key
testname: "open submenu with cursor right",
events: function() {
// on Windows, the disabled 'navigation' item can stll be highlihted
if (navigator.platform.indexOf("Win") == 0)
return [ "popupshowing toolbarpopup", "DOMMenuItemActive navigation",
"popupshown toolbarpopup" ];
else
return [ "popupshowing toolbarpopup", "popupshown toolbarpopup" ];
},
test: function() { sendKey("RIGHT"); },
result: function(testname) {
checkOpen("viewmenu", testname);
checkOpen("toolbar", testname);
}
},
{
// close the submenu with the cursor left key
testname: "close submenu with cursor left",
events: function() {
if (navigator.platform.indexOf("Win") == 0)
return [ "popuphiding toolbarpopup", "popuphidden toolbarpopup",
"DOMMenuItemInactive navigation", "DOMMenuInactive toolbarpopup",
"DOMMenuItemActive toolbar" ];
else
return [ "popuphiding toolbarpopup", "popuphidden toolbarpopup",
"DOMMenuInactive toolbarpopup",
"DOMMenuItemActive toolbar" ];
},
test: function() { sendKey("LEFT"); },
result: function(testname) {
checkOpen("viewmenu", testname);
checkClosed("toolbar", testname);
}
},
{
// open the submenu with the enter key
testname: "open submenu with enter",
events: function() {
// on Windows, the disabled 'navigation' item can stll be highlihted
if (navigator.platform.indexOf("Win") == 0)
return [ "popupshowing toolbarpopup", "DOMMenuItemActive navigation",
"popupshown toolbarpopup" ];
else
return [ "popupshowing toolbarpopup", "popupshown toolbarpopup" ];
},
test: function() { sendKey("ENTER"); },
result: function(testname) {
checkOpen("viewmenu", testname);
checkOpen("toolbar", testname);
},
},
{
// close the submenu with the escape key
testname: "close submenu with escape",
events: function() {
if (navigator.platform.indexOf("Win") == 0)
return [ "popuphiding toolbarpopup", "popuphidden toolbarpopup",
"DOMMenuItemInactive navigation", "DOMMenuInactive toolbarpopup",
"DOMMenuItemActive toolbar" ];
else
return [ "popuphiding toolbarpopup", "popuphidden toolbarpopup",
"DOMMenuInactive toolbarpopup",
"DOMMenuItemActive toolbar" ];
},
test: function() { sendKey("ESCAPE"); },
result: function(testname) {
checkOpen("viewmenu", testname);
checkClosed("toolbar", testname);
},
},
{
// close the main menu with the escape key
testname: "close menubar menu with escape",
events: [ "popuphiding viewpopup", "popuphidden viewpopup",
"DOMMenuItemInactive toolbar", "DOMMenuInactive viewpopup",
"DOMMenuBarInactive menubar",
"DOMMenuItemInactive viewmenu" ],
test: function() { sendKey("ESCAPE"); },
result: function(testname) { checkClosed("viewmenu", testname); },
},
{
// on Windows, pressing Alt should highlight the first menu but not open it,
// but it should be ignored if the alt keydown event is consumed.
testname: "alt shouldn't activate menubar if keydown event is consumed",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
test: function() {
document.addEventListener("keydown", function (aEvent) {
document.removeEventListener("keydown", arguments.callee, true);
aEvent.preventDefault();
}, true);
sendKey("ALT");
},
result: function(testname) {
ok(!document.getElementById("filemenu").openedWithKey, testname);
checkClosed("filemenu", testname);
},
},
{
// on Windows, pressing Alt should highlight the first menu but not open it,
// but it should be ignored if the alt keyup event is consumed.
testname: "alt shouldn't activate menubar if keyup event is consumed",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
test: function() {
document.addEventListener("keyup", function (aEvent) {
document.removeEventListener("keyup", arguments.callee, true);
aEvent.preventDefault();
}, true);
sendKey("ALT");
},
result: function(testname) {
ok(!document.getElementById("filemenu").openedWithKey, testname);
checkClosed("filemenu", testname);
},
},
{
// on Windows, pressing Alt should highlight the first menu but not open it
testname: "alt to activate menubar",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ],
test: function() { sendKey("ALT"); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, true, testname + " openedWithKey");
checkClosed("filemenu", testname);
},
},
{
// pressing cursor left should select the previous menu but not open it
testname: "cursor left on active menubar",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "DOMMenuItemInactive filemenu", "DOMMenuItemActive helpmenu" ],
test: function() { sendKey("LEFT"); },
result: function(testname) { checkClosed("helpmenu", testname); },
},
{
// pressing cursor right should select the previous menu but not open it
testname: "cursor right on active menubar",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "DOMMenuItemInactive helpmenu", "DOMMenuItemActive filemenu" ],
test: function() { sendKey("RIGHT"); },
result: function(testname) { checkClosed("filemenu", testname); },
},
{
// pressing a character should act as an accelerator and open the menu
testname: "accelerator on active menubar",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "popupshowing helppopup",
"DOMMenuItemInactive filemenu", "DOMMenuItemActive helpmenu",
"DOMMenuItemActive contents", "popupshown helppopup" ],
test: function() { sendChar("h"); },
result: function(testname) {
checkOpen("helpmenu", testname);
is(document.getElementById("helpmenu").openedWithKey, true, testname + " openedWithKey");
},
},
{
testname: "open with accelerator again",
condition: function() { return (navigator.platform.indexOf("Win") == -1) },
events: [ "DOMMenuBarActive menubar", "popupshowing helppopup",
"DOMMenuItemActive helpmenu", "DOMMenuItemActive contents",
"popupshown helppopup" ],
test: function() { synthesizeKey("H", { altKey: true }); },
result: function(testname) {
checkOpen("helpmenu", testname);
is(document.getElementById("helpmenu").openedWithKey, true, testname + " openedWithKey");
},
},
{
// check that pressing cursor up skips non menuitems
testname: "cursor up wrap",
events: [ "DOMMenuItemInactive contents", "DOMMenuItemActive about" ],
test: function() { sendKey("UP"); },
result: function(testname) { }
},
{
// check that pressing cursor down skips non menuitems
testname: "cursor down wrap",
events: [ "DOMMenuItemInactive about", "DOMMenuItemActive contents" ],
test: function() { sendKey("DOWN"); },
result: function(testname) { }
},
{
// check that pressing a menuitem's accelerator selects it
testname: "menuitem accelerator",
events: [ "DOMMenuItemInactive contents", "DOMMenuItemActive amenu",
"DOMMenuItemInactive amenu", "DOMMenuInactive helppopup",
"DOMMenuBarInactive menubar", "DOMMenuItemInactive helpmenu",
"DOMMenuItemInactive helpmenu",
"command amenu", "popuphiding helppopup", "popuphidden helppopup",
"DOMMenuItemInactive amenu",
],
test: function() { sendChar("m"); },
result: function(testname) { checkClosed("helpmenu", testname); }
},
{
// pressing F10 should highlight the first menu but not open it
testname: "F10 to activate menubar",
events: [ "DOMMenuBarActive menubar", "popupshowing filepopup", "DOMMenuItemActive item1", "popupshown filepopup" ],
test: function() { sendKey("F10"); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, true, testname + " openedWithKey");
checkOpen("filemenu", testname);
},
},
{
// pressing cursor down should open a menu
testname: "cursor down on menu",
events: [
"DOMMenuItemInactive filemenu", "DOMMenuItemActive helpmenu",
// This is in a different order than the
// "accelerator on active menubar" because menus opened from a
// shortcut key are fired asynchronously
"popuphiding filepopup",
"popuphidden filepopup",
"popupshowing helppopup",
"DOMMenuItemInactive item1",
"DOMMenuItemActive item2",
"DOMMenuItemInactive item2",
"DOMMenuInactive filepopup",
"DOMMenuItemActive contents",
"popupshown helppopup" ],
test: function() { sendKey("LEFT"); sendKey("DOWN"); },
result: function(testname) {
is(document.getElementById("helpmenu").openedWithKey, true, testname + " openedWithKey");
}
},
{
// pressing a letter that doesn't correspond to an accelerator. The menu
// should not close because there is more than one item corresponding to
// that letter
testname: "menuitem with no accelerator",
events: [ "DOMMenuItemInactive contents", "DOMMenuItemActive one" ],
test: function() { sendChar("o"); },
result: function(testname) { checkOpen("helpmenu", testname); }
},
{
// pressing the letter again should select the next one that starts with
// that letter
testname: "menuitem with no accelerator again",
events: [ "DOMMenuItemInactive one", "DOMMenuItemActive only" ],
test: function() { sendChar("o"); },
result: function(testname) {
// 'only' is a menu but it should not be open
checkOpen("helpmenu", testname);
checkClosed("only", testname);
}
},
{
// pressing the letter again when the next item is disabled should still
// select the disabled item
testname: "menuitem with no accelerator disabled",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "DOMMenuItemInactive only", "DOMMenuItemActive other" ],
test: function() { sendChar("o"); },
result: function(testname) { }
},
{
// when only one menuitem starting with that letter exists, it should be
// selected and the menu closed
testname: "menuitem with no accelerator single",
events: function() {
var elist = [ "DOMMenuItemInactive other", "DOMMenuItemActive third",
"DOMMenuItemInactive third", "DOMMenuInactive helppopup",
"DOMMenuBarInactive menubar",
"DOMMenuItemInactive helpmenu",
"DOMMenuItemInactive helpmenu",
"command third", "popuphiding helppopup",
"popuphidden helppopup", "DOMMenuItemInactive third",
];
if (navigator.platform.indexOf("Win") == -1)
elist[0] = "DOMMenuItemInactive only";
return elist;
},
test: function() { sendChar("t"); },
result: function(testname) { checkClosed("helpmenu", testname); }
},
{
// pressing F10 should highlight the first menu but not open it
testname: "F10 to activate menubar again",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "DOMMenuBarActive menubar", "popupshowing filepopup", "DOMMenuItemActive item1", "popupshown filepopup" ],
test: function() { sendKey("F10"); },
result: function(testname) { checkOpen("filemenu", testname); },
},
{
// pressing an accelerator for a disabled item should deactivate the menubar
testname: "accelerator for disabled menu",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "DOMMenuItemInactive filemenu", "DOMMenuBarInactive menubar" ],
test: function() { sendChar("s"); },
result: function(testname) {
checkClosed("secretmenu", testname);
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
},
},
{
testname: "press on disabled menu",
test: function() {
synthesizeMouse(document.getElementById("secretmenu"), 8, 8, { });
},
result: function (testname) {
checkClosed("secretmenu", testname);
}
},
{
testname: "press on second menu with shift",
events: [ "popupshowing editpopup", "DOMMenuBarActive menubar",
"DOMMenuItemActive editmenu", "popupshown editpopup" ],
test: function() {
synthesizeMouse(document.getElementById("editmenu"), 8, 8, { shiftKey : true });
},
result: function (testname) {
checkOpen("editmenu", testname);
checkActive(document.getElementById("menubar"), "editmenu", testname);
}
},
{
testname: "press on disabled menuitem",
test: function() {
synthesizeMouse(document.getElementById("cut"), 8, 8, { });
},
result: function (testname) {
checkOpen("editmenu", testname);
}
},
{
testname: "press on menuitem",
events: [ "DOMMenuInactive editpopup",
"DOMMenuBarInactive menubar",
"DOMMenuItemInactive editmenu",
"DOMMenuItemInactive editmenu",
"command copy", "popuphiding editpopup", "popuphidden editpopup",
"DOMMenuItemInactive copy",
],
test: function() {
synthesizeMouse(document.getElementById("copy"), 8, 8, { });
},
result: function (testname) {
checkClosed("editmenu", testname);
}
},
{
// this test ensures that the menu can still be opened by clicking after selecting
// a menuitem from the menu. See bug 399350.
testname: "press on menu after menuitem selected",
events: [ "popupshowing editpopup", "DOMMenuBarActive menubar",
"DOMMenuItemActive editmenu", "popupshown editpopup" ],
test: function() { synthesizeMouse(document.getElementById("editmenu"), 8, 8, { }); },
result: function (testname) {
checkActive(document.getElementById("editpopup"), "", testname);
checkOpen("editmenu", testname);
}
},
{ // try selecting a different command
testname: "press on menuitem again",
events: [ "DOMMenuInactive editpopup",
"DOMMenuBarInactive menubar",
"DOMMenuItemInactive editmenu",
"DOMMenuItemInactive editmenu",
"command paste", "popuphiding editpopup", "popuphidden editpopup",
"DOMMenuItemInactive paste",
],
test: function() {
synthesizeMouse(document.getElementById("paste"), 8, 8, { });
},
result: function (testname) {
checkClosed("editmenu", testname);
}
},
{
testname: "F10 to activate menubar for tab deactivation",
events: [ "DOMMenuBarActive menubar", "popupshowing filepopup", "DOMMenuItemActive item1", "popupshown filepopup"],
test: function() { sendKey("F10"); },
},
{
testname: "Deactivate menubar with tab key",
events: [ "popuphiding filepopup", "popuphidden filepopup", "DOMMenuItemInactive item1",
"DOMMenuInactive filepopup", "DOMMenuBarInactive menubar",
"DOMMenuItemInactive filemenu", "DOMMenuItemInactive filemenu"],
test: function() { sendKey("TAB"); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
testname: "F10 to activate menubar for escape deactivation",
events: [ "DOMMenuBarActive menubar", "popupshowing filepopup", "DOMMenuItemActive item1", "popupshown filepopup"],
test: function() { sendKey("F10"); },
},
{
testname: "Deactivate menubar with escape key",
events: [ "popuphiding filepopup", "popuphidden filepopup", "DOMMenuItemInactive item1",
"DOMMenuInactive filepopup", "DOMMenuBarInactive menubar",
"DOMMenuItemInactive filemenu"],
test: function() { sendKey("ESCAPE"); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
testname: "F10 to activate menubar for f10 deactivation",
events: [ "DOMMenuBarActive menubar", "popupshowing filepopup", "DOMMenuItemActive item1", "popupshown filepopup"],
test: function() { sendKey("F10"); },
},
{
testname: "Deactivate menubar with f10 key",
events: [ "popuphiding filepopup", "popuphidden filepopup", "DOMMenuItemInactive item1",
"DOMMenuInactive filepopup", "DOMMenuBarInactive menubar",
"DOMMenuItemInactive filemenu", "DOMMenuItemInactive filemenu"],
test: function() { sendKey("F10"); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
testname: "F10 to activate menubar for alt deactivation",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ],
test: function() { sendKey("F10"); },
},
{
testname: "Deactivate menubar with alt key",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "DOMMenuBarInactive menubar", "DOMMenuItemInactive filemenu" ],
test: function() { sendKey("ALT"); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
testname: "Don't activate menubar with mousedown during alt key auto-repeat",
test: function() {
synthesizeKey("VK_ALT", { type: "keydown" });
synthesizeMouse(document.getElementById("menubar"), 8, -30, { type: "mousedown", altKey: true });
synthesizeKey("VK_ALT", { type: "keydown" });
synthesizeMouse(document.getElementById("menubar"), 8, -30, { type: "mouseup", altKey: true });
synthesizeKey("VK_ALT", { type: "keydown" });
synthesizeKey("VK_ALT", { type: "keyup" });
},
result: function (testname) {
checkActive(document.getElementById("menubar"), "", testname);
}
},
// Fllowing 4 tests are a test of bug 616797, don't insert any new tests
// between them.
{
testname: "Open file menu by accelerator",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: function() {
return [ "DOMMenuBarActive menubar", "popupshowing filepopup",
"DOMMenuItemActive filemenu", "DOMMenuItemActive item1",
"popupshown filepopup" ];
},
test: function() {
synthesizeKey("VK_ALT", { type: "keydown" });
synthesizeKey("F", { altKey: true });
synthesizeKey("VK_ALT", { type: "keyup" });
}
},
{
testname: "Close file menu by click at outside of popup menu",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: function() {
return [ "popuphiding filepopup", "popuphidden filepopup",
"DOMMenuItemInactive item1", "DOMMenuInactive filepopup",
"DOMMenuBarInactive menubar", "DOMMenuItemInactive filemenu",
"DOMMenuItemInactive filemenu" ];
},
test: function() {
// XXX hidePopup() causes DOMMenuItemInactive event to be fired twice.
document.getElementById("filepopup").hidePopup();
}
},
{
testname: "Alt keydown set focus the menubar",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: function() {
return [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ];
},
test: function() {
sendKey("ALT");
},
result: function (testname) {
checkClosed("filemenu", testname);
}
},
{
testname: "unset focus the menubar",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: function() {
return [ "DOMMenuBarInactive menubar", "DOMMenuItemInactive filemenu" ];
},
test: function() {
sendKey("ALT");
}
},
// bug 625151
{
testname: "Alt key state before deactivating the window shouldn't prevent " +
"next Alt key handling",
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: function() {
return [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ];
},
test: function() {
synthesizeKey("VK_ALT", { type: "keydown" });
synthesizeKey("VK_TAB", { type: "keydown" }); // cancels the Alt key
var thisWindow = window;
var newWindow =
window.open("data:text/html,", "_blank", "width=100,height=100");
newWindow.addEventListener("focus", function () {
newWindow.removeEventListener("focus", arguments.callee, false);
thisWindow.addEventListener("focus", function () {
thisWindow.removeEventListener("focus", arguments.callee, false);
setTimeout(function () {
sendKey("ALT", thisWindow);
}, 0);
}, false);
newWindow.close();
thisWindow.focus();
// Note that our window dispatches a hacky key event if IMM is installed
// on the system during focus change only if Alt key is pressed.
synthesizeKey("`", { type: "keypress" }, thisWindow);
}, false);
}
}
];
]]>
</script>
</window>