mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Fix crash in Mac OS X native menus when attribute change notifications come in an order we don't expect. Allow for any attribute change notification order. b=433858 r=mstange sr=roc
This commit is contained in:
parent
4f8f3b0027
commit
904c2da266
@ -226,14 +226,10 @@ nsresult nsMenuBarX::InsertMenuAtIndex(nsMenuX* aMenu, PRUint32 aIndex)
|
||||
nsIContent* menuContent = aMenu->Content();
|
||||
if (menuContent->GetChildCount() > 0 &&
|
||||
!nsMenuUtilsX::NodeIsHiddenOrCollapsed(menuContent)) {
|
||||
PRUint32 insertAfter = 0;
|
||||
nsresult rv = nsMenuUtilsX::CountVisibleBefore(this, aMenu, &insertAfter);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "nsMenuUtilsX::CountVisibleBefore failed!\n");
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
int insertionIndex = nsMenuUtilsX::CalculateNativeInsertionPoint(this, aMenu);
|
||||
if (MenuContainsAppMenu())
|
||||
insertAfter++;
|
||||
[mNativeMenu insertItem:aMenu->NativeMenuItem() atIndex:insertAfter];
|
||||
insertionIndex++;
|
||||
[mNativeMenu insertItem:aMenu->NativeMenuItem() atIndex:insertionIndex];
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -62,7 +62,7 @@ namespace nsMenuUtilsX
|
||||
nsMenuBarX* GetHiddenWindowMenuBar(); // returned object is not retained
|
||||
NSMenuItem* GetStandardEditMenuItem(); // returned object is not retained
|
||||
PRBool NodeIsHiddenOrCollapsed(nsIContent* inContent);
|
||||
nsresult CountVisibleBefore(nsMenuObjectX* aMenuObject, nsMenuObjectX* aChild, PRUint32* outVisibleBefore);
|
||||
int CalculateNativeInsertionPoint(nsMenuObjectX* aParent, nsMenuObjectX* aChild);
|
||||
}
|
||||
|
||||
#endif // nsMenuUtilsX_h_
|
||||
|
@ -45,8 +45,6 @@
|
||||
#include "nsCocoaWindow.h"
|
||||
#include "nsWidgetAtoms.h"
|
||||
|
||||
#import <Carbon/Carbon.h>
|
||||
|
||||
nsEventStatus nsMenuUtilsX::DispatchCommandTo(nsIContent* aTargetContent)
|
||||
{
|
||||
NS_PRECONDITION(aTargetContent, "null ptr");
|
||||
@ -199,41 +197,40 @@ PRBool nsMenuUtilsX::NodeIsHiddenOrCollapsed(nsIContent* inContent)
|
||||
|
||||
|
||||
// Determines how many items are visible among the siblings in a menu that are
|
||||
// before the given child. Note that this will not count the application menu.
|
||||
nsresult nsMenuUtilsX::CountVisibleBefore(nsMenuObjectX* aParentMenu, nsMenuObjectX* aChild, PRUint32* outVisibleBefore)
|
||||
// before the given child. This will not count the application menu.
|
||||
int nsMenuUtilsX::CalculateNativeInsertionPoint(nsMenuObjectX* aParent,
|
||||
nsMenuObjectX* aChild)
|
||||
{
|
||||
NS_ASSERTION(outVisibleBefore, "bad index param in nsMenuX::CountVisibleBefore");
|
||||
|
||||
nsMenuObjectTypeX parentType = aParentMenu->MenuObjectType();
|
||||
int insertionPoint = 0;
|
||||
nsMenuObjectTypeX parentType = aParent->MenuObjectType();
|
||||
if (parentType == eMenuBarObjectType) {
|
||||
*outVisibleBefore = 0;
|
||||
nsMenuBarX* menubarParent = static_cast<nsMenuBarX*>(aParentMenu);
|
||||
nsMenuBarX* menubarParent = static_cast<nsMenuBarX*>(aParent);
|
||||
PRUint32 numMenus = menubarParent->GetMenuCount();
|
||||
for (PRUint32 i = 0; i < numMenus; i++) {
|
||||
nsMenuX* currMenu = menubarParent->GetMenuAt(i);
|
||||
if (currMenu == aChild)
|
||||
return NS_OK; // we found ourselves, break out
|
||||
if (currMenu) {
|
||||
nsIContent* menuContent = currMenu->Content();
|
||||
if (menuContent->GetChildCount() > 0 &&
|
||||
!nsMenuUtilsX::NodeIsHiddenOrCollapsed(menuContent)) {
|
||||
++(*outVisibleBefore);
|
||||
}
|
||||
}
|
||||
return insertionPoint; // we found ourselves, break out
|
||||
if (currMenu && [currMenu->NativeMenuItem() menu])
|
||||
insertionPoint++;
|
||||
}
|
||||
}
|
||||
else if (parentType == eSubmenuObjectType) {
|
||||
*outVisibleBefore = 0;
|
||||
nsMenuX* menuParent = static_cast<nsMenuX*>(aParentMenu);
|
||||
nsMenuX* menuParent = static_cast<nsMenuX*>(aParent);
|
||||
PRUint32 numItems = menuParent->GetItemCount();
|
||||
for (PRUint32 i = 0; i < numItems; i++) {
|
||||
// Using GetItemAt instead of GetVisibleItemAt to avoid O(N^2)
|
||||
nsMenuObjectX* currItem = menuParent->GetItemAt(i);
|
||||
if (currItem == aChild)
|
||||
return NS_OK; // we found ourselves, break out
|
||||
if (!nsMenuUtilsX::NodeIsHiddenOrCollapsed(currItem->Content()))
|
||||
++(*outVisibleBefore);
|
||||
return insertionPoint; // we found ourselves, break out
|
||||
NSMenuItem* nativeItem = nil;
|
||||
nsMenuObjectTypeX currItemType = currItem->MenuObjectType();
|
||||
if (currItemType == eSubmenuObjectType)
|
||||
nativeItem = static_cast<nsMenuX*>(currItem)->NativeMenuItem();
|
||||
else
|
||||
nativeItem = (NSMenuItem*)(currItem->NativeData());
|
||||
if ([nativeItem menu])
|
||||
insertionPoint++;
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
return insertionPoint;
|
||||
}
|
||||
|
@ -806,21 +806,19 @@ void nsMenuX::ObserveAttributeChanged(nsIDocument *aDocument, nsIContent *aConte
|
||||
}
|
||||
}
|
||||
else {
|
||||
PRUint32 insertAfter = 0;
|
||||
if (NS_SUCCEEDED(nsMenuUtilsX::CountVisibleBefore(mParent, this, &insertAfter))) {
|
||||
if (parentType == eMenuBarObjectType || parentType == eSubmenuObjectType) {
|
||||
if (parentType == eMenuBarObjectType) {
|
||||
// Before inserting we need to figure out if we should take the native
|
||||
// application menu into account.
|
||||
nsMenuBarX* mb = static_cast<nsMenuBarX*>(mParent);
|
||||
if (mb->MenuContainsAppMenu())
|
||||
insertAfter++;
|
||||
}
|
||||
NSMenu* parentMenu = (NSMenu*)mParent->NativeData();
|
||||
[parentMenu insertItem:mNativeMenuItem atIndex:insertAfter];
|
||||
[mNativeMenuItem setSubmenu:mNativeMenu];
|
||||
mVisible = PR_TRUE;
|
||||
if (parentType == eMenuBarObjectType || parentType == eSubmenuObjectType) {
|
||||
int insertionIndex = nsMenuUtilsX::CalculateNativeInsertionPoint(mParent, this);
|
||||
if (parentType == eMenuBarObjectType) {
|
||||
// Before inserting we need to figure out if we should take the native
|
||||
// application menu into account.
|
||||
nsMenuBarX* mb = static_cast<nsMenuBarX*>(mParent);
|
||||
if (mb->MenuContainsAppMenu())
|
||||
insertionIndex++;
|
||||
}
|
||||
NSMenu* parentMenu = (NSMenu*)mParent->NativeData();
|
||||
[parentMenu insertItem:mNativeMenuItem atIndex:insertionIndex];
|
||||
[mNativeMenuItem setSubmenu:mNativeMenu];
|
||||
mVisible = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -292,6 +292,16 @@
|
||||
menubarNode.removeChild(tmpMenu0);
|
||||
delete tmpMenu0;
|
||||
|
||||
// This test is basically a crash test for bug 433858.
|
||||
newMenuItem1.setAttribute("hidden", "true");
|
||||
newMenuItem2.setAttribute("hidden", "true");
|
||||
newMenu1.setAttribute("hidden", "true");
|
||||
forceUpdateNativeMenuAt("1");
|
||||
newMenuItem1.setAttribute("hidden", "false");
|
||||
newMenuItem2.setAttribute("hidden", "false");
|
||||
newMenu1.setAttribute("hidden", "false");
|
||||
forceUpdateNativeMenuAt("1");
|
||||
|
||||
onTestsFinished();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user