diff --git a/editor/ui/composer/content/editorOverlay.xul b/editor/ui/composer/content/editorOverlay.xul index 75bba03bf587..94c7c09d6857 100644 --- a/editor/ui/composer/content/editorOverlay.xul +++ b/editor/ui/composer/content/editorOverlay.xul @@ -304,7 +304,6 @@ where "position" is assumed to be 14. Change that label if menu position changes. --> - @@ -341,7 +340,7 @@ - + diff --git a/mailnews/addrbook/resources/content/addressbook.xul b/mailnews/addrbook/resources/content/addressbook.xul index 0cf0e6d17c3c..31101fbba2a1 100644 --- a/mailnews/addrbook/resources/content/addressbook.xul +++ b/mailnews/addrbook/resources/content/addressbook.xul @@ -135,7 +135,6 @@ Rights Reserved. - @@ -149,7 +148,7 @@ Rights Reserved. accesskey="&cardPropertiesCmd.accesskey;" key="key_CardProperties" command="cmd_CardProperties"/> - + diff --git a/mailnews/base/resources/content/mailWindowOverlay.xul b/mailnews/base/resources/content/mailWindowOverlay.xul index f61ad462b2d5..293fe065eb6c 100644 --- a/mailnews/base/resources/content/mailWindowOverlay.xul +++ b/mailnews/base/resources/content/mailWindowOverlay.xul @@ -869,7 +869,6 @@ Rights Reserved. - diff --git a/mailnews/compose/resources/content/messengercompose.xul b/mailnews/compose/resources/content/messengercompose.xul index 27a6e8aec31b..3b4a6df110a5 100644 --- a/mailnews/compose/resources/content/messengercompose.xul +++ b/mailnews/compose/resources/content/messengercompose.xul @@ -208,7 +208,6 @@ - diff --git a/widget/src/mac/nsMenuBarX.cpp b/widget/src/mac/nsMenuBarX.cpp index c0ad17cc8dd2..2aaeedeee753 100644 --- a/widget/src/mac/nsMenuBarX.cpp +++ b/widget/src/mac/nsMenuBarX.cpp @@ -65,6 +65,7 @@ #include #include #include +#include #include "nsMacResources.h" #include "nsGUIEvent.h" @@ -77,7 +78,8 @@ static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID); NS_IMPL_ISUPPORTS5(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIDocumentObserver, nsIChangeManager, nsISupportsWeakReference) -MenuRef nsMenuBarX::sAppleMenu; +MenuRef nsMenuBarX::sAppleMenu = nsnull; +EventHandlerUPP nsMenuBarX::sCommandEventHandler = nsnull; // @@ -93,6 +95,10 @@ nsMenuBarX::nsMenuBarX() OSStatus status = ::CreateNewMenu(0, 0, &mRootMenu); NS_ASSERTION(status == noErr, "nsMenuBarX::nsMenuBarX: creation of root menu failed."); + + // create our global carbon event command handler shared by all windows + if ( !sCommandEventHandler ) + sCommandEventHandler = ::NewEventHandlerUPP(CommandEventHandler); } // @@ -240,6 +246,173 @@ nsMenuBarX :: RegisterAsDocumentObserver ( nsIWebShell* inWebShell ) } // RegisterAsDocumentObesrver +#if TARGET_CARBON + +// +// AquifyMenuBar +// +// Do what's necessary to conform to the Aqua guidelines for menus. Initially, this +// means removing 'Quit' from the file menu and 'Preferences' from the edit menu, along +// with their various separators (if present). +// +void +nsMenuBarX :: AquifyMenuBar ( ) +{ + nsCOMPtr containingDoc; + mMenuBarContent->GetDocument ( *getter_AddRefs(containingDoc) ); + nsCOMPtr domDoc ( do_QueryInterface(containingDoc) ); + if ( domDoc ) { + // remove quit item and its separator + HideItem ( domDoc, NS_LITERAL_STRING("menu_FileQuitSeparator"), nsnull ); + HideItem ( domDoc, NS_LITERAL_STRING("menu_FileQuitItem"), getter_AddRefs(mQuitItemContent) ); + + // remove prefs item and its separator, but save off the pref content node + // so we can invoke its command later. + HideItem ( domDoc, NS_LITERAL_STRING("menu_PrefsSeparator"), nsnull ); + HideItem ( domDoc, NS_LITERAL_STRING("menu_preferences"), getter_AddRefs(mPrefItemContent) ); + } + + // Install the command handler to deal with prefs/quit. We have to install it on the window because the + // menubar isn't in the event chain for a menu command event. Don't enable the prefs item + // just yet, wait until we actually find a pref node in the DOM. + WindowRef myWindow = NS_REINTERPRET_CAST(WindowRef, mParent->GetNativeData(NS_NATIVE_DISPLAY)); + NS_ASSERTION ( myWindow, "Can't get WindowRef to install command handler!" ); + if ( myWindow && sCommandEventHandler ) { + EventTypeSpec commandEventList[] = { {kEventClassCommand, kEventCommandProcess}, + {kEventClassCommand, kEventCommandUpdateStatus} }; + OSStatus err = ::InstallWindowEventHandler ( myWindow, sCommandEventHandler, 2, commandEventList, this, NULL ); + NS_ASSERTION ( err == noErr, "Uh oh, command handler not installed" ); + } + +} // AquifyMenuBar + + +// +// CommandEventHandler +// +// Processes Command carbon events from enabling/selecting of items in the menu. +// +// NOTE: eventually, all menu dispatching will go through this routine, for now, we only +// dispatch prefs and quit this way +// +pascal OSStatus +nsMenuBarX :: CommandEventHandler ( EventHandlerCallRef inHandlerChain, EventRef inEvent, void* userData ) +{ + OSStatus handled = eventNotHandledErr; + + HICommand command; + OSErr err1 = ::GetEventParameter ( inEvent, kEventParamDirectObject, typeHICommand, + NULL, sizeof(HICommand), NULL, &command ); + if ( err1 ) + return handled; + + nsMenuBarX* self = NS_REINTERPRET_CAST(nsMenuBarX*, userData); + switch ( ::GetEventKind(inEvent) ) { + // user selected a menu item. See if it's one we handle. + case kEventCommandProcess: + { + switch ( command.commandID ) { + case kHICommandPreferences: + { + nsEventStatus status = self->ExecuteCommand(self->mPrefItemContent); + if ( status == nsEventStatus_eConsumeNoDefault ) // event handled, no other processing + handled = noErr; + break; + } + + case kHICommandQuit: + { + nsEventStatus status = self->ExecuteCommand(self->mQuitItemContent); + if ( status == nsEventStatus_eConsumeNoDefault ) // event handled, no other processing + handled = noErr; + break; + } + +#if NOT_YET + case kHICommandAbout: + handled = noErr; + break; +#endif + } // switch on commandID + break; + } + + // enable/disable menu id's + case kEventCommandUpdateStatus: + { + // only enable the preferences item in the app menu if we found a pref + // item DOM node in this menubar. + if ( command.commandID == kHICommandPreferences ) { + if ( self->mPrefItemContent ) + ::EnableMenuCommand ( nsnull, kHICommandPreferences ); + else + ::DisableMenuCommand ( nsnull, kHICommandPreferences ); + handled = noErr; + } + break; + } + } // switch on event type + + return handled; + +} // CommandEventHandler + + +// +// ExecuteCommand +// +// Execute the menu item by sending a command message to the +// DOM node specified in |inDispatchTo|. +// +nsEventStatus +nsMenuBarX :: ExecuteCommand ( nsIContent* inDispatchTo ) +{ + nsEventStatus status = nsEventStatus_eIgnore; + if ( inDispatchTo ) { + nsCOMPtr webShell = do_QueryReferent(mWebShellWeakRef); + if (!webShell) + return nsEventStatus_eConsumeNoDefault; + nsCOMPtr presContext; + MenuHelpersX::WebShellToPresContext(webShell, getter_AddRefs(presContext)); + + nsMouseEvent event; + event.eventStructType = NS_MOUSE_EVENT; + event.message = NS_XUL_COMMAND; + + inDispatchTo->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); + } + + return status; +} // ExecuteCommand + + +// +// HideItem +// +// Hide the item in the menu by setting the 'hidden' attribute. Returns it in |outHiddenNode| so +// the caller can hang onto it if they so choose. It is acceptable to pass nsull +// for |outHiddenNode| if the caller doesn't care about the hidden node. +// +void +nsMenuBarX :: HideItem ( nsIDOMDocument* inDoc, nsAReadableString & inID, nsIContent** outHiddenNode ) +{ + nsCOMPtr menuItem; + inDoc->GetElementById(inID, getter_AddRefs(menuItem)); + nsCOMPtr menuContent ( do_QueryInterface(menuItem) ); + if ( menuContent ) { + menuContent->SetAttr ( kNameSpaceID_None, nsWidgetAtoms::hidden, NS_LITERAL_STRING("true"), PR_FALSE ); + if ( outHiddenNode ) { + *outHiddenNode = menuContent.get(); + NS_IF_ADDREF(*outHiddenNode); + } + } + +} // HideItem + + +#endif + + nsEventStatus nsMenuBarX::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow, void * menubarNode, void * aWebShell ) @@ -252,6 +425,15 @@ nsMenuBarX::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWin return nsEventStatus_eIgnore; Create(aParentWindow); + +#if TARGET_CARBON + // if we're on X (using aqua UI guidelines for menus), remove quit and prefs + // from our menubar. + SInt32 result = 0L; + OSStatus err = ::Gestalt ( gestaltMenuMgrAttr, &result ); + if ( !err && (result & gestaltMenuMgrAquaLayoutMask) ) + AquifyMenuBar(); +#endif nsCOMPtr webShell = do_QueryReferent(mWebShellWeakRef); if (webShell) RegisterAsDocumentObserver(webShell); diff --git a/widget/src/mac/nsMenuBarX.h b/widget/src/mac/nsMenuBarX.h index 348b5294d133..53b3f184c4c7 100644 --- a/widget/src/mac/nsMenuBarX.h +++ b/widget/src/mac/nsMenuBarX.h @@ -52,11 +52,13 @@ #include #include #include +#include extern nsWeakPtr gMacMenubarX; class nsIWidget; class nsIDocument; +class nsIDOMNode; namespace MenuHelpersX { @@ -169,6 +171,17 @@ protected: void GetDocument ( nsIWebShell* inWebShell, nsIDocument** outDocument ) ; void RegisterAsDocumentObserver ( nsIWebShell* inWebShell ) ; +#if TARGET_CARBON + // Make our menubar conform to Aqua UI guidelines + void AquifyMenuBar ( ) ; + void HideItem ( nsIDOMDocument* inDoc, nsAReadableString & inID, nsIContent** outHiddenNode ) ; + + // command handler for some special menu items (prefs/quit/etc) + pascal static OSStatus CommandEventHandler ( EventHandlerCallRef inHandlerChain, + EventRef inEvent, void* userData ) ; + nsEventStatus ExecuteCommand ( nsIContent* inDispatchTo ) ; +#endif + // build the Apple menu shared by all menu bars. nsresult CreateAppleMenu ( nsIMenu* inMenu ) ; @@ -177,6 +190,11 @@ protected: PRUint32 mNumMenus; nsSupportsArray mMenusArray; // holds refs nsCOMPtr mMenuBarContent; // menubar content node, strong ref + #if TARGET_CARBON + nsCOMPtr mPrefItemContent; // on X, holds the content node for the prefs item that has + // been removed from the menubar + nsCOMPtr mQuitItemContent; // as above, but for quit + #endif nsIWidget* mParent; // weak ref PRBool mIsMenuBarAdded; @@ -187,6 +205,10 @@ protected: MenuRef mRootMenu; // root menu, representing entire menu bar. static MenuRef sAppleMenu; // AppleMenu shared by all menubars + +#if TARGET_CARBON + static EventHandlerUPP sCommandEventHandler; // carbon event handler for commands, shared +#endif }; #endif // nsMenuBarX_h__ diff --git a/widget/src/mac/nsMenuX.cpp b/widget/src/mac/nsMenuX.cpp index b52b58c16cde..5d73fbf9136e 100644 --- a/widget/src/mac/nsMenuX.cpp +++ b/widget/src/mac/nsMenuX.cpp @@ -370,7 +370,7 @@ nsMenuX :: InsertMenuItemWithTruncation ( nsAutoString & inItemLabel, PRUint32 i //------------------------------------------------------------------------- -NS_METHOD nsMenuX::AddSeparator() +NS_METHOD nsMenuX::AddSeparator() { // HACK - We're not really appending an nsMenuItem but it // needs to be here to make sure that event dispatching isn't off by one. @@ -674,7 +674,7 @@ nsEventStatus nsMenuX::MenuConstruct( if ( tag == nsWidgetAtoms::menuitem ) LoadMenuItem(this, child); else if ( tag == nsWidgetAtoms::menuseparator ) - AddSeparator(); + LoadSeparator(child); else if ( tag == nsWidgetAtoms::menu ) LoadSubMenu(this, child); } @@ -720,7 +720,7 @@ nsEventStatus nsMenuX::HelpMenuConstruct( if ( tag == nsWidgetAtoms::menuitem ) LoadMenuItem(this, child); else if ( tag == nsWidgetAtoms::menuseparator ) - AddSeparator(); + LoadSeparator(child); else if ( tag == nsWidgetAtoms::menu ) LoadSubMenu(this, child); } @@ -1050,6 +1050,19 @@ nsMenuX::LoadSubMenu( nsIMenu * pParentMenu, nsIContent* inMenuItemContent ) } +void +nsMenuX::LoadSeparator ( nsIContent* inMenuItemContent ) +{ + // if item should be hidden, bail + nsAutoString hidden; + inMenuItemContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::hidden, hidden); + if ( hidden == NS_LITERAL_STRING("true") ) + return; + + AddSeparator(); +} + + // // OnCreate diff --git a/widget/src/mac/nsMenuX.h b/widget/src/mac/nsMenuX.h index a63c4bd9bbf2..423b32f96b03 100644 --- a/widget/src/mac/nsMenuX.h +++ b/widget/src/mac/nsMenuX.h @@ -128,8 +128,10 @@ protected: PRBool OnDestroyed() ; PRBool OnCreated() ; - void LoadMenuItem ( nsIMenu* pParentMenu, nsIContent* menuitemContent); - void LoadSubMenu( nsIMenu * pParentMenu, nsIContent* menuitemContent); + void LoadMenuItem ( nsIMenu* pParentMenu, nsIContent* menuitemContent ); + void LoadSubMenu ( nsIMenu * pParentMenu, nsIContent* menuitemContent ); + void LoadSeparator ( nsIContent* menuitemContent ); + nsEventStatus HelpMenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow, void* unused, void* aWebShell); diff --git a/xpfe/browser/resources/content/navigatorOverlay.xul b/xpfe/browser/resources/content/navigatorOverlay.xul index f339977f461c..097998984d4c 100644 --- a/xpfe/browser/resources/content/navigatorOverlay.xul +++ b/xpfe/browser/resources/content/navigatorOverlay.xul @@ -189,9 +189,8 @@ - + - @@ -206,7 +205,7 @@ - + diff --git a/xpfe/components/bookmarks/resources/bookmarks.xul b/xpfe/components/bookmarks/resources/bookmarks.xul index 9de003fef5d4..1ebaca1db991 100644 --- a/xpfe/components/bookmarks/resources/bookmarks.xul +++ b/xpfe/components/bookmarks/resources/bookmarks.xul @@ -140,7 +140,7 @@ - +