[Not part of build] Updated to use SetRootMenu() and SetMenuItemHierarchicalMenu() rather than juggling menu bars.

This commit is contained in:
beard%netscape.com 2000-12-15 21:43:22 +00:00
Родитель b2951a4ef6
Коммит 725b574834
4 изменённых файлов: 334 добавлений и 488 удалений

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

@ -51,27 +51,16 @@
#include <Appearance.h> #include <Appearance.h>
#include "nsMacResources.h" #include "nsMacResources.h"
static NS_DEFINE_IID(kIStringBundleServiceIID, NS_ISTRINGBUNDLESERVICE_IID);
static NS_DEFINE_IID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
nsWeakPtr gMacMenubarX;
#if !TARGET_CARBON
extern nsMenuStack gPreviousMenuStack;
#endif
// CIDs // CIDs
#include "nsWidgetsCID.h" #include "nsWidgetsCID.h"
static NS_DEFINE_CID(kMenuBarCID, NS_MENUBAR_CID); static NS_DEFINE_CID(kMenuBarCID, NS_MENUBAR_CID);
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID); static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID); static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID);
PRInt32 gMenuBarCounterX = 0;
NS_IMPL_ISUPPORTS5(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIDocumentObserver, nsIChangeManager, nsISupportsWeakReference) NS_IMPL_ISUPPORTS5(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIDocumentObserver, nsIChangeManager, nsISupportsWeakReference)
static MenuRef gDefaultRootMenu = nsnull;
// //
// nsMenuBarX constructor // nsMenuBarX constructor
// //
@ -81,16 +70,14 @@ nsMenuBarX::nsMenuBarX()
mNumMenus = 0; mNumMenus = 0;
mParent = nsnull; mParent = nsnull;
mIsMenuBarAdded = PR_FALSE; mIsMenuBarAdded = PR_FALSE;
mMacMBarHandle = nsnull;
++gMenuBarCounterX;
// if there's already a menu bar, save off its contents, so we have a clean slate. OSStatus status = ::CreateNewMenu(0, 0, &mRootMenu);
if (gMacMenubarX) { NS_ASSERTION(status == noErr, "nsMenuBarX::nsMenuBarX: creation of root menu failed.");
nsCOMPtr<nsIMenuBar> menuBar = do_QueryReferent(gMacMenubarX);
if (menuBar) menuBar->SetNativeData(::GetMenuBar()); if (gDefaultRootMenu == nsnull) {
gMacMenubarX = nsnull; gDefaultRootMenu = ::AcquireRootMenu();
NS_ASSERTION(gDefaultRootMenu != nsnull, "nsMenuBarX::nsMenuBarX: no default root menu!.");
} }
::ClearMenuBar();
} }
// //
@ -109,12 +96,11 @@ nsMenuBarX::~nsMenuBarX()
doc->RemoveObserver(observer); doc->RemoveObserver(observer);
} }
--gMenuBarCounterX; if (mRootMenu != NULL) {
if (gMenuBarCounterX == 0) NS_ASSERTION(gDefaultRootMenu != nsnull, "nsMenuBarX::~nsMenuBarX: no default root menu!.");
::ClearMenuBar(); ::SetRootMenu(gDefaultRootMenu);
::ReleaseMenu(mRootMenu);
if (mMacMBarHandle) }
::DisposeHandle(mMacMBarHandle);
} }
nsEventStatus nsEventStatus
@ -246,8 +232,6 @@ nsEventStatus
nsMenuBarX::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow, nsMenuBarX::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow,
void * menubarNode, void * aWebShell ) void * menubarNode, void * aWebShell )
{ {
gMacMenubarX = getter_AddRefs(NS_GetWeakReference((nsIMenuBar*)this));
mWebShellWeakRef = getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIWebShell*, aWebShell))); mWebShellWeakRef = getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIWebShell*, aWebShell)));
mDOMNode = NS_STATIC_CAST(nsIDOMNode*, menubarNode); // strong ref mDOMNode = NS_STATIC_CAST(nsIDOMNode*, menubarNode); // strong ref
@ -308,9 +292,6 @@ nsMenuBarX::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWin
// The parent takes ownership // The parent takes ownership
aParentWindow->SetMenuBar(this); aParentWindow->SetMenuBar(this);
// Get a copy of the menu list
SetNativeData(::GetMenuBar());
return nsEventStatus_eIgnore; return nsEventStatus_eIgnore;
} }
@ -351,13 +332,11 @@ NS_METHOD nsMenuBarX::SetParent(nsIWidget *aParent)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
NS_METHOD nsMenuBarX::AddMenu(nsIMenu * aMenu) NS_METHOD nsMenuBarX::AddMenu(nsIMenu * aMenu)
{ {
// XXX add to internal data structure // keep track of all added menus.
nsCOMPtr<nsISupports> supports = do_QueryInterface(aMenu); mMenusArray.AppendElement(aMenu); // owner
if(supports)
mMenusArray.AppendElement(supports); // owner
MenuHandle menuHandle = nsnull; MenuRef menuRef = nsnull;
aMenu->GetNativeData((void**)&menuHandle); aMenu->GetNativeData((void**)&menuRef);
mNumMenus++; mNumMenus++;
PRBool helpMenu; PRBool helpMenu;
@ -368,8 +347,12 @@ NS_METHOD nsMenuBarX::AddMenu(nsIMenu * aMenu)
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(domNode); nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(domNode);
nsAutoString menuHidden; nsAutoString menuHidden;
domElement->GetAttribute(NS_LITERAL_STRING("hidden"), menuHidden); domElement->GetAttribute(NS_LITERAL_STRING("hidden"), menuHidden);
if( menuHidden != NS_LITERAL_STRING("true")) if (menuHidden != NS_LITERAL_STRING("true")) {
::InsertMenu(menuHandle, 0); Str255 title;
::InsertMenuItem(mRootMenu, ::GetMenuTitle(menuRef, title), mNumMenus);
OSStatus status = ::SetMenuItemHierarchicalMenu(mRootMenu, mNumMenus, menuRef);
NS_ASSERTION(status == noErr, "nsMenuBarX::AddMenu: SetMenuItemHierarchicalMenu failed.");
}
} }
return NS_OK; return NS_OK;
@ -418,19 +401,19 @@ NS_METHOD nsMenuBarX::RemoveAll()
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
NS_METHOD nsMenuBarX::GetNativeData(void *& aData) NS_METHOD nsMenuBarX::GetNativeData(void *& aData)
{ {
aData = (void *) mMacMBarHandle; aData = (void *) mRootMenu;
return NS_OK; return NS_OK;
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
NS_METHOD nsMenuBarX::SetNativeData(void* aData) NS_METHOD nsMenuBarX::SetNativeData(void* aData)
{ {
#if 0
Handle menubarHandle = (Handle)aData; Handle menubarHandle = (Handle)aData;
if (mMacMBarHandle && mMacMBarHandle != menubarHandle) if (mMacMBarHandle && mMacMBarHandle != menubarHandle)
::DisposeHandle(mMacMBarHandle); ::DisposeHandle(mMacMBarHandle);
mMacMBarHandle = menubarHandle; mMacMBarHandle = menubarHandle;
#endif
return NS_OK; return NS_OK;
} }
@ -438,14 +421,8 @@ NS_METHOD nsMenuBarX::SetNativeData(void* aData)
NS_METHOD nsMenuBarX::Paint() NS_METHOD nsMenuBarX::Paint()
{ {
// hack to correctly swap menu bars. // hack to correctly swap menu bars.
nsCOMPtr<nsIMenuBar> menuBar = do_QueryReferent(gMacMenubarX); // hopefully this is fast enough.
if (menuBar.get() != (nsIMenuBar*)this) { ::SetRootMenu(mRootMenu);
if (menuBar)
menuBar->SetNativeData(::GetMenuBar());
gMacMenubarX = getter_AddRefs(NS_GetWeakReference((nsIMenuBar*)this));
if (mMacMBarHandle)
::SetMenuBar(mMacMBarHandle);
}
#if !TARGET_CARBON #if !TARGET_CARBON
// Now we have blown away the merged Help menu, so we have to rebuild it // Now we have blown away the merged Help menu, so we have to rebuild it

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

@ -157,8 +157,6 @@ protected:
void GetDocument ( nsIWebShell* inWebShell, nsIDocument** outDocument ) ; void GetDocument ( nsIWebShell* inWebShell, nsIDocument** outDocument ) ;
void RegisterAsDocumentObserver ( nsIWebShell* inWebShell ) ; void RegisterAsDocumentObserver ( nsIWebShell* inWebShell ) ;
static void SwapMenuBar();
nsHashtable mObserverTable; // stores observers for content change notification nsHashtable mObserverTable; // stores observers for content change notification
PRUint32 mNumMenus; PRUint32 mNumMenus;
@ -170,8 +168,7 @@ protected:
nsWeakPtr mWebShellWeakRef; // weak ref to webshell nsWeakPtr mWebShellWeakRef; // weak ref to webshell
// Mac Specific MenuRef mRootMenu; // root menu, representing entire menu bar.
Handle mMacMBarHandle;
}; };
#endif // nsMenuBarX_h__ #endif // nsMenuBarX_h__

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

@ -52,15 +52,8 @@
#include "nsDynamicMDEF.h" #include "nsDynamicMDEF.h"
// Beginning ID for top level menus. IDs 2-5 are the 4 Golden Hierarchical Menus const PRInt16 kMacMenuIDX = 1;
const PRInt16 kMacMenuIDX = 6; static PRInt16 gMacMenuIDCountX = kMacMenuIDX;
// Submenu depth tracking
PRInt16 gMenuDepthX = 0;
PRInt16 gCurrentMenuDepthX = 1;
PRInt16 mMacMenuIDCountX = kMacMenuIDX;
static PRBool gConstructingMenu = PR_FALSE; static PRBool gConstructingMenu = PR_FALSE;
#if DEBUG #if DEBUG
@ -95,48 +88,12 @@ NS_IMPL_ISUPPORTS4(nsMenuX, nsIMenu, nsIMenuListener, nsIChangeObserver, nsISupp
// nsMenuX constructor // nsMenuX constructor
// //
nsMenuX::nsMenuX() nsMenuX::nsMenuX()
: mNumMenuItems(0), mParent(nsnull), mManager(nsnull),
mMacMenuID(0), mMacMenuHandle(nsnull), mHelpMenuOSItemsCount(0),
mIsHelpMenu(PR_FALSE), mIsEnabled(PR_TRUE), mDestroyHandlerCalled(PR_FALSE),
mNeedsRebuild(PR_TRUE), mConstructed(PR_FALSE)
{ {
NS_INIT_REFCNT(); NS_INIT_REFCNT();
mNumMenuItems = 0;
mMenuParent = nsnull;
mMenuBarParent = nsnull;
mManager = nsnull;
mMacMenuID = 0;
mMacMenuHandle = nsnull;
mIsHelpMenu = PR_FALSE;
mHelpMenuOSItemsCount = 0;
mIsEnabled = PR_TRUE;
mConstructed = nsnull;
mDestroyHandlerCalled = PR_FALSE;
mNeedsRebuild = PR_TRUE;
//
// create a multi-destination Unicode converter which can handle all of the installed
// script systems
//
// To fix the menu bar problem, we add the primary script by using 0x80000000 with one
// script. This will make sure the converter first try to convert to the system script
// before it try other script.
//
// Mac OS 8 and 9 Developer Document > Text and Other Interionational Service >
// Text Encoding Converter Manager
// Inside Macintosh: Programming With the Text Encoding Conversion Manager
// CreateUnicodeToTextRunInfoByScriptCode
// iNumberOfScriptCodes
// The number of desired scripts. .... If you set the high-order bit for this parameter, the
// Unicode converter assumes that the iScripts parameter contains a singel element specifying
// the preferred script. This feature i ssupported beginning with the Text
// Encoding Conversion Manager 1.2
// Also .. from About Eariler Release:
// .. TEC Manager 1.2 was included with Mac OS 8 in July 1997...
ScriptCode ps[1];
ps[0] = ::GetScriptManagerVariable(smSysScript);
OSErr err = ::CreateUnicodeToTextRunInfoByScriptCode(0x80000000,ps,&mUnicodeTextRunConverter);
NS_ASSERTION(err==noErr,"nsMenuX::nsMenuX: CreateUnicodeToTextRunInfoByScriptCode failed.");
#if DEBUG #if DEBUG
++gMenuCounterX; ++gMenuCounterX;
@ -151,14 +108,8 @@ nsMenuX::~nsMenuX()
{ {
RemoveAll(); RemoveAll();
OSErr err = ::DisposeUnicodeToTextRunInfo(&mUnicodeTextRunConverter); if (mMacMenuHandle != NULL)
NS_ASSERTION(err==noErr,"nsMenuX::~nsMenuX: DisposeUnicodeToTextRunInfo failed."); ::ReleaseMenu(mMacMenuHandle);
// Don't destroy the 4 Golden Hierarchical Menu
if((mMacMenuID > 5) || (mMacMenuID < 2) && !mIsHelpMenu) {
//printf("WARNING: DeleteMenu called!!! \n");
::DeleteMenu(mMacMenuID);
}
// alert the change notifier we don't care no more // alert the change notifier we don't care no more
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode); nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
@ -189,19 +140,15 @@ nsMenuX::Create(nsISupports * aParent, const nsAReadableString &aLabel, const ns
NS_ASSERTION ( mDOMNode, "Menu not given a dom node at creation time" ); NS_ASSERTION ( mDOMNode, "Menu not given a dom node at creation time" );
NS_ASSERTION ( mManager, "No change manager given, can't tell content model updates" ); NS_ASSERTION ( mManager, "No change manager given, can't tell content model updates" );
mParent = aParent;
// our parent could be either a menu bar (if we're toplevel) or a menu (if we're a submenu) // our parent could be either a menu bar (if we're toplevel) or a menu (if we're a submenu)
PRBool isValidParent = PR_FALSE;
if (aParent) { if (aParent) {
nsCOMPtr<nsIMenuBar> menubar = do_QueryInterface(aParent); nsCOMPtr<nsIMenuBar> menubar = do_QueryInterface(aParent);
if (menubar)
mMenuBarParent = menubar; // weak ref
else
{
nsCOMPtr<nsIMenu> menu = do_QueryInterface(aParent); nsCOMPtr<nsIMenu> menu = do_QueryInterface(aParent);
if (menu) isValidParent = (menubar || menu);
mMenuParent = menu; // weak ref
} }
} NS_ASSERTION(isValidParent, "Menu parent not a menu bar or menu!" );
NS_ASSERTION( mMenuParent || mMenuBarParent, "Menu parent not a menu bar or menu!" );
SetLabel(aLabel); SetLabel(aLabel);
SetAccessKey(aAccessKey); SetAccessKey(aAccessKey);
@ -212,13 +159,9 @@ nsMenuX::Create(nsISupports * aParent, const nsAReadableString &aLabel, const ns
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
NS_METHOD nsMenuX::GetParent(nsISupports*& aParent) NS_METHOD nsMenuX::GetParent(nsISupports*& aParent)
{ {
aParent = nsnull; aParent = mParent;
if (mMenuParent) NS_IF_ADDREF(aParent);
return mMenuParent->QueryInterface(NS_GET_IID(nsISupports),(void**)&aParent); return NS_OK;
else if (mMenuBarParent)
return mMenuBarParent->QueryInterface(NS_GET_IID(nsISupports),(void**)&aParent);
return NS_ERROR_FAILURE;
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -262,7 +205,7 @@ NS_METHOD nsMenuX::SetLabel(const nsAReadableString &aText)
// first time? create the menu handle, attach event handler to it. // first time? create the menu handle, attach event handler to it.
if (mMacMenuHandle == nsnull) { if (mMacMenuHandle == nsnull) {
mMacMenuID = mMacMenuIDCountX++; mMacMenuID = gMacMenuIDCountX++;
mMacMenuHandle = NSStringNewMenu(mMacMenuID, mLabel); mMacMenuHandle = NSStringNewMenu(mMacMenuID, mLabel);
} }
@ -286,18 +229,19 @@ NS_METHOD nsMenuX::SetAccessKey(const nsAReadableString &aText)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
NS_METHOD nsMenuX::AddItem(nsISupports* aItem) NS_METHOD nsMenuX::AddItem(nsISupports* aItem)
{ {
nsresult rv = NS_ERROR_FAILURE;
if (aItem) { if (aItem) {
// Figure out what we're adding // Figure out what we're adding
nsCOMPtr<nsIMenuItem> menuitem(do_QueryInterface(aItem)); nsCOMPtr<nsIMenuItem> menuItem(do_QueryInterface(aItem));
if (menuitem) { if (menuItem) {
AddMenuItem(menuitem); rv = AddMenuItem(menuItem);
} else { } else {
nsCOMPtr<nsIMenu> menu(do_QueryInterface(aItem)); nsCOMPtr<nsIMenu> menu(do_QueryInterface(aItem));
if (menu) if (menu)
AddMenu(menu); rv = AddMenu(menu);
} }
} }
return NS_OK; return rv;
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -305,10 +249,7 @@ NS_METHOD nsMenuX::AddMenuItem(nsIMenuItem * aMenuItem)
{ {
if(!aMenuItem) return NS_ERROR_NULL_POINTER; if(!aMenuItem) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsISupports> supports = do_QueryInterface(aMenuItem); mMenuItemsArray.AppendElement(aMenuItem); // owning ref
if (!supports) return NS_ERROR_NO_INTERFACE;
mMenuItemsArray.AppendElement(supports); // owning ref
PRUint32 currItemIndex; PRUint32 currItemIndex;
mMenuItemsArray.Count(&currItemIndex); mMenuItemsArray.Count(&currItemIndex);
@ -316,13 +257,14 @@ NS_METHOD nsMenuX::AddMenuItem(nsIMenuItem * aMenuItem)
nsAutoString label; nsAutoString label;
aMenuItem->GetLabel(label); aMenuItem->GetLabel(label);
//printf("%s \n", label.ToNewCString()); // ::InsertMenuItem(mMacMenuHandle, "\p(Blank menu item", currItemIndex);
//printf("%d = mMacMenuID\n", mMacMenuID); // MenuHelpersX::SetMenuItemText(mMacMenuHandle, currItemIndex, label, mUnicodeTextRunConverter);
::InsertMenuItem(mMacMenuHandle, "\p(Blank menu item", currItemIndex); CFStringRef labelRef = ::CFStringCreateWithCharacters(kCFAllocatorDefault, (UniChar*)label.GetUnicode(), label.Length());
MenuHelpersX::SetMenuItemText(mMacMenuHandle, currItemIndex, label, mUnicodeTextRunConverter); ::InsertMenuItemTextWithCFString(mMacMenuHandle, labelRef, currItemIndex, 0, 0);
::CFRelease(labelRef);
// I want to be internationalized too! // I want to be internationalized too!
nsAutoString keyEquivalent; keyEquivalent.AssignWithConversion(" "); nsAutoString keyEquivalent(NS_LITERAL_STRING(" "));
aMenuItem->GetShortcutChar(keyEquivalent); aMenuItem->GetShortcutChar(keyEquivalent);
if (keyEquivalent != NS_LITERAL_STRING(" ")) { if (keyEquivalent != NS_LITERAL_STRING(" ")) {
keyEquivalent.ToUpperCase(); keyEquivalent.ToUpperCase();
@ -387,8 +329,11 @@ NS_METHOD nsMenuX::AddMenu(nsIMenu * aMenu)
aMenu->GetLabel(label); aMenu->GetLabel(label);
//printf("AddMenu %s \n", label.ToNewCString()); //printf("AddMenu %s \n", label.ToNewCString());
::InsertMenuItem(mMacMenuHandle, "\p(Blank Menu", currItemIndex); // ::InsertMenuItem(mMacMenuHandle, "\p(Blank Menu", currItemIndex);
MenuHelpersX::SetMenuItemText(mMacMenuHandle, currItemIndex, label, mUnicodeTextRunConverter); // MenuHelpersX::SetMenuItemText(mMacMenuHandle, currItemIndex, label, mUnicodeTextRunConverter);
CFStringRef labelRef = ::CFStringCreateWithCharacters(kCFAllocatorDefault, (UniChar*)label.GetUnicode(), label.Length());
::InsertMenuItemTextWithCFString(mMacMenuHandle, labelRef, currItemIndex, 0, 0);
::CFRelease(labelRef);
PRBool isEnabled; PRBool isEnabled;
aMenu->GetEnabled(&isEnabled); aMenu->GetEnabled(&isEnabled);
@ -398,10 +343,8 @@ NS_METHOD nsMenuX::AddMenu(nsIMenu * aMenu)
::DisableMenuItem(mMacMenuHandle, currItemIndex); ::DisableMenuItem(mMacMenuHandle, currItemIndex);
MenuHandle childMenu; MenuHandle childMenu;
if (aMenu->GetNativeData(&childMenu) == NS_OK) { if (aMenu->GetNativeData(&childMenu) == NS_OK)
::InsertMenu(childMenu, hierMenu); ::SetMenuItemHierarchicalMenu((MenuHandle) mMacMenuHandle, currItemIndex, childMenu);
::SetMenuItemHierarchicalID((MenuHandle) mMacMenuHandle, currItemIndex, ::GetMenuID(childMenu));
}
return NS_OK; return NS_OK;
} }
@ -449,26 +392,8 @@ NS_METHOD nsMenuX::RemoveItem(const PRUint32 aPos)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
NS_METHOD nsMenuX::RemoveAll() NS_METHOD nsMenuX::RemoveAll()
{ {
#ifdef notdef if (mMacMenuHandle != NULL)
#if !TARGET_CARBON ::DeleteMenuItems(mMacMenuHandle, 1, ::CountMenuItems(mMacMenuHandle));
MenuHandle helpmh;
::HMGetHelpMenuHandle(&helpmh);
if ( helpmh != mMacMenuHandle)
helpmh = nsnull;
#endif
#endif
PRUint32 curItem;
mMenuItemsArray.Count(&curItem);
while (curItem > 0)
{
/* don't delete the actual Mac menu item if it's a MacOS item */
if (curItem > mHelpMenuOSItemsCount)
::DeleteMenuItem(mMacMenuHandle, curItem);
curItem --;
}
mMenuItemsArray.Clear(); // remove all items mMenuItemsArray.Clear(); // remove all items
return NS_OK; return NS_OK;
} }
@ -516,6 +441,7 @@ nsEventStatus nsMenuX::MenuItemSelected(const nsMenuEvent & aMenuEvent)
// Determine if this is the correct menu to handle the event // Determine if this is the correct menu to handle the event
PRInt16 menuID = HiWord(((nsMenuEvent)aMenuEvent).mCommand); PRInt16 menuID = HiWord(((nsMenuEvent)aMenuEvent).mCommand);
#if !TARGET_CARBON
if ((kHMHelpMenuID == menuID) && (menuID != mMacMenuID)) if ((kHMHelpMenuID == menuID) && (menuID != mMacMenuID))
{ {
/* 'this' is not correct; we need to find the help nsMenuX */ /* 'this' is not correct; we need to find the help nsMenuX */
@ -532,10 +458,8 @@ nsEventStatus nsMenuX::MenuItemSelected(const nsMenuEvent & aMenuEvent)
/* set up a default event to query with */ /* set up a default event to query with */
nsMenuEvent event; nsMenuEvent event;
MenuHandle handle; MenuHandle handle;
#if !TARGET_CARBON
// XXX fix me for carbon! // XXX fix me for carbon!
::HMGetHelpMenuHandle(&handle); ::HMGetHelpMenuHandle(&handle);
#endif
event.mCommand = (unsigned int) handle; event.mCommand = (unsigned int) handle;
/* loop through the top-level menus in the menubar */ /* loop through the top-level menus in the menubar */
@ -567,7 +491,9 @@ nsEventStatus nsMenuX::MenuItemSelected(const nsMenuEvent & aMenuEvent)
} }
} }
} }
else if (mMacMenuID == menuID) else
#endif
if (mMacMenuID == menuID)
{ {
// Call MenuItemSelected on the correct nsMenuItem // Call MenuItemSelected on the correct nsMenuItem
PRInt16 menuItemID = LoWord(((nsMenuEvent)aMenuEvent).mCommand); PRInt16 menuItemID = LoWord(((nsMenuEvent)aMenuEvent).mCommand);
@ -620,8 +546,7 @@ nsEventStatus nsMenuX::MenuSelected(const nsMenuEvent & aMenuEvent)
// Determine if this is the correct menu to handle the event // Determine if this is the correct menu to handle the event
MenuHandle selectedMenuHandle = (MenuHandle) aMenuEvent.mCommand; MenuHandle selectedMenuHandle = (MenuHandle) aMenuEvent.mCommand;
if(mMacMenuHandle == selectedMenuHandle) if (mMacMenuHandle == selectedMenuHandle) {
{
if (mIsHelpMenu && mConstructed){ if (mIsHelpMenu && mConstructed){
RemoveAll(); RemoveAll();
mConstructed = false; mConstructed = false;
@ -640,8 +565,7 @@ nsEventStatus nsMenuX::MenuSelected(const nsMenuEvent & aMenuEvent)
return nsEventStatus_eConsumeNoDefault; return nsEventStatus_eConsumeNoDefault;
} }
if(!mConstructed || mNeedsRebuild) if(!mConstructed || mNeedsRebuild) {
{
if (mNeedsRebuild) if (mNeedsRebuild)
RemoveAll(); RemoveAll();
@ -661,14 +585,11 @@ nsEventStatus nsMenuX::MenuSelected(const nsMenuEvent & aMenuEvent)
//printf("Menu already constructed \n"); //printf("Menu already constructed \n");
} }
eventStatus = nsEventStatus_eConsumeNoDefault; eventStatus = nsEventStatus_eConsumeNoDefault;
} } else {
else
{
// Make sure none of our submenus are the ones that should be handling this // Make sure none of our submenus are the ones that should be handling this
PRUint32 numItems; PRUint32 numItems;
mMenuItemsArray.Count(&numItems); mMenuItemsArray.Count(&numItems);
for (PRUint32 i = numItems; i > 0; i--) for (PRUint32 i = numItems; i > 0; i--) {
{
nsCOMPtr<nsISupports> menuSupports = getter_AddRefs(mMenuItemsArray.ElementAt(i - 1)); nsCOMPtr<nsISupports> menuSupports = getter_AddRefs(mMenuItemsArray.ElementAt(i - 1));
nsCOMPtr<nsIMenu> submenu = do_QueryInterface(menuSupports); nsCOMPtr<nsIMenu> submenu = do_QueryInterface(menuSupports);
nsCOMPtr<nsIMenuListener> menuListener = do_QueryInterface(submenu); nsCOMPtr<nsIMenuListener> menuListener = do_QueryInterface(submenu);
@ -678,7 +599,6 @@ nsEventStatus nsMenuX::MenuSelected(const nsMenuEvent & aMenuEvent)
return eventStatus; return eventStatus;
} }
} }
} }
return eventStatus; return eventStatus;
@ -687,13 +607,11 @@ nsEventStatus nsMenuX::MenuSelected(const nsMenuEvent & aMenuEvent)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
nsEventStatus nsMenuX::MenuDeselected(const nsMenuEvent & aMenuEvent) nsEventStatus nsMenuX::MenuDeselected(const nsMenuEvent & aMenuEvent)
{ {
//printf("MenuDeselect called for %s\n", mLabel.ToNewCString());
// Destroy the menu // Destroy the menu
if (mConstructed) { if (mConstructed) {
MenuDestruct(aMenuEvent); MenuDestruct(aMenuEvent);
mConstructed = false; mConstructed = false;
} }
return nsEventStatus_eIgnore; return nsEventStatus_eIgnore;
} }
@ -713,8 +631,6 @@ nsEventStatus nsMenuX::MenuConstruct(
//printf("nsMenuX::MenuConstruct called for %s = %d \n", mLabel.ToNewCString(), mMacMenuHandle); //printf("nsMenuX::MenuConstruct called for %s = %d \n", mLabel.ToNewCString(), mMacMenuHandle);
// Begin menuitem inner loop // Begin menuitem inner loop
gCurrentMenuDepthX++;
// Now get the kids. Retrieve our menupopup child. // Now get the kids. Retrieve our menupopup child.
nsCOMPtr<nsIDOMNode> menuPopupNode; nsCOMPtr<nsIDOMNode> menuPopupNode;
GetMenuPopupElement(getter_AddRefs(menuPopupNode)); GetMenuPopupElement(getter_AddRefs(menuPopupNode));
@ -728,8 +644,7 @@ nsEventStatus nsMenuX::MenuConstruct(
while (menuitemNode) while (menuitemNode)
{ {
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode)); nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
if (menuitemElement) if (menuitemElement) {
{
nsAutoString label; nsAutoString label;
menuitemElement->GetAttribute(NS_LITERAL_STRING("value"), label); menuitemElement->GetAttribute(NS_LITERAL_STRING("value"), label);
//printf("label = %s \n", label.ToNewCString()); //printf("label = %s \n", label.ToNewCString());
@ -753,8 +668,6 @@ nsEventStatus nsMenuX::MenuConstruct(
mNeedsRebuild = PR_FALSE; mNeedsRebuild = PR_FALSE;
//printf(" Done building, mMenuItemVoidArray.Count() = %d \n", mMenuItemVoidArray.Count()); //printf(" Done building, mMenuItemVoidArray.Count() = %d \n", mMenuItemVoidArray.Count());
gCurrentMenuDepthX--;
return nsEventStatus_eIgnore; return nsEventStatus_eIgnore;
} }
@ -774,8 +687,6 @@ nsEventStatus nsMenuX::HelpMenuConstruct(
mMenuItemsArray.AppendElement(&gDummyMenuItemX); mMenuItemsArray.AppendElement(&gDummyMenuItemX);
} }
gCurrentMenuDepthX++;
// Now get the kids. Retrieve our menupopup child. // Now get the kids. Retrieve our menupopup child.
nsCOMPtr<nsIDOMNode> menuPopupNode; nsCOMPtr<nsIDOMNode> menuPopupNode;
GetMenuPopupElement ( getter_AddRefs(menuPopupNode) ); GetMenuPopupElement ( getter_AddRefs(menuPopupNode) );
@ -815,8 +726,6 @@ nsEventStatus nsMenuX::HelpMenuConstruct(
//printf(" Done building, mMenuItemVoidArray.Count() = %d \n", mMenuItemVoidArray.Count()); //printf(" Done building, mMenuItemVoidArray.Count() = %d \n", mMenuItemVoidArray.Count());
gCurrentMenuDepthX--;
//PreviousMenuStackUnwind(this, mMacMenuHandle); //PreviousMenuStackUnwind(this, mMacMenuHandle);
//PushMenu(this); //PushMenu(this);
@ -830,22 +739,7 @@ nsEventStatus nsMenuX::MenuDestruct(const nsMenuEvent & aMenuEvent)
// Fire our ondestroy handler. If we're told to stop, don't destroy the menu // Fire our ondestroy handler. If we're told to stop, don't destroy the menu
PRBool keepProcessing = OnDestroy(); PRBool keepProcessing = OnDestroy();
if ( keepProcessing ) if ( keepProcessing ) {
{
#if !TARGET_CARBON
if( mMacMenuHandle == gLevel2HierMenuX ||
mMacMenuHandle == gLevel3HierMenuX ||
mMacMenuHandle == gLevel4HierMenuX ||
mMacMenuHandle == gLevel5HierMenuX)
{
mNeedsRebuild = PR_TRUE;
}
#else
// perhaps this needs to be true if we are hierarchical?
if (mMenuBarParent == NULL)
mNeedsRebuild = PR_TRUE;
#endif
if(mNeedsRebuild) { if(mNeedsRebuild) {
RemoveAll(); RemoveAll();
mConstructed = false; mConstructed = false;
@ -902,17 +796,10 @@ NS_METHOD nsMenuX::SetEnabled(PRBool aIsEnabled)
{ {
mIsEnabled = aIsEnabled; mIsEnabled = aIsEnabled;
// If we're at the depth of a top-level menu, enable/disable the menu explicity.
// Otherwise we're working with a single "golden child" menu shared by all hierarchicals
// so if we touch it, it will affect the display of every other hierarchical spawnded from
// this menu (which would be bad).
if ( gCurrentMenuDepthX < 2 &&
(mMacMenuID > 5 || mMacMenuID < 2)) {
if ( aIsEnabled ) if ( aIsEnabled )
::EnableMenuItem(mMacMenuHandle, 0); ::EnableMenuItem(mMacMenuHandle, 0);
else else
::DisableMenuItem(mMacMenuHandle, 0); ::DisableMenuItem(mMacMenuHandle, 0);
}
return NS_OK; return NS_OK;
} }
@ -924,8 +811,8 @@ NS_METHOD nsMenuX::SetEnabled(PRBool aIsEnabled)
*/ */
NS_METHOD nsMenuX::GetEnabled(PRBool* aIsEnabled) NS_METHOD nsMenuX::GetEnabled(PRBool* aIsEnabled)
{ {
NS_ENSURE_ARG_POINTER(aIsEnabled);
*aIsEnabled = mIsEnabled; *aIsEnabled = mIsEnabled;
return NS_OK; return NS_OK;
} }
@ -936,6 +823,7 @@ NS_METHOD nsMenuX::GetEnabled(PRBool* aIsEnabled)
*/ */
NS_METHOD nsMenuX::IsHelpMenu(PRBool* aIsHelpMenu) NS_METHOD nsMenuX::IsHelpMenu(PRBool* aIsHelpMenu)
{ {
NS_ENSURE_ARG_POINTER(aIsHelpMenu);
*aIsHelpMenu = mIsHelpMenu; *aIsHelpMenu = mIsHelpMenu;
return NS_OK; return NS_OK;
} }
@ -962,7 +850,7 @@ static pascal OSStatus MyMenuEventHandler(EventHandlerCallRef myHandler, EventRe
OSStatus result = eventNotHandledErr; OSStatus result = eventNotHandledErr;
UInt32 kind = ::GetEventKind(event); UInt32 kind = ::GetEventKind(event);
if (kind == kEventMenuOpening) { if (kind == kEventMenuOpening || kind == kEventMenuClosed) {
nsISupports* supports = reinterpret_cast<nsISupports*>(userData); nsISupports* supports = reinterpret_cast<nsISupports*>(userData);
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(supports)); nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(supports));
if (listener) { if (listener) {
@ -976,7 +864,10 @@ static pascal OSStatus MyMenuEventHandler(EventHandlerCallRef myHandler, EventRe
menuEvent.widget = nsnull; menuEvent.widget = nsnull;
menuEvent.time = PR_IntervalNow(); menuEvent.time = PR_IntervalNow();
menuEvent.mCommand = (PRUint32) menuRef; menuEvent.mCommand = (PRUint32) menuRef;
if (kind == kEventMenuOpening)
listener->MenuSelected(menuEvent); listener->MenuSelected(menuEvent);
else
listener->MenuDeselected(menuEvent);
} }
} }
@ -1336,10 +1227,12 @@ nsresult
nsMenuX::GetNextVisibleMenu(nsIMenu** outNextVisibleMenu) nsMenuX::GetNextVisibleMenu(nsIMenu** outNextVisibleMenu)
{ {
*outNextVisibleMenu = nsnull; *outNextVisibleMenu = nsnull;
if (!mMenuBarParent) return NS_ERROR_FAILURE;
nsCOMPtr<nsIMenuBar> menubarParent = do_QueryInterface(mParent);
if (!menubarParent) return NS_ERROR_FAILURE;
PRUint32 numMenus; PRUint32 numMenus;
mMenuBarParent->GetMenuCount(numMenus); menubarParent->GetMenuCount(numMenus);
PRBool gotThisMenu = PR_FALSE; PRBool gotThisMenu = PR_FALSE;
PRUint32 thisMenuIndex; PRUint32 thisMenuIndex;
@ -1347,7 +1240,7 @@ nsMenuX::GetNextVisibleMenu(nsIMenu** outNextVisibleMenu)
for (PRUint32 i = 0; i < numMenus; i ++) for (PRUint32 i = 0; i < numMenus; i ++)
{ {
nsCOMPtr<nsIMenu> thisMenu; nsCOMPtr<nsIMenu> thisMenu;
mMenuBarParent->GetMenuAt(i, *getter_AddRefs(thisMenu)); menubarParent->GetMenuAt(i, *getter_AddRefs(thisMenu));
if (!thisMenu) continue; if (!thisMenu) continue;
if (gotThisMenu) // we're looking for the next visible if (gotThisMenu) // we're looking for the next visible
@ -1410,6 +1303,8 @@ nsMenuX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom
return NS_OK; return NS_OK;
} }
nsCOMPtr<nsIMenuBar> menubarParent = do_QueryInterface(mParent);
if (aAttribute == disabledAtom.get()) // disabled if (aAttribute == disabledAtom.get()) // disabled
{ {
mNeedsRebuild = PR_TRUE; mNeedsRebuild = PR_TRUE;
@ -1429,39 +1324,17 @@ nsMenuX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom
domElement->GetAttribute(NS_LITERAL_STRING("value"), mLabel); domElement->GetAttribute(NS_LITERAL_STRING("value"), mLabel);
if((mMacMenuID <= 5) && (mMacMenuID >= 2)) // reuse the existing menu, to avoid invalidating root menu bar.
return NS_OK; NS_ASSERTION(mMacMenuHandle != NULL, "nsMenuX::AttributeChanged: invalid menu handle.");
RemoveAll();
CFStringRef titleRef = ::CFStringCreateWithCharacters(kCFAllocatorDefault, (UniChar*)mLabel.GetUnicode(), mLabel.Length());
NS_ASSERTION(titleRef, "nsMenuX::AttributeChanged: CFStringCreateWithCharacters failed.");
::SetMenuTitleWithCFString(mMacMenuHandle, titleRef);
::CFRelease(titleRef);
::DeleteMenu(mMacMenuID); if (menubarParent)
mMacMenuHandle = NSStringNewMenu(mMacMenuID, mLabel);
// Need to get the menuID of the next visible menu
SInt16 nextMenuID = -1; // default to the submenu case
if (mMenuBarParent) // this is a top-level menu
{
nsCOMPtr<nsIMenu> nextVisibleMenu;
GetNextVisibleMenu(getter_AddRefs(nextVisibleMenu));
if (nextVisibleMenu)
{
MenuHandle nextHandle;
nextVisibleMenu->GetNativeData((void **)&nextHandle);
nextMenuID = (nextHandle) ? ::GetMenuID(nextHandle) : mMacMenuID + 1;
}
else
{
nextMenuID = mMacMenuID + 1;
}
}
::InsertMenu(mMacMenuHandle, nextMenuID);
if(mMenuBarParent)
{
mMenuBarParent->SetNativeData(::GetMenuBar());
::DrawMenuBar(); ::DrawMenuBar();
}
} }
else if(aAttribute == hiddenAtom.get() || aAttribute == collapsedAtom.get()) // hidden of collapsed else if(aAttribute == hiddenAtom.get() || aAttribute == collapsedAtom.get()) // hidden of collapsed
{ {
@ -1472,14 +1345,14 @@ nsMenuX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom
domElement->GetAttribute(NS_LITERAL_STRING("collapsed"), collapsedValue); domElement->GetAttribute(NS_LITERAL_STRING("collapsed"), collapsedValue);
if (hiddenValue == NS_LITERAL_STRING("true") || collapsedValue == NS_LITERAL_STRING("true")) { if (hiddenValue == NS_LITERAL_STRING("true") || collapsedValue == NS_LITERAL_STRING("true")) {
// hide this menu // hide this menu
::DeleteMenu(mMacMenuID); NS_ASSERTION(PR_FALSE, "nsMenuX::AttributeChanged: WRITE HIDE CODE.");
} }
else else
{ {
// Need to get the menuID of the next visible menu // Need to get the menuID of the next visible menu
SInt16 nextMenuID = -1; // default to the submenu case SInt16 nextMenuID = -1; // default to the submenu case
if (mMenuBarParent) // this is a top-level menu if (menubarParent) // this is a top-level menu
{ {
nsCOMPtr<nsIMenu> nextVisibleMenu; nsCOMPtr<nsIMenu> nextVisibleMenu;
GetNextVisibleMenu(getter_AddRefs(nextVisibleMenu)); GetNextVisibleMenu(getter_AddRefs(nextVisibleMenu));
@ -1497,10 +1370,9 @@ nsMenuX::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom
} }
// show this menu // show this menu
::InsertMenu(mMacMenuHandle, nextMenuID); NS_ASSERTION(PR_FALSE, "nsMenuX::AttributeChanged: WRITE SHOW CODE.");
} }
if(mMenuBarParent) { if (menubarParent) {
mMenuBarParent->SetNativeData(::GetMenuBar());
::DrawMenuBar(); ::DrawMenuBar();
} }
} }

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

@ -116,17 +116,17 @@ protected:
PRUint32 mNumMenuItems; PRUint32 mNumMenuItems;
nsSupportsArray mMenuItemsArray; // array holds refs nsSupportsArray mMenuItemsArray; // array holds refs
nsIMenu* mMenuParent; // weak, my parent owns me nsISupports* mParent; // weak, my parent owns me
nsIMenuBar* mMenuBarParent; // nsIMenu* mMenuParent;
// nsIMenuBar* mMenuBarParent;
nsIChangeManager* mManager; // weak ref, it will outlive us nsIChangeManager* mManager; // weak ref, it will outlive us
nsWeakPtr mWebShellWeakRef; // weak ref to webshell nsWeakPtr mWebShellWeakRef; // weak ref to webshell
nsCOMPtr<nsIDOMNode> mDOMNode; // strong ref nsCOMPtr<nsIDOMNode> mDOMNode; // strong ref
nsCOMPtr<nsIMenuListener> mListener; nsCOMPtr<nsIMenuListener> mListener; // strong ref
// MacSpecific // MacSpecific
PRInt16 mMacMenuID; PRInt16 mMacMenuID;
MenuHandle mMacMenuHandle; MenuHandle mMacMenuHandle;
UnicodeToTextRunInfo mUnicodeTextRunConverter;
PRInt16 mHelpMenuOSItemsCount; PRInt16 mHelpMenuOSItemsCount;
PRPackedBool mIsHelpMenu; PRPackedBool mIsHelpMenu;
PRPackedBool mIsEnabled; PRPackedBool mIsEnabled;