From f482ae90c3c9351dfd72687ae370f43d5b87bd03 Mon Sep 17 00:00:00 2001 From: "joshmoz%gmail.com" Date: Thu, 6 Apr 2006 07:41:34 +0000 Subject: [PATCH] handle hidden window menu bar and menu bar switching in general better. gets rid of a lot of crashes. b=330586 r=pav git-svn-id: svn://10.0.0.236/trunk@193674 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/widget/src/cocoa/Makefile.in | 1 + mozilla/widget/src/cocoa/nsCocoaWindow.mm | 83 ++++++++++++++++++++--- mozilla/widget/src/cocoa/nsMenuBarX.h | 2 + mozilla/widget/src/cocoa/nsMenuBarX.mm | 14 +++- mozilla/widget/src/cocoa/nsMenuItemX.mm | 2 +- 5 files changed, 88 insertions(+), 14 deletions(-) diff --git a/mozilla/widget/src/cocoa/Makefile.in b/mozilla/widget/src/cocoa/Makefile.in index 9bc4046179c..5c458006b33 100644 --- a/mozilla/widget/src/cocoa/Makefile.in +++ b/mozilla/widget/src/cocoa/Makefile.in @@ -71,6 +71,7 @@ REQUIRES = xpcom \ mimetype \ unicharutil \ exthandler \ + appshell \ $(NULL) ifdef MOZ_ENABLE_CAIRO_GFX diff --git a/mozilla/widget/src/cocoa/nsCocoaWindow.mm b/mozilla/widget/src/cocoa/nsCocoaWindow.mm index db7b50b9629..8b717417b32 100644 --- a/mozilla/widget/src/cocoa/nsCocoaWindow.mm +++ b/mozilla/widget/src/cocoa/nsCocoaWindow.mm @@ -38,6 +38,7 @@ #include "nsCocoaWindow.h" +#include "nsCOMPtr.h" #include "nsIServiceManager.h" // for drag and drop #include "nsWidgetsCID.h" #include "nsIDragService.h" @@ -48,7 +49,12 @@ #include "nsGUIEvent.h" #include "nsMacResources.h" #include "nsIRollupListener.h" -#import "nsChildView.h" +#include "nsChildView.h" +#include "nsIAppShell.h" +#include "nsIAppShellService.h" +#include "nsIBaseWindow.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIXULWindow.h" #include "nsIEventQueueService.h" @@ -59,6 +65,11 @@ static NS_DEFINE_CID(kCDragServiceCID, NS_DRAGSERVICE_CID); extern nsIRollupListener * gRollupListener; extern nsIWidget * gRollupWidget; +#define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/appshell/appShellService;1" + +// call getHiddenWindowNativeMenu, don't use this directly +static nsIMenuBar* gHiddenWindowMenuBar = nsnull; + NS_IMPL_ISUPPORTS_INHERITED0(nsCocoaWindow, Inherited) @@ -142,6 +153,48 @@ nsCocoaWindow::~nsCocoaWindow() } +static nsIMenuBar* GetHiddenWindowMenuBar() +{ + if (gHiddenWindowMenuBar) + return gHiddenWindowMenuBar; + + nsCOMPtr appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID)); + if (!appShell) { + NS_WARNING("Couldn't get AppShellService in order to get hidden window ref"); + return NULL; + } + + nsCOMPtr hiddenWindow; + appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow)); + if (!hiddenWindow) { + NS_WARNING("Couldn't get hidden window from appshell"); + return NULL; + } + + nsCOMPtr baseHiddenWindow; + baseHiddenWindow = do_GetInterface(hiddenWindow); + if (!baseHiddenWindow) { + NS_WARNING("Couldn't get nsIBaseWindow from hidden window (nsIXULWindow)"); + return NULL; + } + + nsCOMPtr hiddenWindowWidget; + if (NS_FAILED(baseHiddenWindow->GetMainWidget(getter_AddRefs(hiddenWindowWidget)))) { + NS_WARNING("Couldn't get nsIWidget from hidden window (nsIBaseWindow)"); + return NULL; + } + + nsIWidget* hiddenWindowWidgetNoCOMPtr = hiddenWindowWidget; + nsIMenuBar* geckoMenuBar = NS_STATIC_CAST(nsCocoaWindow*, hiddenWindowWidgetNoCOMPtr)->GetMenuBar(); + + if (geckoMenuBar) { + gHiddenWindowMenuBar = geckoMenuBar; + } + + return gHiddenWindowMenuBar; +} + + //------------------------------------------------------------------------- // // Utility method for implementing both Create(nsIWidget ...) and @@ -397,14 +450,16 @@ nsCocoaWindow::IsVisible(PRBool & aState) //------------------------------------------------------------------------- NS_IMETHODIMP nsCocoaWindow::Show(PRBool bState) { - if (bState) - [mWindow orderFront:NULL]; - else - [mWindow orderOut:NULL]; - - mVisible = bState; - - return NS_OK; + if (bState) { + [mWindow orderFront:NULL]; + } + else { + [mWindow orderOut:NULL]; + } + + mVisible = bState; + + return NS_OK; } @@ -737,8 +792,10 @@ NS_IMETHODIMP nsCocoaWindow::CaptureRollupEvents(nsIRollupListener * aListener, - (void)windowDidBecomeMain:(NSNotification *)aNotification { nsIMenuBar* myMenuBar = mGeckoWindow->GetMenuBar(); - if (myMenuBar) + if (myMenuBar) { + // printf("painting window menu bar due to window becoming main\n"); myMenuBar->Paint(); + } nsGUIEvent guiEvent(PR_TRUE, NS_GOTFOCUS, mGeckoWindow); guiEvent.time = PR_IntervalNow(); @@ -753,6 +810,12 @@ NS_IMETHODIMP nsCocoaWindow::CaptureRollupEvents(nsIRollupListener * aListener, if (gRollupListener != nsnull && gRollupWidget != nsnull) gRollupListener->Rollup(); + nsCOMPtr hiddenWindowMenuBar = GetHiddenWindowMenuBar(); + if (hiddenWindowMenuBar) { + // printf("painting hidden window menu bar due to nsCocoaWindow::Show(false)\n"); + hiddenWindowMenuBar->Paint(); + } + // tell Gecko that we lost focus nsGUIEvent guiEvent(PR_TRUE, NS_LOSTFOCUS, mGeckoWindow); guiEvent.time = PR_IntervalNow(); diff --git a/mozilla/widget/src/cocoa/nsMenuBarX.h b/mozilla/widget/src/cocoa/nsMenuBarX.h index 2b22b96d157..85860e18d09 100644 --- a/mozilla/widget/src/cocoa/nsMenuBarX.h +++ b/mozilla/widget/src/cocoa/nsMenuBarX.h @@ -98,6 +98,8 @@ public: // |NSMenuItem|s target Objective-C objects static NativeMenuItemTarget* sNativeEventTarget; + static NSWindow* sEventTargetWindow; + NS_DECL_ISUPPORTS NS_DECL_NSICHANGEMANAGER NS_DECL_NSIMENUCOMMANDDISPATCHER diff --git a/mozilla/widget/src/cocoa/nsMenuBarX.mm b/mozilla/widget/src/cocoa/nsMenuBarX.mm index b44c82c387e..2d4f35cba2c 100644 --- a/mozilla/widget/src/cocoa/nsMenuBarX.mm +++ b/mozilla/widget/src/cocoa/nsMenuBarX.mm @@ -74,6 +74,7 @@ NS_IMPL_ISUPPORTS6(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIDocumentObserver, NSMenu* nsMenuBarX::sApplicationMenu = nsnull; EventHandlerUPP nsMenuBarX::sCommandEventHandler = nsnull; NativeMenuItemTarget* nsMenuBarX::sNativeEventTarget = nil; +NSWindow* nsMenuBarX::sEventTargetWindow = nil; nsMenuBarX::nsMenuBarX() @@ -97,7 +98,7 @@ nsMenuBarX::~nsMenuBarX() mDocument->RemoveObserver(observer); } - [mRootMenu release]; + [mRootMenu autorelease]; } nsEventStatus @@ -809,7 +810,8 @@ NS_IMETHODIMP nsMenuBarX::Paint() [[mRootMenu itemAtIndex:0] setSubmenu:sApplicationMenu]; } - [NSApp setMainMenu:mRootMenu]; + [NSApp setMainMenu:mRootMenu]; + nsMenuBarX::sEventTargetWindow = (NSWindow*)mParent->GetNativeData(NS_NATIVE_WINDOW); return NS_OK; } @@ -1135,6 +1137,12 @@ unsigned int MenuHelpersX::MacModifiersForGeckoModifiers(PRUint8 geckoModifiers) // called when some menu item in this menu gets hit -(IBAction)menuItemHit:(id)sender { + // just abort if we don't have a target window for events + if (!nsMenuBarX::sEventTargetWindow) { + NS_WARNING("No target window for keyboard events!"); + return; + } + MenuRef senderMenuRef = _NSGetCarbonMenu([sender menu]); int senderCarbonMenuItemIndex = [[sender menu] indexOfItem:sender] + 1; @@ -1159,7 +1167,7 @@ unsigned int MenuHelpersX::MacModifiersForGeckoModifiers(PRUint8 geckoModifiers) if (err == noErr) { err = ::SetEventParameter(newEvent, kEventParamDirectObject, typeHICommand, sizeof(HICommand), &menuHICommand); if (err == noErr) { - err = ::SendEventToEventTarget(newEvent, GetWindowEventTarget((WindowRef)[[NSApp keyWindow] windowRef])); + err = ::SendEventToEventTarget(newEvent, GetWindowEventTarget((WindowRef)[nsMenuBarX::sEventTargetWindow windowRef])); NS_ASSERTION(err == noErr, "Carbon event for menu hit not sent!"); } } diff --git a/mozilla/widget/src/cocoa/nsMenuItemX.mm b/mozilla/widget/src/cocoa/nsMenuItemX.mm index 0ba20bd26ae..81b20ccaee9 100644 --- a/mozilla/widget/src/cocoa/nsMenuItemX.mm +++ b/mozilla/widget/src/cocoa/nsMenuItemX.mm @@ -76,7 +76,7 @@ nsMenuItemX::nsMenuItemX() nsMenuItemX::~nsMenuItemX() { - [mNativeMenuItem release]; + [mNativeMenuItem autorelease]; mManager->Unregister(mContent); }