зеркало из https://github.com/mozilla/gecko-dev.git
Fixes for Mac menu bugs 49576, and 49142. r=pinkerton
This commit is contained in:
Родитель
971108565b
Коммит
a43fa40784
|
@ -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:
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче