From 3b1531ab56612e502ebe525aaf9ff4b7471aecb4 Mon Sep 17 00:00:00 2001 From: "dbaron%dbaron.org" Date: Thu, 30 Oct 2003 01:48:41 +0000 Subject: [PATCH] Fix shutdown leak of GDK windows by destroying hidden widget before event loop shutdown. b=219521 r=blizzard sr=bryner --- widget/src/gtk/nsDragService.cpp | 34 +++++++++++++++++++++++++++---- widget/src/gtk/nsDragService.h | 7 ++++++- widget/src/gtk2/nsDragService.cpp | 29 ++++++++++++++++++++++++-- widget/src/gtk2/nsDragService.h | 8 +++++++- 4 files changed, 70 insertions(+), 8 deletions(-) diff --git a/widget/src/gtk/nsDragService.cpp b/widget/src/gtk/nsDragService.cpp index f61d0e40b90..48afad9a5ce 100644 --- a/widget/src/gtk/nsDragService.cpp +++ b/widget/src/gtk/nsDragService.cpp @@ -25,6 +25,7 @@ #include "nsIServiceManager.h" #include "nsXPCOM.h" #include "nsISupportsPrimitives.h" +#include "nsIObserverService.h" #include "prlog.h" #include "nsVoidArray.h" #include "nsXPIDLString.h" @@ -45,8 +46,11 @@ static const char gTextUriListType[] = "text/uri-list"; NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService) NS_IMPL_RELEASE_INHERITED(nsDragService, nsBaseDragService) -NS_IMPL_QUERY_INTERFACE3(nsDragService, nsIDragService, nsIDragSession, \ - nsIDragSessionGTK) +NS_IMPL_QUERY_INTERFACE4(nsDragService, + nsIDragService, + nsIDragSession, + nsIDragSessionGTK, + nsIObserver) static void invisibleSourceDragEnd (GtkWidget *aWidget, @@ -63,6 +67,11 @@ invisibleSourceDragDataGet (GtkWidget *aWidget, nsDragService::nsDragService() { + // We have to destroy the hidden widget before the event loop stops running. + nsCOMPtr obsServ = + do_GetService("@mozilla.org/observer-service;1"); + obsServ->AddObserver(this, "quit-application", PR_FALSE); + // our hidden source widget mHiddenWidget = gtk_invisible_new(); // make sure that the widget is realized so that @@ -94,8 +103,25 @@ nsDragService::nsDragService() nsDragService::~nsDragService() { PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::~nsDragService")); - gtk_widget_unref(mHiddenWidget); - TargetResetData(); +} + +// nsIObserver + +NS_IMETHODIMP +nsDragService::Observe(nsISupports *aSubject, const char *aTopic, + const PRUnichar *aData) +{ + if (!nsCRT::strcmp(aTopic, "quit-application")) { + PR_LOG(sDragLm, PR_LOG_DEBUG, + ("nsDragService::Observe(\"quit-application\")")); + gtk_widget_unref(mHiddenWidget); + TargetResetData(); + } else { + NS_NOTREACHED("unexpected topic"); + return NS_ERROR_UNEXPECTED; + } + + return NS_OK; } // nsIDragService diff --git a/widget/src/gtk/nsDragService.h b/widget/src/gtk/nsDragService.h index 289f0d7b737..f38a8386306 100644 --- a/widget/src/gtk/nsDragService.h +++ b/widget/src/gtk/nsDragService.h @@ -25,6 +25,7 @@ #include "nsBaseDragService.h" #include "nsIDragSessionGTK.h" +#include "nsIObserver.h" #include @@ -32,7 +33,9 @@ * Native GTK DragService wrapper */ -class nsDragService : public nsBaseDragService, public nsIDragSessionGTK +class nsDragService : public nsBaseDragService, + public nsIDragSessionGTK, + public nsIObserver { public: @@ -41,6 +44,8 @@ public: NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIOBSERVER + // nsIDragService NS_IMETHOD InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * anArrayTransferables, diff --git a/widget/src/gtk2/nsDragService.cpp b/widget/src/gtk2/nsDragService.cpp index ff99f3b8773..e3d1e0d5e93 100644 --- a/widget/src/gtk2/nsDragService.cpp +++ b/widget/src/gtk2/nsDragService.cpp @@ -26,6 +26,7 @@ * ***** END LICENSE BLOCK ***** */ #include "nsDragService.h" +#include "nsIObserverService.h" #include "nsWidgetsCID.h" #include "nsWindow.h" #include "nsIServiceManager.h" @@ -50,10 +51,11 @@ static const char gTextUriListType[] = "text/uri-list"; NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService) NS_IMPL_RELEASE_INHERITED(nsDragService, nsBaseDragService) -NS_IMPL_QUERY_INTERFACE3(nsDragService, +NS_IMPL_QUERY_INTERFACE4(nsDragService, nsIDragService, nsIDragSession, - nsIDragSessionGTK) + nsIDragSessionGTK, + nsIObserver) static void invisibleSourceDragEnd(GtkWidget *aWidget, @@ -70,6 +72,12 @@ invisibleSourceDragDataGet(GtkWidget *aWidget, nsDragService::nsDragService() { + // We have to destroy the hidden widget before the event loop stops + // running. + nsCOMPtr obsServ = + do_GetService("@mozilla.org/observer-service;1"); + obsServ->AddObserver(this, "quit-application", PR_FALSE); + // our hidden source widget mHiddenWidget = gtk_invisible_new(); // make sure that the widget is realized so that @@ -98,8 +106,25 @@ nsDragService::nsDragService() nsDragService::~nsDragService() { PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::~nsDragService")); +} + +// nsIObserver + +NS_IMETHODIMP +nsDragService::Observe(nsISupports *aSubject, const char *aTopic, + const PRUnichar *aData) +{ + if (!nsCRT::strcmp(aTopic, "quit-application")) { + PR_LOG(sDragLm, PR_LOG_DEBUG, + ("nsDragService::Observe(\"quit-application\")")); gtk_widget_destroy(mHiddenWidget); TargetResetData(); + } else { + NS_NOTREACHED("unexpected topic"); + return NS_ERROR_UNEXPECTED; + } + + return NS_OK; } // nsIDragService diff --git a/widget/src/gtk2/nsDragService.h b/widget/src/gtk2/nsDragService.h index 201362acb13..b02b1d4a104 100644 --- a/widget/src/gtk2/nsDragService.h +++ b/widget/src/gtk2/nsDragService.h @@ -30,6 +30,7 @@ #include "nsBaseDragService.h" #include "nsIDragSessionGTK.h" +#include "nsIObserver.h" #include @@ -37,13 +38,18 @@ * Native GTK DragService wrapper */ -class nsDragService : public nsBaseDragService, public nsIDragSessionGTK { +class nsDragService : public nsBaseDragService, + public nsIDragSessionGTK, + public nsIObserver +{ public: nsDragService(); virtual ~nsDragService(); NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIOBSERVER + // nsIDragService NS_IMETHOD InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * anArrayTransferables,