--- 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); }