Index: ChangeLog
===================================================================
--- ChangeLog	(revision 17605)
+++ ChangeLog	(working copy)
@@ -1,3 +1,9 @@
+2007-04-17  Dan Winship  <danw@novell.com>
+
+	* gdk/x11/gdkdisplay-x11.c (gdk_x11_display_broadcast_sn_message):
+	marshalls and sends a Startup Notification message.
+	(gdk_notify_startup_complete_with_id): Use that
+
 2007-04-16  Alexander Larsson  <alexl@redhat.com>
 
 	* gtk/gtkprintoperation.c (gtk_print_operation_run):
Index: gdk/x11/gdkx.h
===================================================================
--- gdk/x11/gdkx.h	(revision 17605)
+++ gdk/x11/gdkx.h	(working copy)
@@ -148,6 +148,10 @@
 						const gchar *theme,
 						const gint   size);
 
+void gdk_x11_display_broadcast_sn_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 17605)
+++ 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,
@@ -1046,6 +1019,63 @@
 }
 
 /**
+ * gdk_x11_display_broadcast_sn_message:
+ * @display: a #GdkDisplay
+ * @message_type: startup notification message type
+ * @...: 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. See the Startup Notification Protocol specification for
+ * more details.
+ **/
+void
+gdk_x11_display_broadcast_sn_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 +1094,6 @@
 {
   GdkDisplay *display;
   GdkDisplayX11 *display_x11;
-  gchar *escaped_id;
-  gchar *message;
 
   display = gdk_display_get_default ();
   if (!display)
@@ -1101,23 +1129,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_sn_message (display, "remove",
+					"ID", startup_id,
+					NULL);
 }
 
 /**
