[gnome-shell] Use a fixed ordering for well-known icons



commit 7f5c60013343889924b336f2322aa7284730ffae
Author: Colin Walters <walters verbum org>
Date:   Thu Oct 15 09:44:09 2009 -0400

    Use a fixed ordering for well-known icons
    
    Define the ordering for well-known icons; see
    the page http://live.gnome.org/Features/StandardIconOrdering
    
    https://bugzilla.gnome.org/show_bug.cgi?id=598313

 js/ui/panel.js           |   49 +++++++++++++++++++----
 src/shell-tray-manager.c |   97 ++++++++++++++++++++++++++++++++++++++--------
 src/shell-tray-manager.h |    3 +-
 3 files changed, 123 insertions(+), 26 deletions(-)
---
diff --git a/js/ui/panel.js b/js/ui/panel.js
index c796635..9b48123 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -63,6 +63,14 @@ const TRAY_BORDER_WIDTH = 0;
 
 const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5;
 
+const STANDARD_TRAY_ICON_ORDER = ['keyboard', 'volume', 'bluetooth', 'network', 'battery']
+const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
+    'bluetooth-applet': 'bluetooth',
+    'gnome-volume-control-applet': 'volume',
+    'nm-applet': 'network',
+    'gnome-power-manager': 'battery'
+};
+
 function AppPanelMenu() {
     this._init();
 }
@@ -358,14 +366,7 @@ Panel.prototype = {
         trayContainer.append(trayBox, Big.BoxPackFlags.NONE);
 
         this._traymanager = new Shell.TrayManager({ bg_color: TRAY_BACKGROUND_COLOR });
-        this._traymanager.connect('tray-icon-added',
-            Lang.bind(this, function(o, icon) {
-                trayBox.append(icon, Big.BoxPackFlags.NONE);
-
-                // Make sure the trayBox is shown.
-                trayBox.show();
-                this._recomputeTraySize();
-            }));
+        this._traymanager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
         this._traymanager.connect('tray-icon-removed',
             Lang.bind(this, function(o, icon) {
                 trayBox.remove_actor(icon);
@@ -442,6 +443,38 @@ Panel.prototype = {
                          });
     },
 
+    _onTrayIconAdded: function(o, icon, wmClass) {
+        let role = STANDARD_TRAY_ICON_IMPLEMENTATIONS[wmClass];
+        if (!role) {
+            // Unknown icons go first in undefined order
+            this._trayBox.prepend(icon, Big.BoxPackFlags.NONE);
+        } else {
+            icon._role = role;
+            // Figure out the index in our well-known order for this icon
+            let position = STANDARD_TRAY_ICON_ORDER.indexOf(role);
+            icon._rolePosition = position;
+            let children = this._trayBox.get_children();
+            let i;
+            // Walk children backwards, until we find one that isn't
+            // well-known, or one where we should follow
+            for (i = children.length - 1; i >= 0; i--) {
+                let rolePosition = children[i]._rolePosition;
+                if (!rolePosition || position > rolePosition) {
+                    this._trayBox.insert_after(icon, children[i], Big.BoxPackFlags.NONE);
+                    break;
+                }
+            }
+            if (i == -1) {
+                // If we didn't find a position, we must be first
+                this._trayBox.prepend(icon, Big.BoxPackFlags.NONE);
+            }
+        }
+
+        // Make sure the trayBox is shown.
+        this._trayBox.show();
+        this._recomputeTraySize();
+    },
+
     // By default, tray icons have a spacing of TRAY_SPACING.  However this
     // starts to fail if we have too many as can sadly happen; just jump down
     // to a spacing of 8 if we're over 6.
diff --git a/src/shell-tray-manager.c b/src/shell-tray-manager.c
index 681fba3..9940461 100644
--- a/src/shell-tray-manager.c
+++ b/src/shell-tray-manager.c
@@ -4,11 +4,16 @@
 #include <clutter/x11/clutter-x11.h>
 #include <gtk/gtk.h>
 
+#include <display.h>
+
+#include <girepository.h>
+
 #include "shell-tray-manager.h"
 #include "na-tray-manager.h"
 
 #include "shell-gtk-embed.h"
 #include "shell-embedded-window.h"
+#include "shell-global.h"
 
 struct _ShellTrayManagerPrivate {
   NaTrayManager *na_manager;
@@ -23,6 +28,7 @@ typedef struct {
   GtkWidget *socket;
   GtkWidget *window;
   ClutterActor *actor;
+  gboolean emitted_plugged;
 } ShellTrayManagerChild;
 
 enum {
@@ -148,21 +154,22 @@ shell_tray_manager_class_init (ShellTrayManagerClass *klass)
 
   shell_tray_manager_signals[TRAY_ICON_ADDED] =
     g_signal_new ("tray-icon-added",
-		  G_TYPE_FROM_CLASS (klass),
-		  G_SIGNAL_RUN_LAST,
-		  G_STRUCT_OFFSET (ShellTrayManagerClass, tray_icon_added),
-		  NULL, NULL,
-		  g_cclosure_marshal_VOID__OBJECT,
-		  G_TYPE_NONE, 1,
-                  CLUTTER_TYPE_ACTOR);
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ShellTrayManagerClass, tray_icon_added),
+                  NULL, NULL,
+                  gi_cclosure_marshal_generic,
+                  G_TYPE_NONE, 2,
+                  CLUTTER_TYPE_ACTOR,
+                  G_TYPE_STRING);
   shell_tray_manager_signals[TRAY_ICON_REMOVED] =
     g_signal_new ("tray-icon-removed",
-		  G_TYPE_FROM_CLASS (klass),
-		  G_SIGNAL_RUN_LAST,
-		  G_STRUCT_OFFSET (ShellTrayManagerClass, tray_icon_removed),
-		  NULL, NULL,
-		  g_cclosure_marshal_VOID__OBJECT,
-		  G_TYPE_NONE, 1,
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ShellTrayManagerClass, tray_icon_removed),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__OBJECT,
+                  G_TYPE_NONE, 1,
                   CLUTTER_TYPE_ACTOR);
 
   /* Lifting the CONSTRUCT_ONLY here isn't hard; you just need to
@@ -265,6 +272,64 @@ shell_tray_manager_child_on_realize (GtkWidget             *widget,
     }
 }
 
+static char *
+get_lowercase_wm_class_from_socket (ShellTrayManager  *manager,
+                                    GtkSocket         *socket)
+{
+  GdkWindow *window;
+  MetaScreen *screen;
+  MetaDisplay *display;
+  XClassHint class_hint;
+  gboolean success;
+  char *result;
+
+  window = gtk_socket_get_plug_window (socket);
+  g_return_val_if_fail (window != NULL, NULL);
+
+  screen = shell_global_get_screen (shell_global_get ());
+  display = meta_screen_get_display (screen);
+
+  gdk_error_trap_push ();
+
+  success = XGetClassHint (meta_display_get_xdisplay (display), GDK_WINDOW_XWINDOW (window), &class_hint);
+
+  gdk_error_trap_pop ();
+
+  if (!success)
+    return NULL;
+
+  result = g_ascii_strdown (class_hint.res_class, -1);
+  XFree (class_hint.res_name);
+  XFree (class_hint.res_class);
+  return result;
+}
+
+static void
+on_plug_added (GtkSocket        *socket,
+               ShellTrayManager *manager)
+{
+  ShellTrayManagerChild *child;
+  char *wm_class;
+
+  child = g_hash_table_lookup (manager->priv->icons, socket);
+  /* Only emit this signal once; the point of waiting until we
+   * get the first plugged notification is to be able to get the WM_CLASS
+   * from the child window.  But we don't want to emit this signal twice
+   * if for some reason the socket gets replugged.
+   */
+  if (child->emitted_plugged)
+    return;
+  child->emitted_plugged = TRUE;
+
+  wm_class = get_lowercase_wm_class_from_socket (manager, socket);
+  if (!wm_class)
+    return;
+
+  g_signal_emit (manager, shell_tray_manager_signals[TRAY_ICON_ADDED], 0,
+                 child->actor, wm_class);
+  g_free (wm_class);
+}
+
 static void
 na_tray_icon_added (NaTrayManager *na_manager, GtkWidget *socket,
                     gpointer user_data)
@@ -289,7 +354,7 @@ na_tray_icon_added (NaTrayManager *na_manager, GtkWidget *socket,
    * the window we put it in match that as well */
   gtk_widget_set_colormap (win, gtk_widget_get_colormap (socket));
 
-  child = g_slice_new (ShellTrayManagerChild);
+  child = g_slice_new0 (ShellTrayManagerChild);
   child->manager = manager;
   child->window = win;
   child->socket = socket;
@@ -304,9 +369,7 @@ na_tray_icon_added (NaTrayManager *na_manager, GtkWidget *socket,
   child->actor = g_object_ref (icon);
   g_hash_table_insert (manager->priv->icons, socket, child);
 
-  g_signal_emit (manager,
-                 shell_tray_manager_signals[TRAY_ICON_ADDED], 0,
-                 icon);
+  g_signal_connect (socket, "plug-added", G_CALLBACK (on_plug_added), manager);
 }
 
 static void
diff --git a/src/shell-tray-manager.h b/src/shell-tray-manager.h
index 7df38bb..d991631 100644
--- a/src/shell-tray-manager.h
+++ b/src/shell-tray-manager.h
@@ -30,7 +30,8 @@ struct _ShellTrayManagerClass
   GObjectClass parent_class;
 
   void (* tray_icon_added)   (ShellTrayManager *manager,
-			      ClutterActor     *icon); 
+			      ClutterActor     *icon,
+			      const char       *lowercase_wm_class);
   void (* tray_icon_removed) (ShellTrayManager *manager,
 			      ClutterActor     *icon);
 



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