Index: ChangeLog
===================================================================
--- ChangeLog	(revision 17706)
+++ ChangeLog	(working copy)
@@ -1,3 +1,10 @@
+2007-04-29  Dan Winship  <danw@novell.com>
+
+	* gdk/x11/gdkdisplay-x11.c
+	(gdk_x11_display_broadcast_startup_message): New method to
+	marshall and send a Startup Notification message. (from #415070)
+	(gdk_notify_startup_complete_with_id): Use that
+
 2007-04-29  Matthias Clasen  <mclasen@redhat.com>
 
 	* gtk/gtktoolbar.c (_gtk_toolbar_elide_underscores): 
Index: gdk/x11/gdkx.h
===================================================================
--- gdk/x11/gdkx.h	(revision 17706)
+++ gdk/x11/gdkx.h	(working copy)
@@ -148,6 +148,10 @@
 						const gchar *theme,
 						const gint   size);
 
+void gdk_x11_display_broadcast_startup_message (GdkDisplay *display,
+						const char *message_type,
+						...) G_GNUC_NULL_TERMINATED;
+
 /* returns TRUE if we support the given WM spec feature */
 gboolean gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen,
 					      GdkAtom    property);
Index: gdk/x11/gdkdisplay-x11.c
===================================================================
--- gdk/x11/gdkdisplay-x11.c	(revision 17706)
+++ gdk/x11/gdkdisplay-x11.c	(working copy)
@@ -930,33 +930,6 @@
     }
 }
 
-static char*
-escape_for_xmessage (const char *str)
-{
-  GString *retval;
-  const char *p;
-  
-  retval = g_string_new (NULL);
-
-  p = str;
-  while (*p)
-    {
-      switch (*p)
-        {
-        case ' ':
-        case '"':
-        case '\\':
-          g_string_append_c (retval, '\\');
-          break;
-        }
-
-      g_string_append_c (retval, *p);
-      ++p;
-    }
-
-  return g_string_free (retval, FALSE);
-}
-
 static void
 broadcast_xmessage (GdkDisplay *display,
 		    const char *message_type,
@@ -972,6 +945,9 @@
   Atom type_atom_begin;
   Window xwindow;
 
+  if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
+    return;
+
   {
     XSetWindowAttributes attrs;
 
@@ -1046,6 +1022,72 @@
 }
 
 /**
+ * gdk_x11_display_broadcast_startup_message:
+ * @display: a #GdkDisplay
+ * @message_type: startup notification message type ("new", "change",
+ * or "remove")
+ * @...: a list of key/value pairs (as strings), terminated by a
+ * %NULL key. (A %NULL value for a key will cause that key to be
+ * skipped in the output.)
+ *
+ * Sends a startup notification message of type @message_type to
+ * @display. 
+ *
+ * This is a convenience function for use by code that implements the
+ * freedesktop startup notification specification. Applications should
+ * not normally need to call it directly. See the <ulink
+ * url="http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt">Startup
+ * Notification Protocol specification</ulink> for
+ * definitions of the message types and keys that can be used.
+ *
+ * Since: 2.12
+ **/
+void
+gdk_x11_display_broadcast_startup_message (GdkDisplay *display,
+					   const char *message_type,
+					   ...)
+{
+  GString *message;
+  va_list ap;
+  const char *key, *value, *p;
+
+  message = g_string_new (message_type);
+  g_string_append_c (message, ':');
+
+  va_start (ap, message_type);
+  while ((key = va_arg (ap, const char *)))
+    {
+      value = va_arg (ap, const char *);
+      if (!value)
+	continue;
+
+      g_string_append_printf (message, " %s=\"", key);
+      for (p = value; *p; p++)
+	{
+	  switch (*p)
+	    {
+	    case ' ':
+	    case '"':
+	    case '\\':
+	      g_string_append_c (message, '\\');
+	      break;
+	    }
+
+	  g_string_append_c (message, *p);
+	}
+      g_string_append_c (message, '\"');
+    }
+  va_end (ap);
+
+  broadcast_xmessage (display,
+		      "_NET_STARTUP_INFO",
+                      "_NET_STARTUP_INFO_BEGIN",
+                      message->str);
+
+  g_string_free (message, TRUE);
+}
+
+/**
  * gdk_notify_startup_complete:
  * 
  * Indicates to the GUI environment that the application has finished
@@ -1064,8 +1106,6 @@
 {
   GdkDisplay *display;
   GdkDisplayX11 *display_x11;
-  gchar *escaped_id;
-  gchar *message;
 
   display = gdk_display_get_default ();
   if (!display)
@@ -1076,9 +1116,6 @@
   if (display_x11->startup_notification_id == NULL)
     return;
 
-  if (!G_LIKELY (display_x11->trusted_client))
-    return;
-
   gdk_notify_startup_complete_with_id (display_x11->startup_notification_id);
 }
 
@@ -1101,23 +1138,14 @@
 gdk_notify_startup_complete_with_id (const gchar* startup_id)
 {
   GdkDisplay *display;
-  gchar *escaped_id;
-  gchar *message;
 
   display = gdk_display_get_default ();
   if (!display)
     return;
 
-  escaped_id = escape_for_xmessage (startup_id);
-  message = g_strdup_printf ("remove: ID=%s", escaped_id);
-  g_free (escaped_id);
-
-  broadcast_xmessage (display,
-		      "_NET_STARTUP_INFO",
-                      "_NET_STARTUP_INFO_BEGIN",
-                      message);
-
-  g_free (message);
+  gdk_x11_display_broadcast_startup_message (display, "remove",
+					     "ID", startup_id,
+					     NULL);
 }
 
 /**
Index: docs/reference/ChangeLog
===================================================================
--- docs/reference/ChangeLog	(revision 17706)
+++ docs/reference/ChangeLog	(working copy)
@@ -1,3 +1,9 @@
+2007-04-29  Dan Winship  <danw@novell.com>
+
+	* gdk/gdk-sections.txt: Add
+	gdk_x11_display_broadcast_startup_message and some other missing
+	startup-notification-related methods
+
 2007-04-29  Matthias Clasen  <mclasen@redhat.com>
 
 	* gtk/gtk-sections.txt: Add new functions to serialize/
Index: docs/reference/gdk/gdk-sections.txt
===================================================================
--- docs/reference/gdk/gdk-sections.txt	(revision 17706)
+++ docs/reference/gdk/gdk-sections.txt	(working copy)
@@ -12,6 +12,7 @@
 gdk_set_sm_client_id
 gdk_exit
 gdk_notify_startup_complete
+gdk_notify_startup_complete_with_id
 
 <SUBSECTION>
 gdk_get_program_class
@@ -744,6 +745,7 @@
 gdk_window_set_icon_name
 gdk_window_set_transient_for
 gdk_window_set_role
+gdk_window_set_startup_id
 gdk_window_set_group
 gdk_window_get_group
 gdk_window_set_decorations
@@ -1287,6 +1289,8 @@
 gdk_x11_colormap_get_xdisplay
 gdk_x11_cursor_get_xcursor
 gdk_x11_cursor_get_xdisplay
+gdk_x11_display_broadcast_startup_message
+gdk_x11_display_get_startup_notification_id
 gdk_x11_display_get_xdisplay
 gdk_x11_display_grab
 gdk_x11_display_ungrab
Index: docs/reference/gdk/tmpl/windows.sgml
===================================================================
--- docs/reference/gdk/tmpl/windows.sgml	(revision 17706)
+++ docs/reference/gdk/tmpl/windows.sgml	(working copy)
@@ -1351,6 +1351,15 @@
 @role: 
 
 
+<!-- ##### FUNCTION gdk_window_set_startup_id ##### -->
+<para>
+
+</para>
+
+@window: 
+@startup_id: 
+
+
 <!-- ##### FUNCTION gdk_window_set_group ##### -->
 <para>
 
Index: docs/reference/gdk/tmpl/x_interaction.sgml
===================================================================
--- docs/reference/gdk/tmpl/x_interaction.sgml	(revision 17706)
+++ docs/reference/gdk/tmpl/x_interaction.sgml	(working copy)
@@ -515,6 +515,25 @@
 @Returns: 
 
 
+<!-- ##### FUNCTION gdk_x11_display_broadcast_startup_message ##### -->
+<para>
+
+</para>
+
+@display: 
+@message_type: 
+@Varargs: 
+
+
+<!-- ##### FUNCTION gdk_x11_display_get_startup_notification_id ##### -->
+<para>
+
+</para>
+
+@display: 
+@Returns: 
+
+
 <!-- ##### FUNCTION gdk_x11_display_get_xdisplay ##### -->
 <para>
 
Index: docs/reference/gdk/tmpl/general.sgml
===================================================================
--- docs/reference/gdk/tmpl/general.sgml	(revision 17706)
+++ docs/reference/gdk/tmpl/general.sgml	(working copy)
@@ -125,6 +125,14 @@
 
 
 
+<!-- ##### FUNCTION gdk_notify_startup_complete_with_id ##### -->
+<para>
+
+</para>
+
+@startup_id: 
+
+
 <!-- ##### FUNCTION gdk_get_program_class ##### -->
 <para>
 Gets the program class. Unless the program class has explicitly
