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