diff --git a/widget/src/gtk/nsGtkEventHandler.cpp b/widget/src/gtk/nsGtkEventHandler.cpp index 17486bb12b56..2f2edb463776 100644 --- a/widget/src/gtk/nsGtkEventHandler.cpp +++ b/widget/src/gtk/nsGtkEventHandler.cpp @@ -773,6 +773,11 @@ handle_gdk_event (GdkEvent *event, gpointer data) // It was an event on one of our superwindows nsWindow *window = (nsWindow *)gtk_object_get_data (object, "nsWindow"); + + // if we don't have a window here anymore, we are probably in the process of being or have been destroyed + if (!window) + return; + GtkWidget *current_grab = gtk_grab_get_current(); // if there's a grab in progress, make sure to send it right to that widget. diff --git a/widget/src/gtk/nsWidget.cpp b/widget/src/gtk/nsWidget.cpp index e12094ebaf68..ae3efe548bd3 100644 --- a/widget/src/gtk/nsWidget.cpp +++ b/widget/src/gtk/nsWidget.cpp @@ -260,11 +260,8 @@ nsWidget::nsWidget() mIsDragDest = PR_FALSE; mIsToplevel = PR_FALSE; - if (NS_OK == nsComponentManager::CreateInstance(kRegionCID, - nsnull, - NS_GET_IID(nsIRegion), - (void**)&mUpdateArea)) - { + mUpdateArea = do_CreateInstance(kRegionCID); + if (mUpdateArea) { mUpdateArea->Init(); mUpdateArea->SetTo(0, 0, 0, 0); } @@ -338,13 +335,11 @@ nsWidget::~nsWidget() printf("nsWidget::~nsWidget:%p\n", this); #endif - NS_IF_RELEASE(mUpdateArea); - // it's safe to always call Destroy() because it will only allow itself // to be called once Destroy(); - if (!sWidgetCount--) { + if (!--sWidgetCount) { NS_IF_RELEASE(sLookAndFeel); } @@ -424,6 +419,10 @@ NS_IMETHODIMP nsWidget::Destroy(void) if (mIsDestroying) return NS_OK; + // we don't want people sending us events if we are the button motion target + if (sButtonMotionTarget == this) + sButtonMotionTarget = nsnull; + // ok, set our state mIsDestroying = PR_TRUE; @@ -1642,6 +1641,9 @@ nsWidget::InstallRealizeSignal(GtkWidget * aWidget) nsWidget::OnMotionNotifySignal(GdkEventMotion * aGdkMotionEvent) { + if (mIsDestroying) + return; + nsMouseEvent event; event.message = NS_MOUSE_MOVE; diff --git a/widget/src/gtk/nsWidget.h b/widget/src/gtk/nsWidget.h index f021e6050834..15bf7721b96a 100644 --- a/widget/src/gtk/nsWidget.h +++ b/widget/src/gtk/nsWidget.h @@ -487,7 +487,7 @@ protected: // This is the composite update area (union of all the calls to // Invalidate) - nsIRegion *mUpdateArea; + nsCOMPtr mUpdateArea; PRBool mShown; diff --git a/widget/src/gtk/nsWindow.cpp b/widget/src/gtk/nsWindow.cpp index b7b75fef8dba..5713d8cb304a 100644 --- a/widget/src/gtk/nsWindow.cpp +++ b/widget/src/gtk/nsWindow.cpp @@ -165,6 +165,22 @@ nsWindow::~nsWindow() UnqueueDraw(); } +NS_IMETHODIMP nsWindow::Destroy(void) +{ + // remove our pointer from the object so that we event handlers don't send us events + // after we are gone or in the process of going away + + if (mSuperWin) + gtk_object_remove_data(GTK_OBJECT(mSuperWin), "nsWindow"); + if (mShell) + gtk_object_remove_data(GTK_OBJECT(mShell), "nsWindow"); + if (mMozArea) + gtk_object_remove_data(GTK_OBJECT(mMozArea), "nsWindow"); + + return nsWidget::Destroy(); +} + + PRBool nsWindow::IsChild() const { return PR_FALSE; @@ -1028,6 +1044,9 @@ nsWindow::InstallFocusOutSignal(GtkWidget * aWidget) void nsWindow::HandleGDKEvent(GdkEvent *event) { + if (mIsDestroying) + return; + switch (event->any.type) { case GDK_MOTION_NOTIFY: @@ -2543,6 +2562,9 @@ nsWindow::HandleXlibExposeEvent(XEvent *event) void nsWindow::HandleXlibButtonEvent(XButtonEvent * aButtonEvent) { + if (mIsDestroying) + return; + nsMouseEvent event; PRUint32 eventType = 0; diff --git a/widget/src/gtk/nsWindow.h b/widget/src/gtk/nsWindow.h index 58f1e97827f4..0f1991766e5e 100644 --- a/widget/src/gtk/nsWindow.h +++ b/widget/src/gtk/nsWindow.h @@ -86,6 +86,7 @@ public: NS_IMETHOD SetCursor(nsCursor aCursor); NS_IMETHOD SetFocus(void); NS_IMETHOD GetAttention(void); + NS_IMETHOD Destroy(); void QueueDraw(); void UnqueueDraw();