From 7e65db1e9d22e53415e412a9dcc5cc14904edf35 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 25 Jul 2008 16:32:41 +1200 Subject: [PATCH] Back out bug 442972 to fix DOM Inspector (bug 447042). --- dom/public/idl/base/nsIDOMWindowUtils.idl | 10 - dom/src/base/nsDOMWindowUtils.cpp | 18 -- widget/public/nsIWidget.h | 8 - widget/src/cocoa/nsChildView.h | 3 +- widget/src/cocoa/nsChildView.mm | 34 +-- widget/src/cocoa/nsMenuBarX.h | 13 +- widget/src/cocoa/nsMenuBarX.mm | 166 +++++-------- widget/src/cocoa/nsMenuX.h | 9 +- widget/src/cocoa/nsMenuX.mm | 56 +++-- widget/src/xpwidgets/nsBaseWidget.h | 1 - widget/tests/native_menus_window.xul | 390 +++++++++--------------------- 11 files changed, 220 insertions(+), 488 deletions(-) rewrite widget/tests/native_menus_window.xul (66%) diff --git a/dom/public/idl/base/nsIDOMWindowUtils.idl b/dom/public/idl/base/nsIDOMWindowUtils.idl index 3387e8d5b4..860c67ec80 100644 --- a/dom/public/idl/base/nsIDOMWindowUtils.idl +++ b/dom/public/idl/base/nsIDOMWindowUtils.idl @@ -197,16 +197,6 @@ interface nsIDOMWindowUtils : nsISupports { void activateNativeMenuItemAt(in AString indexString); /** - * See nsIWidget::ForceNativeMenuReload - * - * This is used for native menu system testing. Calling this forces a full - * reload of the menu system, reloading all native menus and their items. - * This is important for testing because changes to the DOM can affect the - * native menu system lazily. - */ - void forceNativeMenuReload(); - - /** * Focus the element aElement. The element should be in the same document * that the window is displaying. Pass null to blur the element, if any, * that currently has focus, and focus the document. diff --git a/dom/src/base/nsDOMWindowUtils.cpp b/dom/src/base/nsDOMWindowUtils.cpp index 88760ef70d..a9a24f94e7 100644 --- a/dom/src/base/nsDOMWindowUtils.cpp +++ b/dom/src/base/nsDOMWindowUtils.cpp @@ -367,24 +367,6 @@ nsDOMWindowUtils::ActivateNativeMenuItemAt(const nsAString& indexString) return widget->ActivateNativeMenuItemAt(indexString); } - -NS_IMETHODIMP -nsDOMWindowUtils::ForceNativeMenuReload() -{ - PRBool hasCap = PR_FALSE; - if (NS_FAILED(nsContentUtils::GetSecurityManager()->IsCapabilityEnabled("UniversalXPConnect", &hasCap)) - || !hasCap) - return NS_ERROR_DOM_SECURITY_ERR; - - // get the widget to send the event to - nsCOMPtr widget = GetWidget(); - if (!widget) - return NS_ERROR_FAILURE; - - return widget->ForceNativeMenuReload(); -} - - nsIWidget* nsDOMWindowUtils::GetWidget() { diff --git a/widget/public/nsIWidget.h b/widget/public/nsIWidget.h index 729b7e9a63..e72f474cd9 100644 --- a/widget/public/nsIWidget.h +++ b/widget/public/nsIWidget.h @@ -1196,14 +1196,6 @@ class nsIWidget : public nsISupports { */ NS_IMETHOD GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState) = 0; - /** - * This is used for native menu system testing. Calling this forces a full - * reload of the menu system, reloading all native menus and their items. - * This is important for testing because changes to the DOM can affect the - * native menu system lazily. - */ - virtual nsresult ForceNativeMenuReload() = 0; - protected: // keep the list of children. We also keep track of our siblings. // The ownership model is as follows: parent holds a strong ref to diff --git a/widget/src/cocoa/nsChildView.h b/widget/src/cocoa/nsChildView.h index fb7208118d..e9e28f0878 100644 --- a/widget/src/cocoa/nsChildView.h +++ b/widget/src/cocoa/nsChildView.h @@ -331,8 +331,7 @@ public: NS_IMETHOD GetAttention(PRInt32 aCycleCount); - NS_IMETHOD ActivateNativeMenuItemAt(const nsAString& indexString); - NS_IMETHOD ForceNativeMenuReload(); + NS_IMETHOD ActivateNativeMenuItemAt(const nsAString& indexString); NS_IMETHOD ResetInputState(); NS_IMETHOD SetIMEOpenState(PRBool aState); diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm index 7c943d7407..fd31b7176d 100644 --- a/widget/src/cocoa/nsChildView.mm +++ b/widget/src/cocoa/nsChildView.mm @@ -1380,9 +1380,7 @@ nsresult nsChildView::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout, // Used for testing native menu system structure and event handling. NS_IMETHODIMP nsChildView::ActivateNativeMenuItemAt(const nsAString& indexString) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - +{ NSString* title = [NSString stringWithCharacters:indexString.BeginReading() length:indexString.Length()]; NSArray* indexes = [title componentsSeparatedByString:@"|"]; unsigned int indexCount = [indexes count]; @@ -1413,40 +1411,18 @@ NS_IMETHODIMP nsChildView::ActivateNativeMenuItemAt(const nsAString& indexString int itemCount = [currentSubmenu numberOfItems]; int targetIndex = [[indexes objectAtIndex:(indexCount - 1)] intValue]; - // We can't perform an action on an item with a submenu, that will raise - // an obj-c exception. - if (targetIndex < itemCount && ![[currentSubmenu itemAtIndex:targetIndex] hasSubmenu]) { - // NSLog(@"Performing action for native menu item titled: %@\n", - // [[currentSubmenu itemAtIndex:targetIndex] title]); - [currentSubmenu performActionForItemAtIndex:targetIndex]; + if (targetIndex < itemCount) { + // NSLog(@"Performing action for native menu item titled: %@\n", + // [[currentSubmenu itemAtIndex:targetIndex] title]); + [currentSubmenu performActionForItemAtIndex:targetIndex]; } else { return NS_ERROR_FAILURE; } return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - - -NS_IMETHODIMP nsChildView::ForceNativeMenuReload() -{ - id windowDelegate = [[mView nativeWindow] delegate]; - if (windowDelegate && [windowDelegate isKindOfClass:[WindowDelegate class]]) { - nsCocoaWindow *widget = [(WindowDelegate *)windowDelegate geckoWidget]; - if (widget) { - nsMenuBarX* mb = widget->GetMenuBar(); - if (mb) { - mb->ForceNativeMenuReload(); - } - } - } - - return NS_OK; } - #pragma mark - diff --git a/widget/src/cocoa/nsMenuBarX.h b/widget/src/cocoa/nsMenuBarX.h index 4774cde03e..bc456e169d 100644 --- a/widget/src/cocoa/nsMenuBarX.h +++ b/widget/src/cocoa/nsMenuBarX.h @@ -106,7 +106,7 @@ public: NS_DECL_NSIMUTATIONOBSERVER // nsMenuObjectX - void* NativeData() {return (void*)mNativeMenu;} + void* NativeData() {return (void*)mRootMenu;} nsMenuObjectTypeX MenuObjectType() {return eMenuBarObjectType;} // nsMenuBarX @@ -120,13 +120,10 @@ public: nsMenuX* GetMenuAt(PRUint32 aIndex); nsMenuItemX* GetMenuItemForCommandID(PRUint32 inCommandID); nsresult Paint(); - void ForceNativeMenuReload(); // used for testing protected: - void ConstructNativeMenus(); - bool MenuContainsAppMenu(); - nsresult InsertMenuAtIndex(nsMenuX* aMenu, PRUint32 aIndex); - void RemoveMenuAtIndex(PRUint32 aIndex); + nsresult AddMenu(nsMenuX* aMenu); + void RemoveMenu(PRUint32 aIndex); nsChangeObserver* LookupContentChangeObserver(nsIContent* aContent); void HideItem(nsIDOMDocument* inDoc, const nsAString & inID, nsIContent** outHiddenNode); void AquifyMenuBar(); @@ -135,10 +132,10 @@ protected: nsresult CreateApplicationMenu(nsMenuX* inMenu); nsTArray< nsAutoPtr > mMenuArray; - nsIWidget* mParentWindow; // [weak] + nsIWidget* mParent; // [weak] PRUint32 mCurrentCommandID; // unique command id (per menu-bar) to give to next item that asks nsIDocument* mDocument; // pointer to document - GeckoNSMenu* mNativeMenu; // root menu, representing entire menu bar + GeckoNSMenu* mRootMenu; // root menu, representing entire menu bar nsHashtable mObserverTable; // stores observers for content change notification }; diff --git a/widget/src/cocoa/nsMenuBarX.mm b/widget/src/cocoa/nsMenuBarX.mm index 9f7847cd0f..dc1764d3cb 100644 --- a/widget/src/cocoa/nsMenuBarX.mm +++ b/widget/src/cocoa/nsMenuBarX.mm @@ -98,13 +98,13 @@ NS_IMETHODIMP nsNativeMenuServiceX::CreateNativeMenuBar(nsIWidget* aParent, nsIC nsMenuBarX::nsMenuBarX() -: mParentWindow(nsnull), +: mParent(nsnull), mCurrentCommandID(eCommand_ID_Last), mDocument(nsnull) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - mNativeMenu = [[GeckoNSMenu alloc] initWithTitle:@"MainMenuBar"]; + mRootMenu = [[GeckoNSMenu alloc] initWithTitle:@"MainMenuBar"]; NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -136,7 +136,7 @@ nsMenuBarX::~nsMenuBarX() // before the registration hash table is destroyed. mMenuArray.Clear(); - [mNativeMenu release]; + [mRootMenu release]; NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -147,7 +147,7 @@ nsresult nsMenuBarX::Create(nsIWidget* aParent, nsIContent* aContent) if (!aParent || !aContent) return NS_ERROR_INVALID_ARG; - mParentWindow = aParent; + mParent = aParent; mContent = aContent; AquifyMenuBar(); @@ -158,31 +158,28 @@ nsresult nsMenuBarX::Create(nsIWidget* aParent, nsIContent* aContent) doc->AddMutationObserver(this); mDocument = doc; - ConstructNativeMenus(); - - // Give this to the parent window. The parent takes ownership. - return mParentWindow->SetMenuBar(this); -} - - -void nsMenuBarX::ConstructNativeMenus() -{ PRUint32 count = mContent->GetChildCount(); for (PRUint32 i = 0; i < count; i++) { nsIContent *menuContent = mContent->GetChildAt(i); - if (menuContent && - menuContent->Tag() == nsWidgetAtoms::menu && - menuContent->IsNodeOfType(nsINode::eXUL)) { - nsMenuX* newMenu = new nsMenuX(); - if (newMenu) { - nsresult rv = newMenu->Create(this, this, menuContent); - if (NS_SUCCEEDED(rv)) - InsertMenuAtIndex(newMenu, GetMenuCount()); - else - delete newMenu; + if (menuContent) { + if (menuContent->Tag() == nsWidgetAtoms::menu && + menuContent->IsNodeOfType(nsINode::eXUL)) { + nsAutoString menuName; + menuContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::label, menuName); + nsMenuX* newMenu = new nsMenuX(); + if (newMenu) { + nsresult rv = newMenu->Create(this, menuName, this, menuContent); + if (NS_SUCCEEDED(rv)) + AddMenu(newMenu); + else + delete newMenu; + } } } - } + } + + // Give this to the parent window. The parent takes ownership. + return mParent->SetMenuBar(this); } @@ -192,18 +189,7 @@ PRUint32 nsMenuBarX::GetMenuCount() } -bool nsMenuBarX::MenuContainsAppMenu() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return ([mNativeMenu numberOfItems] > 0 && - [[mNativeMenu itemAtIndex:0] submenu] == sApplicationMenu); - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); -} - - -nsresult nsMenuBarX::InsertMenuAtIndex(nsMenuX* aMenu, PRUint32 aIndex) +nsresult nsMenuBarX::AddMenu(nsMenuX* aMenu) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; @@ -219,19 +205,16 @@ nsresult nsMenuBarX::InsertMenuAtIndex(nsMenuX* aMenu, PRUint32 aIndex) [[mainMenu itemAtIndex:0] setSubmenu:sApplicationMenu]; } - // add menu to array that owns our menus - mMenuArray.InsertElementAt(aIndex, aMenu); + // keep track of all added menus + mMenuArray.AppendElement(aMenu); // owner - // hook up submenus + NSMenu* nativeMenu = (NSMenu*)aMenu->NativeData(); nsIContent* menuContent = aMenu->Content(); if (menuContent->GetChildCount() > 0 && !nsMenuUtilsX::NodeIsHiddenOrCollapsed(menuContent)) { - NSMenuItem* newMenuItem = aMenu->NativeMenuItem(); - // If the application menu is in our menu bar we need to insert past it - PRUint32 targetIndex = aIndex; - if (MenuContainsAppMenu()) - targetIndex++; - [mNativeMenu insertItem:newMenuItem atIndex:targetIndex]; + NSMenuItem* newMenuItem = [[[NSMenuItem alloc] initWithTitle:[nativeMenu title] action:NULL keyEquivalent:@""] autorelease]; + [mRootMenu addItem:newMenuItem]; + [newMenuItem setSubmenu:nativeMenu]; } return NS_OK; @@ -240,7 +223,7 @@ nsresult nsMenuBarX::InsertMenuAtIndex(nsMenuX* aMenu, PRUint32 aIndex) } -void nsMenuBarX::RemoveMenuAtIndex(PRUint32 aIndex) +void nsMenuBarX::RemoveMenu(PRUint32 aIndex) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; @@ -249,32 +232,13 @@ void nsMenuBarX::RemoveMenuAtIndex(PRUint32 aIndex) // Our native menu and our internal menu object array might be out of sync. // This happens, for example, when a submenu is hidden. Because of this we // should not assume that a native submenu is hooked up. - NSMenuItem* nativeMenuItem = mMenuArray[aIndex]->NativeMenuItem(); - int nativeMenuItemIndex = [mNativeMenu indexOfItem:nativeMenuItem]; - if (nativeMenuItemIndex != -1) - [mNativeMenu removeItemAtIndex:nativeMenuItemIndex]; - + [mRootMenu removeItem:(mMenuArray[aIndex]->NativeMenuItem())]; mMenuArray.RemoveElementAt(aIndex); NS_OBJC_END_TRY_ABORT_BLOCK; } -// Calling this forces a full reload of the menu system, reloading all native -// menus and their items. -// Without this testing is hard because changes to the DOM affect the native -// menu system lazily. -void nsMenuBarX::ForceNativeMenuReload() -{ - // tear down everything - while (GetMenuCount() > 0) - RemoveMenuAtIndex(0); - - // construct everything - ConstructNativeMenus(); -} - - nsMenuX* nsMenuBarX::GetMenuAt(PRUint32 aIndex) { if (mMenuArray.Length() <= aIndex) { @@ -288,22 +252,20 @@ nsMenuX* nsMenuBarX::GetMenuAt(PRUint32 aIndex) nsresult nsMenuBarX::Paint() { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; + + NSMenu* mainMenu = [NSApp mainMenu]; + NS_ASSERTION([mainMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!"); - NSMenu* outgoingMenu = [NSApp mainMenu]; - NS_ASSERTION([outgoingMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!"); + // Swap out first item into incoming menu bar. We have to keep the same menu item for the + // Application menu and its submenu is global so we keep passing it along. + NSMenuItem* firstMenuItem = [[mainMenu itemAtIndex:0] retain]; + [mainMenu removeItemAtIndex:0]; + [mRootMenu insertItem:firstMenuItem atIndex:0]; + [firstMenuItem release]; - // We have to keep the same menu item for the Application menu so we keep - // passing it along. - if (sLastGeckoMenuBarPainted != this) { - NSMenuItem* appMenuItem = [[outgoingMenu itemAtIndex:0] retain]; - [outgoingMenu removeItemAtIndex:0]; - [mNativeMenu insertItem:appMenuItem atIndex:0]; - [appMenuItem release]; - - // Set menu bar and event target. - [NSApp setMainMenu:mNativeMenu]; - nsMenuBarX::sLastGeckoMenuBarPainted = this; - } + // Set menu bar and event target. + [NSApp setMainMenu:mRootMenu]; + nsMenuBarX::sLastGeckoMenuBarPainted = this; gSomeMenuBarPainted = YES; @@ -592,15 +554,13 @@ nsresult nsMenuBarX::CreateApplicationMenu(nsMenuX* inMenu) void nsMenuBarX::SetParent(nsIWidget* aParent) { - mParentWindow = aParent; + mParent = aParent; } - // // nsIMutationObserver // - void nsMenuBarX::CharacterDataWillChange(nsIDocument* aDocument, nsIContent* aContent, CharacterDataChangeInfo* aInfo) @@ -618,18 +578,24 @@ void nsMenuBarX::CharacterDataChanged(nsIDocument* aDocument, void nsMenuBarX::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer, PRInt32 aNewIndexInContainer) { - PRUint32 childCount = aContainer->GetChildCount(); - while ((PRUint32)aNewIndexInContainer < childCount) { - nsIContent *child = aContainer->GetChildAt(aNewIndexInContainer); - ContentInserted(aDocument, aContainer, child, aNewIndexInContainer); - aNewIndexInContainer++; + if (aContainer != mContent) { + nsChangeObserver* obs = LookupContentChangeObserver(aContainer); + if (obs) + obs->ObserveContentInserted(aDocument, aContainer, aNewIndexInContainer); + else { + nsCOMPtr parent = aContainer->GetParent(); + if (parent) { + obs = LookupContentChangeObserver(parent); + if (obs) + obs->ObserveContentInserted(aDocument, aContainer, aNewIndexInContainer); + } + } } } void nsMenuBarX::NodeWillBeDestroyed(const nsINode * aNode) { - // our menu bar node is being destroyed mDocument = nsnull; } @@ -638,6 +604,7 @@ void nsMenuBarX::AttributeChanged(nsIDocument * aDocument, nsIContent * aContent PRInt32 aNameSpaceID, nsIAtom * aAttribute, PRInt32 aModType, PRUint32 aStateMask) { + // lookup and dispatch to registered thang nsChangeObserver* obs = LookupContentChangeObserver(aContent); if (obs) obs->ObserveAttributeChanged(aDocument, aContent, aAttribute); @@ -648,7 +615,8 @@ void nsMenuBarX::ContentRemoved(nsIDocument * aDocument, nsIContent * aContainer nsIContent * aChild, PRInt32 aIndexInContainer) { if (aContainer == mContent) { - RemoveMenuAtIndex(aIndexInContainer); + UnregisterForContentChanges(aChild); + RemoveMenu(aIndexInContainer); } else { nsChangeObserver* obs = LookupContentChangeObserver(aContainer); @@ -656,9 +624,6 @@ void nsMenuBarX::ContentRemoved(nsIDocument * aDocument, nsIContent * aContainer obs->ObserveContentRemoved(aDocument, aChild, aIndexInContainer); } else { - // We do a lookup on the parent container in case things were removed - // under a "menupopup" item. That is basically a wrapper for the contents - // of a "menu" node. nsCOMPtr parent = aContainer->GetParent(); if (parent) { obs = LookupContentChangeObserver(parent); @@ -673,24 +638,11 @@ void nsMenuBarX::ContentRemoved(nsIDocument * aDocument, nsIContent * aContainer void nsMenuBarX::ContentInserted(nsIDocument * aDocument, nsIContent * aContainer, nsIContent * aChild, PRInt32 aIndexInContainer) { - if (aContainer == mContent) { - nsMenuX* newMenu = new nsMenuX(); - if (newMenu) { - nsresult rv = newMenu->Create(this, this, aChild); - if (NS_SUCCEEDED(rv)) - InsertMenuAtIndex(newMenu, aIndexInContainer); - else - delete newMenu; - } - } - else { + if (aContainer != mContent) { nsChangeObserver* obs = LookupContentChangeObserver(aContainer); if (obs) obs->ObserveContentInserted(aDocument, aChild, aIndexInContainer); else { - // We do a lookup on the parent container in case things were removed - // under a "menupopup" item. That is basically a wrapper for the contents - // of a "menu" node. nsCOMPtr parent = aContainer->GetParent(); if (parent) { obs = LookupContentChangeObserver(parent); diff --git a/widget/src/cocoa/nsMenuX.h b/widget/src/cocoa/nsMenuX.h index 33440ab687..a73c4b6c84 100644 --- a/widget/src/cocoa/nsMenuX.h +++ b/widget/src/cocoa/nsMenuX.h @@ -83,11 +83,12 @@ public: NS_DECL_CHANGEOBSERVER // nsMenuObjectX - void* NativeData() {return (void*)mNativeMenu;} + void* NativeData() {return (void*)mMacMenu;} nsMenuObjectTypeX MenuObjectType() {return eSubmenuObjectType;} // nsMenuX - nsresult Create(nsMenuObjectX* aParent, nsMenuBarX* aMenuBar, nsIContent* aNode); + nsresult Create(nsMenuObjectX* aParent, const nsAString &aLabel, + nsMenuBarX* aMenuBar, nsIContent* aNode); PRUint32 GetItemCount(); nsMenuObjectX* GetItemAt(PRUint32 aPos); nsresult GetVisibleItemCount(PRUint32 &aCount); @@ -98,7 +99,7 @@ public: NSMenuItem* NativeMenuItem(); protected: - void MenuConstruct(); + void MenuConstruct(nsIWidget* aParentWindow, void* aMenuNode); nsresult RemoveAll(); nsresult SetEnabled(PRBool aIsEnabled); nsresult GetEnabled(PRBool* aIsEnabled); @@ -121,7 +122,7 @@ protected: nsMenuObjectX* mParent; // [weak] nsMenuBarX* mMenuBar; // [weak] nsRefPtr mIcon; - GeckoNSMenu* mNativeMenu; // [strong] + GeckoNSMenu* mMacMenu; // [strong] MenuDelegate* mMenuDelegate; // [strong] NSMenuItem* mNativeMenuItem; // [strong] PRPackedBool mIsEnabled; diff --git a/widget/src/cocoa/nsMenuX.mm b/widget/src/cocoa/nsMenuX.mm index 291e8028d1..a3b47fe8ac 100644 --- a/widget/src/cocoa/nsMenuX.mm +++ b/widget/src/cocoa/nsMenuX.mm @@ -84,7 +84,7 @@ PRInt32 nsMenuX::sIndexingMenuLevel = 0; nsMenuX::nsMenuX() : mVisibleItemsCount(0), mParent(nsnull), mMenuBar(nsnull), - mNativeMenu(nil), mNativeMenuItem(nil), mIsEnabled(PR_TRUE), + mMacMenu(nil), mNativeMenuItem(nil), mIsEnabled(PR_TRUE), mDestroyHandlerCalled(PR_FALSE), mNeedsRebuild(PR_TRUE), mConstructed(PR_FALSE), mVisible(PR_TRUE), mXBLAttached(PR_FALSE) { @@ -118,8 +118,8 @@ nsMenuX::~nsMenuX() RemoveAll(); - [mNativeMenu setDelegate:nil]; - [mNativeMenu release]; + [mMacMenu setDelegate:nil]; + [mMacMenu release]; [mMenuDelegate release]; [mNativeMenuItem release]; @@ -133,13 +133,14 @@ nsMenuX::~nsMenuX() } -nsresult nsMenuX::Create(nsMenuObjectX* aParent, nsMenuBarX* aMenuBar, nsIContent* aNode) +nsresult nsMenuX::Create(nsMenuObjectX* aParent, const nsAString& aLabel, + nsMenuBarX* aMenuBar, nsIContent* aNode) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; mContent = aNode; - mContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::label, mLabel); - mNativeMenu = CreateMenuWithGeckoString(mLabel); + mLabel = aLabel; + mMacMenu = CreateMenuWithGeckoString(mLabel); // register this menu to be notified when changes are made to our content object mMenuBar = aMenuBar; // weak ref @@ -163,7 +164,6 @@ nsresult nsMenuX::Create(nsMenuObjectX* aParent, nsMenuBarX* aMenuBar, nsIConten NSString *newCocoaLabelString = nsMenuUtilsX::CreateTruncatedCocoaLabel(mLabel); mNativeMenuItem = [[NSMenuItem alloc] initWithTitle:newCocoaLabelString action:nil keyEquivalent:@""]; [newCocoaLabelString release]; - [mNativeMenuItem setSubmenu:mNativeMenu]; [mNativeMenuItem setEnabled:(BOOL)mIsEnabled]; @@ -171,7 +171,7 @@ nsresult nsMenuX::Create(nsMenuObjectX* aParent, nsMenuBarX* aMenuBar, nsIConten // native menu items being created. If we only call MenuConstruct when a menu // is actually selected, then we can't access keyboard commands until the // menu gets selected, which is bad. - MenuConstruct(); + MenuConstruct(nsnull, nsnull); mIcon = new nsMenuItemIconX(this, mContent, mNativeMenuItem); @@ -196,7 +196,7 @@ nsresult nsMenuX::AddMenuItem(nsMenuItemX* aMenuItem) NSMenuItem* newNativeMenuItem = (NSMenuItem*)aMenuItem->NativeData(); // add the menu item to this menu - [mNativeMenu addItem:newNativeMenuItem]; + [mMacMenu addItem:newNativeMenuItem]; // set up target/action [newNativeMenuItem setTarget:nsMenuBarX::sNativeEventTarget]; @@ -225,10 +225,10 @@ nsresult nsMenuX::AddMenu(nsMenuX* aMenu) ++mVisibleItemsCount; // We have to add a menu item and then associate the menu with it - NSMenuItem* newNativeMenuItem = aMenu->NativeMenuItem(); + NSMenuItem* newNativeMenuItem = (static_cast(aMenu))->NativeMenuItem(); if (!newNativeMenuItem) return NS_ERROR_FAILURE; - [mNativeMenu addItem:newNativeMenuItem]; + [mMacMenu addItem:newNativeMenuItem]; [newNativeMenuItem setSubmenu:(NSMenu*)aMenu->NativeData()]; @@ -306,14 +306,14 @@ nsresult nsMenuX::RemoveAll() { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - if (mNativeMenu) { + if (mMacMenu) { // clear command id's - int itemCount = [mNativeMenu numberOfItems]; + int itemCount = [mMacMenu numberOfItems]; for (int i = 0; i < itemCount; i++) - mMenuBar->UnregisterCommand((PRUint32)[[mNativeMenu itemAtIndex:i] tag]); + mMenuBar->UnregisterCommand((PRUint32)[[mMacMenu itemAtIndex:i] tag]); // get rid of Cocoa menu items - for (int i = [mNativeMenu numberOfItems] - 1; i >= 0; i--) - [mNativeMenu removeItemAtIndex:i]; + for (int i = [mMacMenu numberOfItems] - 1; i >= 0; i--) + [mMacMenu removeItemAtIndex:i]; } mMenuObjectsArray.Clear(); @@ -334,7 +334,7 @@ nsEventStatus nsMenuX::MenuOpened(const nsMenuEvent & aMenuEvent) // at this point, the carbon event handler was installed so there // must be a carbon MenuRef to be had - if (_NSGetCarbonMenu(mNativeMenu) == selectedMenuHandle) { + if (_NSGetCarbonMenu(mMacMenu) == selectedMenuHandle) { // Open the node. mContent->SetAttr(kNameSpaceID_None, nsWidgetAtoms::open, NS_LITERAL_STRING("true"), PR_TRUE); @@ -348,7 +348,7 @@ nsEventStatus nsMenuX::MenuOpened(const nsMenuEvent & aMenuEvent) if (mNeedsRebuild) RemoveAll(); - MenuConstruct(); + MenuConstruct(nsnull, nsnull); mConstructed = true; } @@ -394,16 +394,16 @@ void nsMenuX::MenuClosed(const nsMenuEvent & aMenuEvent) } -void nsMenuX::MenuConstruct() +void nsMenuX::MenuConstruct(nsIWidget* aParentWindow, void* aMenuNode) { mConstructed = false; gConstructingMenu = PR_TRUE; // reset destroy handler flag so that we'll know to fire it next time this menu goes away. mDestroyHandlerCalled = PR_FALSE; - - //printf("nsMenuX::MenuConstruct called for %s = %d \n", NS_LossyConvertUTF16toASCII(mLabel).get(), mNativeMenu); - + + //printf("nsMenuX::MenuConstruct called for %s = %d \n", NS_LossyConvertUTF16toASCII(mLabel).get(), mMacMenu); + // Retrieve our menupopup. nsCOMPtr menuPopup; GetMenuPopupContent(getter_AddRefs(menuPopup)); @@ -551,11 +551,15 @@ void nsMenuX::LoadMenuItem(nsIContent* inMenuItemContent) void nsMenuX::LoadSubMenu(nsIContent* inMenuContent) { + nsAutoString menuName; + inMenuContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::label, menuName); + //printf("Creating Menu [%s] \n", NS_LossyConvertUTF16toASCII(menuName).get()); + nsAutoPtr menu(new nsMenuX()); if (!menu) return; - nsresult rv = menu->Create(this, mMenuBar, inMenuContent); + nsresult rv = menu->Create(this, menuName, mMenuBar, inMenuContent); if (NS_FAILED(rv)) return; @@ -835,9 +839,9 @@ void nsMenuX::ObserveAttributeChanged(nsIDocument *aDocument, nsIContent *aConte // a regular menu, just change the title and redraw the menubar. if (parentType == eMenuBarObjectType) { // reuse the existing menu, to avoid rebuilding the root menu bar. - NS_ASSERTION(mNativeMenu, "nsMenuX::AttributeChanged: invalid menu handle."); + NS_ASSERTION(mMacMenu, "nsMenuX::AttributeChanged: invalid menu handle."); NSString *newCocoaLabelString = nsMenuUtilsX::CreateTruncatedCocoaLabel(mLabel); - [mNativeMenu setTitle:newCocoaLabelString]; + [mMacMenu setTitle:newCocoaLabelString]; [newCocoaLabelString release]; } else { @@ -869,7 +873,7 @@ void nsMenuX::ObserveAttributeChanged(nsIDocument *aDocument, nsIContent *aConte if (parentType == eMenuBarObjectType || parentType == eSubmenuObjectType) { NSMenu* parentMenu = (NSMenu*)mParent->NativeData(); [parentMenu insertItem:mNativeMenuItem atIndex:insertAfter]; - [mNativeMenuItem setSubmenu:mNativeMenu]; + [mNativeMenuItem setSubmenu:mMacMenu]; mVisible = PR_TRUE; } } diff --git a/widget/src/xpwidgets/nsBaseWidget.h b/widget/src/xpwidgets/nsBaseWidget.h index 376c9f3210..0b5ff723e4 100644 --- a/widget/src/xpwidgets/nsBaseWidget.h +++ b/widget/src/xpwidgets/nsBaseWidget.h @@ -137,7 +137,6 @@ public: virtual void FreeNativeData(void * data, PRUint32 aDataType) {} NS_IMETHOD BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical); virtual nsresult ActivateNativeMenuItemAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; } - virtual nsresult ForceNativeMenuReload() { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHOD ResetInputState() { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHOD SetIMEOpenState(PRBool aState) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHOD GetIMEOpenState(PRBool* aState) { return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/widget/tests/native_menus_window.xul b/widget/tests/native_menus_window.xul dissimilarity index 66% index 6c461e8a98..26e6f6730e 100644 --- a/widget/tests/native_menus_window.xul +++ b/widget/tests/native_menus_window.xul @@ -1,275 +1,115 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.11.4.GIT