  changeset:   312069:3c2bd9158ad3
  user:        Timothy Nikkel <tnikkel@gmail.com>
  Date:        Tue May 10 22:58:47 2016 -0500
  summary:     Bug 1261752. Part 3. r=mats a=ritu

diff -r 73cc9a2d8fc1 -r 3c2bd9158ad3 layout/forms/nsComboboxControlFrame.cpp
--- a/layout/forms/nsComboboxControlFrame.cpp	Tue May 10 22:58:47 2016 -0500
+++ b/layout/forms/nsComboboxControlFrame.cpp	Tue May 10 22:58:47 2016 -0500
@@ -1417,7 +1417,11 @@
     // The popup's visibility doesn't update until the minimize animation has
     // finished, so call UpdateWidgetGeometry to update it right away.
     nsViewManager* viewManager = mDropdownFrame->GetView()->GetViewManager();
-    viewManager->UpdateWidgetGeometry();
+    viewManager->UpdateWidgetGeometry(); // might destroy us
+  }
+
+  if (!weakFrame.IsAlive()) {
+    return consume;
   }
 
   return consume;
diff -r 73cc9a2d8fc1 -r 3c2bd9158ad3 view/nsViewManager.cpp
--- a/view/nsViewManager.cpp	Tue May 10 22:58:47 2016 -0500
+++ b/view/nsViewManager.cpp	Tue May 10 22:58:47 2016 -0500
@@ -670,15 +670,16 @@
 
 void nsViewManager::WillPaintWindow(nsIWidget* aWidget)
 {
-  if (aWidget) {
-    nsView* view = nsView::GetViewFor(aWidget);
-    LayerManager *manager = aWidget->GetLayerManager();
+  RefPtr<nsIWidget> widget(aWidget);
+  if (widget) {
+    nsView* view = nsView::GetViewFor(widget);
+    LayerManager* manager = widget->GetLayerManager();
     if (view &&
         (view->ForcedRepaint() || !manager->NeedsWidgetInvalidation())) {
       ProcessPendingUpdates();
       // Re-get the view pointer here since the ProcessPendingUpdates might have
       // destroyed it during CallWillPaintOnObservers.
-      view = nsView::GetViewFor(aWidget);
+      view = nsView::GetViewFor(widget);
       if (view) {
         view->SetForcedRepaint(false);
       }
diff -r 73cc9a2d8fc1 -r 3c2bd9158ad3 widget/PuppetWidget.cpp
--- a/widget/PuppetWidget.cpp	Tue May 10 22:58:47 2016 -0500
+++ b/widget/PuppetWidget.cpp	Tue May 10 22:58:47 2016 -0500
@@ -823,6 +823,8 @@
   mDirtyRegion.SetEmpty();
   mPaintTask.Revoke();
 
+  RefPtr<PuppetWidget> strongThis(this);
+
   mAttachedWidgetListener->WillPaintWindow(this);
 
   if (mAttachedWidgetListener) {
diff -r 73cc9a2d8fc1 -r 3c2bd9158ad3 widget/cocoa/nsChildView.mm
--- a/widget/cocoa/nsChildView.mm	Tue May 10 22:58:47 2016 -0500
+++ b/widget/cocoa/nsChildView.mm	Tue May 10 22:58:47 2016 -0500
@@ -3716,6 +3716,8 @@
 
 - (void)viewWillDraw
 {
+  nsAutoRetainCocoaObject kungFuDeathGrip(self);
+
   if (mGeckoChild) {
     // The OS normally *will* draw our NSWindow, no matter what we do here.
     // But Gecko can delete our parent widget(s) (along with mGeckoChild)
diff -r 73cc9a2d8fc1 -r 3c2bd9158ad3 widget/gonk/nsWindow.cpp
--- a/widget/gonk/nsWindow.cpp	Tue May 10 22:58:47 2016 -0500
+++ b/widget/gonk/nsWindow.cpp	Tue May 10 22:58:47 2016 -0500
@@ -196,7 +196,7 @@
         return;
     }
 
-    nsWindow *targetWindow = (nsWindow *)sTopWindows[0];
+    RefPtr<nsWindow> targetWindow = (nsWindow *)sTopWindows[0];
     while (targetWindow->GetLastChild())
         targetWindow = (nsWindow *)targetWindow->GetLastChild();
 
@@ -205,15 +205,15 @@
         listener->WillPaintWindow(targetWindow);
     }
 
-    LayerManager* lm = targetWindow->GetLayerManager();
-    if (mozilla::layers::LayersBackend::LAYERS_CLIENT == lm->GetBackendType()) {
-      // No need to do anything, the compositor will handle drawing
-    } else {
-        NS_RUNTIMEABORT("Unexpected layer manager type");
-    }
-
     listener = targetWindow->GetWidgetListener();
     if (listener) {
+        LayerManager* lm = targetWindow->GetLayerManager();
+        if (mozilla::layers::LayersBackend::LAYERS_CLIENT == lm->GetBackendType()) {
+            // No need to do anything, the compositor will handle drawing
+        } else {
+            NS_RUNTIMEABORT("Unexpected layer manager type");
+        }
+
         listener->DidPaintWindow();
     }
 }
diff -r 73cc9a2d8fc1 -r 3c2bd9158ad3 widget/gtk/nsWindow.cpp
--- a/widget/gtk/nsWindow.cpp	Tue May 10 22:58:47 2016 -0500
+++ b/widget/gtk/nsWindow.cpp	Tue May 10 22:58:47 2016 -0500
@@ -469,6 +469,12 @@
     }
 }
 
+nsIWidgetListener*
+nsWindow::GetListener()
+{
+    return mAttachedWidgetListener ? mAttachedWidgetListener : mWidgetListener;
+}
+
 nsresult
 nsWindow::DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus)
 {
@@ -481,8 +487,7 @@
     aEvent->refPoint.y = GdkCoordToDevicePixels(aEvent->refPoint.y);
 
     aStatus = nsEventStatus_eIgnore;
-    nsIWidgetListener* listener =
-        mAttachedWidgetListener ? mAttachedWidgetListener : mWidgetListener;
+    nsIWidgetListener* listener = GetListener();
     if (listener) {
       aStatus = listener->HandleEvent(aEvent, mUseAttachedEvents);
     }
@@ -2119,8 +2124,7 @@
     if (!mGdkWindow || mIsFullyObscured || !mHasMappedToplevel)
         return FALSE;
 
-    nsIWidgetListener *listener =
-        mAttachedWidgetListener ? mAttachedWidgetListener : mWidgetListener;
+    nsIWidgetListener *listener = GetListener();
     if (!listener)
         return FALSE;
 
@@ -2149,6 +2153,8 @@
         clientLayers->SendInvalidRegion(region);
     }
 
+    RefPtr<nsWindow> strongThis(this);
+
     // Dispatch WillPaintWindow notification to allow scripts etc. to run
     // before we paint
     {
@@ -2161,8 +2167,7 @@
 
         // Re-get the listener since the will paint notification might have
         // killed it.
-        listener =
-            mAttachedWidgetListener ? mAttachedWidgetListener : mWidgetListener;
+        listener = GetListener();
         if (!listener)
             return FALSE;
     }
@@ -2223,6 +2228,13 @@
     // If this widget uses OMTC...
     if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
         listener->PaintWindow(this, region);
+
+        // Re-get the listener since the will paint notification might have
+        // killed it.
+        listener = GetListener();
+        if (!listener)
+            return TRUE;
+
         listener->DidPaintWindow();
         return TRUE;
     }
@@ -2307,6 +2319,13 @@
       if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) {
         AutoLayerManagerSetup setupLayerManager(this, ctx, layerBuffering);
         painted = listener->PaintWindow(this, region);
+
+        // Re-get the listener since the will paint notification might have
+        // killed it.
+        listener = GetListener();
+        if (!listener)
+            return TRUE;
+
       }
     }
 
diff -r 73cc9a2d8fc1 -r 3c2bd9158ad3 widget/gtk/nsWindow.h
--- a/widget/gtk/nsWindow.h	Tue May 10 22:58:47 2016 -0500
+++ b/widget/gtk/nsWindow.h	Tue May 10 22:58:47 2016 -0500
@@ -359,6 +359,7 @@
                                    GdkWindow** aWindow, gint* aButton,
                                    gint* aRootX, gint* aRootY);
     void               ClearCachedResources();
+    nsIWidgetListener* GetListener();
 
     GtkWidget          *mShell;
     MozContainer       *mContainer;
diff -r 73cc9a2d8fc1 -r 3c2bd9158ad3 widget/qt/nsWindow.cpp
--- a/widget/qt/nsWindow.cpp	Tue May 10 22:58:47 2016 -0500
+++ b/widget/qt/nsWindow.cpp	Tue May 10 22:58:47 2016 -0500
@@ -857,18 +857,28 @@
 
 // EVENTS
 
+nsIWidgetListener*
+nsWindow::GetPaintListener()
+{
+    return mAttachedWidgetListener ? mAttachedWidgetListener : mWidgetListener;
+}
+
 void
 nsWindow::OnPaint()
 {
     LOGDRAW(("nsWindow::%s [%p]\n", __FUNCTION__, (void *)this));
-    nsIWidgetListener* listener =
-        mAttachedWidgetListener ? mAttachedWidgetListener : mWidgetListener;
+    nsIWidgetListener* listener = GetPaintListener();
     if (!listener) {
         return;
     }
 
     listener->WillPaintWindow(this);
 
+    nsIWidgetListener* listener = GetPaintListener();
+    if (!listener) {
+        return;
+    }
+
     switch (GetLayerManager()->GetBackendType()) {
         case mozilla::layers::LayersBackend::LAYERS_CLIENT: {
             nsIntRegion region(nsIntRect(0, 0, mWidget->width(), mWidget->height()));
@@ -879,6 +889,11 @@
             NS_ERROR("Invalid layer manager");
     }
 
+    nsIWidgetListener* listener = GetPaintListener();
+    if (!listener) {
+        return;
+    }
+
     listener->DidPaintWindow();
 }
 
diff -r 73cc9a2d8fc1 -r 3c2bd9158ad3 widget/qt/nsWindow.h
--- a/widget/qt/nsWindow.h	Tue May 10 22:58:47 2016 -0500
+++ b/widget/qt/nsWindow.h	Tue May 10 22:58:47 2016 -0500
@@ -254,6 +254,7 @@
         bool needDispatch;
     } MozCachedMoveEvent;
 
+    nsIWidgetListener* GetPaintListener();
     bool               CheckForRollup(double aMouseX, double aMouseY, bool aIsWheel);
     void*              SetupPluginPort(void);
     nsresult           SetWindowIconList(const nsTArray<nsCString> &aIconList);
diff -r 73cc9a2d8fc1 -r 3c2bd9158ad3 widget/windows/nsWindowGfx.cpp
--- a/widget/windows/nsWindowGfx.cpp	Tue May 10 22:58:47 2016 -0500
+++ b/widget/windows/nsWindowGfx.cpp	Tue May 10 22:58:47 2016 -0500
@@ -298,6 +298,8 @@
     clientLayerManager->SendInvalidRegion(region);
   }
 
+  RefPtr<nsWindow> strongThis(this);
+
   nsIWidgetListener* listener = GetPaintListener();
   if (listener) {
     listener->WillPaintWindow(this);
