b=522635 destroy child nsWindows when destroying the parent r=roc

--HG--
extra : rebase_source : 53b4061a728721db67c9b253e0454ee815a0fad9
This commit is contained in:
Karl Tomlinson 2009-11-11 10:57:25 +13:00
parent 80f6afa68a
commit 41b65db823
2 changed files with 41 additions and 29 deletions

View File

@ -652,9 +652,7 @@ CheckDestroyInvisibleContainer()
// Change the containing GtkWidget on a sub-hierarchy of GdkWindows belonging
// to aOldWidget and rooted at aWindow, and reparent any child GtkWidgets of
// the GdkWindow hierarchy. If aNewWidget is NULL, the reference to
// aOldWidget is removed from its GdkWindows, and child GtkWidgets are
// destroyed.
// the GdkWindow hierarchy to aNewWidget.
static void
SetWidgetForHierarchy(GdkWindow *aWindow,
GtkWidget *aOldWidget,
@ -673,13 +671,7 @@ SetWidgetForHierarchy(GdkWindow *aWindow,
// This window belongs to a child widget, which will no longer be a
// child of aOldWidget.
if (aNewWidget) {
gtk_widget_reparent(widget, aNewWidget);
} else {
// aNewWidget == NULL indicates that the window is about to be
// destroyed.
gtk_widget_destroy(widget);
}
gtk_widget_reparent(widget, aNewWidget);
return;
}
@ -693,6 +685,34 @@ SetWidgetForHierarchy(GdkWindow *aWindow,
gdk_window_set_user_data(aWindow, aNewWidget);
}
// Walk the list of child windows and call destroy on them.
void
nsWindow::DestroyChildWindows()
{
if (!mGdkWindow)
return;
GList *children = gdk_window_get_children(mGdkWindow);
for(GList *list = children; list; list = list->next) {
GdkWindow *child = GDK_WINDOW(children->data);
nsWindow *kid = get_window_for_gdk_window(child);
if (kid) {
kid->Destroy();
} else {
// This child is not an nsWindow.
// Destroy the child GtkWidget.
gpointer data;
gdk_window_get_user_data(child, &data);
if (GTK_IS_WIDGET(data)) {
gtk_widget_destroy(static_cast<GtkWidget*>(data));
}
}
}
g_list_free(children);
}
NS_IMETHODIMP
nsWindow::Destroy(void)
{
@ -730,15 +750,6 @@ nsWindow::Destroy(void)
NativeShow(PR_FALSE);
// walk the list of children and call destroy on them. Have to be
// careful, though -- calling destroy on a kid may actually remove
// it from our child list, losing its sibling links.
for (nsIWidget* kid = mFirstChild; kid; ) {
nsIWidget* next = kid->GetNextSibling();
kid->Destroy();
kid = next;
}
#ifdef USE_XIM
IMEDestroyContext();
#endif
@ -790,16 +801,13 @@ nsWindow::Destroy(void)
"mGdkWindow should be NULL when mContainer is destroyed");
}
else if (mGdkWindow) {
// Remove references from GdkWindows back to their container
// widget while the GdkWindow hierarchy is still available.
// (OnContainerUnrealize does this when the MozContainer widget is
// destroyed.)
if (owningWidget) {
SetWidgetForHierarchy(mGdkWindow, owningWidget, NULL);
}
NS_ASSERTION(!get_gtk_widget_for_gdk_window(mGdkWindow),
"widget reference not removed");
// Destroy child windows to ensure that their mThebesSurfaces are
// released and to remove references from GdkWindows back to their
// container widget. (OnContainerUnrealize() does this when the
// MozContainer widget is destroyed.)
DestroyChildWindows();
gdk_window_set_user_data(mGdkWindow, NULL);
g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", NULL);
gdk_window_destroy(mGdkWindow);
mGdkWindow = nsnull;
@ -2384,7 +2392,7 @@ nsWindow::OnContainerUnrealize(GtkWidget *aWidget)
"unexpected \"unrealize\" signal");
if (mGdkWindow) {
SetWidgetForHierarchy(mGdkWindow, aWidget, NULL);
DestroyChildWindows();
g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", NULL);
mGdkWindow = NULL;
@ -7211,6 +7219,9 @@ nsWindow::GetSurfaceForGdkDrawable(GdkDrawable* aDrawable,
gfxASurface*
nsWindow::GetThebesSurface()
{
if (!mGdkWindow)
return nsnull;
GdkDrawable* d;
gint x_offset, y_offset;
gdk_window_get_internal_paint_info(mGdkWindow, &d, &x_offset, &y_offset);

View File

@ -432,6 +432,7 @@ protected:
PRPackedBool mPlaced;
private:
void DestroyChildWindows();
void GetToplevelWidget(GtkWidget **aWidget);
GtkWidget *GetMozContainerWidget();
nsWindow *GetContainerWindow();