--- gnome-panel-2.28.0/applets/notification_area/na-tray-child.c 2009-08-11 12:56:35.000000000 -0400
+++ hacked/applets/notification_area/na-tray-child.c 2009-10-16 00:18:25.057041777 -0400
@@ -428,3 +428,84 @@
#endif
}
}
+
+
+/* from libwnck xutils.c */
+static char *
+latin1_to_utf8 (const char *latin1)
+{
+ GString *str;
+ const char *p;
+
+ str = g_string_new (NULL);
+
+ p = latin1;
+ while (*p)
+ {
+ g_string_append_unichar (str, (gunichar) *p);
+ ++p;
+ }
+
+ return g_string_free (str, FALSE);
+}
+
+/* derived from libwnck xutils.c */
+static void
+_get_wmclass (Display *xdisplay,
+ Window xwindow,
+ char **res_class,
+ char **res_name)
+{
+ XClassHint ch;
+ char *retval;
+
+ gdk_error_trap_push ();
+
+ ch.res_name = NULL;
+ ch.res_class = NULL;
+
+ XGetClassHint (xdisplay, xwindow, &ch);
+
+ gdk_error_trap_pop ();
+
+ retval = NULL;
+
+ if (res_class)
+ *res_class = NULL;
+
+ if (res_name)
+ *res_name = NULL;
+
+ if (ch.res_name)
+ {
+ if (res_name)
+ *res_name = latin1_to_utf8 (ch.res_name);
+
+ XFree (ch.res_name);
+ }
+
+ if (ch.res_class)
+ {
+ if (res_class)
+ *res_class = latin1_to_utf8 (ch.res_class);
+
+ XFree (ch.res_class);
+ }
+}
+
+void
+na_tray_child_get_wm_class (NaTrayChild *child,
+ char **res_name,
+ char **res_class)
+{
+ GdkDisplay *display;
+
+ g_return_if_fail (NA_IS_TRAY_CHILD (child));
+
+ display = gtk_widget_get_display (GTK_WIDGET (child));
+
+ _get_wmclass (GDK_DISPLAY_XDISPLAY (display),
+ child->icon_window,
+ res_class,
+ res_name);
+}
--- gnome-panel-2.28.0/applets/notification_area/na-tray-child.h 2009-08-11 12:55:28.000000000 -0400
+++ hacked/applets/notification_area/na-tray-child.h 2009-10-16 00:19:19.841050913 -0400
@@ -61,7 +61,10 @@
gboolean na_tray_child_has_alpha (NaTrayChild *child);
void na_tray_child_set_composited (NaTrayChild *child,
gboolean composited);
-void na_tray_child_force_redraw (NaTrayChild *child);
+void na_tray_child_force_redraw (NaTrayChild *child);
+void na_tray_child_get_wm_class (NaTrayChild *child,
+ char **res_name,
+ char **res_class);
G_END_DECLS
--- gnome-panel-2.28.0/applets/notification_area/na-tray.c 2009-08-11 16:27:41.000000000 -0400
+++ hacked/applets/notification_area/na-tray.c 2009-10-16 01:38:03.211041558 -0400
@@ -117,6 +117,51 @@
return trays_screen->all_trays->data;
}
+const char *roles[] = {
+ "keyboard",
+ "volume",
+ "bluetooth",
+ "network",
+ "battery",
+ NULL
+};
+
+const char *wmclass_roles[] = {
+ "Bluetooth-applet", "bluetooth",
+ "Gnome-volume-control-applet", "volume",
+ "Nm-applet", "network",
+ "Gnome-power-manager", "battery",
+ NULL,
+};
+
+static const char *
+find_role (const char *wmclass)
+{
+ int i;
+
+ for (i = 0; wmclass_roles[i]; i += 2)
+ {
+ if (strcmp (wmclass, wmclass_roles[i]) == 0)
+ return wmclass_roles[i + 1];
+ }
+
+ return NULL;
+}
+
+static int
+find_role_pos (const char *role)
+{
+ int i;
+
+ for (i = 0; roles[i]; i++)
+ {
+ if (strcmp (role, roles[i]) == 0)
+ break;
+ }
+
+ return i + 1;
+}
+
static void
tray_added (NaTrayManager *manager,
GtkWidget *icon,
@@ -124,6 +169,11 @@
{
NaTray *tray;
NaTrayPrivate *priv;
+ GList *l, *children;
+ int position;
+ char *class_a;
+ const char *role;
+ int role_position;
tray = get_tray (trays_screen);
if (tray == NULL)
@@ -132,10 +182,45 @@
priv = tray->priv;
g_assert (priv->trays_screen == trays_screen);
-
+
g_hash_table_insert (trays_screen->icon_table, icon, tray);
- gtk_box_pack_end (GTK_BOX (priv->box), icon, FALSE, FALSE, 0);
+ position = 0;
+
+ class_a = NULL;
+ na_tray_child_get_wm_class (NA_TRAY_CHILD (icon), NULL, &class_a);
+ if (!class_a)
+ goto insert;
+
+ role = find_role (class_a);
+ g_free (class_a);
+ if (!role)
+ goto insert;
+
+ role_position = find_role_pos (role);
+ g_object_set_data (G_OBJECT (icon), "role-position", GINT_TO_POINTER (role_position));
+
+ children = gtk_container_get_children (GTK_CONTAINER (priv->box));
+ for (l = g_list_last (children); l; l = l->prev)
+ {
+ GtkWidget *child = l->data;
+ gint rp;
+
+ rp = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (child), "role-position"));
+ if (rp == 0 || rp < role_position)
+ {
+ position = g_list_index (children, child) + 1;
+ break;
+ }
+ }
+ g_list_free (children);
+
+ if (position < 0)
+ position = 0;
+
+insert:
+ gtk_box_pack_start (GTK_BOX (priv->box), icon, FALSE, FALSE, 0);
+ gtk_box_reorder_child (GTK_BOX (priv->box), icon, position);
gtk_widget_show (icon);
}