Index: applets/notification_area/na-tray.c
===================================================================
--- applets/notification_area/na-tray.c	(revision 11085)
+++ applets/notification_area/na-tray.c	(working copy)
@@ -56,6 +56,9 @@
 
   guint idle_redraw_id;
 
+  GSList *order;
+  GSList *hidden;
+
   GtkOrientation orientation;
 };
 
@@ -83,6 +86,14 @@
   PROP_SCREEN
 };
 
+enum
+{
+  ORDER_CHANGED,
+  LAST_SIGNAL
+};
+
+static guint tray_signals[LAST_SIGNAL];
+
 static gboolean     initialized   = FALSE;
 static TraysScreen *trays_screens = NULL;
 
@@ -99,6 +110,43 @@
   return trays_screen->all_trays->data;
 }
 
+static int
+get_icon_position (NaTray *tray,
+                   const char *wm_class)
+{
+  NaTrayPrivate *priv;
+  GSList *llink;
+  char *data;
+
+  priv = tray->priv;
+
+  llink = g_slist_find_custom (priv->order, wm_class, (GCompareFunc) strcmp);
+  if (llink != NULL)
+    return g_slist_position (priv->order, llink);
+
+  data = g_strdup (wm_class);
+
+  priv->order = g_slist_append (priv->order, data);
+
+  g_signal_emit (tray, tray_signals[ORDER_CHANGED], 0);
+
+  return g_slist_index (priv->order, wm_class);
+}
+
+static gboolean
+is_icon_hidden (NaTray     *tray,
+                const char *wm_class)
+{
+  NaTrayPrivate *priv;
+  GSList *llink;
+
+  priv = tray->priv;
+
+  llink = g_slist_find_custom (priv->hidden, wm_class, (GCompareFunc) strcmp);
+
+  return (llink != NULL);
+}
+
 static void
 tray_added (NaTrayManager *manager,
             GtkWidget     *icon,
@@ -106,6 +154,9 @@
 {
   NaTray *tray;
   NaTrayPrivate *priv;
+  char *wm_class;
+  int position;
+  gboolean hidden;
 
   tray = get_tray (trays_screen);
   if (tray == NULL)
@@ -114,12 +165,20 @@
   priv = tray->priv;
 
   g_assert (priv->trays_screen == trays_screen);
-  
+
+  wm_class = g_object_get_data (G_OBJECT (icon), "na-tray-child-wm-class");
+  position = get_icon_position (tray, wm_class);
+  hidden = is_icon_hidden (tray, wm_class);
+
   g_hash_table_insert (trays_screen->icon_table, icon, tray);
 
   gtk_box_pack_end (GTK_BOX (priv->box), icon, FALSE, FALSE, 0);
+  gtk_container_child_set (GTK_CONTAINER (priv->box), icon, "position", position, NULL);
+  if (hidden)
+    gtk_widget_hide (icon);
+  else
+    gtk_widget_show (icon);
 
-  gtk_widget_show (icon);
   na_tray_force_redraw (tray);
 }
 
@@ -426,6 +485,9 @@
   gtk_box_set_spacing (GTK_BOX (priv->box), ICON_SPACING);
   gtk_container_add (GTK_CONTAINER (priv->frame), priv->box);
   gtk_widget_show (priv->box);
+
+  priv->order = NULL;
+  priv->hidden = NULL;
 }
 
 static GObject *
@@ -543,6 +605,12 @@
 
   priv->trays_screen = NULL;
 
+  g_slist_foreach (priv->order, (GFunc) g_free, NULL);
+  g_slist_free (priv->order);
+
+  g_slist_foreach (priv->hidden, (GFunc) g_free, NULL);
+  g_slist_free (priv->hidden);
+
   if (priv->idle_redraw_id != 0)
     {
       g_source_remove (priv->idle_redraw_id);
@@ -625,6 +693,15 @@
 			  G_PARAM_STATIC_NICK |
 			  G_PARAM_STATIC_BLURB));
 
+  tray_signals[ORDER_CHANGED] =
+    g_signal_new ("order-changed",
+                  G_OBJECT_CLASS_TYPE (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (NaTrayClass, order_changed),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
   g_type_class_add_private (gobject_class, sizeof (NaTrayPrivate));
 }
 
@@ -682,3 +759,81 @@
   if (priv->idle_redraw_id == 0)
     priv->idle_redraw_id = g_idle_add ((GSourceFunc) idle_redraw_cb, tray);
 }
+
+void
+na_tray_set_order (NaTray *tray,
+        	   GSList *order)
+{
+  NaTrayPrivate *priv = tray->priv;
+  GList *children, *it;
+
+  if (priv->order != NULL)
+    {
+      g_slist_foreach (priv->order, (GFunc) g_free, NULL);
+      g_slist_free (priv->order);
+    }
+
+  priv->order = order;
+
+  children = gtk_container_get_children (GTK_CONTAINER (priv->box));
+  for (it = children; it != NULL; it = it->next)
+    {
+      GtkWidget *icon = GTK_WIDGET (it->data);
+      char *wm_class = g_object_get_data (G_OBJECT (icon), "na-tray-child-wm-class");
+
+      gtk_container_child_set (GTK_CONTAINER (priv->box),
+                               icon,
+                               "position", get_icon_position (tray, wm_class),
+                               NULL);
+    }
+  g_list_free (children);
+
+  na_tray_force_redraw (tray);
+}
+
+GSList *
+na_tray_get_order (NaTray *tray)
+{
+  NaTrayPrivate *priv = tray->priv;
+
+  return priv->order;
+}
+
+void
+na_tray_set_hidden (NaTray *tray,
+        	    GSList *hidden)
+{
+  NaTrayPrivate *priv = tray->priv;
+  GList *children, *it;
+
+  if (priv->hidden != NULL)
+    {
+      g_slist_foreach (priv->hidden, (GFunc) g_free, NULL);
+      g_slist_free (priv->hidden);
+    }
+
+  priv->hidden = hidden;
+
+  children = gtk_container_get_children (GTK_CONTAINER (priv->box));
+  for (it = children; it != NULL; it = it->next)
+    {
+      GtkWidget *icon = GTK_WIDGET (it->data);
+      char *wm_class = g_object_get_data (G_OBJECT (icon), "na-tray-child-wm-class");
+
+      if (is_icon_hidden (tray, wm_class))
+        gtk_widget_hide (icon);
+      else
+        gtk_widget_show (icon);
+    }
+  g_list_free (children);
+
+  na_tray_force_redraw (tray);
+}
+
+GSList *
+na_tray_get_hidden (NaTray *tray)
+{
+  NaTrayPrivate *priv = tray->priv;
+
+  return priv->hidden;
+}
Index: applets/notification_area/na-tray.h
===================================================================
--- applets/notification_area/na-tray.h	(revision 11085)
+++ applets/notification_area/na-tray.h	(working copy)
@@ -53,6 +53,8 @@
 struct _NaTrayClass
 {
   GtkBinClass parent_class;
+
+  void (*order_changed) (NaTray *tray);
 };
 
 GType           na_tray_get_type        (void);
@@ -63,6 +65,13 @@
 GtkOrientation  na_tray_get_orientation (NaTray        *tray);
 void		na_tray_force_redraw	(NaTray        *tray);
 
+void		na_tray_set_order	(NaTray        *tray,
+					 GSList        *order);
+GSList	       *na_tray_get_order	(NaTray        *tray);
+void		na_tray_set_hidden	(NaTray        *tray,
+					 GSList        *hidden);
+GSList	       *na_tray_get_hidden	(NaTray        *tray);
+
 G_END_DECLS
 
 #endif /* __NA_TRAY_H__ */
Index: applets/notification_area/na-tray-manager.c
===================================================================
--- applets/notification_area/na-tray-manager.c	(revision 11085)
+++ applets/notification_area/na-tray-manager.c	(working copy)
@@ -300,6 +300,51 @@
   na_tray_manager_make_socket_transparent (widget, user_data);
 }
 
+#ifdef GDK_WINDOWING_X11
+static char *
+na_tray_manager_get_child_class (Display                 *display,
+				 Window                  *child_window)
+{
+  char *retval = NULL;
+  Atom string, atom, type;
+  int result;
+  int format;
+  gulong nitems;
+  gulong bytes_after;
+  gchar *val;
+
+  string = XInternAtom (display, "STRING", FALSE);
+  atom = XInternAtom (display, "WM_CLASS", FALSE);
+
+  gdk_error_trap_push ();
+
+  result = XGetWindowProperty (display,
+			       *child_window,
+			       atom,
+			       0, G_MAXLONG,
+			       False, string,
+			       &type, &format, &nitems,
+			       &bytes_after, (guchar **)&val);
+  
+  if (gdk_error_trap_pop () || result != Success)
+    return NULL;
+
+  if (type != string ||
+      format != 8 ||
+      nitems == 0)
+    {
+      if (val)
+	XFree (val);
+      return NULL;
+    }
+
+  retval = g_strndup (val, nitems);
+
+  XFree (val);
+  return retval;
+}
+#endif
+
 static void
 na_tray_manager_handle_dock_request (NaTrayManager       *manager,
 				     XClientMessageEvent *xevent)
@@ -307,6 +352,7 @@
   GtkWidget *socket;
   Window *window;
   GtkRequisition req;
+  gchar *wm_class;
 
   if (g_hash_table_lookup (manager->socket_table, GINT_TO_POINTER (xevent->data.l[2])))
     {
@@ -336,6 +382,13 @@
   g_object_set_data_full (G_OBJECT (socket),
 			  "na-tray-child-window",
 			  window, g_free);
+#ifdef GDK_WINDOWING_X11
+  wm_class = na_tray_manager_get_child_class (xevent->display, window);
+  g_object_set_data_full (G_OBJECT (socket),
+			  "na-tray-child-wm-class",
+			  wm_class, g_free);
+#endif
+
   g_signal_emit (manager, manager_signals[TRAY_ICON_ADDED], 0,
 		 socket);
 
Index: applets/notification_area/main.c
===================================================================
--- applets/notification_area/main.c	(revision 11085)
+++ applets/notification_area/main.c	(working copy)
@@ -29,6 +29,7 @@
 #include <gtk/gtkmessagedialog.h>
 #include <gtk/gtkhbox.h>
 #include <libgnomeui/gnome-help.h>
+#include <gconf/gconf-client.h>
 
 #include "na-tray-manager.h"
 #include "na-tray.h"
@@ -37,6 +38,11 @@
 
 #define NOTIFICATION_AREA_ICON "gnome-panel-notification-area"
 
+#define KEY_ORDER "order"
+#define KEY_HIDDEN "hidden"
+
+#define NOTIFICATION_AREA_SCHEMA_DIR "/schemas/apps/notification_area_applet/prefs"
+
 typedef struct
 {
   PanelApplet *applet;
@@ -194,6 +200,83 @@
   g_slice_free (AppletData, data);
 }
 
+static void
+order_changed (GConfClient  *client,
+               guint         cnxn_id,
+	       GConfEntry   *entry,
+	       AppletData   *data)
+{
+  GSList *order = NULL, *it;
+
+  if (!entry->value || entry->value->type != GCONF_VALUE_LIST)
+    return;
+
+  it = gconf_value_get_list (entry->value);
+
+  while (it)
+    {
+      const char *string = gconf_value_get_string (it->data);
+
+      order = g_slist_append (order, g_strdup (string));
+
+      it = it->next;
+    }
+
+  na_tray_set_order (data->tray, order);
+}
+
+static void
+hidden_changed (GConfClient  *client,
+                guint         cnxn_id,
+	        GConfEntry   *entry,
+	        AppletData   *data)
+{
+  GSList *hidden = NULL, *it;
+
+  if (!entry->value || entry->value->type != GCONF_VALUE_LIST)
+    return;
+
+  it = gconf_value_get_list (entry->value);
+
+  while (it)
+    {
+      const char *string = gconf_value_get_string (it->data);
+
+      hidden = g_slist_append (hidden, g_strdup (string));
+
+      it = it->next;
+    }
+
+  na_tray_set_hidden (data->tray, hidden);
+}
+
+
+static void
+setup_gconf (AppletData *data)
+{
+  GConfClient *client;
+  char *key;
+
+  client = gconf_client_get_default ();
+
+  key = panel_applet_gconf_get_full_key (data->applet, KEY_ORDER);
+  gconf_client_notify_add (client, key, (GConfClientNotifyFunc) order_changed, data, NULL, NULL);
+  g_free (key);
+
+  key = panel_applet_gconf_get_full_key (data->applet, KEY_HIDDEN);
+  gconf_client_notify_add (client, key, (GConfClientNotifyFunc) hidden_changed, data, NULL, NULL);
+  g_free (key);
+
+  g_object_unref (G_OBJECT (client));
+}
+
+static void
+order_changed_cb (NaTray     *tray,
+                  AppletData *data)
+{
+  panel_applet_gconf_set_list (data->applet, KEY_ORDER, GCONF_VALUE_STRING, na_tray_get_order (tray), NULL);
+}
+
 static gboolean
 applet_factory (PanelApplet *applet,
                 const gchar *iid,
@@ -207,14 +290,24 @@
         strcmp (iid, "OAFIID:GNOME_SystemTrayApplet") == 0))
     return FALSE;
 
+  panel_applet_add_preferences (applet, NOTIFICATION_AREA_SCHEMA_DIR, NULL);
+
   tray = na_tray_new_for_screen (gtk_widget_get_screen (GTK_WIDGET (applet)),
 				 get_orientation_from_applet (applet));
-
   data = g_slice_new (AppletData);
   data->applet = applet;
   data->tray = tray;
   data->about_dialog = NULL;
 
+  setup_gconf (data);
+  g_signal_connect (tray, "order-changed",
+                    G_CALLBACK (order_changed_cb), data);
+
+  na_tray_set_order (tray,
+      panel_applet_gconf_get_list (applet, KEY_ORDER, GCONF_VALUE_STRING, NULL));
+  na_tray_set_hidden (tray,
+      panel_applet_gconf_get_list (applet, KEY_HIDDEN, GCONF_VALUE_STRING, NULL));
+
   g_object_set_data_full (G_OBJECT (applet),
                           "system-tray-data",
                           data,
@@ -240,7 +333,8 @@
 #ifndef NOTIFICATION_AREA_INPROCESS
   gtk_window_set_default_icon_name (NOTIFICATION_AREA_ICON);
 #endif
-  gtk_widget_show_all (GTK_WIDGET (applet));
+  gtk_widget_show (GTK_WIDGET (tray));
+  gtk_widget_show (GTK_WIDGET (applet));
 
   panel_applet_setup_menu_from_file (applet,
   			             NULL,
Index: applets/notification_area/Makefile.am
===================================================================
--- applets/notification_area/Makefile.am	(revision 11085)
+++ applets/notification_area/Makefile.am	(working copy)
@@ -64,6 +64,24 @@
 
 @INTLTOOL_SERVER_RULE@
 
+schemasdir       = $(GCONF_SCHEMA_FILE_DIR)
+schemas_in_files = notification-area.schemas.in
+schemas_DATA     = $(schemas_in_files:.schemas.in=.schemas)
+
+@INTLTOOL_SCHEMAS_RULE@
+
+if GCONF_SCHEMAS_INSTALL
+# don't do this if we are building in eg. rpm
+install-data-local:
+	if test -z "$(DESTDIR)" ; then \
+		for p in $(schemas_DATA) ; do \
+		        GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(top_builddir)/applets/notification_area/$$p ; \
+		done \
+	fi
+else
+install-data-local:
+endif
+
 uidir = $(datadir)/gnome-2.0/ui
 ui_DATA = GNOME_NotificationAreaApplet.xml
 
