? gnome-desktop.patch
Index: libgnome-desktop/gnome-desktop-item.c
===================================================================
RCS file: /cvs/gnome/gnome-desktop/libgnome-desktop/gnome-desktop-item.c,v
retrieving revision 1.133
diff -p -u -r1.133 gnome-desktop-item.c
--- libgnome-desktop/gnome-desktop-item.c	29 Feb 2004 13:23:40 -0000	1.133
+++ libgnome-desktop/gnome-desktop-item.c	18 Jul 2004 21:34:15 -0000
@@ -87,6 +87,10 @@ struct _GnomeDesktopItem {
 	char *location;
 
 	time_t mtime;
+
+        /* Xserver timestamp of event that initiated
+         * this application launch */
+        Time timestamp;
 };
 
 /* If mtime is set to this, set_location won't update mtime,
@@ -366,6 +370,8 @@ gnome_desktop_item_new (void)
 				       GNOME_DESKTOP_ITEM_VERSION,
 				       "1.0");
 
+        retval->timestamp = CurrentTime;
+
 	return retval;
 }
 
@@ -418,6 +424,7 @@ gnome_desktop_item_copy (const GnomeDesk
 	retval->modified = item->modified;
 	retval->location = g_strdup (item->location);
 	retval->mtime = item->mtime;
+        retval->timestamp = item->timestamp;
 
 	/* Languages */
 	retval->languages = g_list_copy (item->languages);
@@ -1572,6 +1579,68 @@ stringify_files (GSList *args)
 	return g_string_free (str, FALSE);
 }
 
+#ifdef HAVE_STARTUP_NOTIFICATION
+#if 0
+/* This is the wrong way to do this; there should be some event
+ * (e.g. button press) available with a good time.  A function like
+ * this should not be needed.  But...if we wanted to gracefully
+ * handle faulty applications that don't call 
+ * gnome_desktop_item_set_launch_time as they should, then this
+ * function could be useful.
+ */
+static Time
+slowly_and_stupidly_obtain_timestamp(SnDisplay *display)
+{
+  Window xwindow;
+  Display *xdisplay;
+  XEvent event;
+
+  xdisplay = sn_display_get_x_display (display);
+
+  {
+    XSetWindowAttributes attrs;
+    Atom atom_name;
+    Atom atom_type;
+    char* name;
+
+    attrs.override_redirect = True;
+    attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
+
+    xwindow =
+      XCreateWindow (xdisplay,
+                     RootWindow (xdisplay, 0),
+                     -100, -100, 1, 1,
+                     0,
+                     CopyFromParent,
+                     CopyFromParent,
+                     CopyFromParent,
+                     CWOverrideRedirect | CWEventMask,
+                     &attrs);
+
+    atom_name = XInternAtom (xdisplay, "WM_NAME", TRUE);
+    g_assert (atom_name != None);
+    atom_type = XInternAtom (xdisplay, "STRING", TRUE);
+    g_assert (atom_type != None);
+
+    name = "Fake Window";
+    XChangeProperty (xdisplay, 
+                     xwindow, atom_name,
+                     atom_type,
+                     8, PropModeReplace, name, strlen (name));
+  }
+  
+  XWindowEvent (xdisplay,
+                xwindow,
+                PropertyChangeMask,
+                &event);
+
+  XDestroyWindow(xdisplay, xwindow);
+
+  return event.xproperty.time;
+}
+#endif
+#endif
+
 static int
 ditem_execute (const GnomeDesktopItem *item,
 	       const char *exec,
@@ -1756,6 +1825,17 @@ ditem_execute (const GnomeDesktopItem *i
 		if (sn_context != NULL &&
 		    !sn_launcher_context_get_initiated (sn_context)) {
 
+			if (item->timestamp == CurrentTime) {
+				g_warning ("Baaad application.  This application should go to jail.\n"
+                                           "Directly to jail.  Without passing Go and without "
+                                           "collecting $200.\n"
+					   "Please file a bug and tell the authors to call the "
+					   "gnome_desktop_item_set_launch_time() function.");
+#if 0
+				item->timestamp = slowly_and_stupidly_obtain_timestamp (sn_display);
+#endif
+			}
+
 			/* This means that we always use the first real_argv[0]
 			 * we select for the "binary name", but it's probably
 			 * OK to do that. Binary name isn't super-important
@@ -1769,7 +1849,7 @@ ditem_execute (const GnomeDesktopItem *i
 			sn_launcher_context_initiate (sn_context,
 						      g_get_prgname () ? g_get_prgname () : "unknown",
 						      real_argv[0],
-						      CurrentTime);
+						      item->timestamp);
 
 			envp = make_spawn_environment_for_sn_context (sn_context, envp);
 			if (free_me)
@@ -2937,6 +3017,15 @@ gnome_desktop_item_set_boolean (GnomeDes
 
 	set (item, attr, value ? "true" : "false");
 }
+
+#ifdef HAVE_STARTUP_NOTIFICATION
+void
+gnome_desktop_item_set_launch_time (GnomeDesktopItem *item,
+                                    Time              timestamp)
+{
+	item->timestamp = timestamp;
+}
+#endif
 
 /*
 * Clearing attributes
Index: libgnome-desktop/libgnome/gnome-desktop-item.h
===================================================================
RCS file: /cvs/gnome/gnome-desktop/libgnome-desktop/libgnome/gnome-desktop-item.h,v
retrieving revision 1.49
diff -p -u -r1.49 gnome-desktop-item.h
--- libgnome-desktop/libgnome/gnome-desktop-item.h	28 Nov 2002 11:38:41 -0000	1.49
+++ libgnome-desktop/libgnome/gnome-desktop-item.h	18 Jul 2004 21:34:15 -0000
@@ -33,6 +33,10 @@
 
 #include <gdk/gdk.h>
 #include <libgnomeui/gnome-icon-theme.h>
+#ifdef HAVE_STARTUP_NOTIFICATION
+#include <gdk/gdkx.h>
+#endif
+
 
 G_BEGIN_DECLS
 
@@ -284,6 +288,14 @@ gboolean                gnome_desktop_it
 void                    gnome_desktop_item_set_boolean       (GnomeDesktopItem           *item,
 							      const char		 *attr,
 							      gboolean                    value);
+
+#ifdef HAVE_STARTUP_NOTIFICATION
+/*
+ * Xserver time of user action that caused the application launch to start.
+ */
+void                    gnome_desktop_item_set_launch_time   (GnomeDesktopItem           *item,
+                                                              Time                        timestamp);
+#endif
 
 /*
  * Clearing attributes
