summaryrefslogtreecommitdiff
path: root/firefox-2.0-startup-notify.patch
diff options
context:
space:
mode:
authorChristopher Aillon <caillon@fedoraproject.org>2007-09-25 03:36:23 +0000
committerChristopher Aillon <caillon@fedoraproject.org>2007-09-25 03:36:23 +0000
commitf0eebf3f41f35c38dfff4c7155f5e5d67c87f9b6 (patch)
tree65f1ccf166908435e1ae3fb670a043446af373e7 /firefox-2.0-startup-notify.patch
parent- Fix crashes when using GTK+ themes containing a gtkrc which specify (diff)
downloadlibrewolf-fedora-ff-f0eebf3f41f35c38dfff4c7155f5e5d67c87f9b6.tar.gz
librewolf-fedora-ff-f0eebf3f41f35c38dfff4c7155f5e5d67c87f9b6.tar.bz2
librewolf-fedora-ff-f0eebf3f41f35c38dfff4c7155f5e5d67c87f9b6.zip
- Startup notification support
Diffstat (limited to 'firefox-2.0-startup-notify.patch')
-rw-r--r--firefox-2.0-startup-notify.patch1121
1 files changed, 1121 insertions, 0 deletions
diff --git a/firefox-2.0-startup-notify.patch b/firefox-2.0-startup-notify.patch
new file mode 100644
index 0000000..9598113
--- /dev/null
+++ b/firefox-2.0-startup-notify.patch
@@ -0,0 +1,1121 @@
+https://bugzilla.mozilla.org/show_bug.cgi?id=223492
+
+--- config/autoconf.mk.in 2006-09-14 14:07:03.000000000 -0400
++++ config/autoconf.mk.in 2007-07-03 18:01:36.000000000 -0400
+@@ -223,6 +223,10 @@
+ MOZ_GNOMEUI_CFLAGS = @MOZ_GNOMEUI_CFLAGS@
+ MOZ_GNOMEUI_LIBS = @MOZ_GNOMEUI_LIBS@
+
++MOZ_ENABLE_STARTUP_NOTIFICATION = @MOZ_ENABLE_STARTUP_NOTIFICATION@
++MOZ_STARTUP_NOTIFICATION_CFLAGS = @MOZ_STARTUP_NOTIFICATION_CFLAGS@
++MOZ_STARTUP_NOTIFICATION_LIBS = @MOZ_STARTUP_NOTIFICATION_LIBS@
++
+ MOZ_GNOMEVFS_CFLAGS = @MOZ_GNOMEVFS_CFLAGS@
+ MOZ_GNOMEVFS_LIBS = @MOZ_GNOMEVFS_LIBS@
+
+--- toolkit/components/remote/nsGTKRemoteService.cpp 2006-01-05 22:19:20.000000000 -0500
++++ toolkit/components/remote/nsGTKRemoteService.cpp 2007-07-05 17:34:41.000000000 -0400
+@@ -50,7 +50,9 @@
+
+ #include "nsIBaseWindow.h"
+ #include "nsIDocShell.h"
++#include "nsIDocument.h"
+ #include "nsIDOMWindow.h"
++#include "nsPIDOMWindow.h"
+ #include "nsIGenericFactory.h"
+ #include "nsILocalFile.h"
+ #include "nsIObserverService.h"
+@@ -58,6 +60,8 @@
+ #include "nsIServiceManager.h"
+ #include "nsIWeakReference.h"
+ #include "nsIWidget.h"
++#include "nsIAppShellService.h"
++#include "nsAppShellCID.h"
+
+ #include "nsCOMPtr.h"
+ #include "nsString.h"
+@@ -65,6 +69,10 @@
+ #include "prenv.h"
+ #include "nsCRT.h"
+
++#ifdef MOZ_WIDGET_GTK2
++#include "nsGTKToolkit.h"
++#endif
++
+ #ifdef MOZ_XUL_APP
+ #include "nsICommandLineRunner.h"
+ #include "nsXULAppAPI.h"
+@@ -155,20 +163,46 @@
+ return PL_DHASH_NEXT;
+ }
+
++static nsIWidget* GetMainWidget(nsIDOMWindow* aWindow)
++{
++ // get the native window for this instance
++ nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aWindow));
++ NS_ENSURE_TRUE(window, nsnull);
++ nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
++ NS_ENSURE_TRUE(doc, nsnull);
++ nsCOMPtr<nsISupports> container = doc->GetContainer();
++ nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(container));
++ NS_ENSURE_TRUE(baseWindow, nsnull);
++
++ nsCOMPtr<nsIWidget> mainWidget;
++ baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
++ return mainWidget;
++}
++
++static nsGTKToolkit* GetGTKToolkit()
++{
++ nsCOMPtr<nsIAppShellService> svc = do_GetService(NS_APPSHELLSERVICE_CONTRACTID);
++ if (!svc)
++ return nsnull;
++ nsCOMPtr<nsIDOMWindowInternal> window;
++ svc->GetHiddenDOMWindow(getter_AddRefs(window));
++ if (!window)
++ return nsnull;
++ nsIWidget* widget = GetMainWidget(window);
++ if (!widget)
++ return nsnull;
++ nsIToolkit* toolkit = widget->GetToolkit();
++ if (!toolkit)
++ return nsnull;
++ return NS_STATIC_CAST(nsGTKToolkit*, toolkit);
++}
++
++
+ NS_IMETHODIMP
+ nsGTKRemoteService::RegisterWindow(nsIDOMWindow* aWindow)
+ {
+ // get the native window for this instance
+- nsCOMPtr<nsIScriptGlobalObject> scriptObject
+- (do_QueryInterface(aWindow));
+- NS_ENSURE_TRUE(scriptObject, NS_ERROR_FAILURE);
+-
+- nsCOMPtr<nsIBaseWindow> baseWindow
+- (do_QueryInterface(scriptObject->GetDocShell()));
+- NS_ENSURE_TRUE(baseWindow, NS_ERROR_FAILURE);
+-
+- nsCOMPtr<nsIWidget> mainWidget;
+- baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
++ nsIWidget* mainWidget = GetMainWidget(aWindow);
+ NS_ENSURE_TRUE(mainWidget, NS_ERROR_FAILURE);
+
+ // walk up the widget tree and find the toplevel window in the
+@@ -201,7 +235,6 @@
+
+ return NS_OK;
+ }
+-
+ NS_IMETHODIMP
+ nsGTKRemoteService::Shutdown()
+ {
+@@ -260,7 +293,7 @@
+
+ #ifndef MOZ_XUL_APP
+ const char*
+-nsGTKRemoteService::HandleCommand(char* aCommand, nsIDOMWindow* aWindow)
++nsGTKRemoteService::HandleCommand(char* aCommand, nsIDOMWindow* aWindow, PRUint32 aTimestamp)
+ {
+ nsresult rv;
+
+@@ -283,8 +316,60 @@
+ }
+
+ #else //MOZ_XUL_APP
++
++// Set desktop startup ID to the passed ID, if there is one, so that any created
++// windows get created with the right window manager metadata, and any windows
++// that get new tabs and are activated also get the right WM metadata.
++// If there is no desktop startup ID, then use the X event's timestamp
++// for _NET_ACTIVE_WINDOW when the window gets focused or shown.
++static void
++SetDesktopStartupIDOrTimestamp(const nsACString& aDesktopStartupID,
++ PRUint32 aTimestamp) {
++#ifdef MOZ_WIDGET_GTK2
++ nsGTKToolkit* toolkit = GetGTKToolkit();
++ if (!toolkit)
++ return;
++ if (!aDesktopStartupID.IsEmpty()) {
++ toolkit->SetDesktopStartupID(aDesktopStartupID);
++ } else {
++ toolkit->SetFocusTimestamp(aTimestamp);
++ }
++#endif
++}
++
++static PRBool
++FindExtensionParameterInCommand(const char* aParameterName,
++ const nsACString& aCommand,
++ char aSeparator,
++ nsACString* aValue)
++{
++ nsCAutoString searchFor;
++ searchFor.Append(aSeparator);
++ searchFor.Append(aParameterName);
++ searchFor.Append('=');
++
++ nsACString::const_iterator start, end;
++ aCommand.BeginReading(start);
++ aCommand.EndReading(end);
++ if (!FindInReadable(searchFor, start, end))
++ return PR_FALSE;
++
++ nsACString::const_iterator charStart, charEnd;
++ charStart = end;
++ aCommand.EndReading(charEnd);
++ nsACString::const_iterator idStart = charStart, idEnd;
++ if (FindCharInReadable(aSeparator, charStart, charEnd)) {
++ idEnd = charStart;
++ } else {
++ idEnd = charEnd;
++ }
++ *aValue = nsDependentCSubstring(idStart, idEnd);
++ return PR_TRUE;
++}
++
+ const char*
+-nsGTKRemoteService::HandleCommand(char* aCommand, nsIDOMWindow* aWindow)
++nsGTKRemoteService::HandleCommand(char* aCommand, nsIDOMWindow* aWindow,
++ PRUint32 aTimestamp)
+ {
+ nsresult rv;
+
+@@ -314,6 +399,12 @@
+ #endif
+
+ if (!command.EqualsLiteral("ping")) {
++ nsCAutoString desktopStartupID;
++ nsDependentCString cmd(aCommand);
++ FindExtensionParameterInCommand("DESKTOP_STARTUP_ID",
++ cmd, '\n',
++ &desktopStartupID);
++
+ char* argv[3] = {"dummyappname", "-remote", aCommand};
+ rv = cmdline->Init(3, argv, nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT);
+ if (NS_FAILED(rv))
+@@ -322,6 +413,8 @@
+ if (aWindow)
+ cmdline->SetWindowContext(aWindow);
+
++ SetDesktopStartupIDOrTimestamp(desktopStartupID, aTimestamp);
++
+ rv = cmdline->Run();
+ if (NS_ERROR_ABORT == rv)
+ return "500 command not parseable";
+@@ -333,7 +426,8 @@
+ }
+
+ const char*
+-nsGTKRemoteService::HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow)
++nsGTKRemoteService::HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow,
++ PRUint32 aTimestamp)
+ {
+ nsresult rv;
+
+@@ -364,6 +458,8 @@
+ if (NS_FAILED(rv))
+ return "509 internal error";
+
++ nsCAutoString desktopStartupID;
++
+ char **argv = (char**) malloc(sizeof(char*) * argc);
+ if (!argv) return "509 internal error";
+
+@@ -372,6 +468,12 @@
+ for (int i = 0; i < argc; ++i) {
+ argv[i] = aBuffer + TO_LITTLE_ENDIAN32(offset[i]);
+
++ if (i == 0) {
++ nsDependentCString cmd(argv[0]);
++ FindExtensionParameterInCommand("DESKTOP_STARTUP_ID",
++ cmd, ' ',
++ &desktopStartupID);
++ }
+ #ifdef DEBUG_bsmedberg
+ printf(" argv[%i]:\t%s\n", i, argv[i]);
+ #endif
+@@ -386,7 +488,10 @@
+ if (aWindow)
+ cmdline->SetWindowContext(aWindow);
+
++ SetDesktopStartupIDOrTimestamp(desktopStartupID, aTimestamp);
++
+ rv = cmdline->Run();
++
+ if (NS_ERROR_ABORT == rv)
+ return "500 command not parseable";
+
+@@ -486,7 +591,7 @@
+ return FALSE;
+
+ // cool, we got the property data.
+- const char *response = HandleCommand(data, window);
++ const char *response = HandleCommand(data, window, pevent->time);
+
+ // put the property onto the window as the response
+ XChangeProperty (GDK_DISPLAY(), GDK_WINDOW_XWINDOW(pevent->window),
+@@ -531,7 +636,7 @@
+ return FALSE;
+
+ // cool, we got the property data.
+- const char *response = HandleCommandLine(data, window);
++ const char *response = HandleCommandLine(data, window, pevent->time);
+
+ // put the property onto the window as the response
+ XChangeProperty (GDK_DISPLAY(), GDK_WINDOW_XWINDOW(pevent->window),
+--- toolkit/components/remote/nsGTKRemoteService.h 2005-04-04 19:11:42.000000000 -0400
++++ toolkit/components/remote/nsGTKRemoteService.h 2007-07-03 18:01:36.000000000 -0400
+@@ -80,10 +80,12 @@
+ nsIWeakReference* aData,
+ void* aClosure);
+
+- static const char* HandleCommand(char* aCommand, nsIDOMWindow* aWindow);
++ static const char* HandleCommand(char* aCommand, nsIDOMWindow* aWindow,
++ PRUint32 aTimestamp);
+
+ #ifdef MOZ_XUL_APP
+- static const char* HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow);
++ static const char* HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow,
++ PRUint32 aTimestamp);
+ #endif
+
+ static gboolean HandlePropertyChange(GtkWidget *widget,
+--- toolkit/components/remote/Makefile.in 2005-04-08 00:59:36.000000000 -0400
++++ toolkit/components/remote/Makefile.in 2007-07-05 17:45:55.000000000 -0400
+@@ -56,7 +56,9 @@
+ string \
+ appcomps \
+ toolkitcomps \
+- appcomps \
++ appshell \
++ layout \
++ content \
+ xulapp \
+ widget \
+ gfx \
+--- toolkit/library/Makefile.in 2007-04-03 10:32:27.000000000 -0400
++++ toolkit/library/Makefile.in 2007-07-03 18:01:36.000000000 -0400
+@@ -357,6 +357,10 @@
+ EXTRA_DSO_LDOPTS += $(MOZ_XPRINT_LDFLAGS)
+ endif
+
++ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
++EXTRA_DSO_LDOPTS += $(MOZ_STARTUP_NOTIFICATION_LIBS)
++endif
++
+ ifdef MOZ_ENABLE_PANGO
+ EXTRA_DSO_LDOPTS += $(MOZ_PANGO_LIBS)
+ endif
+--- toolkit/xre/nsAppRunner.cpp 2007-04-30 13:26:58.000000000 -0400
++++ toolkit/xre/nsAppRunner.cpp 2007-07-05 17:48:51.000000000 -0400
+@@ -72,6 +72,7 @@
+ #include "nsIComponentRegistrar.h"
+ #include "nsIContentHandler.h"
+ #include "nsIDialogParamBlock.h"
++#include "nsIDocument.h"
+ #include "nsIDOMWindow.h"
+ #include "nsIEventQueueService.h"
+ #include "nsIExtensionManager.h"
+@@ -99,6 +100,11 @@
+ #ifdef XP_WIN
+ #include "nsIWinAppHelper.h"
+ #endif
++#include "nsPIDOMWindow.h"
++#include "nsIBaseWindow.h"
++#include "nsIWidget.h"
++#include "nsIDocShell.h"
++#include "nsAppShellCID.h"
+
+ #include "nsCRT.h"
+ #include "nsCOMPtr.h"
+@@ -262,6 +268,9 @@
+ #if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
+ #include <gtk/gtk.h>
+ #endif //MOZ_WIDGET_GTK || MOZ_WIDGET_GTK2
++#if defined(MOZ_WIDGET_GTK2)
++#include "nsGTKToolkit.h"
++#endif
+
+ #if defined(MOZ_WIDGET_QT)
+ #include <qapplication.h>
+@@ -1105,7 +1114,7 @@
+ // use int here instead of a PR type since it will be returned
+ // from main - just to keep types consistent
+ static int
+-HandleRemoteArgument(const char* remote)
++HandleRemoteArgument(const char* remote, const char* aDesktopStartupID)
+ {
+ nsresult rv;
+ ArgResult ar;
+@@ -1146,7 +1155,7 @@
+ nsXPIDLCString response;
+ PRBool success = PR_FALSE;
+ rv = client.SendCommand(program.get(), username, profile, remote,
+- getter_Copies(response), &success);
++ aDesktopStartupID, getter_Copies(response), &success);
+ // did the command fail?
+ if (NS_FAILED(rv)) {
+ PR_fprintf(PR_STDERR, "Error: Failed to send command: %s\n",
+@@ -1163,7 +1172,7 @@
+ }
+
+ static PRBool
+-RemoteCommandLine()
++RemoteCommandLine(const char* aDesktopStartupID)
+ {
+ nsresult rv;
+ ArgResult ar;
+@@ -1195,7 +1204,7 @@
+ nsXPIDLCString response;
+ PRBool success = PR_FALSE;
+ rv = client.SendCommandLine(program.get(), username, nsnull,
+- gArgc, gArgv,
++ gArgc, gArgv, aDesktopStartupID,
+ getter_Copies(response), &success);
+ // did the command fail?
+ if (NS_FAILED(rv) || !success)
+@@ -2059,6 +2068,53 @@
+ #ifdef MOZ_WIDGET_GTK2
+ #include "prlink.h"
+ typedef void (*_g_set_application_name_fn)(const gchar *application_name);
++typedef void (*_gtk_window_set_auto_startup_notification_fn)(gboolean setting);
++
++static PRFuncPtr FindFunction(const char* aName)
++{
++ PRLibrary *lib = nsnull;
++ PRFuncPtr result = PR_FindFunctionSymbolAndLibrary(aName, &lib);
++ // Since the library was already loaded, we can safely unload it here.
++ if (lib) {
++ PR_UnloadLibrary(lib);
++ }
++ return result;
++}
++
++static nsIWidget* GetMainWidget(nsIDOMWindow* aWindow)
++{
++ // get the native window for this instance
++ nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(aWindow));
++ NS_ENSURE_TRUE(window, nsnull);
++ nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
++ NS_ENSURE_TRUE(doc, nsnull);
++ nsCOMPtr<nsISupports> container = doc->GetContainer();
++ nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(container));
++ NS_ENSURE_TRUE(baseWindow, nsnull);
++
++ nsCOMPtr<nsIWidget> mainWidget;
++ baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
++ return mainWidget;
++}
++
++static nsGTKToolkit* GetGTKToolkit()
++{
++ nsCOMPtr<nsIAppShellService> svc = do_GetService(NS_APPSHELLSERVICE_CONTRACTID);
++ if (!svc)
++ return nsnull;
++ nsCOMPtr<nsIDOMWindowInternal> window;
++ svc->GetHiddenDOMWindow(getter_AddRefs(window));
++ if (!window)
++ return nsnull;
++ nsIWidget* widget = GetMainWidget(window);
++ if (!widget)
++ return nsnull;
++ nsIToolkit* toolkit = widget->GetToolkit();
++ if (!toolkit)
++ return nsnull;
++ return NS_STATIC_CAST(nsGTKToolkit*, toolkit);
++}
++
+ #endif
+
+ int
+@@ -2235,6 +2291,16 @@
+ if (CheckArg("install"))
+ gdk_rgb_set_install(TRUE);
+
++#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2) || defined(MOZ_ENABLE_XREMOTE)
++ // Stash DESKTOP_STARTUP_ID in malloc'ed memory becaus gtk_init will clear it.
++#define HAVE_DESKTOP_STARTUP_ID
++ const char* desktopStartupIDEnv = PR_GetEnv("DESKTOP_STARTUP_ID");
++ nsCAutoString desktopStartupID;
++ if (desktopStartupIDEnv) {
++ desktopStartupID.Assign(desktopStartupIDEnv);
++ }
++#endif
++
+ // Initialize GTK+1/2 here for splash
+ #if defined(MOZ_WIDGET_GTK)
+ gtk_set_locale();
+@@ -2243,15 +2309,15 @@
+
+ #if defined(MOZ_WIDGET_GTK2)
+ // g_set_application_name () is only defined in glib2.2 and higher.
+- PRLibrary *glib2 = nsnull;
+- _g_set_application_name_fn _g_set_application_name =
+- (_g_set_application_name_fn)PR_FindFunctionSymbolAndLibrary("g_set_application_name", &glib2);
++ _g_set_application_name_fn _g_set_application_name =
++ (_g_set_application_name_fn)FindFunction("g_set_application_name");
+ if (_g_set_application_name) {
+ _g_set_application_name(gAppData->name);
+ }
+- if (glib2) {
+- PR_UnloadLibrary(glib2);
+- }
++ _gtk_window_set_auto_startup_notification_fn _gtk_window_set_auto_startup_notification =
++ (_gtk_window_set_auto_startup_notification_fn)FindFunction("gtk_window_set_auto_startup_notification");
++ if (_gtk_window_set_auto_startup_notification)
++ _gtk_window_set_auto_startup_notification(PR_FALSE);
+ #endif
+
+ gtk_widget_set_default_visual(gdk_rgb_get_visual());
+@@ -2315,13 +2381,15 @@
+ PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n");
+ return 1;
+ }
++ const char* desktopStartupIDPtr =
++ desktopStartupID.IsEmpty() ? nsnull : desktopStartupID.get();
+ if (ar) {
+- return HandleRemoteArgument(xremotearg);
++ return HandleRemoteArgument(xremotearg, desktopStartupIDPtr);
+ }
+
+ if (!PR_GetEnv("MOZ_NO_REMOTE")) {
+ // Try to remote the entire command line. If this fails, start up normally.
+- if (RemoteCommandLine())
++ if (RemoteCommandLine(desktopStartupIDPtr))
+ return 0;
+ }
+ #endif
+@@ -2533,6 +2601,13 @@
+ NS_TIMELINE_LEAVE("appStartup->CreateHiddenWindow");
+ NS_ENSURE_SUCCESS(rv, 1);
+
++#if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK2)
++ nsRefPtr<nsGTKToolkit> toolkit = GetGTKToolkit();
++ if (toolkit && !desktopStartupID.IsEmpty()) {
++ toolkit->SetDesktopStartupID(desktopStartupID);
++ }
++#endif
++
+ // Extension Compatibility Checking and Startup
+ if (gAppData->flags & NS_XRE_ENABLE_EXTENSION_MANAGER) {
+ nsCOMPtr<nsIExtensionManager> em(do_GetService("@mozilla.org/extensions/manager;1"));
+@@ -2713,6 +2788,21 @@
+ }
+ #endif
+
++#if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_TOOLKIT_GTK2)
++ nsGTKToolkit* toolkit = GetGTKToolkit();
++ if (toolkit) {
++ nsCAutoString currentDesktopStartupID;
++ toolkit->GetDesktopStartupID(&currentDesktopStartupID);
++ if (!currentDesktopStartupID.IsEmpty()) {
++ nsCAutoString desktopStartupEnv;
++ desktopStartupEnv.AssignLiteral("DESKTOP_STARTUP_ID=");
++ desktopStartupEnv.Append(currentDesktopStartupID);
++ // Leak it with extreme prejudice!
++ PR_SetEnv(ToNewCString(desktopStartupEnv));
++ }
++ }
++#endif
++
+ rv = LaunchChild(nativeApp, appInitiatedRestart, upgraded ? -1 : 0);
+ return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
+ }
+--- toolkit/xre/Makefile.in 2007-02-06 02:13:20.000000000 -0500
++++ toolkit/xre/Makefile.in 2007-07-03 18:01:36.000000000 -0400
+@@ -69,6 +69,7 @@
+ shellservice \
+ string \
+ uriloader \
++ layout \
+ widget \
+ windowwatcher \
+ xpcom \
+--- configure.in 2007-04-03 11:40:02.000000000 -0400
++++ configure.in 2007-07-03 18:01:36.000000000 -0400
+@@ -125,6 +125,7 @@
+ GNOMEUI_VERSION=2.2.0
+ GCONF_VERSION=1.2.1
+ LIBGNOME_VERSION=2.0
++STARTUP_NOTIFICATION_VERSION=0.8
+
+ dnl Set various checks
+ dnl ========================================================
+@@ -4156,6 +4157,41 @@
+
+ AC_SUBST(MOZ_DEFAULT_TOOLKIT)
+
++dnl ========================================================
++dnl = startup-notification support module
++dnl ========================================================
++
++if test "$MOZ_ENABLE_GTK2"
++then
++ MOZ_ENABLE_STARTUP_NOTIFICATION=
++
++ MOZ_ARG_ENABLE_BOOL(startup-notification,
++ [ --enable-startup-notification Enable startup-notification support (default: disabled) ],
++ MOZ_ENABLE_STARTUP_NOTIFICATION=force,
++ MOZ_ENABLE_STARTUP_NOTIFICATION=)
++ if test "$MOZ_ENABLE_STARTUP_NOTIFICATION"
++ then
++ PKG_CHECK_MODULES(MOZ_STARTUP_NOTIFICATION,
++ libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_VERSION,
++ [MOZ_ENABLE_STARTUP_NOTIFICATION=1], [
++ if test "$MOZ_ENABLE_STARTUP_NOTIFICATION" = "force"
++ then
++ AC_MSG_ERROR([* * * Could not find startup-notification >= $STARTUP_NOTIFICATION_VERSION])
++ fi
++ MOZ_ENABLE_STARTUP_NOTIFICATION=
++ ])
++ fi
++
++ if test "$MOZ_ENABLE_STARTUP_NOTIFICATION"; then
++ AC_DEFINE(MOZ_ENABLE_STARTUP_NOTIFICATION)
++ fi
++
++ TK_LIBS="$TK_LIBS $MOZ_STARTUP_NOTIFICATION_LIBS"
++fi
++AC_SUBST(MOZ_ENABLE_STARTUP_NOTIFICATION)
++AC_SUBST(MOZ_STARTUP_NOTIFICATION_CFLAGS)
++AC_SUBST(MOZ_STARTUP_NOTIFICATION_LIBS)
++
+ AC_SUBST(GTK_CONFIG)
+ AC_SUBST(TK_CFLAGS)
+ AC_SUBST(TK_LIBS)
+--- widget/src/gtk2/nsWindow.cpp 2007-04-19 14:46:03.000000000 -0400
++++ widget/src/gtk2/nsWindow.cpp 2007-07-03 18:01:36.000000000 -0400
+@@ -40,7 +40,7 @@
+ #include "prlink.h"
+
+ #include "nsWindow.h"
+-#include "nsToolkit.h"
++#include "nsGTKToolkit.h"
+ #include "nsIRenderingContext.h"
+ #include "nsIRegion.h"
+ #include "nsIRollupListener.h"
+@@ -58,6 +58,11 @@
+ #include <gdk/gdkx.h>
+ #include <gdk/gdkkeysyms.h>
+
++#ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
++#define SN_API_NOT_YET_FROZEN
++#include <startup-notification-1.0/libsn/sn.h>
++#endif
++
+ #include "gtk2xtbin.h"
+
+ #include "nsIPrefService.h"
+@@ -660,6 +665,75 @@
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
++typedef void (* SetUserTimeFunc)(GdkWindow* aWindow, guint32 aTimestamp);
++
++// This will become obsolete when new GTK APIs are widely supported,
++// as described here: http://bugzilla.gnome.org/show_bug.cgi?id=347375
++static void
++SetUserTimeAndStartupIDForActivatedWindow(GtkWidget* aWindow)
++{
++ nsCOMPtr<nsIToolkit> toolkit;
++ NS_GetCurrentToolkit(getter_AddRefs(toolkit));
++ if (!toolkit)
++ return;
++
++ nsGTKToolkit* GTKToolkit = NS_STATIC_CAST(nsGTKToolkit*,
++ NS_STATIC_CAST(nsIToolkit*, toolkit));
++ nsCAutoString desktopStartupID;
++ GTKToolkit->GetDesktopStartupID(&desktopStartupID);
++ if (desktopStartupID.IsEmpty()) {
++ // We don't have the data we need. Fall back to an
++ // approximation ... using the timestamp of the remote command
++ // being received as a guess for the timestamp of the user event
++ // that triggered it.
++ PRUint32 timestamp = GTKToolkit->GetFocusTimestamp();
++ if (timestamp) {
++ gdk_window_focus(aWindow->window, timestamp);
++ GTKToolkit->SetFocusTimestamp(0);
++ }
++ return;
++ }
++
++#ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
++ GdkDrawable* drawable = GDK_DRAWABLE(aWindow->window);
++ GtkWindow* win = GTK_WINDOW(aWindow);
++ if (!win) {
++ NS_WARNING("Passed in widget was not a GdkWindow!");
++ return;
++ }
++ GdkScreen* screen = gtk_window_get_screen(win);
++ SnDisplay* snd =
++ sn_display_new(gdk_x11_drawable_get_xdisplay(drawable), nsnull, nsnull);
++ if (!snd)
++ return;
++ SnLauncheeContext* ctx =
++ sn_launchee_context_new(snd, gdk_screen_get_number(screen),
++ desktopStartupID.get());
++ if (!ctx) {
++ sn_display_unref(snd);
++ return;
++ }
++
++ if (sn_launchee_context_get_id_has_timestamp(ctx)) {
++ PRLibrary* gtkLibrary;
++ SetUserTimeFunc setUserTimeFunc = (SetUserTimeFunc)
++ PR_FindFunctionSymbolAndLibrary("gdk_x11_window_set_user_time", &gtkLibrary);
++ if (setUserTimeFunc) {
++ setUserTimeFunc(aWindow->window, sn_launchee_context_get_timestamp(ctx));
++ PR_UnloadLibrary(gtkLibrary);
++ }
++ }
++
++ sn_launchee_context_setup_window(ctx, gdk_x11_drawable_get_xid(drawable));
++ sn_launchee_context_complete(ctx);
++
++ sn_launchee_context_unref(ctx);
++ sn_display_unref(snd);
++#endif
++
++ GTKToolkit->SetDesktopStartupID(EmptyCString());
++}
++
+ NS_IMETHODIMP
+ nsWindow::SetFocus(PRBool aRaise)
+ {
+@@ -680,6 +754,10 @@
+ // set properly.
+ GtkWidget *toplevelWidget = gtk_widget_get_toplevel(owningWidget);
+
++ if (toplevelWidget && aRaise) {
++ SetUserTimeAndStartupIDForActivatedWindow(toplevelWidget);
++ }
++
+ if (gRaiseWindows && aRaise && toplevelWidget &&
+ !GTK_WIDGET_HAS_FOCUS(owningWidget) &&
+ !GTK_WIDGET_HAS_FOCUS(toplevelWidget)) {
+@@ -1167,7 +1245,7 @@
+
+ case NS_NATIVE_GRAPHIC: {
+ NS_ASSERTION(nsnull != mToolkit, "NULL toolkit, unable to get a GC");
+- return (void *)NS_STATIC_CAST(nsToolkit *, mToolkit)->GetSharedGC();
++ return (void *)NS_STATIC_CAST(nsGTKToolkit *, mToolkit)->GetSharedGC();
+ break;
+ }
+
+@@ -2802,13 +2880,18 @@
+ // is shown.
+ // XXX that may or may not be true for GTK+ 2.x
+ if (mTransparencyBitmap) {
+- ApplyTransparencyBitmap();
++ ApplyTransparencyBitmap();
+ }
+
+ // unset our flag now that our window has been shown
+ mNeedsShow = PR_FALSE;
+
+ if (mIsTopLevel) {
++ // Set up usertime/startupID metadata for the created window.
++ if (mWindowType != eWindowType_invisible) {
++ SetUserTimeAndStartupIDForActivatedWindow(mShell);
++ }
++
+ moz_drawingarea_set_visibility(mDrawingarea, aAction);
+ gtk_widget_show(GTK_WIDGET(mContainer));
+ gtk_widget_show(mShell);
+--- widget/src/gtk2/Makefile.in 2006-06-17 11:16:14.000000000 -0400
++++ widget/src/gtk2/Makefile.in 2007-07-03 18:01:36.000000000 -0400
+@@ -97,6 +97,7 @@
+ $(MOZ_COMPONENT_LIBS) \
+ -lgkgfx \
+ -lgtkxtbin \
++ $(MOZ_STARTUP_NOTIFICATION_LIBS) \
+ $(XLDFLAGS) \
+ $(XLIBS) \
+ $(MOZ_GTK2_LIBS)
+@@ -107,14 +108,15 @@
+
+ EXPORTS = \
+ nsIGdkPixbufImage.h \
++ nsGTKToolkit.h \
+ mozdrawingarea.h \
+ mozcontainer.h \
+ $(NULL)
+
+ include $(topsrcdir)/config/rules.mk
+
+-CFLAGS += $(MOZ_GTK2_CFLAGS)
+-CXXFLAGS += $(MOZ_GTK2_CFLAGS)
++CFLAGS += $(MOZ_GTK2_CFLAGS) $(MOZ_STARTUP_NOTIFICATION_CFLAGS)
++CXXFLAGS += $(MOZ_GTK2_CFLAGS) $(MOZ_STARTUP_NOTIFICATION_CFLAGS)
+
+ DEFINES += -DUSE_XIM
+
+--- widget/src/gtk2/nsToolkit.cpp 2004-04-18 18:00:17.000000000 -0400
++++ widget/src/gtk2/nsToolkit.cpp 2007-07-03 18:01:36.000000000 -0400
+@@ -38,7 +38,7 @@
+ * ***** END LICENSE BLOCK ***** */
+
+ #include "nscore.h" // needed for 'nsnull'
+-#include "nsToolkit.h"
++#include "nsGTKToolkit.h"
+
+ //
+ // Static thread local storage index of the Toolkit
+@@ -51,9 +51,10 @@
+ // constructor
+ //
+ //-------------------------------------------------------------------------
+-nsToolkit::nsToolkit()
++nsGTKToolkit::nsGTKToolkit()
+ {
+ mSharedGC = nsnull;
++ mFocusTimestamp = 0;
+ }
+
+ //-------------------------------------------------------------------------
+@@ -61,7 +62,7 @@
+ // destructor
+ //
+ //-------------------------------------------------------------------------
+-nsToolkit::~nsToolkit()
++nsGTKToolkit::~nsGTKToolkit()
+ {
+ if (mSharedGC) {
+ gdk_gc_unref(mSharedGC);
+@@ -77,9 +78,9 @@
+ //
+ //-------------------------------------------------------------------------
+
+-NS_IMPL_ISUPPORTS1(nsToolkit, nsIToolkit)
++NS_IMPL_ISUPPORTS1(nsGTKToolkit, nsIToolkit)
+
+-void nsToolkit::CreateSharedGC(void)
++void nsGTKToolkit::CreateSharedGC(void)
+ {
+ GdkPixmap *pixmap;
+
+@@ -91,7 +92,7 @@
+ gdk_pixmap_unref(pixmap);
+ }
+
+-GdkGC *nsToolkit::GetSharedGC(void)
++GdkGC *nsGTKToolkit::GetSharedGC(void)
+ {
+ return gdk_gc_ref(mSharedGC);
+ }
+@@ -100,7 +101,7 @@
+ //
+ //
+ //-------------------------------------------------------------------------
+-NS_IMETHODIMP nsToolkit::Init(PRThread *aThread)
++NS_IMETHODIMP nsGTKToolkit::Init(PRThread *aThread)
+ {
+ CreateSharedGC();
+
+@@ -135,7 +136,7 @@
+ // Create a new toolkit for this thread...
+ //
+ if (!toolkit) {
+- toolkit = new nsToolkit();
++ toolkit = new nsGTKToolkit();
+
+ if (!toolkit) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+--- widget/src/xremoteclient/mozilla-xremote-client.cpp 2005-04-04 15:08:51.000000000 -0400
++++ widget/src/xremoteclient/mozilla-xremote-client.cpp 2007-07-03 18:01:36.000000000 -0400
+@@ -40,6 +40,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <plgetopt.h>
++#include <prenv.h>
+ #ifdef MOZ_WIDGET_PHOTON
+ #include "PhRemoteClient.h"
+ #else
+@@ -99,7 +100,7 @@
+ // send the command - it doesn't get any easier than this
+ PRBool success = PR_FALSE;
+ char *error = 0;
+- rv = client.SendCommand(browser, username, profile, command,
++ rv = client.SendCommand(browser, username, profile, command, nsnull,
+ &error, &success);
+
+ // failed to send command
+--- widget/src/xremoteclient/XRemoteClient.cpp 2006-03-30 03:01:13.000000000 -0500
++++ widget/src/xremoteclient/XRemoteClient.cpp 2007-07-03 18:01:36.000000000 -0400
+@@ -173,6 +173,7 @@
+ nsresult
+ XRemoteClient::SendCommand (const char *aProgram, const char *aUsername,
+ const char *aProfile, const char *aCommand,
++ const char* aDesktopStartupID,
+ char **aResponse, PRBool *aWindowFound)
+ {
+ PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("XRemoteClient::SendCommand"));
+@@ -198,7 +199,7 @@
+
+ if (NS_SUCCEEDED(rv)) {
+ // send our command
+- rv = DoSendCommand(w, aCommand, aResponse, &destroyed);
++ rv = DoSendCommand(w, aCommand, aDesktopStartupID, aResponse, &destroyed);
+
+ // if the window was destroyed, don't bother trying to free the
+ // lock.
+@@ -217,6 +218,7 @@
+ XRemoteClient::SendCommandLine (const char *aProgram, const char *aUsername,
+ const char *aProfile,
+ PRInt32 argc, char **argv,
++ const char* aDesktopStartupID,
+ char **aResponse, PRBool *aWindowFound)
+ {
+ PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("XRemoteClient::SendCommandLine"));
+@@ -242,7 +244,7 @@
+
+ if (NS_SUCCEEDED(rv)) {
+ // send our command
+- rv = DoSendCommandLine(w, argc, argv, aResponse, &destroyed);
++ rv = DoSendCommandLine(w, argc, argv, aDesktopStartupID, aResponse, &destroyed);
+
+ // if the window was destroyed, don't bother trying to free the
+ // lock.
+@@ -643,6 +645,7 @@
+
+ nsresult
+ XRemoteClient::DoSendCommand(Window aWindow, const char *aCommand,
++ const char* aDesktopStartupID,
+ char **aResponse, PRBool *aDestroyed)
+ {
+ *aDestroyed = PR_FALSE;
+@@ -651,9 +654,28 @@
+ ("(writing " MOZILLA_COMMAND_PROP " \"%s\" to 0x%x)\n",
+ aCommand, (unsigned int) aWindow));
+
++ // We add the DESKTOP_STARTUP_ID setting as an extra line of
++ // the command string. Firefox ignores all lines but the first.
++ static char desktopStartupPrefix[] = "\nDESKTOP_STARTUP_ID=";
++
++ PRInt32 len = strlen(aCommand);
++ if (aDesktopStartupID) {
++ len += sizeof(desktopStartupPrefix) - 1 + strlen(aDesktopStartupID);
++ }
++ char* buffer = (char*)malloc(len + 1);
++ if (!buffer)
++ return NS_ERROR_OUT_OF_MEMORY;
++
++ strcpy(buffer, aCommand);
++ if (aDesktopStartupID) {
++ strcat(buffer, desktopStartupPrefix);
++ strcat(buffer, aDesktopStartupID);
++ }
++
+ XChangeProperty (mDisplay, aWindow, mMozCommandAtom, XA_STRING, 8,
+- PropModeReplace, (unsigned char *)aCommand,
+- strlen(aCommand));
++ PropModeReplace, (unsigned char *)buffer, len);
++
++ free(buffer);
+
+ if (!WaitForResponse(aWindow, aResponse, aDestroyed, mMozCommandAtom))
+ return NS_ERROR_FAILURE;
+@@ -663,7 +685,7 @@
+
+ /* like strcpy, but return the char after the final null */
+ static char*
+-estrcpy(char* s, char* d)
++estrcpy(const char* s, char* d)
+ {
+ while (*s)
+ *d++ = *s++;
+@@ -674,6 +696,7 @@
+
+ nsresult
+ XRemoteClient::DoSendCommandLine(Window aWindow, PRInt32 argc, char **argv,
++ const char* aDesktopStartupID,
+ char **aResponse, PRBool *aDestroyed)
+ {
+ int i;
+@@ -690,9 +713,16 @@
+ // [argc][offsetargv0][offsetargv1...]<workingdir>\0<argv[0]>\0argv[1]...\0
+ // (offset is from the beginning of the buffer)
+
++ static char desktopStartupPrefix[] = " DESKTOP_STARTUP_ID=";
++
+ PRInt32 argvlen = strlen(cwdbuf);
+- for (i = 0; i < argc; ++i)
+- argvlen += strlen(argv[i]);
++ for (i = 0; i < argc; ++i) {
++ PRInt32 len = strlen(argv[i]);
++ if (i == 0 && aDesktopStartupID) {
++ len += sizeof(desktopStartupPrefix) - 1 + strlen(aDesktopStartupID);
++ }
++ argvlen += len;
++ }
+
+ PRInt32* buffer = (PRInt32*) malloc(argvlen + argc + 1 +
+ sizeof(PRInt32) * (argc + 1));
+@@ -708,6 +738,10 @@
+ for (int i = 0; i < argc; ++i) {
+ buffer[i + 1] = TO_LITTLE_ENDIAN32(bufend - ((char*) buffer));
+ bufend = estrcpy(argv[i], bufend);
++ if (i == 0 && aDesktopStartupID) {
++ bufend = estrcpy(desktopStartupPrefix, bufend - 1);
++ bufend = estrcpy(aDesktopStartupID, bufend - 1);
++ }
+ }
+
+ #ifdef DEBUG_bsmedberg
+--- widget/src/xremoteclient/nsRemoteClient.h 2005-04-04 15:08:51.000000000 -0400
++++ widget/src/xremoteclient/nsRemoteClient.h 2007-07-03 18:01:36.000000000 -0400
+@@ -76,6 +76,10 @@
+ * @param aCommand This is the command that is passed to the server.
+ * Please see the additional information located at:
+ * http://www.mozilla.org/unix/remote.html
++ *
++ * @param aDesktopStartupID the contents of the DESKTOP_STARTUP_ID environment
++ * variable defined by the Startup Notification specification
++ * http://standards.freedesktop.org/startup-notification-spec/startup-notification-0.1.txt
+ *
+ * @param aResponse If there is a response, it will be here. This
+ * includes error messages. The string is allocated using stdlib
+@@ -85,11 +89,16 @@
+ */
+ virtual nsresult SendCommand(const char *aProgram, const char *aUsername,
+ const char *aProfile, const char *aCommand,
++ const char* aDesktopStartupID,
+ char **aResponse, PRBool *aSucceeded) = 0;
+
+ /**
+ * Send a complete command line to a running instance.
+ *
++ * @param aDesktopStartupID the contents of the DESKTOP_STARTUP_ID environment
++ * variable defined by the Startup Notification specification
++ * http://standards.freedesktop.org/startup-notification-spec/startup-notification-0.1.txt
++ *
+ * @see sendCommand
+ * @param argc The number of command-line arguments.
+ *
+@@ -97,6 +106,7 @@
+ virtual nsresult SendCommandLine(const char *aProgram, const char *aUsername,
+ const char *aProfile,
+ PRInt32 argc, char **argv,
++ const char* aDesktopStartupID,
+ char **aResponse, PRBool *aSucceeded) = 0;
+ };
+
+--- widget/src/xremoteclient/XRemoteClient.h 2006-03-30 03:01:13.000000000 -0500
++++ widget/src/xremoteclient/XRemoteClient.h 2007-07-03 18:01:36.000000000 -0400
+@@ -48,10 +48,12 @@
+ virtual nsresult Init();
+ virtual nsresult SendCommand(const char *aProgram, const char *aUsername,
+ const char *aProfile, const char *aCommand,
++ const char* aDesktopStartupID,
+ char **aResponse, PRBool *aSucceeded);
+ virtual nsresult SendCommandLine(const char *aProgram, const char *aUsername,
+ const char *aProfile,
+ PRInt32 argc, char **argv,
++ const char* aDesktopStartupID,
+ char **aResponse, PRBool *aSucceeded);
+ void Shutdown();
+
+@@ -67,10 +69,12 @@
+ PRBool aSupportsCommandLine);
+ nsresult DoSendCommand (Window aWindow,
+ const char *aCommand,
++ const char* aDesktopStartupID,
+ char **aResponse,
+ PRBool *aDestroyed);
+ nsresult DoSendCommandLine(Window aWindow,
+ PRInt32 argc, char **argv,
++ const char* aDesktopStartupID,
+ char **aResponse,
+ PRBool *aDestroyed);
+ PRBool WaitForResponse (Window aWindow, char **aResponse,
+--- /dev/null 2007-07-05 17:03:04.116204904 -0400
++++ widget/src/gtk2/nsGTKToolkit.h 2007-07-03 18:01:36.000000000 -0400
+@@ -0,0 +1,87 @@
++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
++/* vim:expandtab:shiftwidth=4:tabstop=4:
++ */
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
++ * for the specific language governing rights and limitations under the
++ * License.
++ *
++ * The Original Code is mozilla.org code.
++ *
++ * The Initial Developer of the Original Code is
++ * Netscape Communications Corporation.
++ * Portions created by the Initial Developer are Copyright (C) 1998
++ * the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++#ifndef GTKTOOLKIT_H
++#define GTKTOOLKIT_H
++
++#include "nsIToolkit.h"
++#include "nsString.h"
++#include <gtk/gtk.h>
++
++/**
++ * Wrapper around the thread running the message pump.
++ * The toolkit abstraction is necessary because the message pump must
++ * execute within the same thread that created the widget under Win32.
++ */
++
++class nsGTKToolkit : public nsIToolkit
++{
++public:
++ nsGTKToolkit();
++ virtual ~nsGTKToolkit();
++
++ NS_DECL_ISUPPORTS
++
++ NS_IMETHOD Init(PRThread *aThread);
++
++ void CreateSharedGC(void);
++ GdkGC *GetSharedGC(void);
++
++ /**
++ * Get/set our value of DESKTOP_STARTUP_ID. When non-empty, this is applied
++ * to the next toplevel window to be shown or focused (and then immediately
++ * cleared).
++ */
++ void SetDesktopStartupID(const nsACString& aID) { mDesktopStartupID = aID; }
++ void GetDesktopStartupID(nsACString* aID) { *aID = mDesktopStartupID; }
++
++ /**
++ * Get/set the timestamp value to be used, if non-zero, to focus the
++ * next top-level window to be shown or focused (upon which it is cleared).
++ */
++ void SetFocusTimestamp(PRUint32 aTimestamp) { mFocusTimestamp = aTimestamp; }
++ PRUint32 GetFocusTimestamp() { return mFocusTimestamp; }
++
++private:
++ GdkGC *mSharedGC;
++ nsCString mDesktopStartupID;
++ PRUint32 mFocusTimestamp;
++};
++
++#endif // GTKTOOLKIT_H
bgstack15