Bug 126189, pass modifiers on to command events in menus when enter was pressed, r=neil

This commit is contained in:
Neil Deakin 2011-04-13 13:53:24 -04:00
Родитель 2c8b7f99fd
Коммит 5fbfdbbb1c
8 изменённых файлов: 67 добавлений и 13 удалений

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

@ -414,13 +414,13 @@ nsMenuBarFrame::ChangeMenuItem(nsMenuFrame* aMenuItem,
}
nsMenuFrame*
nsMenuBarFrame::Enter()
nsMenuBarFrame::Enter(nsGUIEvent* aEvent)
{
if (!mCurrentMenu)
return nsnull;
if (mCurrentMenu->IsOpen())
return mCurrentMenu->Enter();
return mCurrentMenu->Enter(aEvent);
return mCurrentMenu;
}

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

@ -112,7 +112,7 @@ public:
// Called when Enter is pressed while the menubar is focused. If the current
// menu is open, let the child handle the key.
nsMenuFrame* Enter();
nsMenuFrame* Enter(nsGUIEvent* aEvent);
// Used to handle ALT+key combos
nsMenuFrame* FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent);

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

@ -832,7 +832,7 @@ nsMenuFrame::SetDebug(nsBoxLayoutState& aState, nsIFrame* aList, PRBool aDebug)
// In either case, do nothing if the item is disabled.
//
nsMenuFrame*
nsMenuFrame::Enter()
nsMenuFrame::Enter(nsGUIEvent *aEvent)
{
if (IsDisabled()) {
#ifdef XP_WIN
@ -853,7 +853,7 @@ nsMenuFrame::Enter()
if (!IsOpen()) {
// The enter key press applies to us.
if (!IsMenu() && mMenuParent)
Execute(0); // Execute our event handler
Execute(aEvent); // Execute our event handler
else
return this;
}

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

@ -174,7 +174,7 @@ public:
// one in its parent popup. This will carry out the command attached to
// the menuitem. If the menu should be opened, this frame will be returned,
// otherwise null will be returned.
nsMenuFrame* Enter();
nsMenuFrame* Enter(nsGUIEvent* aEvent);
virtual void SetParent(nsIFrame* aParent);

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

@ -1537,13 +1537,13 @@ nsMenuPopupFrame::ChangeMenuItem(nsMenuFrame* aMenuItem,
}
nsMenuFrame*
nsMenuPopupFrame::Enter()
nsMenuPopupFrame::Enter(nsGUIEvent* aEvent)
{
mIncrementalString.Truncate();
// Give it to the child.
if (mCurrentMenu)
return mCurrentMenu->Enter();
return mCurrentMenu->Enter(aEvent);
return nsnull;
}

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

@ -234,7 +234,7 @@ public:
// that menu, or null if no menu should be opened. Also, calling Enter will
// reset the current incremental search string, calculated in
// FindMenuWithShortcut.
nsMenuFrame* Enter();
nsMenuFrame* Enter(nsGUIEvent* aEvent);
nsPopupType PopupType() const { return mPopupType; }
PRBool IsMenu() { return mPopupType == ePopupTypeMenu; }

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

@ -1731,6 +1731,13 @@ nsXULPopupManager::CancelMenuTimer(nsMenuParent* aMenuParent)
}
}
static nsGUIEvent* DOMKeyEventToGUIEvent(nsIDOMEvent* aEvent)
{
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aEvent));
nsEvent* evt = privateEvent ? privateEvent->GetInternalNSEvent() : nsnull;
return (evt->eventStructType == NS_KEY_EVENT) ? static_cast<nsGUIEvent *>(evt) : nsnull;
}
PRBool
nsXULPopupManager::HandleShortcutNavigation(nsIDOMKeyEvent* aKeyEvent,
nsMenuPopupFrame* aFrame)
@ -1745,7 +1752,8 @@ nsXULPopupManager::HandleShortcutNavigation(nsIDOMKeyEvent* aKeyEvent,
if (result) {
aFrame->ChangeMenuItem(result, PR_FALSE);
if (action) {
nsMenuFrame* menuToOpen = result->Enter();
nsGUIEvent* evt = DOMKeyEventToGUIEvent(aKeyEvent);
nsMenuFrame* menuToOpen = result->Enter(evt);
if (menuToOpen) {
nsCOMPtr<nsIContent> content = menuToOpen->GetContent();
ShowMenu(content, PR_TRUE, PR_FALSE);
@ -2178,10 +2186,11 @@ nsXULPopupManager::KeyPress(nsIDOMEvent* aKeyEvent)
// Enter method will return a menu if one needs to be opened as a result.
nsMenuFrame* menuToOpen = nsnull;
nsMenuChainItem* item = GetTopVisibleMenu();
nsGUIEvent* evt = DOMKeyEventToGUIEvent(aKeyEvent);
if (item)
menuToOpen = item->Frame()->Enter();
menuToOpen = item->Frame()->Enter(evt);
else if (mActiveMenuBar)
menuToOpen = mActiveMenuBar->Enter();
menuToOpen = mActiveMenuBar->Enter(evt);
if (menuToOpen) {
nsCOMPtr<nsIContent> content = menuToOpen->GetContent();
ShowMenu(content, PR_TRUE, PR_FALSE);

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

@ -27,6 +27,7 @@
SimpleTest.waitForExplicitFinish();
var gShowPopup = false;
var gModifiers = 0;
var iswin = (navigator.platform.indexOf("Win") == 0);
@ -112,7 +113,7 @@ function differentPressed()
list.open = false;
SimpleTest.finish();
checkEnter();
}
function keyCheck(list, key, index, testname)
@ -122,6 +123,50 @@ function keyCheck(list, key, index, testname)
is(list.selectedItem, item, testname + " selectedItem");
}
function checkModifiers(event)
{
var expectedModifiers = (gModifiers == 1);
is(event.shiftKey, expectedModifiers, "shift key pressed");
is(event.ctrlKey, expectedModifiers, "ctrl key pressed");
is(event.altKey, expectedModifiers, "alt key pressed");
is(event.metaKey, expectedModifiers, "meta key pressed");
gModifiers++;
}
function checkEnter()
{
var list = $("list");
list.addEventListener("popuphidden", checkEnterWithModifiers, false);
list.addEventListener("command", checkModifiers, false);
list.open = true;
synthesizeKey("VK_ENTER", { });
}
function checkEnterWithModifiers()
{
is(gModifiers, 1, "modifiers checked when not set");
var list = $("list");
ok(!list.open, "list closed on enter press");
list.removeEventListener("popuphidden", checkEnterWithModifiers, false);
list.addEventListener("popuphidden", done, false);
list.open = true;
synthesizeKey("VK_ENTER", { shiftKey: true, ctrlKey: true, altKey: true, metaKey: true });
}
function done()
{
is(gModifiers, 2, "modifiers checked when set");
var list = $("list");
ok(!list.open, "list closed on enter press with modifiers");
list.removeEventListener("popuphidden", done, false);
SimpleTest.finish();
}
SimpleTest.waitForFocus(runTests);
]]>