[gdm] Add ordering patch to na-tray



commit b2bd208cd0057e25b0aac380d519376b243537e0
Author: Ray Strode <rstrode redhat com>
Date:   Thu Oct 22 22:07:52 2009 -0400

    Add ordering patch to na-tray
    
    This makes sure system utilities come up in the right order.

 .../libnotificationarea/na-tray-child.c            |   81 ++++++++++++++++++
 .../libnotificationarea/na-tray-child.h            |    5 +-
 gui/simple-greeter/libnotificationarea/na-tray.c   |   89 +++++++++++++++++++-
 3 files changed, 172 insertions(+), 3 deletions(-)
---
diff --git a/gui/simple-greeter/libnotificationarea/na-tray-child.c b/gui/simple-greeter/libnotificationarea/na-tray-child.c
index c7e3f61..98769bd 100644
--- a/gui/simple-greeter/libnotificationarea/na-tray-child.c
+++ b/gui/simple-greeter/libnotificationarea/na-tray-child.c
@@ -428,3 +428,84 @@ na_tray_child_force_redraw (NaTrayChild *child)
 #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);
+}
diff --git a/gui/simple-greeter/libnotificationarea/na-tray-child.h b/gui/simple-greeter/libnotificationarea/na-tray-child.h
index c174abe..ff036a7 100644
--- a/gui/simple-greeter/libnotificationarea/na-tray-child.h
+++ b/gui/simple-greeter/libnotificationarea/na-tray-child.h
@@ -61,7 +61,10 @@ char           *na_tray_child_get_title      (NaTrayChild *child);
 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
 
diff --git a/gui/simple-greeter/libnotificationarea/na-tray.c b/gui/simple-greeter/libnotificationarea/na-tray.c
index 051a811..3bd1258 100644
--- a/gui/simple-greeter/libnotificationarea/na-tray.c
+++ b/gui/simple-greeter/libnotificationarea/na-tray.c
@@ -114,6 +114,51 @@ get_tray (TraysScreen *trays_screen)
   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,
@@ -121,6 +166,11 @@ tray_added (NaTrayManager *manager,
 {
   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)
@@ -129,10 +179,45 @@ tray_added (NaTrayManager *manager,
   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);
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]