Fixes for Mac menu bugs 49576, and 49142. r=pinkerton

This commit is contained in:
saari%netscape.com 2000-08-31 02:26:08 +00:00
Родитель 971108565b
Коммит a43fa40784
7 изменённых файлов: 163 добавлений и 42 удалений

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

@ -78,6 +78,9 @@ class nsIMenuListener : public nsISupports {
virtual nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent) = 0;
virtual nsEventStatus CheckRebuild(PRBool & aMenuEvent) = 0;
virtual nsEventStatus SetRebuild(PRBool & aMenuEvent) = 0;
};
#endif // nsIMenuListener_h__

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

@ -51,6 +51,11 @@
#include "nsDynamicMDEF.h"
extern MenuHandle gLevel2HierMenu;
extern MenuHandle gLevel3HierMenu;
extern MenuHandle gLevel4HierMenu;
extern MenuHandle gLevel5HierMenu;
// Beginning ID for top level menus. IDs 2-5 are the 4 Golden Hierarchical Menus
const PRInt16 kMacMenuID = 6;
@ -115,6 +120,8 @@ nsMenu::nsMenu()
mIsEnabled = PR_TRUE;
mConstructed = nsnull;
mDestroyHandlerCalled = PR_FALSE;
mNeedsRebuild = PR_TRUE;
//
// create a multi-destination Unicode converter which can handle all of the installed
@ -720,30 +727,44 @@ nsEventStatus nsMenu::MenuSelected(const nsMenuEvent & aMenuEvent)
if(mMacMenuHandle == selectedMenuHandle)
{
if (mIsHelpMenu && mConstructed){
RemoveAll();
mConstructed = false;
}
if(!mConstructed)
{
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
if (!webShell) {
NS_ERROR("No web shell");
return nsEventStatus_eConsumeNoDefault;
}
if(mIsHelpMenu) {
HelpMenuConstruct(aMenuEvent, nsnull /* mParentWindow */, mDOMNode, webShell);
mConstructed = true;
} else {
MenuConstruct(aMenuEvent, nsnull /* mParentWindow */, mDOMNode, webShell);
mConstructed = true;
}
} else {
//printf("Menu already constructed \n");
}
eventStatus = nsEventStatus_eConsumeNoDefault;
RemoveAll();
mConstructed = false;
mNeedsRebuild = PR_TRUE;
}
// Open the node.
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if (domElement)
domElement->SetAttribute(NS_ConvertASCIItoUCS2("open"), NS_ConvertASCIItoUCS2("true"));
// Fire our oncreate handler. If we're told to stop, don't build the menu at all
PRBool keepProcessing = OnCreate();
if(!mIsHelpMenu && !mNeedsRebuild || !keepProcessing) {
return nsEventStatus_eConsumeNoDefault;
}
if(!mConstructed || mNeedsRebuild)
{
if(mNeedsRebuild)
RemoveAll();
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
if (!webShell) {
NS_ERROR("No web shell");
return nsEventStatus_eConsumeNoDefault;
}
if(mIsHelpMenu) {
HelpMenuConstruct(aMenuEvent, nsnull /* mParentWindow */, mDOMNode, webShell);
mConstructed = true;
} else {
MenuConstruct(aMenuEvent, nsnull /* mParentWindow */, mDOMNode, webShell);
mConstructed = true;
}
} else {
//printf("Menu already constructed \n");
}
eventStatus = nsEventStatus_eConsumeNoDefault;
}
else
{
@ -787,6 +808,7 @@ nsEventStatus nsMenu::MenuConstruct(
void * menuNode,
void * aWebShell)
{
mConstructed = false;
gConstructingMenu = PR_TRUE;
// reset destroy handler flag so that we'll know to fire it next time this menu goes away.
@ -796,14 +818,14 @@ nsEventStatus nsMenu::MenuConstruct(
// Begin menuitem inner loop
// Open the node.
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if (domElement)
domElement->SetAttribute(NS_ConvertASCIItoUCS2("open"), NS_ConvertASCIItoUCS2("true"));
//nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
//if (domElement)
// domElement->SetAttribute(NS_ConvertASCIItoUCS2("open"), NS_ConvertASCIItoUCS2("true"));
gCurrentMenuDepth++;
// Fire our oncreate handler. If we're told to stop, don't build the menu at all
PRBool keepProcessing = OnCreate();
//PRBool keepProcessing = OnCreate();
// Now get the kids. Retrieve our menupopup child.
nsCOMPtr<nsIDOMNode> menuPopupNode;
@ -816,7 +838,7 @@ nsEventStatus nsMenu::MenuConstruct(
menuPopupNode->GetFirstChild(getter_AddRefs(menuitemNode));
unsigned short menuIndex = 0;
if ( keepProcessing )
if ( /* keepProcessing */ true )
{
while (menuitemNode)
{
@ -845,6 +867,7 @@ nsEventStatus nsMenu::MenuConstruct(
}
gConstructingMenu = PR_FALSE;
mNeedsRebuild = PR_FALSE;
//printf(" Done building, mMenuItemVoidArray.Count() = %d \n", mMenuItemVoidArray.Count());
gCurrentMenuDepth--;
@ -939,9 +962,21 @@ nsEventStatus nsMenu::MenuDestruct(const nsMenuEvent & aMenuEvent)
PRBool keepProcessing = OnDestroy();
if ( keepProcessing )
{
RemoveAll();
//printf(" mMenuItemVoidArray.Count() = %d \n", mMenuItemVoidArray.Count());
// Close the node.
if( mMacMenuHandle == gLevel2HierMenu ||
mMacMenuHandle == gLevel3HierMenu ||
mMacMenuHandle == gLevel4HierMenu ||
mMacMenuHandle == gLevel5HierMenu)
{
mNeedsRebuild = PR_TRUE;
}
if(mNeedsRebuild) {
RemoveAll();
mConstructed = false;
//printf(" mMenuItemVoidArray.Count() = %d \n", mMenuItemVoidArray.Count());
// Close the node.
mNeedsRebuild = PR_TRUE;
}
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if(!domElement) {
NS_ERROR("Unable to QI dom element.");
@ -964,6 +999,24 @@ nsEventStatus nsMenu::MenuDestruct(const nsMenuEvent & aMenuEvent)
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenu::CheckRebuild(PRBool & aNeedsRebuild)
{
aNeedsRebuild = PR_TRUE; //mNeedsRebuild;
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenu::SetRebuild(PRBool & aNeedsRebuild)
{
if(!gConstructingMenu) {
mNeedsRebuild = aNeedsRebuild;
//if(mNeedsRebuild)
// RemoveAll();
}
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
/**
* Set enabled state
@ -1436,6 +1489,8 @@ nsMenu::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom *
if(aAttribute == disabledAtom.get()) // disabled
{
mNeedsRebuild = PR_TRUE;
nsAutoString valueString;
domElement->GetAttribute(NS_ConvertASCIItoUCS2("disabled"), valueString);
if(valueString.EqualsWithConversion("true"))
@ -1447,6 +1502,8 @@ nsMenu::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom *
}
else if(aAttribute == valueAtom.get()) // value
{
mNeedsRebuild = PR_TRUE;
domElement->GetAttribute(NS_ConvertASCIItoUCS2("value"), mLabel);
::DeleteMenu(mMacMenuID);
@ -1497,6 +1554,8 @@ nsMenu::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom *
}
else if(aAttribute == hiddenAtom.get() || aAttribute == collapsedAtom.get()) // hidden of collapsed
{
mNeedsRebuild = PR_TRUE;
nsAutoString hiddenValue, collapsedValue;
domElement->GetAttribute(NS_ConvertASCIItoUCS2("hidden"), hiddenValue);
domElement->GetAttribute(NS_ConvertASCIItoUCS2("collapsed"), collapsedValue);
@ -1542,10 +1601,12 @@ nsMenu::AttributeChanged(nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom *
NS_IMETHODIMP
nsMenu :: ContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)
{
{
if(gConstructingMenu)
return NS_OK;
mNeedsRebuild = PR_TRUE;
RemoveItem(aIndexInContainer);
mManager->Unregister ( aChild );

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

@ -70,7 +70,9 @@ public:
nsEventStatus MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow,
void * menuNode, void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
nsEventStatus CheckRebuild(PRBool & aMenuEvent);
nsEventStatus SetRebuild(PRBool & aMenuEvent);
// nsIMenu Methods
NS_IMETHOD Create ( nsISupports * aParent, const nsString &aLabel, const nsString &aAccessKey,
nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode ) ;
@ -128,7 +130,7 @@ protected:
PRPackedBool mIsHelpMenu;
PRPackedBool mIsEnabled;
PRPackedBool mDestroyHandlerCalled;
PRPackedBool mNeedsRebuild;
nsresult GetNextVisibleMenu(nsIMenu** outNextVisibleMenu);

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

@ -65,6 +65,7 @@ typedef struct {
Handle gMDEF = nsnull;
Handle gSystemMDEFHandle = nsnull;
nsWeakPtr gMacMenubar;
nsWeakPtr gOriginalMenuBar;
bool gFirstMenuBar = true;
// The four Golden Hierarchical Child Menus
@ -159,10 +160,15 @@ nsMenuBar::~nsMenuBar()
doc->RemoveObserver(observer);
}
::DisposeHandle(mMacMBarHandle);
::DisposeHandle(mOriginalMacMBarHandle);
--gMenuBarCounter;
if(gMenuBarCounter == 1) {
nsCOMPtr<nsIMenuBar> menubar = do_QueryReferent(gOriginalMenuBar);
if(menubar)
menubar->Paint();
}
::DisposeHandle(mOriginalMacMBarHandle);
::DisposeHandle(mMacMBarHandle);
}
@ -240,6 +246,18 @@ nsMenuBar::MenuDeselected(const nsMenuEvent & aMenuEvent)
return nsEventStatus_eIgnore;
}
nsEventStatus
nsMenuBar::CheckRebuild(PRBool & aNeedsRebuild)
{
aNeedsRebuild = PR_TRUE;
return nsEventStatus_eIgnore;
}
nsEventStatus
nsMenuBar::SetRebuild(PRBool & aNeedsRebuild)
{
return nsEventStatus_eIgnore;
}
void
nsMenuBar :: GetDocument ( nsIWebShell* inWebShell, nsIDocument** outDocument )
@ -289,6 +307,8 @@ nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind
mDOMNode = NS_STATIC_CAST(nsIDOMNode*, menubarNode); // strong ref
if(gFirstMenuBar) {
gOriginalMenuBar = getter_AddRefs(NS_GetWeakReference((nsIMenuBar *)this));
gFirstMenuBar = false;
// Add the 4 Golden Hierarchical Menus to the MenuList

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

@ -83,6 +83,8 @@ public:
nsEventStatus MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow,
void * menuNode, void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
nsEventStatus CheckRebuild(PRBool & aMenuEvent);
nsEventStatus SetRebuild(PRBool & aMenuEvent);
// nsIDocumentObserver
NS_IMETHOD BeginUpdate(nsIDocument *aDocument);

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

@ -69,10 +69,10 @@ nsMenuItem::~nsMenuItem()
//printf("nsMenuItem::~nsMenuItem() called \n");
// if we're a radio menu, we've been registered to get AttributeChanged, so
// make sure we unregister when we go away.
if (mMenuType == eRadio) {
//if (mMenuType == eRadio) {
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
mManager->Unregister(content);
}
//}
#if DEBUG
--gMenuItemCounter;
@ -93,11 +93,11 @@ NS_METHOD nsMenuItem::Create ( nsIMenu* aParent, const nsString & aLabel, PRBool
// if we're a radio menu, register for AttributeChanged messages
mManager = aManager;
if ( aItemType == eRadio ) {
//if ( aItemType == eRadio ) {
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
nsCOMPtr<nsIChangeObserver> obs = do_QueryInterface(NS_STATIC_CAST(nsIChangeObserver*,this));
mManager->Register(content, obs); // does not addref this
}
//}
mIsSeparator = aIsSeparator;
mLabel = aLabel;
@ -251,6 +251,19 @@ nsEventStatus nsMenuItem::MenuDestruct(const nsMenuEvent & aMenuEvent)
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItem::CheckRebuild(PRBool & aNeedsRebuild)
{
aNeedsRebuild = PR_TRUE;
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItem::SetRebuild(PRBool & aNeedsRebuild)
{
//mNeedsRebuild = aNeedsRebuild;
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
/**
@ -375,14 +388,29 @@ nsMenuItem :: AttributeChanged ( nsIDocument *aDocument, PRInt32 aNameSpaceID, n
PRInt32 aHint)
{
nsCOMPtr<nsIAtom> checkedAtom = NS_NewAtom("checked");
nsCOMPtr<nsIAtom> disabledAtom = NS_NewAtom("disabled");
nsCOMPtr<nsIAtom> valueAtom = NS_NewAtom("value");
nsCOMPtr<nsIAtom> hiddenAtom = NS_NewAtom("hidden");
nsCOMPtr<nsIAtom> collapsedAtom = NS_NewAtom("collapsed");
if (aAttribute == checkedAtom.get())
{
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
nsAutoString checked;
domElement->GetAttribute(NS_ConvertASCIItoUCS2("checked"), checked);
if (checked.EqualsWithConversion("true"))
if (checked.EqualsWithConversion("true"))
UncheckRadioSiblings(domElement);
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
} else if (aAttribute == disabledAtom.get() ||
aAttribute == hiddenAtom.get() ||
aAttribute == collapsedAtom.get() ) {
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
}
return NS_OK;
} // AttributeChanged
@ -391,6 +419,9 @@ nsMenuItem :: AttributeChanged ( nsIDocument *aDocument, PRInt32 aNameSpaceID, n
NS_IMETHODIMP
nsMenuItem :: ContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)
{
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
return NS_OK;
} // ContentRemoved

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

@ -79,6 +79,8 @@ public:
nsEventStatus MenuConstruct(const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow,
void * menuNode, void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
nsEventStatus CheckRebuild(PRBool & aMenuEvent);
nsEventStatus SetRebuild(PRBool & aMenuEvent);
protected: