diff --git a/widget/src/mac/nsMenuBarX.cpp b/widget/src/mac/nsMenuBarX.cpp index 0b2bebfdbd26..c638088c3d65 100644 --- a/widget/src/mac/nsMenuBarX.cpp +++ b/widget/src/mac/nsMenuBarX.cpp @@ -78,7 +78,8 @@ static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID); NS_IMPL_ISUPPORTS5(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIDocumentObserver, nsIChangeManager, nsISupportsWeakReference) -static MenuRef gDefaultRootMenu = nsnull; +MenuRef nsMenuBarX::sAppleMenu; + // // nsMenuBarX constructor @@ -93,11 +94,6 @@ nsMenuBarX::nsMenuBarX() OSStatus status = ::CreateNewMenu(0, 0, &mRootMenu); NS_ASSERTION(status == noErr, "nsMenuBarX::nsMenuBarX: creation of root menu failed."); - - if (gDefaultRootMenu == nsnull) { - gDefaultRootMenu = ::AcquireRootMenu(); - NS_ASSERTION(gDefaultRootMenu != nsnull, "nsMenuBarX::nsMenuBarX: no default root menu!."); - } } // @@ -105,19 +101,16 @@ nsMenuBarX::nsMenuBarX() // nsMenuBarX::~nsMenuBarX() { - mMenusArray.Clear(); // release all menus + mMenusArray.Clear(); // release all menus - // make sure we unregister ourselves as a document observer - if ( mDocument ) { - nsCOMPtr observer ( do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)) ); - mDocument->RemoveObserver(observer); - } + // make sure we unregister ourselves as a document observer + if ( mDocument ) { + nsCOMPtr observer ( do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)) ); + mDocument->RemoveObserver(observer); + } - if (mRootMenu != NULL) { - NS_ASSERTION(gDefaultRootMenu != nsnull, "nsMenuBarX::~nsMenuBarX: no default root menu!."); - ::SetRootMenu(gDefaultRootMenu); - ::ReleaseMenu(mRootMenu); - } + if ( mRootMenu ) + ::ReleaseMenu(mRootMenu); } nsEventStatus @@ -255,7 +248,10 @@ nsMenuBarX::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWin mWebShellWeakRef = getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIWebShell*, aWebShell))); nsIDOMNode* aDOMNode = NS_STATIC_CAST(nsIDOMNode*, menubarNode); mMenuBarContent = do_QueryInterface(aDOMNode); // strong ref - + NS_ASSERTION ( mMenuBarContent, "No content specified for this menubar" ); + if ( !mMenuBarContent ) + return nsEventStatus_eIgnore; + Create(aParentWindow); nsCOMPtr webShell = do_QueryReferent(mWebShellWeakRef); @@ -354,45 +350,21 @@ NS_METHOD nsMenuBarX::AddMenu(nsIMenu * aMenu) // keep track of all added menus. mMenusArray.AppendElement(aMenu); // owner - if (mNumMenus == 0) - { - Str32 menuStr = { 1, kMenuAppleLogoFilledGlyph }; - MenuHandle appleMenu; - OSStatus s = ::CreateNewMenu(kAppleMenuID, 0, &appleMenu); - ::SetMenuTitle(appleMenu, menuStr); - - if (appleMenu) - { - // this code reads the "label" attribute from the with - // id="aboutName" and puts its label in the Apple Menu - nsAutoString label; - nsCOMPtr menu; - aMenu->GetMenuContent(getter_AddRefs(menu)); - if (menu) { - nsCOMPtr doc; - menu->GetDocument(*getter_AddRefs(doc)); - if (doc) { - nsCOMPtr domdoc ( do_QueryInterface(doc) ); - if ( domdoc ) { - nsCOMPtr aboutMenuItem; - domdoc->GetElementById(NS_LITERAL_STRING("aboutName"), getter_AddRefs(aboutMenuItem)); - if (aboutMenuItem) - aboutMenuItem->GetAttribute(NS_LITERAL_STRING("label"), label); - } - } - } - - CFStringRef labelRef = ::CFStringCreateWithCharacters(kCFAllocatorDefault, (UniChar*)label.get(), label.Length()); - ::InsertMenuItemTextWithCFString(appleMenu, labelRef, 1, 0, 0); - ::CFRelease(labelRef); - + if (mNumMenus == 0) { + // if apple menu hasn't been created, create it. + if ( !sAppleMenu ) { + nsresult rv = CreateAppleMenu(aMenu); + NS_ASSERTION ( NS_SUCCEEDED(rv), "Can't create Apple menu" ); + } + + // add shared Apple menu to our menubar + if ( sAppleMenu ) { // InsertMenuItem() is 1-based, so the apple/application menu needs to // be at index 1. |mNumMenus| will be incremented below, so the following menu (File) // won't overwrite the apple menu by reusing the ID. mNumMenus = 1; - ::AppendMenu(appleMenu, "\p-"); - ::InsertMenuItem(mRootMenu, menuStr, mNumMenus); - OSStatus status = ::SetMenuItemHierarchicalMenu(mRootMenu, mNumMenus, appleMenu); + ::InsertMenuItem(mRootMenu, "\pA", mNumMenus); + OSStatus status = ::SetMenuItemHierarchicalMenu(mRootMenu, 1, sAppleMenu); } } @@ -411,8 +383,7 @@ NS_METHOD nsMenuBarX::AddMenu(nsIMenu * aMenu) // we use it as an index of where to insert the next menu. mNumMenus++; - Str255 title; - ::InsertMenuItem(mRootMenu, ::GetMenuTitle(menuRef, title), mNumMenus); + ::InsertMenuItem(mRootMenu, "\pPlaceholder", mNumMenus); OSStatus status = ::SetMenuItemHierarchicalMenu(mRootMenu, mNumMenus, menuRef); NS_ASSERTION(status == noErr, "nsMenuBarX::AddMenu: SetMenuItemHierarchicalMenu failed."); } @@ -421,7 +392,53 @@ NS_METHOD nsMenuBarX::AddMenu(nsIMenu * aMenu) return NS_OK; } - + +// +// CreateAppleMenu +// +// build the Apple menu shared by all menu bars. +// +nsresult +nsMenuBarX :: CreateAppleMenu ( nsIMenu* inMenu ) +{ + Str32 menuStr = { 1, kMenuAppleLogoFilledGlyph }; + OSStatus s = ::CreateNewMenu(kAppleMenuID, 0, &sAppleMenu); + + if ( s == noErr && sAppleMenu ) { + ::SetMenuTitle(sAppleMenu, menuStr); + + // this code reads the "label" attribute from the with + // id="aboutName" and puts its label in the Apple Menu + nsAutoString label; + nsCOMPtr menu; + inMenu->GetMenuContent(getter_AddRefs(menu)); + if (menu) { + nsCOMPtr doc; + menu->GetDocument(*getter_AddRefs(doc)); + if (doc) { + nsCOMPtr domdoc ( do_QueryInterface(doc) ); + if ( domdoc ) { + nsCOMPtr aboutMenuItem; + domdoc->GetElementById(NS_LITERAL_STRING("aboutName"), getter_AddRefs(aboutMenuItem)); + if (aboutMenuItem) + aboutMenuItem->GetAttribute(NS_LITERAL_STRING("label"), label); + } + } + } + + CFStringRef labelRef = ::CFStringCreateWithCharacters(kCFAllocatorDefault, (UniChar*)label.get(), label.Length()); + if ( labelRef ) { + ::InsertMenuItemTextWithCFString(sAppleMenu, labelRef, 1, 0, 0); + ::CFRelease(labelRef); + } + + ::AppendMenu(sAppleMenu, "\p-"); + } + + return (s == noErr && sAppleMenu) ? NS_OK : NS_ERROR_FAILURE; +} + + //------------------------------------------------------------------------- NS_METHOD nsMenuBarX::GetMenuCount(PRUint32 &aCount) { @@ -449,6 +466,7 @@ NS_METHOD nsMenuBarX::InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu) NS_METHOD nsMenuBarX::RemoveMenu(const PRUint32 aCount) { mMenusArray.RemoveElementAt(aCount); + ::DeleteMenuItem(mRootMenu, aCount + 1); // MenuManager is 1-based ::DrawMenuBar(); return NS_OK; }