diff --git a/layout/xul/base/src/nsMenuBarFrame.cpp b/layout/xul/base/src/nsMenuBarFrame.cpp index 8fc9f1d3c03..c3b34abc3f7 100644 --- a/layout/xul/base/src/nsMenuBarFrame.cpp +++ b/layout/xul/base/src/nsMenuBarFrame.cpp @@ -30,6 +30,14 @@ #include "nsIDOMEventReceiver.h" #include "nsXULAtoms.h" +// XXX Notes to self +// 1. The menu bar should get its own view, and it should capture all events when the ALT key +// goes down. +// +// 2. Collapsing the menu bar will destroy the frame. The menu bar will need to unregister its +// listeners when this happens. +// + // // NS_NewMenuBarFrame // @@ -139,15 +147,7 @@ nsMenuBarFrame::KeyboardNavigation(PRUint32 aDirection) GetNextMenuItem(mCurrentMenu, getter_AddRefs(nextItem)); else GetPreviousMenuItem(mCurrentMenu, getter_AddRefs(nextItem)); - if (mCurrentMenu == nextItem.get()) - return; - - // Unset the current child. - mCurrentMenu->UnsetAttribute(kNameSpaceID_None, nsXULAtoms::menuactive, PR_TRUE); - - // Set the new child. - nextItem->SetAttribute(kNameSpaceID_None, nsXULAtoms::menuactive, "true", PR_TRUE); - mCurrentMenu = nextItem; + SetCurrentMenuItem(nextItem); } } } @@ -251,3 +251,16 @@ nsMenuBarFrame::GetPreviousMenuItem(nsIContent* aStart, nsIContent** aResult) NS_IF_ADDREF(aStart); } +void nsMenuBarFrame::SetCurrentMenuItem(nsIContent* aMenuItem) +{ + if (mCurrentMenu == aMenuItem) + return; + + // Unset the current child. + mCurrentMenu->UnsetAttribute(kNameSpaceID_None, nsXULAtoms::menuactive, PR_TRUE); + + // Set the new child. + aMenuItem->SetAttribute(kNameSpaceID_None, nsXULAtoms::menuactive, "true", PR_TRUE); + mCurrentMenu = aMenuItem; +} + diff --git a/layout/xul/base/src/nsMenuBarFrame.h b/layout/xul/base/src/nsMenuBarFrame.h index db7ae916fcc..20507bb0dfe 100644 --- a/layout/xul/base/src/nsMenuBarFrame.h +++ b/layout/xul/base/src/nsMenuBarFrame.h @@ -51,6 +51,8 @@ public: void GetPreviousMenuItem(nsIContent* aStart, nsIContent** aResult); void KeyboardNavigation(PRUint32 aDirection); + void SetCurrentMenuItem(nsIContent* aMenuItem); + protected: nsMenuBarListener* mMenuBarListener; // The listener that tells us about key and mouse events. PRBool mIsActive; // Whether or not the menu bar is active (a menu item is highlighted or shown). diff --git a/layout/xul/base/src/nsMenuBarListener.cpp b/layout/xul/base/src/nsMenuBarListener.cpp index 09aa98b3ef7..11617ba63d0 100644 --- a/layout/xul/base/src/nsMenuBarListener.cpp +++ b/layout/xul/base/src/nsMenuBarListener.cpp @@ -133,6 +133,33 @@ nsMenuBarListener::HandleEvent(nsIDOMEvent* aEvent) nsresult nsMenuBarListener::MouseMove(nsIDOMEvent* aMouseEvent) { + if (mMenuBarFrame->IsActive()) { + // Make sure the active menu gets set properly. + // If we're over something then switch to it. + nsCOMPtr target; + aMouseEvent->GetTarget(getter_AddRefs(target)); + + nsCOMPtr current = do_QueryInterface(target); + nsCOMPtr menuBar; + mMenuBarFrame->GetContent(getter_AddRefs(menuBar)); + + while (current && (current.get() != menuBar)) { + // See if we're a menu item. + nsCOMPtr tag; + current->GetTag(*getter_AddRefs(tag)); + if (tag && (tag.get() == nsXULAtoms::xpmenu)) { + // We found a menu. + mMenuBarFrame->SetCurrentMenuItem(current); + break; + } + + // Get our parent. + nsCOMPtr parent; + current->GetParent(*getter_AddRefs(parent)); + current = parent.get(); + } + } + return NS_OK; // means I am NOT consuming event }