diff --git a/widget/xpwidgets/nsBaseWidget.cpp b/widget/xpwidgets/nsBaseWidget.cpp index ad8b62752b5e..22f50b3d0624 100644 --- a/widget/xpwidgets/nsBaseWidget.cpp +++ b/widget/xpwidgets/nsBaseWidget.cpp @@ -118,8 +118,31 @@ nsBaseWidget::nsBaseWidget() #ifdef DEBUG debug_RegisterPrefCallbacks(); #endif + + mShutdownObserver = new WidgetShutdownObserver(this); + nsContentUtils::RegisterShutdownObserver(mShutdownObserver); } +NS_IMPL_ISUPPORTS1(WidgetShutdownObserver, nsIObserver) + +NS_IMETHODIMP +WidgetShutdownObserver::Observe(nsISupports *aSubject, + const char *aTopic, + const PRUnichar *aData) +{ + if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) { + mWidget->Shutdown(); + nsContentUtils::UnregisterShutdownObserver(this); + } + return NS_OK; +} + +void +nsBaseWidget::Shutdown() +{ + DestroyCompositor(); + mShutdownObserver = nullptr; +} static void DeferredDestroyCompositor(CompositorParent* aCompositorParent, CompositorChild* aCompositorChild) @@ -171,6 +194,10 @@ nsBaseWidget::~nsBaseWidget() mLayerManager = nullptr; } + if (mShutdownObserver) { + nsContentUtils::UnregisterShutdownObserver(mShutdownObserver); + } + DestroyCompositor(); #ifdef NOISY_WIDGET_LEAKS @@ -893,6 +920,12 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight) // Recreating this is tricky, as we may still have an old and we need // to make sure it's properly destroyed by calling DestroyCompositor! + // If we've already received a shutdown notification, don't try + // create a new compositor. + if (!mShutdownObserver) { + return; + } + mCompositorParent = NewCompositorParent(aWidth, aHeight); AsyncChannel *parentChannel = mCompositorParent->GetIPCChannel(); LayerManager* lm = new ClientLayerManager(this); diff --git a/widget/xpwidgets/nsBaseWidget.h b/widget/xpwidgets/nsBaseWidget.h index 87ff5eedc752..d3efcb931b39 100644 --- a/widget/xpwidgets/nsBaseWidget.h +++ b/widget/xpwidgets/nsBaseWidget.h @@ -15,6 +15,7 @@ #include "nsGUIEvent.h" #include "nsAutoPtr.h" #include "nsIRollupListener.h" +#include "nsIObserver.h" #include class nsIContent; class nsAutoRollup; @@ -38,6 +39,22 @@ namespace base { class Thread; } +class nsBaseWidget; + +class WidgetShutdownObserver MOZ_FINAL : public nsIObserver +{ +public: + WidgetShutdownObserver(nsBaseWidget* aWidget) + : mWidget(aWidget) + { } + + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + +private: + nsBaseWidget *mWidget; +}; + /** * Common widget implementation used as base class for native * or crossplatform implementations of Widgets. @@ -254,6 +271,8 @@ public: static nsIRollupListener* GetActiveRollupListener(); + void Shutdown(); + protected: virtual void ResolveIconName(const nsAString &aIconName, @@ -356,6 +375,7 @@ protected: nsRefPtr mBasicLayerManager; nsRefPtr mCompositorChild; nsRefPtr mCompositorParent; + nsCOMPtr mShutdownObserver; nscolor mBackground; nscolor mForeground; nsCursor mCursor;