Bug 607224, add property that specifies if a menu was opened via the keyboard, r=neil,a=blocking

This commit is contained in:
Neil Deakin 2011-01-04 12:24:51 -05:00
Родитель 20bd210d2f
Коммит 5829e48552
7 изменённых файлов: 94 добавлений и 10 удалений

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

@ -41,7 +41,7 @@
interface nsIDOMElement;
interface nsIDOMKeyEvent;
[scriptable, uuid(F5099746-5049-4e81-A03E-945D5110FEE2)]
[scriptable, uuid(3931F141-D640-48AB-A792-719D62CF1736)]
interface nsIMenuBoxObject : nsISupports
{
void openMenu(in boolean openFlag);
@ -49,6 +49,9 @@ interface nsIMenuBoxObject : nsISupports
attribute nsIDOMElement activeChild;
boolean handleKeyPress(in nsIDOMKeyEvent keyEvent);
// true if the menu or menubar was opened via a keypress.
readonly attribute boolean openedWithKey;
};
%{C++

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

@ -151,6 +151,7 @@ nsMenuBarFrame::SetActive(PRBool aActiveFlag)
InstallKeyboardNavigator();
}
else {
mActiveByKeyboard = PR_FALSE;
RemoveKeyboardNavigator();
}

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

@ -103,6 +103,9 @@ public:
// needs to be closed.
nsMenuFrame* ToggleMenuActiveState();
PRBool IsActiveByKeyboard() { return mActiveByKeyboard; }
void SetActiveByKeyboard() { mActiveByKeyboard = PR_TRUE; }
// indicate that a menu on the menubar was closed. Returns true if the caller
// may deselect the menuitem.
virtual PRBool MenuClosed();
@ -137,6 +140,10 @@ protected:
PRPackedBool mStayActive;
PRPackedBool mIsActive; // Whether or not the menu bar is active (a menu item is highlighted or shown).
// whether the menubar was made active via the keyboard.
PRPackedBool mActiveByKeyboard;
// The current menu that is active (highlighted), which may not be open. This will
// be null if no menu is active.
nsMenuFrame* mCurrentMenu;

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

@ -179,6 +179,9 @@ nsMenuBarListener::KeyUp(nsIDOMEvent* aKeyEvent)
{
// The access key was down and is now up, and no other
// keys were pressed in between.
if (!mMenuBarFrame->IsActive()) {
mMenuBarFrame->SetActiveByKeyboard();
}
ToggleMenuActiveState();
}
mAccessKeyDown = PR_FALSE;
@ -257,6 +260,7 @@ nsMenuBarListener::KeyPress(nsIDOMEvent* aKeyEvent)
// so, we'll know the menu got activated.
nsMenuFrame* result = mMenuBarFrame->FindMenuWithShortcut(keyEvent);
if (result) {
mMenuBarFrame->SetActiveByKeyboard();
mMenuBarFrame->SetActive(PR_TRUE);
result->OpenMenu(PR_TRUE);
@ -275,6 +279,7 @@ nsMenuBarListener::KeyPress(nsIDOMEvent* aKeyEvent)
if ((GetModifiers(keyEvent) & ~MODIFIER_CONTROL) == 0) {
// The F10 key just went down by itself or with ctrl pressed.
// In Windows, both of these activate the menu bar.
mMenuBarFrame->SetActiveByKeyboard();
ToggleMenuActiveState();
aKeyEvent->StopPropagation();

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

@ -41,6 +41,7 @@
#include "nsIFrame.h"
#include "nsGUIEvent.h"
#include "nsIDOMNSUIEvent.h"
#include "nsMenuBarFrame.h"
#include "nsMenuBarListener.h"
#include "nsMenuFrame.h"
#include "nsMenuPopupFrame.h"
@ -157,6 +158,28 @@ NS_IMETHODIMP nsMenuBoxObject::HandleKeyPress(nsIDOMKeyEvent* aKeyEvent, PRBool*
}
}
NS_IMETHODIMP
nsMenuBoxObject::GetOpenedWithKey(PRBool* aOpenedWithKey)
{
*aOpenedWithKey = PR_FALSE;
nsIFrame* frame = GetFrame(PR_FALSE);
if (!frame || frame->GetType() != nsGkAtoms::menuFrame)
return NS_OK;
frame = frame->GetParent();
while (frame) {
if (frame->GetType() == nsGkAtoms::menuBarFrame) {
*aOpenedWithKey = (static_cast<nsMenuBarFrame *>(frame))->IsActiveByKeyboard();
return NS_OK;
}
frame = frame->GetParent();
}
return NS_OK;
}
// Creation Routine ///////////////////////////////////////////////////////////////////////
nsresult

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

@ -85,7 +85,9 @@
window.opener.SimpleTest.waitForFocus(function () {
gFilePopup = document.getElementById("filepopup");
document.getElementById("filemenu").focus();
var filemenu = document.getElementById("filemenu");
filemenu.focus();
is(filemenu.openedWithKey, false, "initial openedWithKey");
startPopupTests(popupTests);
}, window);
@ -98,6 +100,7 @@ var popupTests = [
result: function (testname) {
checkActive(gFilePopup, "", testname);
checkOpen("filemenu", testname);
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
@ -168,6 +171,7 @@ var popupTests = [
checkActive(document.getElementById("editpopup"), expected, testname);
checkClosed("filemenu", testname);
checkOpen("editmenu", testname);
is(document.getElementById("editmenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
@ -188,7 +192,10 @@ var popupTests = [
"DOMMenuItemInactive copy" ];
},
test: function() { synthesizeKey("VK_ENTER", { }); },
result: function(testname) { checkClosed("editmenu", testname); }
result: function(testname) {
checkClosed("editmenu", testname);
is(document.getElementById("editmenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
// pressing Alt + a key should open the corresponding menu
@ -199,7 +206,10 @@ var popupTests = [
"DOMMenuItemActive toolbar", "popupshown viewpopup" ];
},
test: function() { synthesizeKey("V", { altKey: true }); },
result: function(testname) { checkOpen("viewmenu", testname); }
result: function(testname) {
checkOpen("viewmenu", testname);
is(document.getElementById("viewmenu").openedWithKey, true, testname + " openedWithKey");
}
},
{
// open the submenu with the cursor right key
@ -289,7 +299,10 @@ var popupTests = [
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ],
test: function() { synthesizeKey("VK_ALT", { }); },
result: function(testname) { checkClosed("filemenu", testname); },
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
@ -315,7 +328,10 @@ var popupTests = [
"DOMMenuItemInactive filemenu", "DOMMenuItemActive helpmenu",
"DOMMenuItemActive contents", "popupshown helppopup" ],
test: function() { synthesizeKey("H", { }); },
result: function(testname) { checkOpen("helpmenu", testname); },
result: function(testname) {
checkOpen("helpmenu", testname);
is(document.getElementById("helpmenu").openedWithKey, true, testname + " openedWithKey");
},
},
{
testname: "open with accelerator again",
@ -324,7 +340,10 @@ var popupTests = [
"DOMMenuItemActive helpmenu", "DOMMenuItemActive contents",
"popupshown helppopup" ],
test: function() { synthesizeKey("H", { altKey: true }); },
result: function(testname) { checkOpen("helpmenu", testname); },
result: function(testname) {
checkOpen("helpmenu", testname);
is(document.getElementById("helpmenu").openedWithKey, true, testname + " openedWithKey");
},
},
{
// check that pressing cursor up skips non menuitems
@ -358,7 +377,10 @@ var popupTests = [
testname: "F10 to activate menubar",
events: [ "DOMMenuBarActive menubar", "DOMMenuItemActive filemenu" ],
test: function() { synthesizeKey("VK_F10", { }); },
result: function(testname) { checkClosed("filemenu", testname); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, true, testname + " openedWithKey");
checkClosed("filemenu", testname);
},
},
{
// pressing cursor down should open a menu
@ -371,6 +393,9 @@ var popupTests = [
// shortcut key are fired asynchronously
"DOMMenuItemActive contents", "popupshown helppopup" ],
test: function() { synthesizeKey("VK_LEFT", { }); synthesizeKey("VK_DOWN", { }); },
result: function(testname) {
is(document.getElementById("helpmenu").openedWithKey, true, testname + " openedWithKey");
}
},
{
// pressing a letter that doesn't correspond to an accelerator. The menu
@ -436,7 +461,10 @@ var popupTests = [
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "DOMMenuItemInactive filemenu", "DOMMenuBarInactive menubar" ],
test: function() { synthesizeKey("S", { }); },
result: function(testname) { checkClosed("secretmenu", testname); },
result: function(testname) {
checkClosed("secretmenu", testname);
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
},
},
{
testname: "press on disabled menu",
@ -521,6 +549,9 @@ var popupTests = [
testname: "Deactivate menubar with tab key",
events: [ "DOMMenuBarInactive menubar", "DOMMenuItemInactive filemenu" ],
test: function() { synthesizeKey("VK_TAB", { }); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
testname: "F10 to activate menubar for escape deactivation",
@ -531,6 +562,9 @@ var popupTests = [
testname: "Deactivate menubar with escape key",
events: [ "DOMMenuBarInactive menubar", "DOMMenuItemInactive filemenu" ],
test: function() { synthesizeKey("VK_ESCAPE", { }); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
testname: "F10 to activate menubar for f10 deactivation",
@ -541,6 +575,9 @@ var popupTests = [
testname: "Deactivate menubar with f10 key",
events: [ "DOMMenuBarInactive menubar", "DOMMenuItemInactive filemenu" ],
test: function() { synthesizeKey("VK_F10", { }); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
testname: "F10 to activate menubar for alt deactivation",
@ -553,6 +590,9 @@ var popupTests = [
condition: function() { return (navigator.platform.indexOf("Win") == 0) },
events: [ "DOMMenuBarInactive menubar", "DOMMenuItemInactive filemenu" ],
test: function() { synthesizeKey("VK_ALT", { }); },
result: function(testname) {
is(document.getElementById("filemenu").openedWithKey, false, testname + " openedWithKey");
}
},
{
testname: "Don't activate menubar with mousedown during alt key auto-repeat",
@ -628,5 +668,4 @@ var popupTests = [
]]>
</script>
</window>

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

@ -60,6 +60,12 @@
]]></setter>
</property>
<property name="openedWithKey" readonly="true">
<getter><![CDATA[
return this.boxObject.QueryInterface(Components.interfaces.nsIMenuBoxObject).openedWithKey;
]]></getter>
</property>
<!-- nsIDOMXULContainerElement interface -->
<method name="appendItem">
<parameter name="aLabel"/>