diff --git a/mozilla/widget/src/cocoa/nsChildView.mm b/mozilla/widget/src/cocoa/nsChildView.mm index 57c06248b35..491b4d91cec 100644 --- a/mozilla/widget/src/cocoa/nsChildView.mm +++ b/mozilla/widget/src/cocoa/nsChildView.mm @@ -174,23 +174,6 @@ nsIWidget * gRollupWidget = nsnull; @end -// Used to retain an NSView for the remainder of a method's execution. -class nsAutoRetainView { -public: - nsAutoRetainView(NSView *aView) - { - mView = NS_OBJC_TRY_EXPR_ABORT([aView retain]); - } - ~nsAutoRetainView() - { - NS_OBJC_TRY_ABORT([mView release]); - } - -private: - NSView *mView; // [STRONG] -}; - - #pragma mark - @@ -838,7 +821,7 @@ NS_IMETHODIMP nsChildView::SetFocus(PRBool aRaise) mInSetFocus = PR_TRUE; NSWindow* window = [mView window]; if (window) { - nsAutoRetainView kungFuDeathGrip(mView); + nsAutoRetainCocoaObject kungFuDeathGrip(mView); // For reasons that aren't yet clear, focus changes within a window (as // opposed to those between windows or between apps) should only trigger // NS_LOSTFOCUS and NS_GOTFOCUS events (sent to Gecko) in the context of @@ -2557,7 +2540,7 @@ NSEvent* gLastDragEvent = nil; paintEvent.rect = &fullRect; paintEvent.region = rgn; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); mGeckoChild->DispatchWindowEvent(paintEvent); if (!mGeckoChild) return; @@ -2814,7 +2797,7 @@ NSEvent* gLastDragEvent = nil; if (![self ensureCorrectMouseEventTarget:theEvent]) return; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); if ([self maybeRollup:theEvent]) return; @@ -3003,7 +2986,7 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted, if (!mGeckoChild) return; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); if (sLastViewEntered != self) { if (sLastViewEntered) { NSPoint exitEventLocation = [sLastViewEntered convertPoint:windowEventLocation fromView:nil]; @@ -3107,7 +3090,7 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted, if (![self ensureCorrectMouseEventTarget:theEvent]) return; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); [self maybeRollup:theEvent]; if (!mGeckoChild) @@ -3163,7 +3146,7 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted, macEvent.modifiers = controlKey; // fake a context menu click geckoEvent.nativeMsg = &macEvent; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); PRBool handled = mGeckoChild->DispatchMouseEvent(geckoEvent); if (!mGeckoChild) return; @@ -3200,7 +3183,7 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted, if (![self ensureCorrectMouseEventTarget:theEvent]) return; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); if ([self maybeRollup:theEvent]) return; @@ -3281,7 +3264,7 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted, else geckoEvent.delta = (PRInt32)ceilf(scrollDelta); - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); mGeckoChild->DispatchWindowEvent(geckoEvent); if (!mGeckoChild) return; @@ -3336,7 +3319,7 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted, { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); if ([self maybeRollup:theEvent]) return; @@ -3364,7 +3347,7 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted, if (!mGeckoChild || [self isPluginView]) return nil; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); [self maybeRollup:theEvent]; if (!mGeckoChild) @@ -3982,7 +3965,7 @@ static PRBool IsNormalCharInputtingEvent(const nsKeyEvent& aEvent) if (!mGeckoChild) return; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); id arp = [[NSAutoreleasePool alloc] init]; if (![insertString isKindOfClass:[NSAttributedString class]]) @@ -4111,7 +4094,7 @@ static PRBool IsNormalCharInputtingEvent(const nsKeyEvent& aEvent) NSLog(@" aString = '%@'", aString); #endif - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); id arp = [[NSAutoreleasePool alloc] init]; if (![aString isKindOfClass:[NSAttributedString class]]) @@ -4402,7 +4385,7 @@ static PRBool IsNormalCharInputtingEvent(const nsKeyEvent& aEvent) if (!mGeckoChild) return NO; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); mCurKeyEvent = theEvent; BOOL nonDeadKeyPress = [[theEvent characters] length] > 0; @@ -4536,7 +4519,7 @@ static BOOL keyUpAlreadySentKeyDown = NO; if (!mGeckoChild || [[theEvent characters] length] == 0) return; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); // Cocoa doesn't send an NSKeyDown event for control-tab on 10.4, so if this // is an NSKeyUp event for control-tab, send a down event to gecko first. @@ -4613,46 +4596,32 @@ static BOOL keyUpAlreadySentKeyDown = NO; if (!mGeckoChild) return NO; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); // if we aren't the first responder, pass the event on - if ([[self window] firstResponder] != self) - return [super performKeyEquivalent:theEvent]; + id firstResponder = [[self window] firstResponder]; + if (firstResponder != self) { + if ([firstResponder isKindOfClass:[ChildView class]]) + return [(ChildView *)firstResponder performKeyEquivalent:theEvent]; + else + return [super performKeyEquivalent:theEvent]; + } // don't process if we're composing, but don't consume the event if (nsTSMManager::IsComposing()) return NO; - unsigned int modifierFlags = [theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask; - - // see if the menu system will handle the event - if ([[NSApp mainMenu] performKeyEquivalent:theEvent]) { - return YES; - } - else { - // On Mac OS X 10.5 NSMenu's performKeyEquivalent: method returns NO for disabled menu - // items that have a matching key equiv. We need to know if that was the case so we can - // stop here like we would on 10.4 (it returns YES in that case). Since we want to eat - // the event if that happens the system won't give the disabled command beep, do it here - // manually. - if (nsToolkit::OnLeopardOrLater()) { - id delegate = [[self window] delegate]; - if (delegate && [delegate isKindOfClass:[WindowDelegate class]]) { - nsCocoaWindow* toplevelWindow = [delegate geckoWidget]; - if (toplevelWindow) { - nsMenuBarX* menuBar = static_cast(toplevelWindow->GetMenuBar()); - if (menuBar && menuBar->ContainsKeyEquiv(modifierFlags, [theEvent characters])) { - NSBeep(); - return YES; - } - } - } - } - } + // Perform native menu UI feedback even if we stop the event from propagating to it normally. + // Recall that the menu system won't actually execute any commands for keyboard command invocations. + // By checking the class for the main menu we ensure that we don't do any of this for embedders. + NSMenu* mainMenu = [NSApp mainMenu]; + if ([mainMenu isKindOfClass:[GeckoNSMenu class]]) + [(GeckoNSMenu*)mainMenu performMenuUserInterfaceEffectsForEvent:theEvent]; // don't handle this if certain modifiers are down - those should // be sent as normal key up/down events and cocoa will do so automatically // if we reject here + unsigned int modifierFlags = [theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask; if ((modifierFlags & NSFunctionKeyMask) || (modifierFlags & NSNumericPadKeyMask)) return NO; @@ -4677,7 +4646,7 @@ static BOOL keyUpAlreadySentKeyDown = NO; if (!mGeckoChild) return; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); // Fire key up/down events for the modifier keys (shift, alt, ctrl, command). if ([theEvent type] == NSFlagsChanged) { @@ -4745,7 +4714,7 @@ static BOOL keyUpAlreadySentKeyDown = NO; if (!mGeckoChild) return; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); // check to see if the window implements the mozWindow protocol. This // allows embedders to avoid re-entrant calls to -makeKeyAndOrderFront, @@ -4770,7 +4739,7 @@ static BOOL keyUpAlreadySentKeyDown = NO; if (!mGeckoChild) return; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); [self sendFocusEvent:NS_DEACTIVATE]; [self sendFocusEvent:NS_LOSTFOCUS]; @@ -4866,7 +4835,7 @@ static BOOL keyUpAlreadySentKeyDown = NO; geckoEvent.refPoint.x = static_cast(localPoint.x); geckoEvent.refPoint.y = static_cast(localPoint.y); - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); mGeckoChild->DispatchWindowEvent(geckoEvent); if (!mGeckoChild) return YES; @@ -4925,7 +4894,7 @@ static BOOL keyUpAlreadySentKeyDown = NO; { PR_LOG(sCocoaLog, PR_LOG_ALWAYS, ("ChildView draggingExited: entered\n")); - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); [self doDragAction:NS_DRAGDROP_EXIT sender:sender]; NS_IF_RELEASE(mDragService); } @@ -4933,7 +4902,7 @@ static BOOL keyUpAlreadySentKeyDown = NO; - (BOOL)performDragOperation:(id )sender { - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); BOOL handled = [self doDragAction:NS_DRAGDROP_DROP sender:sender]; NS_IF_RELEASE(mDragService); return handled; @@ -5053,7 +5022,7 @@ static BOOL keyUpAlreadySentKeyDown = NO; id nativeAccessible = nil; - nsAutoRetainView kungFuDeathGrip(self); + nsAutoRetainCocoaObject kungFuDeathGrip(self); nsCOMPtr kungFuDeathGrip2(mGeckoChild); nsCOMPtr accessible; mGeckoChild->GetDocumentAccessible(getter_AddRefs(accessible)); diff --git a/mozilla/widget/src/cocoa/nsCocoaUtils.h b/mozilla/widget/src/cocoa/nsCocoaUtils.h index 46191dbb5d9..a75ac928296 100644 --- a/mozilla/widget/src/cocoa/nsCocoaUtils.h +++ b/mozilla/widget/src/cocoa/nsCocoaUtils.h @@ -45,6 +45,7 @@ #include "nsRect.h" #include "nsIWidget.h" +#include "nsObjCExceptions.h" // "Borrowed" in part from the QTKit framework's QTKitDefines.h. This is // needed when building on OS X Tiger (10.4.X) or with a 10.4 SDK. It won't @@ -67,6 +68,23 @@ typedef unsigned int NSUInteger; #endif /* NSINTEGER_DEFINED */ + +// Used to retain a Cocoa object for the remainder of a method's execution. +class nsAutoRetainCocoaObject { +public: +nsAutoRetainCocoaObject(id anObject) +{ + mObject = NS_OBJC_TRY_EXPR_ABORT([anObject retain]); +} +~nsAutoRetainCocoaObject() +{ + NS_OBJC_TRY_ABORT([mObject release]); +} +private: + id mObject; // [STRONG] +}; + + @interface NSApplication (Undocumented) // Present in all versions of OS X from (at least) 10.2.8 through 10.5. diff --git a/mozilla/widget/src/cocoa/nsCocoaUtils.mm b/mozilla/widget/src/cocoa/nsCocoaUtils.mm index 8b7d3b81f6b..750f1a6680e 100644 --- a/mozilla/widget/src/cocoa/nsCocoaUtils.mm +++ b/mozilla/widget/src/cocoa/nsCocoaUtils.mm @@ -39,7 +39,6 @@ * ***** END LICENSE BLOCK ***** */ #include "nsCocoaUtils.h" -#include "nsObjCExceptions.h" #include "nsMenuBarX.h" #include "nsCocoaWindow.h" #include "nsCOMPtr.h" diff --git a/mozilla/widget/src/cocoa/nsCocoaWindow.mm b/mozilla/widget/src/cocoa/nsCocoaWindow.mm index e3698bd2167..0578076659f 100644 --- a/mozilla/widget/src/cocoa/nsCocoaWindow.mm +++ b/mozilla/widget/src/cocoa/nsCocoaWindow.mm @@ -1396,8 +1396,10 @@ NS_IMETHODIMP nsCocoaWindow::EndSecureKeyboardInput() NSMenu* mainMenu = [NSApp mainMenu]; NS_ASSERTION([mainMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!"); - // create a new menu bar - NSMenu* newMenuBar = [[NSMenu alloc] initWithTitle:@"MainMenuBar"]; + // Create a new menu bar. + // We create a GeckoNSMenu because all menu bar NSMenu objects should use that subclass for + // key handling reasons. + GeckoNSMenu* newMenuBar = [[GeckoNSMenu alloc] initWithTitle:@"MainMenuBar"]; // move the application menu from the existing menu bar to the new one NSMenuItem* firstMenuItem = [[mainMenu itemAtIndex:0] retain]; diff --git a/mozilla/widget/src/cocoa/nsMenuBarX.h b/mozilla/widget/src/cocoa/nsMenuBarX.h index 896e2a0c333..ead4be0bbb2 100644 --- a/mozilla/widget/src/cocoa/nsMenuBarX.h +++ b/mozilla/widget/src/cocoa/nsMenuBarX.h @@ -44,7 +44,6 @@ #include "nsIMutationObserver.h" #include "nsCOMArray.h" #include "nsHashtable.h" -#include "nsTHashtable.h" #include "nsWeakReference.h" #include "nsIContent.h" @@ -71,6 +70,17 @@ namespace MenuHelpersX } +// Objective-C class used to allow us to have keyboard commands +// look like they are doing something but actually do nothing. +// We allow mouse actions to work normally. +@interface GeckoNSMenu : NSMenu +{ +} +- (BOOL)performKeyEquivalent:(NSEvent *)theEvent; +- (void)performMenuUserInterfaceEffectsForEvent:(NSEvent*)theEvent; +@end + + // Objective-C class used as action target for menu items @interface NativeMenuItemTarget : NSObject { @@ -79,84 +89,6 @@ namespace MenuHelpersX @end -struct CocoaKeyEquivContainer { - CocoaKeyEquivContainer(const unsigned int modifiers, const NSString* string) - { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - mModifiers = modifiers; - mString = [string retain]; - - NS_OBJC_END_TRY_ABORT_BLOCK; - } - - ~CocoaKeyEquivContainer() - { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - [mString release]; - - NS_OBJC_END_TRY_ABORT_BLOCK; - } - - CocoaKeyEquivContainer(const CocoaKeyEquivContainer& other) - { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - mModifiers = other.mModifiers; - mString = [other.mString retain]; - - NS_OBJC_END_TRY_ABORT_BLOCK; - } - - CocoaKeyEquivContainer& operator=(CocoaKeyEquivContainer& other) - { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - mModifiers = other.mModifiers; - if (mString) - [mString release]; - mString = [other.mString retain]; - return *this; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(*this); - } - - unsigned int mModifiers; - NSString* mString; -}; - - -struct CocoaKeyEquivKey : public PLDHashEntryHdr { - typedef const CocoaKeyEquivContainer& KeyType; - typedef const CocoaKeyEquivContainer* KeyTypePointer; - - CocoaKeyEquivKey(KeyTypePointer aObj) : mObj(*aObj) { } - CocoaKeyEquivKey(const CocoaKeyEquivKey& other) : mObj(other.mObj) { } - ~CocoaKeyEquivKey() { } - - KeyType GetKey() const { return mObj; } - - PRBool KeyEquals(KeyTypePointer aKey) const { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - return aKey->mModifiers == mObj.mModifiers && - [aKey->mString isEqualToString:mObj.mString]; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(PR_FALSE); - } - - static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } - static PLDHashNumber HashKey(KeyTypePointer aKey) { - return [aKey->mString hash] ^ aKey->mModifiers; - } - enum { ALLOW_MEMMOVE = PR_FALSE }; -private: - const CocoaKeyEquivContainer mObj; -}; - - - // // Native menu bar wrapper // @@ -193,7 +125,6 @@ public: NS_IMETHOD Paint(); NS_IMETHOD SetNativeData(void* aData); NS_IMETHOD MenuConstruct(const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow, void * aMenuNode); - PRBool ContainsKeyEquiv(unsigned int modifiers, NSString* string); PRUint32 RegisterForCommand(nsIMenuItem* aItem); void UnregisterCommand(PRUint32 aCommandID); @@ -203,9 +134,6 @@ public: void UnregisterForContentChanges(nsIContent* aContent); nsChangeObserver* LookupContentChangeObserver(nsIContent* aContent); - void RegisterKeyEquivalent(unsigned int modifiers, NSString* string); - void UnregisterKeyEquivalent(unsigned int modifiers, NSString* string); - nsCOMPtr mAboutItemContent; // holds the content node for the about item that has // been removed from the menubar nsCOMPtr mPrefItemContent; // as above, but for prefs @@ -226,9 +154,8 @@ protected: PRBool mIsMenuBarAdded; PRUint32 mCurrentCommandID; // unique command id (per menu-bar) to give to next item that asks nsIDocument* mDocument; // pointer to document - NSMenu* mRootMenu; // root menu, representing entire menu bar + GeckoNSMenu* mRootMenu; // root menu, representing entire menu bar nsHashtable mObserverTable; // stores observers for content change notification - nsTHashtable mKeyEquivTable; }; #endif // nsMenuBarX_h_ diff --git a/mozilla/widget/src/cocoa/nsMenuBarX.mm b/mozilla/widget/src/cocoa/nsMenuBarX.mm index ba5f31f00a5..78415c7c77d 100644 --- a/mozilla/widget/src/cocoa/nsMenuBarX.mm +++ b/mozilla/widget/src/cocoa/nsMenuBarX.mm @@ -109,7 +109,7 @@ nsMenuBarX::nsMenuBarX() { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - mRootMenu = [[NSMenu alloc] initWithTitle:@"MainMenuBar"]; + mRootMenu = [[GeckoNSMenu alloc] initWithTitle:@"MainMenuBar"]; NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -246,8 +246,6 @@ nsMenuBarX::MenuConstruct(const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind NS_IMETHODIMP nsMenuBarX::Create(nsIWidget *aParent) { SetParent(aParent); - if (!mKeyEquivTable.Init()) - return NS_ERROR_OUT_OF_MEMORY; return NS_OK; } @@ -753,27 +751,6 @@ nsMenuBarX::LookupContentChangeObserver(nsIContent* aContent) } -void nsMenuBarX::RegisterKeyEquivalent(unsigned int modifiers, NSString* string) -{ - const CocoaKeyEquivContainer keyEquiv(modifiers, string); - mKeyEquivTable.PutEntry(keyEquiv); -} - - -void nsMenuBarX::UnregisterKeyEquivalent(unsigned int modifiers, NSString* string) -{ - CocoaKeyEquivContainer keyEquiv(modifiers, string); - mKeyEquivTable.RemoveEntry(keyEquiv); -} - - -PRBool nsMenuBarX::ContainsKeyEquiv(unsigned int modifiers, NSString* string) -{ - const CocoaKeyEquivContainer keyEquiv(modifiers, string); - return (mKeyEquivTable.GetEntry(keyEquiv) != nsnull); -} - - // Given a menu item, creates a unique 4-character command ID and // maps it to the item. Returns the id for use by the client. PRUint32 @@ -958,6 +935,54 @@ NSMenuItem* MenuHelpersX::GetStandardEditMenuItem() } +// +// Objective-C class used to allow us to have keyboard commands +// look like they are doing something but actually do nothing. +// We allow mouse actions to work normally. +// + + +// This tells us whether or not pKE is on the stack from a GeckoNSMenu. If it +// is nil, it is not on the stack. The non-nil value is the object that put it +// on the stack first. +static GeckoNSMenu* gPerformKeyEquivOnStack = nil; +// When this variable is set to YES, don't do special command processing. +static BOOL gMenuEffectsOnly = NO; + +@implementation GeckoNSMenu + +- (BOOL)performKeyEquivalent:(NSEvent *)theEvent +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; + + NS_ASSERTION(gPerformKeyEquivOnStack != self, "GeckoNSMenu pKE re-entering for the same object!"); + + // Don't bother doing this if we don't have any items. It appears as though + // the OS will sometimes expect this sort of check. + if ([self numberOfItems] <= 0) + return NO; + + if (!gPerformKeyEquivOnStack) + gPerformKeyEquivOnStack = self; + BOOL rv = [super performKeyEquivalent:theEvent]; + if (gPerformKeyEquivOnStack == self) + gPerformKeyEquivOnStack = nil; + return rv; + + NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO); +} + + +- (void)performMenuUserInterfaceEffectsForEvent:(NSEvent*)theEvent +{ + gMenuEffectsOnly = YES; + [self performKeyEquivalent:theEvent]; + gMenuEffectsOnly = NO; +} + +@end + + // // Objective-C class used as action target for menu items // @@ -970,57 +995,60 @@ NSMenuItem* MenuHelpersX::GetStandardEditMenuItem() { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - nsMenuBarX* menuBar = nsMenuBarX::sLastGeckoMenuBarPainted; int tag = [sender tag]; - switch (tag) { - case eCommand_ID_About: - { + nsMenuBarX* menuBar = nsMenuBarX::sLastGeckoMenuBarPainted; + + // We want to avoid processing app-global commands when we are asked to + // perform native menu effects only. This avoids sending events twice, + // which can lead to major problems. + if (!gMenuEffectsOnly) { + // Do special processing if this is for an app-global command. + if (tag == eCommand_ID_About) { nsIContent* mostSpecificContent = sAboutItemContent; if (menuBar && menuBar->mAboutItemContent) mostSpecificContent = menuBar->mAboutItemContent; MenuHelpersX::DispatchCommandTo(mostSpecificContent); - break; } - - case eCommand_ID_Prefs: - { + else if (tag == eCommand_ID_Prefs) { nsIContent* mostSpecificContent = sPrefItemContent; if (menuBar && menuBar->mPrefItemContent) mostSpecificContent = menuBar->mPrefItemContent; MenuHelpersX::DispatchCommandTo(mostSpecificContent); - break; } - - case eCommand_ID_Quit: - { + else if (tag == eCommand_ID_Quit) { nsIContent* mostSpecificContent = sQuitItemContent; if (menuBar && menuBar->mQuitItemContent) mostSpecificContent = menuBar->mQuitItemContent; // If we have some content for quit we execute it. Otherwise we send a native app terminate // message. If you want to stop a quit from happening, provide quit content and return // the event as unhandled. - if (mostSpecificContent) + if (mostSpecificContent) { MenuHelpersX::DispatchCommandTo(mostSpecificContent); - else + } + else { [NSApp terminate:nil]; - break; - } - - default: - { - // Can't do anything if we don't know the last painted menu bar. - if (!menuBar) return; - // given the commandID, look it up in our hashtable and dispatch to - // that content node. Recall that we store weak pointers to the content - // nodes in the hash table. - nsIMenuItem* content = menuBar->GetMenuItemForCommandID(static_cast(tag)); - if (content) - content->DoCommand(); - break; + } } } + // Don't do anything unless this is not a keyboard command and + // this isn't for the hidden window menu. We assume that if there + // is no main window then the hidden window menu bar is up, even + // if that isn't true for some reason we better play it safe if + // there is no main window. + if (gPerformKeyEquivOnStack && [NSApp mainWindow]) + return; + + // given the commandID, look it up in our hashtable and dispatch to + // that content node. Recall that we store weak pointers to the content + // nodes in the hash table. + if (menuBar) { + nsIMenuItem* content = menuBar->GetMenuItemForCommandID(static_cast(tag)); + if (content) + content->DoCommand(); + } + NS_OBJC_END_TRY_ABORT_BLOCK; } diff --git a/mozilla/widget/src/cocoa/nsMenuItemX.mm b/mozilla/widget/src/cocoa/nsMenuItemX.mm index 6d46a063d43..2cfd8b11823 100644 --- a/mozilla/widget/src/cocoa/nsMenuItemX.mm +++ b/mozilla/widget/src/cocoa/nsMenuItemX.mm @@ -349,8 +349,6 @@ void nsMenuItemX::SetKeyEquiv(PRUint8 aModifiers, const nsString &aText) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - mMenuBar->UnregisterKeyEquivalent([mNativeMenuItem keyEquivalentModifierMask], [mNativeMenuItem keyEquivalent]); - mModifiers = aModifiers; unsigned int macModifiers = MenuHelpersX::MacModifiersForGeckoModifiers(mModifiers); [mNativeMenuItem setKeyEquivalentModifierMask:macModifiers]; @@ -363,8 +361,6 @@ void nsMenuItemX::SetKeyEquiv(PRUint8 aModifiers, const nsString &aText) else [mNativeMenuItem setKeyEquivalent:keyEquivalent]; - mMenuBar->RegisterKeyEquivalent([mNativeMenuItem keyEquivalentModifierMask], [mNativeMenuItem keyEquivalent]); - NS_OBJC_END_TRY_ABORT_BLOCK; } diff --git a/mozilla/widget/src/cocoa/nsMenuX.h b/mozilla/widget/src/cocoa/nsMenuX.h index d8b7bc83e9b..42b86cc9658 100644 --- a/mozilla/widget/src/cocoa/nsMenuX.h +++ b/mozilla/widget/src/cocoa/nsMenuX.h @@ -131,7 +131,7 @@ protected: void LoadMenuItem(nsIContent* inMenuItemContent); void LoadSubMenu(nsIContent* inMenuContent); - NSMenu* CreateMenuWithGeckoString(nsString& menuTitle); + GeckoNSMenu* CreateMenuWithGeckoString(nsString& menuTitle); protected: nsString mLabel; @@ -145,7 +145,7 @@ protected: // Mac specific PRInt16 mMacMenuID; - NSMenu* mMacMenu; // strong ref, we own it + GeckoNSMenu* mMacMenu; // strong ref, we own it MenuDelegate* mMenuDelegate; // strong ref, we keep this around to get events for us NSMenuItem* mNativeMenuItem; // strong ref, we own PRPackedBool mIsEnabled; diff --git a/mozilla/widget/src/cocoa/nsMenuX.mm b/mozilla/widget/src/cocoa/nsMenuX.mm index 8faf6a0fbf8..cc842f3dfd8 100644 --- a/mozilla/widget/src/cocoa/nsMenuX.mm +++ b/mozilla/widget/src/cocoa/nsMenuX.mm @@ -631,12 +631,12 @@ NS_IMETHODIMP nsMenuX::GetMenuContent(nsIContent ** aMenuContent) } -NSMenu* nsMenuX::CreateMenuWithGeckoString(nsString& menuTitle) +GeckoNSMenu* nsMenuX::CreateMenuWithGeckoString(nsString& menuTitle) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; NSString* title = [NSString stringWithCharacters:(UniChar*)menuTitle.get() length:menuTitle.Length()]; - NSMenu* myMenu = [[NSMenu alloc] initWithTitle:title]; + GeckoNSMenu* myMenu = [[GeckoNSMenu alloc] initWithTitle:title]; [myMenu setDelegate:mMenuDelegate]; // We don't want this menu to auto-enable menu items because then Cocoa