[Xfce4-commits] r26037 - in xfce4-panel/trunk: . plugins/systray po

Nick Schermer nick at xfce.org
Sun Sep 2 13:47:55 CEST 2007


Author: nick
Date: 2007-09-02 11:47:54 +0000 (Sun, 02 Sep 2007)
New Revision: 26037

Added:
   xfce4-panel/trunk/plugins/systray/xfce-tray-dialogs.c
   xfce4-panel/trunk/plugins/systray/xfce-tray-dialogs.h
   xfce4-panel/trunk/plugins/systray/xfce-tray-manager.c
   xfce4-panel/trunk/plugins/systray/xfce-tray-manager.h
   xfce4-panel/trunk/plugins/systray/xfce-tray-marshal.list
   xfce4-panel/trunk/plugins/systray/xfce-tray-plugin.c
   xfce4-panel/trunk/plugins/systray/xfce-tray-plugin.h
   xfce4-panel/trunk/plugins/systray/xfce-tray-widget.c
   xfce4-panel/trunk/plugins/systray/xfce-tray-widget.h
Removed:
   xfce4-panel/trunk/plugins/systray/systray.c
Modified:
   xfce4-panel/trunk/NEWS
   xfce4-panel/trunk/plugins/systray/Makefile.am
   xfce4-panel/trunk/po/POTFILES.in
   xfce4-panel/trunk/po/ar.po
   xfce4-panel/trunk/po/az.po
   xfce4-panel/trunk/po/be.po
   xfce4-panel/trunk/po/bg.po
   xfce4-panel/trunk/po/bn_IN.po
   xfce4-panel/trunk/po/ca.po
   xfce4-panel/trunk/po/cs.po
   xfce4-panel/trunk/po/de.po
   xfce4-panel/trunk/po/dz.po
   xfce4-panel/trunk/po/el.po
   xfce4-panel/trunk/po/en_GB.po
   xfce4-panel/trunk/po/eo.po
   xfce4-panel/trunk/po/es.po
   xfce4-panel/trunk/po/es_MX.po
   xfce4-panel/trunk/po/et.po
   xfce4-panel/trunk/po/eu.po
   xfce4-panel/trunk/po/fa.po
   xfce4-panel/trunk/po/fi.po
   xfce4-panel/trunk/po/fr.po
   xfce4-panel/trunk/po/gl.po
   xfce4-panel/trunk/po/gu.po
   xfce4-panel/trunk/po/he.po
   xfce4-panel/trunk/po/hi.po
   xfce4-panel/trunk/po/hu.po
   xfce4-panel/trunk/po/hy.po
   xfce4-panel/trunk/po/it.po
   xfce4-panel/trunk/po/ja.po
   xfce4-panel/trunk/po/ka.po
   xfce4-panel/trunk/po/ko.po
   xfce4-panel/trunk/po/lt.po
   xfce4-panel/trunk/po/mk.po
   xfce4-panel/trunk/po/mr.po
   xfce4-panel/trunk/po/ms.po
   xfce4-panel/trunk/po/nb_NO.po
   xfce4-panel/trunk/po/nl.po
   xfce4-panel/trunk/po/pa.po
   xfce4-panel/trunk/po/pl.po
   xfce4-panel/trunk/po/pt_BR.po
   xfce4-panel/trunk/po/pt_PT.po
   xfce4-panel/trunk/po/ro.po
   xfce4-panel/trunk/po/ru.po
   xfce4-panel/trunk/po/sk.po
   xfce4-panel/trunk/po/sq.po
   xfce4-panel/trunk/po/sv.po
   xfce4-panel/trunk/po/ta.po
   xfce4-panel/trunk/po/tr.po
   xfce4-panel/trunk/po/uk.po
   xfce4-panel/trunk/po/vi.po
   xfce4-panel/trunk/po/xfce4-panel.pot
   xfce4-panel/trunk/po/zh_CN.po
   xfce4-panel/trunk/po/zh_TW.po
Log:
* plugins/systray: Rewrite of the system tray plugin. This should 
  fix the icon size problems (Bugs 3213, 3176, 962, 3478 and 3417), 
  add option to hide icons in the   tray, sort icons by application 
  name and support multiple lines based on the   panel size. The 
  tray manager code is now integrated in the plugin, so it can be
  removed from libxfcegui4.
* NEWS: update
* po/: merge strings


Modified: xfce4-panel/trunk/NEWS
===================================================================
--- xfce4-panel/trunk/NEWS	2007-09-01 21:36:32 UTC (rev 26036)
+++ xfce4-panel/trunk/NEWS	2007-09-02 11:47:54 UTC (rev 26037)
@@ -7,6 +7,11 @@
 - Separator can have different styles: space, expanded space, line (default),
   handle and old-style dotted handle. Initial patch by Landry Breuil. (Jasper)
 - Complete rewrite of the clock plugin. (Nick)
+- Rewrite of the system tray plugin. This should fix the icon size problems
+  (Bugs 3213, 3176, 962, 3478 and 3417), add option to hide icons in the
+  tray, sort icons by application name and support multiple lines based on the
+  panel size. The tray manager code is now integrated in the plugin, so it
+  can be removed from libxfcegui4. (Nick)
 - Fix area that is off-limits to other windows (_NET_WM_STRUT hints) for a
   Xinerama setup with differently sized monitors (Bug #3097). (Jasper)
 - Completely rewritten launcher (Bugs 2336, 2365, 1323, 2262 and 1225)

Modified: xfce4-panel/trunk/plugins/systray/Makefile.am
===================================================================
--- xfce4-panel/trunk/plugins/systray/Makefile.am	2007-09-01 21:36:32 UTC (rev 26036)
+++ xfce4-panel/trunk/plugins/systray/Makefile.am	2007-09-02 11:47:54 UTC (rev 26037)
@@ -11,11 +11,24 @@
 
 plugin_LTLIBRARIES =							\
 	libsystray.la
+	
+libsystray_built_sources =						\
+	xfce-tray-marshal.c						\
+	xfce-tray-marshal.h
 
 libsystray_la_SOURCES = 						\
-	systray.c
+	$(libsystray_built_sources)					\
+	xfce-tray-dialogs.c						\
+	xfce-tray-dialogs.h						\
+	xfce-tray-manager.c						\
+	xfce-tray-manager.h						\
+	xfce-tray-plugin.c						\
+	xfce-tray-plugin.h						\
+	xfce-tray-widget.c						\
+	xfce-tray-widget.h
 
 libsystray_la_CFLAGS =							\
+	$(LIBX11_CFLAGS)						\
 	$(GTK_CFLAGS)							\
 	$(LIBXFCE4UTIL_CFLAGS)						\
 	$(LIBXFCEGUI4_CFLAGS)						\
@@ -33,6 +46,7 @@
 
 libsystray_la_LIBADD =							\
 	$(top_builddir)/libxfce4panel/libxfce4panel.la			\
+	$(LIBX11_LIBS)							\
 	$(GTK_LIBS)							\
 	$(LIBXFCE4UTIL_LIBS)						\
 	$(LIBXFCEGUI4_LIBS)
@@ -59,10 +73,44 @@
 @INTLTOOL_DESKTOP_RULE@
 
 EXTRA_DIST = 								\
-	$(desktop_in_in_files)
+	$(desktop_in_in_files)						\
+	xfce-tray-marshal.list
+	
+CLEANFILES =								\
+	xgen-xtmc							\
+	xgen-xtmh
 
+#
+# Rules to auto-generate built sources
+#
+
+if MAINTAINER_MODE
 DISTCLEANFILES =							\
 	$(desktop_DATA)							\
-	$(desktop_in_files)
+	$(desktop_in_files)						\
+	$(libsystray_built_sources)					\
+	stamp-xfce-tray-marshal.h
 
+BUILT_SOURCES =								\
+	$(libsystray_built_sources)
+
+xfce-tray-marshal.h: stamp-xfce-tray-marshal.h
+	@true
+stamp-xfce-tray-marshal.h: $(srcdir)/xfce-tray-marshal.list Makefile
+	( cd $(srcdir) && glib-genmarshal \
+		--prefix="_xfce_tray_marshal" \
+		--header xfce-tray-marshal.list \
+		| sed -e 's/marshal_data);$$/marshal_data) G_GNUC_INTERNAL;/' ) >> xgen-xtmh \
+	&& ( cmp -s xgen-xtmh xfce-tray-marshal.h || cp xgen-xtmh xfce-tray-marshal.h ) \
+	&& rm -f xgen-xtmh \
+	&& echo timestamp > $(@F)
+
+xfce-tray-marshal.c: xfce-tray-marshal.h Makefile
+	( cd $(srcdir) && glib-genmarshal \
+		--prefix="_xfce_tray_marshal" \
+		--body xfce-tray-marshal.list ) >> xgen-xtmc \
+	&& cp xgen-xtmc xfce-tray-marshal.c \
+	&& rm -f xgen-xtmc
+endif
+
 # vi:set ts=8 sw=8 noet ai nocindent syntax=automake:

Deleted: xfce4-panel/trunk/plugins/systray/systray.c

Added: xfce4-panel/trunk/plugins/systray/xfce-tray-dialogs.c
===================================================================
--- xfce4-panel/trunk/plugins/systray/xfce-tray-dialogs.c	                        (rev 0)
+++ xfce4-panel/trunk/plugins/systray/xfce-tray-dialogs.c	2007-09-02 11:47:54 UTC (rev 26037)
@@ -0,0 +1,339 @@
+/* $Id$ */
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+ 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define XFCE_TRAY_DIALOG_ICON_SIZE 16
+
+#include <gtk/gtk.h>
+#include <libxfce4util/libxfce4util.h>
+#include <libxfcegui4/xfce-titled-dialog.h>
+#include <libxfcegui4/xfce-widget-helpers.h>
+#include <libxfce4panel/xfce-panel-plugin.h>
+#include <libxfce4panel/xfce-panel-macros.h>
+
+#include "xfce-tray-manager.h"
+#include "xfce-tray-widget.h"
+#include "xfce-tray-plugin.h"
+#include "xfce-tray-dialogs.h"
+
+
+
+enum
+{
+    APPLICATION_ICON,
+    APPLICATION_NAME,
+    APPLICATION_HIDDEN,
+    APPLICATION_DATA,
+    N_COLUMNS
+};
+
+
+
+/* prototypes */
+static gchar     *xfce_tray_dialogs_camel_case         (const gchar           *text);
+static GdkPixbuf *xfce_tray_dialogs_icon               (GtkIconTheme          *icon_theme, 
+                                                        const gchar           *name);
+static void       xfce_tray_dialogs_show_frame_toggled (GtkToggleButton       *button,
+                                                        XfceTrayPlugin        *plugin);
+static void       xfce_tray_dialogs_treeview_toggled   (GtkCellRendererToggle *widget,
+                                                        gchar                 *path,
+                                                        GtkWidget             *treeview);
+static void       xfce_tray_dialogs_free_store         (GtkListStore          *store);
+static void       xfce_tray_dialogs_configure_response (GtkWidget             *dialog, 
+                                                        gint                   response, 
+                                                        XfceTrayPlugin        *plugin);
+
+
+
+static gchar *
+xfce_tray_dialogs_camel_case (const gchar *text)
+{
+    const gchar *t;
+    gboolean     upper = TRUE;
+    gunichar     c;
+    GString     *result;
+
+    /* allocate a new string for the result */
+    result = g_string_sized_new (32);
+
+    /* convert the input text */
+    for (t = text; *t != '\0'; t = g_utf8_next_char (t))
+    {
+        /* check the next char */
+        c = g_utf8_get_char (t);
+        if (g_unichar_isspace (c))
+        {
+            upper = TRUE;
+        }
+        else if (upper)
+        {
+            c = g_unichar_toupper (c);
+            upper = FALSE;
+        }
+        else
+        {
+           c = g_unichar_tolower (c);
+        }
+
+        /* append the char to the result */
+        g_string_append_unichar (result, c);
+    }
+
+  return g_string_free (result, FALSE);
+}
+
+
+
+static GdkPixbuf *
+xfce_tray_dialogs_icon (GtkIconTheme *icon_theme,
+                        const gchar  *name)
+{
+    GdkPixbuf *icon;
+    
+    /* try to load the icon from the theme */
+    icon = gtk_icon_theme_load_icon (icon_theme, name, XFCE_TRAY_DIALOG_ICON_SIZE, 0, NULL);
+    
+    /* if no icon was found, we could check the childeren it the name is currently in the
+     * tray, if so, create a pixbuf from the window data
+     */
+    
+    return icon;
+}
+
+
+
+static void       
+xfce_tray_dialogs_show_frame_toggled (GtkToggleButton *button,
+                                      XfceTrayPlugin  *plugin)
+{
+    gboolean active;
+    
+    /* get state */
+    active = gtk_toggle_button_get_active (button);
+    
+    /* set frame shadow */
+    gtk_frame_set_shadow_type (GTK_FRAME (plugin->frame), active ? GTK_SHADOW_IN : GTK_SHADOW_NONE);
+    
+    /* save */
+    plugin->show_frame = active;
+}
+
+
+
+static void
+xfce_tray_dialogs_treeview_toggled (GtkCellRendererToggle *widget,
+                                    gchar                 *path,
+                                    GtkWidget             *treeview)
+{
+    GtkTreeModel        *model;
+    GtkTreeIter          iter;
+    XfceTrayApplication *application;
+    XfceTrayPlugin      *plugin;
+    
+    /* get the tree model */
+    model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
+    
+    /* get the tree iter */
+    if (G_LIKELY (gtk_tree_model_get_iter_from_string (model, &iter, path)))
+    {
+        /* get the application data */
+        gtk_tree_model_get (model, &iter, APPLICATION_DATA, &application, -1);
+        
+        /* get tray plugin */
+        plugin = g_object_get_data (G_OBJECT (treeview), I_("xfce-tray-plugin"));
+        
+        if (G_LIKELY (application && plugin))
+        {
+           /* update the manager */
+           xfce_tray_manager_application_update (plugin->manager, application->name, !application->hidden);
+    
+           /* sort and update the tray widget */
+           xfce_tray_widget_sort (XFCE_TRAY_WIDGET (plugin->tray));
+    
+           /* set the new list value */
+           gtk_list_store_set (GTK_LIST_STORE (model), &iter, APPLICATION_HIDDEN, application->hidden, -1);
+        }
+    }
+}
+
+
+
+static void
+xfce_tray_dialogs_free_store (GtkListStore *store)
+{
+    /* clear store */
+    gtk_list_store_clear (store);
+    
+    /* release the store */
+    g_object_unref (G_OBJECT (store));
+}
+
+
+
+static void
+xfce_tray_dialogs_configure_response (GtkWidget      *dialog, 
+                                      gint            response, 
+                                      XfceTrayPlugin *plugin)
+{
+    /* destroy dialog */
+    gtk_widget_destroy (dialog);
+    
+    /* unblock plugin menu */
+    xfce_panel_plugin_unblock_menu (plugin->panel_plugin);
+}
+
+
+
+void 
+xfce_tray_dialogs_configure (XfceTrayPlugin *plugin)
+{
+    GtkWidget           *dialog, *dialog_vbox;
+    GtkWidget           *frame, *bin, *button;
+    GtkWidget           *scroll, *treeview;
+    GtkListStore        *store;
+    GtkTreeViewColumn   *column;
+    GtkCellRenderer     *renderer;
+    GtkTreeIter          iter;
+    XfceTrayApplication *application;
+    GSList              *applications, *li;
+    gchar               *name;
+    GtkIconTheme        *icon_theme;
+    GdkPixbuf           *pixbuf;
+    
+    /* lock plugin menu */
+    xfce_panel_plugin_block_menu (plugin->panel_plugin);
+    
+    /* create dialog */
+    dialog = xfce_titled_dialog_new_with_buttons (_("System Tray"),
+                                                  NULL,
+                                                  GTK_DIALOG_NO_SEPARATOR,
+                                                  GTK_STOCK_OK, GTK_RESPONSE_OK,
+                                                  NULL);
+    gtk_window_set_screen (GTK_WINDOW (dialog), gtk_widget_get_screen (GTK_WIDGET (plugin->panel_plugin)));
+    gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
+    gtk_window_set_icon_name (GTK_WINDOW (dialog), "xfce4-settings");
+    gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+    g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (xfce_tray_dialogs_configure_response), plugin);
+    
+    dialog_vbox = GTK_DIALOG (dialog)->vbox;
+    
+    /* appearance */
+    frame = xfce_create_framebox (_("Appearance"), &bin);
+    gtk_box_pack_start (GTK_BOX (dialog_vbox), frame, FALSE, TRUE, 0);
+    //gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
+    gtk_widget_show (frame);
+    
+    /* show frame */
+    button = gtk_check_button_new_with_mnemonic (_("Show _frame"));
+    gtk_container_add (GTK_CONTAINER (bin), button);
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), plugin->show_frame);
+    g_signal_connect (button, "toggled", G_CALLBACK (xfce_tray_dialogs_show_frame_toggled), plugin);
+    gtk_widget_show (button);
+    
+    /* applications */
+    frame = xfce_create_framebox (_("Hidden Applications"), &bin);
+    gtk_box_pack_start (GTK_BOX (dialog_vbox), frame, TRUE, TRUE, 0);
+    //gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
+    gtk_widget_show (frame);
+    
+    /* scrolled window */
+    scroll = gtk_scrolled_window_new (NULL, NULL);
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
+    gtk_container_add (GTK_CONTAINER (bin), scroll);
+    gtk_widget_show (scroll);
+    
+    /* create list store */
+    store = gtk_list_store_new (N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER);
+    
+    /* create treeview */
+    treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+    gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+    gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
+    g_signal_connect_swapped (G_OBJECT (treeview), "destroy", G_CALLBACK (xfce_tray_dialogs_free_store), store);
+    gtk_container_add (GTK_CONTAINER (scroll), treeview);
+    gtk_widget_show (treeview);
+    
+    /* connect the plugin to the treeview */
+    g_object_set_data (G_OBJECT (treeview), I_("xfce-tray-plugin"), plugin);
+    
+    /* create column */
+    column = gtk_tree_view_column_new ();
+    gtk_tree_view_column_set_expand (column, TRUE);
+    gtk_tree_view_column_set_resizable (column, FALSE);
+    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+    
+    /* create renders */
+    renderer = gtk_cell_renderer_pixbuf_new();
+    gtk_tree_view_column_pack_start (column, renderer, FALSE);
+    gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", APPLICATION_ICON, NULL);
+    
+    renderer = gtk_cell_renderer_text_new ();
+    gtk_tree_view_column_pack_start (column, renderer, TRUE);
+    gtk_tree_view_column_set_attributes (column, renderer, "text", APPLICATION_NAME, NULL);
+    
+    renderer = gtk_cell_renderer_toggle_new ();
+    gtk_tree_view_column_pack_start (column, renderer, FALSE);
+    gtk_tree_view_column_set_attributes (column, renderer, "active", APPLICATION_HIDDEN, NULL);
+    g_signal_connect (G_OBJECT (renderer), "toggled", G_CALLBACK(xfce_tray_dialogs_treeview_toggled), treeview);
+    
+    /* get the icon theme */
+    if (G_LIKELY (gtk_widget_has_screen (dialog)))
+        icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (dialog));
+    else
+        icon_theme = gtk_icon_theme_get_default ();
+    
+    /* get the sorted list of applications */
+    applications = xfce_tray_manager_application_list (plugin->manager, TRUE);
+    
+    /* add all the application to the list */
+    for (li = applications; li != NULL; li = li->next)
+    {
+        application = li->data;
+        
+        /* create a camel case name of the application */
+        name = xfce_tray_dialogs_camel_case (application->name);
+        
+        /* append the application */
+        gtk_list_store_append (store, &iter);
+        gtk_list_store_set (store, &iter,
+                            APPLICATION_NAME, name,
+                            APPLICATION_HIDDEN, application->hidden,
+                            APPLICATION_DATA, application, -1);
+                            
+        /* cleanup */
+        g_free (name);
+        
+        /* get the application icon */
+        pixbuf = xfce_tray_dialogs_icon (icon_theme, application->name);
+                            
+        if (pixbuf)
+        {
+            /* set the icon */
+            gtk_list_store_set (store, &iter, APPLICATION_ICON, pixbuf, -1);
+            
+            /* release */
+            g_object_unref (G_OBJECT (pixbuf));
+        }
+    }
+    
+    /* show the dialog */
+    gtk_widget_show (dialog);
+}


Property changes on: xfce4-panel/trunk/plugins/systray/xfce-tray-dialogs.c
___________________________________________________________________
Name: keywords
   + Id

Added: xfce4-panel/trunk/plugins/systray/xfce-tray-dialogs.h
===================================================================
--- xfce4-panel/trunk/plugins/systray/xfce-tray-dialogs.h	                        (rev 0)
+++ xfce4-panel/trunk/plugins/systray/xfce-tray-dialogs.h	2007-09-02 11:47:54 UTC (rev 26037)
@@ -0,0 +1,23 @@
+/* $Id$ */
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+ 
+#ifndef __XFCE_TRAY_DIALOGS_H__
+#define __XFCE_TRAY_DIALOGS_H__
+
+void xfce_tray_dialogs_configure (XfceTrayPlugin *plugin);
+
+#endif /* !__XFCE_TRAY_DIALOGS_H__ */


Property changes on: xfce4-panel/trunk/plugins/systray/xfce-tray-dialogs.h
___________________________________________________________________
Name: keywords
   + Id

Added: xfce4-panel/trunk/plugins/systray/xfce-tray-manager.c
===================================================================
--- xfce4-panel/trunk/plugins/systray/xfce-tray-manager.c	                        (rev 0)
+++ xfce4-panel/trunk/plugins/systray/xfce-tray-manager.c	2007-09-02 11:47:54 UTC (rev 26037)
@@ -0,0 +1,1047 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2002      Anders Carlsson <andersca at gnu.org>
+ * Copyright (c) 2003-2004 Benedikt Meurer <benny at xfce.org>
+ * Copyright (c) 2003-2004 Olivier Fourdan <fourdan at xfce.org>
+ * Copyright (c) 2003-2006 Vincent Untz
+ * Copyright (c) 2007      Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+#include <libxfce4panel/xfce-panel-macros.h>
+#include <libxfce4util/libxfce4util.h>
+
+#include "xfce-tray-manager.h"
+#include "xfce-tray-marshal.h"
+
+
+
+#define XFCE_TRAY_MANAGER_REQUEST_DOCK   0
+#define XFCE_TRAY_MANAGER_BEGIN_MESSAGE  1
+#define XFCE_TRAY_MANAGER_CANCEL_MESSAGE 2
+
+#define XFCE_TRAY_MANAGER_ORIENTATION_HORIZONTAL 0
+#define XFCE_TRAY_MANAGER_ORIENTATION_VERTICAL   1
+
+
+
+/* prototypes */
+static void                 xfce_tray_manager_class_init                         (XfceTrayManagerClass *klass);
+static void                 xfce_tray_manager_init                               (XfceTrayManager      *manager);
+static void                 xfce_tray_manager_finalize                           (GObject              *object);
+static void                 xfce_tray_manager_unregister                         (XfceTrayManager      *manager);
+static GdkFilterReturn      xfce_tray_manager_window_filter                      (GdkXEvent            *xev,
+                                                                                  GdkEvent             *event,
+                                                                                  gpointer              user_data);
+static GdkFilterReturn      xfce_tray_manager_handle_client_message_opcode       (GdkXEvent            *xevent,
+                                                                                  GdkEvent             *event,
+                                                                                  gpointer              user_data);
+static GdkFilterReturn      xfce_tray_manager_handle_client_message_message_data (GdkXEvent            *xevent,
+                                                                                  GdkEvent             *event,
+                                                                                  gpointer              user_data);
+static void                 xfce_tray_manager_handle_begin_message               (XfceTrayManager      *manager,
+                                                                                  XClientMessageEvent  *xevent);
+static void                 xfce_tray_manager_handle_cancel_message              (XfceTrayManager      *manager,
+                                                                                  XClientMessageEvent  *xevent);
+static void                 xfce_tray_manager_handle_dock_request                (XfceTrayManager      *manager,
+                                                                                  XClientMessageEvent  *xevent);
+static gboolean             xfce_tray_manager_handle_undock_request              (GtkSocket            *socket,
+                                                                                  gpointer              user_data);
+static gint                 xfce_tray_manager_application_list_compare           (gconstpointer         a,
+                                                                                  gconstpointer         b);
+static void                 xfce_tray_manager_application_free                   (XfceTrayApplication  *application);
+static XfceTrayApplication *xfce_tray_manager_application_find                   (XfceTrayManager      *manager,
+                                                                                  const gchar          *name);
+static void                 xfce_tray_manager_application_set_socket             (XfceTrayManager      *manager,
+                                                                                  GtkWidget            *socket,
+                                                                                  Window                xwindow);
+static void                 xfce_tray_message_free                               (XfceTrayMessage      *message);
+static void                 xfce_tray_message_remove_from_list                   (XfceTrayManager      *manager,
+                                                                                  XClientMessageEvent  *xevent);
+
+
+enum
+{
+  TRAY_ICON_ADDED,
+  TRAY_ICON_REMOVED,
+  TRAY_MESSAGE_SENT,
+  TRAY_MESSAGE_CANCELLED,
+  TRAY_LOST_SELECTION,
+  LAST_SIGNAL
+};
+
+struct _XfceTrayManagerClass
+{
+    GObjectClass __parent__;
+};
+
+struct _XfceTrayManager
+{
+    GObject __parent__;
+
+    /* invisible window */
+    GtkWidget      *invisible;
+
+    /* list of client sockets */
+    GHashTable     *sockets;
+
+    /* orientation of the tray */
+    GtkOrientation  orientation;
+
+    /* list of pending messages */
+    GSList         *messages;
+
+    /* _net_system_tray_opcode atom */
+    Atom            opcode_atom;
+
+    /* _net_system_tray_s%d atom */
+    GdkAtom         selection_atom;
+    
+    /* list of known and hidden applications */
+    GSList         *applications;
+};
+
+struct _XfceTrayMessage
+{
+    /* message string */
+    gchar          *string;
+
+    /* message id */
+    glong           id;
+
+    /* x11 window */
+    Window          window;
+
+    /* numb3rs */
+    glong           length;
+    glong           remaining_length;
+    glong           timeout;
+};
+
+
+
+static guint         xfce_tray_manager_signals[LAST_SIGNAL];
+static GObjectClass *xfce_tray_manager_parent_class;
+
+
+
+GType
+xfce_tray_manager_get_type (void)
+{
+    static GType type = G_TYPE_INVALID;
+
+    if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+        type = g_type_register_static_simple (G_TYPE_OBJECT,
+                                              I_("XfceTrayManager"),
+                                              sizeof (XfceTrayManagerClass),
+                                              (GClassInitFunc) xfce_tray_manager_class_init,
+                                              sizeof (XfceTrayManager),
+                                              (GInstanceInitFunc) xfce_tray_manager_init,
+                                              0);
+    }
+
+    return type;
+}
+
+
+
+static void
+xfce_tray_manager_class_init (XfceTrayManagerClass *klass)
+{
+    GObjectClass *gobject_class;
+
+    /* determine the parent type class */
+    xfce_tray_manager_parent_class = g_type_class_peek_parent (klass);
+
+    gobject_class = (GObjectClass *)klass;
+    gobject_class->finalize = xfce_tray_manager_finalize;
+
+    xfce_tray_manager_signals[TRAY_ICON_ADDED] =
+        g_signal_new (I_("tray-icon-added"),
+                      G_OBJECT_CLASS_TYPE (klass),
+                      G_SIGNAL_RUN_LAST,
+                      0, NULL, NULL,
+                      g_cclosure_marshal_VOID__OBJECT,
+                      G_TYPE_NONE, 1,
+                      GTK_TYPE_SOCKET);
+
+    xfce_tray_manager_signals[TRAY_ICON_REMOVED] =
+        g_signal_new (I_("tray-icon-removed"),
+                      G_OBJECT_CLASS_TYPE (klass),
+                      G_SIGNAL_RUN_LAST,
+                      0, NULL, NULL,
+                      g_cclosure_marshal_VOID__OBJECT,
+                      G_TYPE_NONE, 1,
+                      GTK_TYPE_SOCKET);
+
+    xfce_tray_manager_signals[TRAY_MESSAGE_SENT] =
+        g_signal_new (I_("tray-message-sent"),
+                      G_OBJECT_CLASS_TYPE (klass),
+                      G_SIGNAL_RUN_LAST,
+                      0, NULL, NULL,
+                      _xfce_tray_marshal_VOID__OBJECT_STRING_LONG_LONG,
+                      G_TYPE_NONE, 4,
+                      GTK_TYPE_SOCKET,
+                      G_TYPE_STRING,
+                      G_TYPE_LONG,
+                      G_TYPE_LONG);
+
+    xfce_tray_manager_signals[TRAY_MESSAGE_CANCELLED] =
+        g_signal_new (I_("tray-message-cancelled"),
+                      G_OBJECT_CLASS_TYPE (klass),
+                      G_SIGNAL_RUN_LAST,
+                      0, NULL, NULL,
+                      _xfce_tray_marshal_VOID__OBJECT_LONG,
+                      G_TYPE_NONE, 2,
+                      GTK_TYPE_SOCKET,
+                      G_TYPE_LONG);
+
+    xfce_tray_manager_signals[TRAY_LOST_SELECTION] =
+        g_signal_new (I_("tray-lost-selection"),
+                      G_OBJECT_CLASS_TYPE (klass),
+                      G_SIGNAL_RUN_LAST,
+                      0, NULL, NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE, 0);
+}
+
+
+
+static void
+xfce_tray_manager_init (XfceTrayManager *manager)
+{
+  /* initialize */
+  manager->messages = NULL;
+  manager->invisible = NULL;
+  manager->orientation = GTK_ORIENTATION_HORIZONTAL;
+  manager->applications = NULL;
+
+  /* create new sockets table */
+  manager->sockets = g_hash_table_new (NULL, NULL);
+}
+
+
+
+GQuark
+xfce_tray_manager_error_quark (void)
+{
+    static GQuark q = 0;
+    
+    if (q == 0)
+    {
+        q = g_quark_from_static_string ("xfce-tray-manager-error-quark");
+    }
+    
+    return q;
+}
+
+
+
+static void
+xfce_tray_manager_finalize (GObject *object)
+{
+    XfceTrayManager *manager = XFCE_TRAY_MANAGER (object);
+
+    /* unregsiter the manager */
+    xfce_tray_manager_unregister (manager);
+
+    /* destroy the hash table */
+    g_hash_table_destroy (manager->sockets);
+    
+    if (manager->messages)
+    {
+        /* cleanup all pending messages */
+        g_slist_foreach (manager->messages, (GFunc) xfce_tray_message_free, NULL);
+
+        /* free the list */
+        g_slist_free (manager->messages);
+    }
+
+    if (manager->applications)
+    {
+        /* free all items */
+        g_slist_foreach (manager->applications, (GFunc) xfce_tray_manager_application_free, NULL);
+        
+        /* free the list */
+        g_slist_free (manager->applications);
+    }
+
+    G_OBJECT_CLASS (xfce_tray_manager_parent_class)->finalize (object);
+}
+
+
+XfceTrayManager *
+xfce_tray_manager_new (void)
+{
+    return g_object_new (XFCE_TYPE_TRAY_MANAGER, NULL);
+}
+
+
+gboolean
+xfce_tray_manager_check_running (GdkScreen *screen)
+{
+    gchar      *selection_name;
+    GdkDisplay *display;
+    Atom        selection_atom;
+
+    g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+
+    /* get the display */
+    display = gdk_screen_get_display (screen);
+
+    /* create the selection atom name */
+    selection_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d", gdk_screen_get_number (screen));
+
+    /* get the atom */
+    selection_atom = gdk_x11_get_xatom_by_name_for_display (display, selection_name);
+
+    /* cleanup */
+    g_free (selection_name);
+
+    /* return result */
+    return (XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display), selection_atom) != None);
+}
+
+
+
+gboolean
+xfce_tray_manager_register (XfceTrayManager  *manager,
+                            GdkScreen        *screen,
+                            GError          **error)
+{
+    GdkDisplay          *display;
+    gchar               *selection_name;
+    gboolean             succeed;
+    gint                 screen_number;
+    GtkWidget           *invisible;
+    guint32              timestamp;
+    GdkAtom              opcode_atom;
+    XClientMessageEvent  xevent;
+    Window               root_window;
+
+    g_return_val_if_fail (XFCE_IS_TRAY_MANAGER (manager), FALSE);
+    g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
+    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+    /* create invisible window */
+    invisible = gtk_invisible_new_for_screen (screen);
+    gtk_widget_realize (invisible);
+
+    /* let the invisible window monitor property and configuration changes */
+    gtk_widget_add_events (invisible, GDK_PROPERTY_CHANGE_MASK | GDK_STRUCTURE_MASK);
+    
+    /* get the screen number */
+    screen_number = gdk_screen_get_number (screen);
+
+    /* create the selection atom name */
+    selection_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d", screen_number);
+
+    /* get the selection atom */
+    manager->selection_atom = gdk_atom_intern (selection_name, FALSE);
+
+    /* cleanup */
+    g_free (selection_name);
+
+    /* get the display */
+    display = gdk_screen_get_display (screen);
+
+    /* get the current x server time stamp */
+    timestamp = gdk_x11_get_server_time (invisible->window);
+
+    /* try to become the selection owner of this display */
+    succeed = gdk_selection_owner_set_for_display (display, invisible->window, manager->selection_atom, timestamp, TRUE);
+
+    if (G_LIKELY (succeed))
+    {
+        /* get the root window */
+        root_window = RootWindowOfScreen (GDK_SCREEN_XSCREEN (screen));
+
+        /* send a message to x11 that we're going to handle this display */
+        xevent.type         = ClientMessage;
+        xevent.window       = root_window;
+        xevent.message_type = gdk_x11_get_xatom_by_name_for_display (display, "MANAGER");
+        xevent.format       = 32;
+        xevent.data.l[0]    = timestamp;
+        xevent.data.l[1]    = gdk_x11_atom_to_xatom_for_display (display, manager->selection_atom);
+        xevent.data.l[2]    = GDK_WINDOW_XWINDOW (invisible->window);
+        xevent.data.l[3]    = 0;
+        xevent.data.l[4]    = 0;
+
+        /* send the message */
+        XSendEvent (GDK_DISPLAY_XDISPLAY (display), root_window, False, StructureNotifyMask, (XEvent *)&xevent);
+
+        /* set the invisible window and take a reference */
+        manager->invisible = g_object_ref (G_OBJECT (invisible));
+
+        /* system_tray_request_dock and selectionclear */
+        gdk_window_add_filter (invisible->window, xfce_tray_manager_window_filter, manager);
+
+        /* get the opcode atom (for both gdk and x11) */
+        opcode_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_OPCODE", FALSE);
+        manager->opcode_atom = gdk_x11_atom_to_xatom_for_display (display, opcode_atom);
+
+        /* system_tray_begin_message and system_tray_cancel_message */
+        gdk_display_add_client_message_filter (display,
+                                               opcode_atom,
+                                               xfce_tray_manager_handle_client_message_opcode,
+                                               manager);
+
+        /* _net_system_tray_message_data */
+        gdk_display_add_client_message_filter (display,
+                                               gdk_atom_intern ("_NET_SYSTEM_TRAY_MESSAGE_DATA", FALSE),
+                                               xfce_tray_manager_handle_client_message_message_data,
+                                               manager);
+    }
+    else
+    {
+        /* desktroy the invisible window */
+        gtk_widget_destroy (invisible);
+        
+        /* set an error */
+        g_set_error (error, XFCE_TRAY_MANAGER_ERROR, XFCE_TRAY_MANAGER_ERROR_SELECTION_FAILED,
+                     _("Failed to acquire manager selection for screen %d"), screen_number);
+    }
+
+    return succeed;
+}
+
+
+
+static void
+xfce_tray_manager_unregister (XfceTrayManager *manager)
+{
+    GdkDisplay *display;
+    GtkWidget  *invisible = manager->invisible;
+
+    /* leave when there is no invisible window */
+    if (G_UNLIKELY (invisible == NULL))
+        return;
+
+    g_return_if_fail (GTK_IS_INVISIBLE (invisible));
+    g_return_if_fail (GTK_WIDGET_REALIZED (invisible));
+    g_return_if_fail (GDK_IS_WINDOW (invisible->window));
+
+    /* get the display of the invisible window */
+    display = gtk_widget_get_display (invisible);
+
+    /* remove our handling of the selection if we're the owner */
+    if (gdk_selection_owner_get_for_display (display, manager->selection_atom) == invisible->window)
+    {
+        /* reset the selection owner */
+        gdk_selection_owner_set_for_display (display,
+                                             NULL,
+                                             manager->selection_atom,
+                                             gdk_x11_get_server_time (invisible->window),
+                                             TRUE);
+    }
+
+    /* remove window filter */
+    gdk_window_remove_filter (invisible->window, xfce_tray_manager_window_filter, manager);
+
+    /* destroy and unref the invisible window */
+    manager->invisible = NULL;
+    gtk_widget_destroy (invisible);
+    g_object_unref (G_OBJECT (invisible));
+}
+
+
+
+static GdkFilterReturn
+xfce_tray_manager_window_filter (GdkXEvent *xev,
+                                 GdkEvent  *event,
+                                 gpointer   user_data)
+{
+    XEvent          *xevent = (XEvent *)xev;
+    XfceTrayManager *manager = XFCE_TRAY_MANAGER (user_data);
+    
+    if (xevent->type == ClientMessage)
+    {
+        if (xevent->xclient.message_type == manager->opcode_atom
+            && xevent->xclient.data.l[1] == XFCE_TRAY_MANAGER_REQUEST_DOCK)
+        {
+            /* dock a tray icon */
+            xfce_tray_manager_handle_dock_request (manager, (XClientMessageEvent *) xevent);
+
+            return GDK_FILTER_REMOVE;
+        }
+    }
+    else if (xevent->type == SelectionClear)
+    {
+        /* emit the signal */
+        g_signal_emit (manager, xfce_tray_manager_signals[TRAY_LOST_SELECTION], 0);
+
+        /* unregister the manager */
+        xfce_tray_manager_unregister (manager);
+    }
+
+    return GDK_FILTER_CONTINUE;
+}
+
+
+
+static GdkFilterReturn
+xfce_tray_manager_handle_client_message_opcode (GdkXEvent *xevent,
+                                                GdkEvent  *event,
+                                                gpointer   user_data)
+{
+    XClientMessageEvent *xev;
+    XfceTrayManager     *manager = XFCE_TRAY_MANAGER (user_data);
+
+    g_return_val_if_fail (XFCE_IS_TRAY_MANAGER (manager), GDK_FILTER_REMOVE);
+
+    /* cast to x11 event */
+    xev = (XClientMessageEvent *) xevent;
+
+    switch (xev->data.l[1])
+    {
+        case XFCE_TRAY_MANAGER_REQUEST_DOCK:
+            /* handled in xfce_tray_manager_window_filter () */
+            break;
+
+        case XFCE_TRAY_MANAGER_BEGIN_MESSAGE:
+            xfce_tray_manager_handle_begin_message (manager, xev);
+            return GDK_FILTER_REMOVE;
+
+        case XFCE_TRAY_MANAGER_CANCEL_MESSAGE:
+            xfce_tray_manager_handle_cancel_message (manager, xev);
+            return GDK_FILTER_REMOVE;
+
+        default:
+            break;
+    }
+
+    return GDK_FILTER_CONTINUE;
+}
+
+
+
+static GdkFilterReturn
+xfce_tray_manager_handle_client_message_message_data (GdkXEvent *xevent,
+                                                      GdkEvent  *event,
+                                                      gpointer   user_data)
+{
+    XClientMessageEvent *xev;
+    XfceTrayManager     *manager = XFCE_TRAY_MANAGER (user_data);
+    GSList              *li;
+    XfceTrayMessage     *message;
+    glong                length;
+    GtkSocket           *socket;
+
+    g_return_val_if_fail (XFCE_IS_TRAY_MANAGER (manager), GDK_FILTER_REMOVE);
+
+    /* try to find the pending message in the list */
+    for (li = manager->messages; li != NULL; li = li->next)
+    {
+        message = li->data;
+
+        if (xev->window == message->window)
+        {
+            /* copy the data of this message */
+            length = MIN (message->remaining_length, 20);
+            memcpy ((message->string + message->length - message->remaining_length), &xev->data, length);
+            message->remaining_length -= length;
+
+            /* check if we have the complete message */
+            if (message->remaining_length == 0)
+            {
+                /* try to get the socket from the known tray icons */
+                socket = g_hash_table_lookup (manager->sockets, GUINT_TO_POINTER (message->window));
+
+                if (G_LIKELY (socket))
+                {
+                    /* known socket, send the signal */
+                    g_signal_emit (manager, xfce_tray_manager_signals[TRAY_MESSAGE_SENT], 0,
+                                   socket, message->string, message->id, message->timeout);
+                }
+
+                /* delete the message from the list */
+                manager->messages = g_slist_delete_link (manager->messages, li);
+
+                /* free the message */
+                xfce_tray_message_free (message);
+            }
+
+            /* stop searching */
+            break;
+        }
+    }
+
+    return GDK_FILTER_REMOVE;
+}
+
+
+
+static void
+xfce_tray_manager_handle_begin_message (XfceTrayManager     *manager,
+                                        XClientMessageEvent *xevent)
+{
+    GtkSocket       *socket;
+    XfceTrayMessage *message;
+    glong            length, timeout, id;
+
+    /* try to find the window in the list of known tray icons */
+    socket = g_hash_table_lookup (manager->sockets, GUINT_TO_POINTER (xevent->window));
+
+    /* unkown tray icon: ignore the message */
+    if (G_UNLIKELY (socket == NULL))
+       return;
+
+    /* remove the same message from the list */
+    xfce_tray_message_remove_from_list (manager, xevent);
+
+    /* get some message information */
+    timeout = xevent->data.l[2];
+    length  = xevent->data.l[3];
+    id      = xevent->data.l[4];
+
+    if (length == 0)
+    {
+        /* directly emit empty messages */
+        g_signal_emit (manager, xfce_tray_manager_signals[TRAY_MESSAGE_SENT], 0,
+                       socket, "", id, timeout);
+    }
+    else
+    {
+        /* create new structure */
+        message = panel_slice_new0 (XfceTrayMessage);
+
+        /* set message data */
+        message->window           = xevent->window;
+        message->timeout          = timeout;
+        message->length           = length;
+        message->id               = id;
+        message->remaining_length = length;
+        message->string           = g_malloc (length + 1);
+        message->string[length]   = '\0';
+
+        /* add this message to the list of pending messages */
+        manager->messages = g_slist_prepend (manager->messages, message);
+    }
+}
+
+
+
+static void
+xfce_tray_manager_handle_cancel_message (XfceTrayManager     *manager,
+                                         XClientMessageEvent *xevent)
+{
+    GtkSocket *socket;
+
+    /* remove the same message from the list */
+    xfce_tray_message_remove_from_list (manager, xevent);
+
+    /* try to find the window in the list of known tray icons */
+    socket = g_hash_table_lookup (manager->sockets, GUINT_TO_POINTER (xevent->window));
+
+    if (G_LIKELY (socket))
+    {
+        /* emit the cancelled signal */
+        g_signal_emit (manager, xfce_tray_manager_signals[TRAY_MESSAGE_CANCELLED], 0,
+                       socket, xevent->data.l[2]);
+    }
+}
+
+
+
+static void
+xfce_tray_manager_handle_dock_request (XfceTrayManager     *manager,
+                                       XClientMessageEvent *xevent)
+{
+    GtkWidget *socket;
+    Window    *xwindow;
+
+    /* check if we already have this notification */
+    if (g_hash_table_lookup (manager->sockets, GUINT_TO_POINTER (xevent->data.l[2])))
+        return;
+
+    /* create a new socket */
+    socket = gtk_socket_new ();
+
+    /* allow applications to draw on this widget */
+    gtk_widget_set_app_paintable (socket, TRUE);
+
+    /* allocate and set the xwindow */
+    xwindow = g_new (Window, 1);
+    *xwindow = xevent->data.l[2];
+
+    /* connect the xwindow data to the socket */
+    g_object_set_data_full (G_OBJECT (socket), I_("xfce-tray-manager-xwindow"), xwindow, g_free);
+
+    /* set the application on the socket */
+    xfce_tray_manager_application_set_socket (manager, socket, *xwindow);
+
+    /* emit signal */
+    g_signal_emit (manager, xfce_tray_manager_signals[TRAY_ICON_ADDED], 0, socket);
+
+    /* check if the widget has been attached. if it has not been attached,
+     * there's no need to add the socket to the hash table. */
+    if (G_LIKELY (GTK_IS_WINDOW (gtk_widget_get_toplevel (socket))))
+    {
+        /* signal to monitor if the client is removed from the socket */
+        g_signal_connect (G_OBJECT (socket), "plug-removed", G_CALLBACK (xfce_tray_manager_handle_undock_request), manager);
+
+        /* register the xembed client window id for this socket */
+        gtk_socket_add_id (GTK_SOCKET (socket), *xwindow);
+
+        /* add the socket to the list of known sockets */
+        g_hash_table_insert (manager->sockets, GUINT_TO_POINTER (*xwindow), socket);
+    }
+    else
+    {
+        /* not attached successfully, destroy it */
+        gtk_widget_destroy (socket);
+    }
+}
+
+
+
+static gboolean
+xfce_tray_manager_handle_undock_request (GtkSocket *socket,
+                                         gpointer   user_data)
+{
+    XfceTrayManager *manager = XFCE_TRAY_MANAGER (user_data);
+    Window          *xwindow;
+
+    g_return_val_if_fail (XFCE_IS_TRAY_MANAGER (manager), FALSE);
+
+    /* emit signal that the socket will be removed */
+    g_signal_emit (manager, xfce_tray_manager_signals[TRAY_ICON_REMOVED], 0, socket);
+    
+    /* get the xwindow */
+    xwindow = g_object_get_data (G_OBJECT (socket), I_("xfce-tray-manager-xwindow"));
+
+    /* remove the socket from the list */
+    g_hash_table_remove (manager->sockets, GUINT_TO_POINTER (*xwindow));
+
+    /* unset object data */
+    g_object_set_data (G_OBJECT (socket), I_("xfce-tray-manager-xwindow"), NULL);
+    g_object_set_data (G_OBJECT (socket), I_("xfce-tray-manager-application"), NULL);
+
+    /* destroy the socket */
+    return FALSE;
+}
+
+
+
+GtkOrientation
+xfce_tray_manager_get_orientation (XfceTrayManager *manager)
+{
+    g_return_val_if_fail (XFCE_IS_TRAY_MANAGER (manager), GTK_ORIENTATION_HORIZONTAL);
+
+    return manager->orientation;
+}
+
+
+
+void
+xfce_tray_manager_set_orientation (XfceTrayManager *manager,
+                                   GtkOrientation   orientation)
+{
+    GdkDisplay *display;
+    Atom        orientation_atom;
+    gulong      data[1];
+
+    g_return_if_fail (XFCE_IS_TRAY_MANAGER (manager));
+    g_return_if_fail (GTK_IS_INVISIBLE (manager->invisible));
+
+    if (G_LIKELY (manager->orientation != orientation))
+    {
+        /* set the new orientation */
+        manager->orientation = orientation;
+
+        /* get invisible display */
+        display = gtk_widget_get_display (manager->invisible);
+
+        /* get the xatom for the orientation property */
+        orientation_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_XFCE_TRAY_MANAGER_ORIENTATION");
+
+        /* set the data we're going to send to x */
+        data[0] = (manager->orientation == GTK_ORIENTATION_HORIZONTAL ?
+                   XFCE_TRAY_MANAGER_ORIENTATION_HORIZONTAL : XFCE_TRAY_MANAGER_ORIENTATION_VERTICAL);
+
+        /* change the x property */
+        XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+                         GDK_WINDOW_XWINDOW (manager->invisible->window),
+                         orientation_atom,
+                         XA_CARDINAL, 32,
+                         PropModeReplace,
+                         (guchar *) &data, 1);
+    }
+}
+
+
+
+/**
+ * known tray applications
+ **/
+XfceTrayApplication *
+xfce_tray_manager_application_add (XfceTrayManager *manager,
+                                   const gchar     *name,
+                                   gboolean         hidden)
+{
+    XfceTrayApplication *application;
+    
+    g_return_val_if_fail (XFCE_IS_TRAY_MANAGER (manager), NULL);
+    g_return_val_if_fail (name, NULL);
+    
+    /* create structure */
+    application = panel_slice_new0 (XfceTrayApplication);
+    
+    /* set values */
+    application->name = g_strdup (name);
+    application->hidden = hidden;
+    
+    /* add to the list */
+    manager->applications = g_slist_prepend (manager->applications, application);
+    
+    /* return the pointer */
+    return application;
+}
+
+
+
+void
+xfce_tray_manager_application_update (XfceTrayManager *manager,
+                                      const gchar     *name,
+                                      gboolean         hidden)
+{
+    GSList              *li;
+    XfceTrayApplication *application;
+    
+    g_return_if_fail (XFCE_IS_TRAY_MANAGER (manager));
+    g_return_if_fail (name);
+    
+    /* walk through the known window names */
+    for (li = manager->applications; li != NULL; li = li->next)
+    {
+        application = li->data;
+        
+        /* check if the names match */
+        if (strcmp (application->name, name) == 0)
+        {
+            /* set the new hidden state */
+            application->hidden = hidden;
+            
+            /* stop searching */
+            break;
+        }
+    }
+}
+
+
+
+static gint
+xfce_tray_manager_application_list_compare (gconstpointer a,
+                                            gconstpointer b)
+{
+    XfceTrayApplication *app_a = (XfceTrayApplication *)a;
+    XfceTrayApplication *app_b = (XfceTrayApplication *)b;
+    
+    /* sort order when one of the names is null */
+    if (G_UNLIKELY (app_a->name == NULL || app_b->name == NULL))
+        return (app_a->name == app_b->name ? 0 : (app_a->name == NULL ? -1 : 1));
+        
+    return strcmp (app_a->name, app_b->name);
+}
+
+
+
+GSList *
+xfce_tray_manager_application_list (XfceTrayManager *manager,
+                                    gboolean         sorted)
+{
+    g_return_val_if_fail (XFCE_IS_TRAY_MANAGER (manager), NULL);
+    
+    /* sort the list if requested */
+    if (sorted)
+        manager->applications = g_slist_sort (manager->applications, xfce_tray_manager_application_list_compare);
+
+    /* return the list */
+    return manager->applications;
+}
+
+
+
+static void
+xfce_tray_manager_application_free (XfceTrayApplication *application)
+{
+    /* free name */
+    g_free (application->name);
+    
+    /* free structure */
+    panel_slice_free (XfceTrayApplication, application);
+}
+
+
+
+static XfceTrayApplication *
+xfce_tray_manager_application_find (XfceTrayManager *manager,
+                                    const gchar     *name)
+{
+    GSList              *li;
+    XfceTrayApplication *application;
+    
+    g_return_val_if_fail (name, NULL);
+        
+    /* walk through the known window names */
+    for (li = manager->applications; li != NULL; li = li->next)
+    {
+        application = li->data;
+        
+        /* find a matching name and return the pointer */
+        if (strcmp (application->name, name) == 0)
+            return application;
+    }
+    
+    /* no match was found, add the application and return the pointer */
+    return xfce_tray_manager_application_add (manager, name, FALSE);
+}
+
+
+
+static void
+xfce_tray_manager_application_set_socket (XfceTrayManager *manager,
+                                          GtkWidget       *socket,
+                                          Window           xwindow)
+{
+    gchar               *name;
+    GdkDisplay          *display;
+    gint                 succeed;
+    XTextProperty        xprop;
+    XfceTrayApplication *application;
+
+    /* get the display of the socket */
+    display = gtk_widget_get_display (socket);
+
+    /* avoid exiting the application on X errors */
+    gdk_error_trap_push ();
+
+    /* try to get the wm name (this is more relaiable with qt applications) */
+    succeed = XGetWMName (GDK_DISPLAY_XDISPLAY (display), xwindow, &xprop);
+
+    /* check if everything went fine */
+    if (G_LIKELY (gdk_error_trap_pop () == 0 && succeed >= Success))
+    {
+        /* check the xprop content */
+        if (G_LIKELY (xprop.value && xprop.nitems > 0))
+        {
+            /* if the string is utf-8 valid, set the name */
+            if (G_LIKELY (g_utf8_validate ((const gchar *) xprop.value, xprop.nitems, NULL)))
+            {
+                /* create the application name (lower case) */
+                name = g_utf8_strdown ((const gchar *) xprop.value, xprop.nitems);
+
+                /* find or create a structure */
+                application = xfce_tray_manager_application_find (manager, name);
+                
+                /* cleanup */
+                g_free (name);
+                
+                /* set the object data */
+                g_object_set_data (G_OBJECT (socket), I_("xfce-tray-manager-application"), application);
+            }
+
+            /* cleanup */
+            XFree (xprop.value);
+        }
+    }
+}
+
+
+
+const gchar *
+xfce_tray_manager_application_get_name (GtkWidget *socket)
+{
+    XfceTrayApplication *application;
+    
+    /* get the application data */
+    application = g_object_get_data (G_OBJECT (socket), I_("xfce-tray-manager-application"));
+    
+    return (application ? application->name : NULL);
+}
+
+
+
+gboolean
+xfce_tray_manager_application_get_hidden (GtkWidget *socket)
+{
+    XfceTrayApplication *application;
+    
+    /* get the application data */
+    application = g_object_get_data (G_OBJECT (socket), I_("xfce-tray-manager-application"));
+    
+    return (application ? application->hidden : FALSE);
+}
+
+
+
+/**
+ * tray messages
+ **/
+static void
+xfce_tray_message_free (XfceTrayMessage *message)
+{
+    /* cleanup */
+    g_free (message->string);
+
+    /* remove slice */
+    panel_slice_free (XfceTrayMessage, message);
+}
+
+
+
+static void
+xfce_tray_message_remove_from_list (XfceTrayManager     *manager,
+                                    XClientMessageEvent *xevent)
+{
+    GSList          *li;
+    XfceTrayMessage *message;
+
+    /* seach for the same message in the list of pending messages */
+    for (li = manager->messages; li != NULL; li = li->next)
+    {
+        message = li->data;
+
+        /* check if this is the same message */
+        if (xevent->window == message->window && xevent->data.l[4] == message->id)
+        {
+            /* delete the message from the list */
+            manager->messages = g_slist_delete_link (manager->messages, li);
+
+            /* free the message */
+            xfce_tray_message_free (message);
+
+            break;
+        }
+    }
+}
+


Property changes on: xfce4-panel/trunk/plugins/systray/xfce-tray-manager.c
___________________________________________________________________
Name: keywords
   + Id

Added: xfce4-panel/trunk/plugins/systray/xfce-tray-manager.h
===================================================================
--- xfce4-panel/trunk/plugins/systray/xfce-tray-manager.h	                        (rev 0)
+++ xfce4-panel/trunk/plugins/systray/xfce-tray-manager.h	2007-09-02 11:47:54 UTC (rev 26037)
@@ -0,0 +1,87 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2002      Anders Carlsson <andersca at gnu.org>
+ * Copyright (c) 2003-2004 Benedikt Meurer <benny at xfce.org>
+ * Copyright (c) 2003-2004 Olivier Fourdan <fourdan at xfce.org>
+ * Copyright (c) 2003-2006 Vincent Untz
+ * Copyright (c) 2007      Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __XFCE_TRAY_MANAGER_H__
+#define __XFCE_TRAY_MANAGER_H__
+
+typedef struct _XfceTrayManagerClass XfceTrayManagerClass;
+typedef struct _XfceTrayManager      XfceTrayManager;
+typedef struct _XfceTrayMessage      XfceTrayMessage;
+typedef struct _XfceTrayApplication  XfceTrayApplication;
+
+struct _XfceTrayApplication
+{
+    /* the name of the applications */
+    gchar          *name;
+    
+    /* whether it should be hidden */
+    guint           hidden : 1;  
+};
+
+enum
+{
+    XFCE_TRAY_MANAGER_ERROR_SELECTION_FAILED
+};
+
+#define XFCE_TYPE_TRAY_MANAGER            (xfce_tray_manager_get_type ())
+#define XFCE_TRAY_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_TRAY_MANAGER, XfceTrayManager))
+#define XFCE_TRAY_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_TRAY_MANAGER, XfceTrayManagerClass))
+#define XFCE_IS_TRAY_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_TRAY_MANAGER))
+#define XFCE_IS_TRAY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_TRAY_MANAGER))
+#define XFCE_TRAY_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_TRAY_MANAGER, XfceTrayManagerClass))
+#define XFCE_TRAY_MANAGER_ERROR           (xfce_tray_manager_error_quark())
+
+GType                xfce_tray_manager_get_type               (void) G_GNUC_CONST G_GNUC_INTERNAL;
+
+GQuark               xfce_tray_manager_error_quark            (void) G_GNUC_INTERNAL;
+
+XfceTrayManager     *xfce_tray_manager_new                    (void) G_GNUC_MALLOC G_GNUC_INTERNAL;
+
+gboolean             xfce_tray_manager_check_running          (GdkScreen        *screen) G_GNUC_INTERNAL;
+
+gboolean             xfce_tray_manager_register               (XfceTrayManager  *manager,
+                                                               GdkScreen        *screen,
+                                                               GError          **error) G_GNUC_INTERNAL;
+                                                        
+GtkOrientation       xfce_tray_manager_get_orientation        (XfceTrayManager  *manager) G_GNUC_INTERNAL;
+
+void                 xfce_tray_manager_set_orientation        (XfceTrayManager  *manager,
+                                                               GtkOrientation    orientation) G_GNUC_INTERNAL;
+                                                     
+XfceTrayApplication *xfce_tray_manager_application_add        (XfceTrayManager  *manager,
+                                                               const gchar      *name,
+                                                               gboolean          hidden) G_GNUC_INTERNAL;
+                                                     
+void                 xfce_tray_manager_application_update     (XfceTrayManager  *manager,
+                                                               const gchar      *name,
+                                                               gboolean          hidden) G_GNUC_INTERNAL;
+                                                     
+GSList              *xfce_tray_manager_application_list       (XfceTrayManager  *manager,
+                                                               gboolean          sorted) G_GNUC_MALLOC G_GNUC_INTERNAL;
+                                                     
+const gchar         *xfce_tray_manager_application_get_name   (GtkWidget        *socket) G_GNUC_INTERNAL;
+
+gboolean             xfce_tray_manager_application_get_hidden (GtkWidget        *socket) G_GNUC_INTERNAL;
+                                                     
+
+#endif /* !__XFCE_TRAY_MANAGER_H__ */


Property changes on: xfce4-panel/trunk/plugins/systray/xfce-tray-manager.h
___________________________________________________________________
Name: keywords
   + Id

Added: xfce4-panel/trunk/plugins/systray/xfce-tray-marshal.list
===================================================================
--- xfce4-panel/trunk/plugins/systray/xfce-tray-marshal.list	                        (rev 0)
+++ xfce4-panel/trunk/plugins/systray/xfce-tray-marshal.list	2007-09-02 11:47:54 UTC (rev 26037)
@@ -0,0 +1,2 @@
+VOID:OBJECT,STRING,LONG,LONG
+VOID:OBJECT,LONG


Property changes on: xfce4-panel/trunk/plugins/systray/xfce-tray-marshal.list
___________________________________________________________________
Name: keywords
   + Id

Added: xfce4-panel/trunk/plugins/systray/xfce-tray-plugin.c
===================================================================
--- xfce4-panel/trunk/plugins/systray/xfce-tray-plugin.c	                        (rev 0)
+++ xfce4-panel/trunk/plugins/systray/xfce-tray-plugin.c	2007-09-02 11:47:54 UTC (rev 26037)
@@ -0,0 +1,421 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+ 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define XFCE_TRAY_PLUGIN_LINE_HEIGHT (24 + 2)
+
+#include <gtk/gtk.h>
+#include <libxfce4util/libxfce4util.h>
+#include <libxfce4panel/xfce-panel-plugin.h>
+#include <libxfce4panel/xfce-panel-macros.h>
+
+#include "xfce-tray-manager.h"
+#include "xfce-tray-widget.h"
+#include "xfce-tray-plugin.h"
+#include "xfce-tray-dialogs.h"
+
+
+
+/* prototypes */
+static void            xfce_tray_plugin_message                 (GtkMessageType      type,
+                                                                 GdkScreen          *screen,
+                                                                 const gchar        *message);
+static gboolean        xfce_tray_plugin_check                   (GdkScreen          *screen);
+static GtkArrowType    xfce_tray_plugin_button_position         (XfcePanelPlugin    *panel_plugin);
+static XfceTrayPlugin *xfce_tray_plugin_new                     (XfcePanelPlugin    *panel_plugin);
+static void            xfce_tray_plugin_screen_position_changed (XfceTrayPlugin     *plugin, 
+                                                                 XfceScreenPosition  position);
+static void            xfce_tray_plugin_orientation_changed     (XfceTrayPlugin     *plugin, 
+                                                                 GtkOrientation      orientation);
+static gboolean        xfce_tray_plugin_size_changed            (XfceTrayPlugin     *plugin, 
+                                                                 guint               size);
+static void            xfce_tray_plugin_read                    (XfceTrayPlugin     *plugin);
+static void            xfce_tray_plugin_write                   (XfceTrayPlugin     *plugin);
+static void            xfce_tray_plugin_free                    (XfceTrayPlugin     *plugin);
+static void            xfce_tray_plugin_construct               (XfcePanelPlugin    *panel_plugin);
+
+
+
+/* register the plugin */
+XFCE_PANEL_PLUGIN_REGISTER_INTERNAL_WITH_CHECK (xfce_tray_plugin_construct, xfce_tray_plugin_check);
+
+
+
+static void
+xfce_tray_plugin_message (GtkMessageType  type,
+                          GdkScreen      *screen,
+                          const gchar    *message)
+{
+    GtkWidget *dialog;
+    
+    /* create a dialog */
+    dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, type, GTK_BUTTONS_CLOSE, _("System Tray"));
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s.", message);
+    gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
+    gtk_window_set_screen (GTK_WINDOW (dialog), screen);
+    
+    /* run the dialog */
+    gtk_dialog_run (GTK_DIALOG (dialog));
+    
+    /* destroy */
+    gtk_widget_destroy (dialog);
+}
+
+
+
+static gboolean
+xfce_tray_plugin_check (GdkScreen *screen)
+{
+    gboolean   running;
+    
+    
+    /* check if there is already a tray running */
+    running = xfce_tray_manager_check_running (screen);
+    
+    /* message */
+    if (running)
+        xfce_tray_plugin_message (GTK_MESSAGE_INFO, screen,  
+                                  _("There is already a system tray running on this screen"));
+    
+    return (!running);
+}
+
+
+
+static GtkArrowType
+xfce_tray_plugin_button_position (XfcePanelPlugin *panel_plugin)
+{
+    XfceScreenPosition  position;
+    GdkScreen          *screen;
+    GdkRectangle        geom;
+    gint                mon, x, y;
+    
+    g_return_val_if_fail (GTK_WIDGET_REALIZED (panel_plugin), GTK_ARROW_LEFT);
+    
+    /* get the plugin position */
+    position = xfce_panel_plugin_get_screen_position (panel_plugin);
+    
+    /* get the button position */
+    switch (position)
+    {
+        /*	horizontal west */
+        case XFCE_SCREEN_POSITION_NW_H:
+        case XFCE_SCREEN_POSITION_SW_H:
+            return GTK_ARROW_RIGHT;
+            
+        /* horizontal east */
+        case XFCE_SCREEN_POSITION_N:
+        case XFCE_SCREEN_POSITION_NE_H:
+        case XFCE_SCREEN_POSITION_S:
+        case XFCE_SCREEN_POSITION_SE_H:
+            return GTK_ARROW_LEFT;
+            
+        /* vertical north */
+        case XFCE_SCREEN_POSITION_NW_V:
+        case XFCE_SCREEN_POSITION_NE_V:
+            return GTK_ARROW_DOWN;
+            
+        /* vertical south */
+        case XFCE_SCREEN_POSITION_W:
+        case XFCE_SCREEN_POSITION_SW_V:
+        case XFCE_SCREEN_POSITION_E:
+        case XFCE_SCREEN_POSITION_SE_V:
+            return GTK_ARROW_UP;
+            
+        /* floating */
+        default:
+            /* get the screen information */
+            screen = gtk_widget_get_screen (GTK_WIDGET (panel_plugin));
+            mon = gdk_screen_get_monitor_at_window (screen, GTK_WIDGET (panel_plugin)->window);
+            gdk_screen_get_monitor_geometry (screen, mon, &geom);
+            gdk_window_get_root_origin (GTK_WIDGET (panel_plugin)->window, &x, &y);
+        
+            /* get the position based on the screen position */
+            if (position == XFCE_SCREEN_POSITION_FLOATING_H)
+                return ((x < (geom.x + geom.width / 2)) ? GTK_ARROW_RIGHT : GTK_ARROW_LEFT);
+            else
+                return ((y < (geom.y + geom.height / 2)) ? GTK_ARROW_DOWN : GTK_ARROW_UP);
+    }
+}
+
+
+
+static XfceTrayPlugin *
+xfce_tray_plugin_new (XfcePanelPlugin *panel_plugin)
+{
+    XfceTrayPlugin *plugin;
+    GError         *error = NULL;
+    GtkArrowType    position;
+    GdkScreen      *screen;
+    
+    /* create structure */
+    plugin = panel_slice_new0 (XfceTrayPlugin);
+    
+    /* set some data */
+    plugin->panel_plugin = panel_plugin;
+    plugin->manager = NULL;
+    plugin->show_frame = TRUE;
+    
+    /* get the button position */
+    position = xfce_tray_plugin_button_position (panel_plugin);    
+    
+    /* get the screen of the plugin */
+    screen = gtk_widget_get_screen (GTK_WIDGET (panel_plugin));
+    
+    /* try to create the tray */
+    plugin->tray = xfce_tray_widget_new_for_screen (screen, position, &error);
+    
+    if (G_LIKELY (plugin->tray))
+    {
+        /* get the manager */
+        plugin->manager = xfce_tray_widget_get_manager (XFCE_TRAY_WIDGET (plugin->tray));
+        
+        /* read the plugin settings */
+        xfce_tray_plugin_read (plugin);
+        
+        /* create the frame */
+        plugin->frame = gtk_frame_new (NULL);
+        gtk_frame_set_shadow_type (GTK_FRAME (plugin->frame), plugin->show_frame ? GTK_SHADOW_IN : GTK_SHADOW_NONE);
+        gtk_container_add (GTK_CONTAINER (panel_plugin), plugin->frame);
+        gtk_widget_show (plugin->frame);
+        
+        /* add the tray */
+        gtk_container_add (GTK_CONTAINER (plugin->frame), plugin->tray);
+        gtk_widget_show (plugin->tray);
+    }
+    else
+    {
+        /* show the message */
+        xfce_tray_plugin_message (GTK_MESSAGE_ERROR, screen, error->message);
+        
+        /* cleanup */
+        g_error_free (error);
+    }
+    
+    return plugin;
+}
+
+
+
+static void 
+xfce_tray_plugin_screen_position_changed (XfceTrayPlugin     *plugin, 
+                                          XfceScreenPosition  position)
+{
+    GtkArrowType button_position;
+    
+    /* get the new position */
+    button_position = xfce_tray_plugin_button_position (plugin->panel_plugin);
+    
+    /* set the position */
+    xfce_tray_widget_set_arrow_position (XFCE_TRAY_WIDGET (plugin->tray), button_position);
+    
+    /* set the size again */
+    xfce_tray_plugin_size_changed (plugin, xfce_panel_plugin_get_size (plugin->panel_plugin));
+}
+
+
+
+static void 
+xfce_tray_plugin_orientation_changed (XfceTrayPlugin *plugin, 
+                                      GtkOrientation  orientation)
+{
+    /* invoke the function above */
+    xfce_tray_plugin_screen_position_changed (plugin, XFCE_SCREEN_POSITION_NONE);
+}
+
+
+
+static gboolean 
+xfce_tray_plugin_size_changed (XfceTrayPlugin *plugin, 
+                               guint           size)
+{
+    /* set the frame border size */
+    gtk_container_set_border_width (GTK_CONTAINER (plugin->frame), size > 26 ? 1 : 0);
+    
+    /* extract the frame from the size for the tray */
+    size -= size > 26 ? 6 : 4;
+    
+    /* set the number of lines */
+    xfce_tray_widget_set_lines (XFCE_TRAY_WIDGET (plugin->tray), MAX (1, size / XFCE_TRAY_PLUGIN_LINE_HEIGHT));
+    
+    /* set the size */
+    if (xfce_panel_plugin_get_orientation (plugin->panel_plugin) == GTK_ORIENTATION_HORIZONTAL)
+        gtk_widget_set_size_request (plugin->tray, -1, size);
+    else
+        gtk_widget_set_size_request (plugin->tray, size, -1);
+    
+    /* we handled the size of the plugin */
+    return TRUE;
+}
+
+
+
+static void
+xfce_tray_plugin_read (XfceTrayPlugin *plugin)
+{
+    gchar     *file;
+    gchar    **applications;
+    gboolean   hidden;
+    XfceRc    *rc;
+    guint      i;
+    
+    /* get rc file name */
+    file = xfce_panel_plugin_lookup_rc_file (plugin->panel_plugin);
+    
+    if (G_LIKELY (file))
+    {
+        /* open the file, readonly */
+        rc = xfce_rc_simple_open (file, TRUE);
+        
+        /* cleanup */
+        g_free (file);
+        
+        if (G_LIKELY (rc))
+        {
+            /* save global plugin settings */
+            xfce_rc_set_group (rc, "Global");
+            
+            /* frame setting */
+            plugin->show_frame = xfce_rc_read_bool_entry (rc, "ShowFrame", TRUE);
+            
+            if (G_LIKELY (plugin->manager))
+            {
+                /* list of known applications */
+                applications = xfce_rc_get_entries (rc, "Applications");
+                
+                if (G_LIKELY (applications))
+                {                
+                    /* set the group */
+                    xfce_rc_set_group (rc, "Applications");
+                    
+                    /* read their visibility */
+                    for (i = 0; applications[i] != NULL; i++)
+                    {
+                        /* whether the application is hidden */
+                        hidden = xfce_rc_read_bool_entry (rc, applications[i], FALSE);
+                        
+                        /* add the application name */
+                        xfce_tray_manager_application_add (plugin->manager, applications[i], hidden);
+                    }
+                    
+                    /* cleanup */
+                    g_strfreev (applications);
+                }
+            }
+            
+            /* close the rc file */
+            xfce_rc_close (rc);
+        }        
+    }
+}
+
+
+
+static void
+xfce_tray_plugin_write (XfceTrayPlugin *plugin)
+{
+    gchar               *file;
+    GSList              *applications, *li;
+    XfceRc              *rc;
+    XfceTrayApplication *application;
+    
+    /* get rc file name, create it if needed */
+    file = xfce_panel_plugin_save_location (plugin->panel_plugin, TRUE);
+    
+    if (G_LIKELY (file))
+    {
+        /* open the file, writable */
+        rc = xfce_rc_simple_open (file, FALSE);
+    
+        /* cleanup */
+        g_free (file);
+        
+        if (G_LIKELY (rc))
+        {
+            /* save global plugin settings */
+            xfce_rc_set_group (rc, "Global");
+            
+            /* write setting */
+            xfce_rc_write_bool_entry (rc, "ShowFrame", plugin->show_frame);
+            
+            if (G_LIKELY (plugin->manager))
+            {
+                /* save the list of known applications and their visibility */
+                xfce_rc_set_group (rc, "Applications");
+                
+                /* get the list of known applications */
+                applications = xfce_tray_manager_application_list (plugin->manager, FALSE);
+                
+                /* save their state */
+                for (li = applications; li != NULL; li = li->next)
+                {
+                    application = li->data;
+                    
+                    if (G_LIKELY (application->name))
+                        xfce_rc_write_bool_entry (rc, application->name, application->hidden);
+                }
+            }
+            
+            /* close the rc file */
+            xfce_rc_close (rc);
+        }
+    }
+}
+
+
+
+static void 
+xfce_tray_plugin_free (XfceTrayPlugin *plugin)
+{
+    /* free slice */
+    panel_slice_free (XfceTrayPlugin, plugin);
+}
+
+
+
+static void 
+xfce_tray_plugin_construct (XfcePanelPlugin *panel_plugin)
+{
+    XfceTrayPlugin *plugin;
+    
+    /* create the tray panel plugin */
+    plugin = xfce_tray_plugin_new (panel_plugin);
+    
+    /* set the action widgets and show configure */
+    xfce_panel_plugin_add_action_widget (panel_plugin, plugin->frame);
+    xfce_panel_plugin_add_action_widget (panel_plugin, plugin->tray);
+    xfce_panel_plugin_menu_show_configure (panel_plugin);
+    
+    /* connect signals */
+    g_signal_connect_swapped (G_OBJECT (panel_plugin), "screen-position-changed", 
+                              G_CALLBACK (xfce_tray_plugin_screen_position_changed), plugin);
+    g_signal_connect_swapped (G_OBJECT (panel_plugin), "orientation-changed",  
+                              G_CALLBACK (xfce_tray_plugin_orientation_changed), plugin);
+    g_signal_connect_swapped (G_OBJECT (panel_plugin), "size-changed",  
+                              G_CALLBACK (xfce_tray_plugin_size_changed), plugin);
+    g_signal_connect_swapped (G_OBJECT (panel_plugin), "save",  
+                              G_CALLBACK (xfce_tray_plugin_write), plugin);
+    g_signal_connect_swapped (G_OBJECT (panel_plugin), "free-data",  
+                              G_CALLBACK (xfce_tray_plugin_free), plugin);
+    g_signal_connect_swapped (G_OBJECT (panel_plugin), "configure-plugin",  
+                              G_CALLBACK (xfce_tray_dialogs_configure), plugin);
+}


Property changes on: xfce4-panel/trunk/plugins/systray/xfce-tray-plugin.c
___________________________________________________________________
Name: keywords
   + Id

Added: xfce4-panel/trunk/plugins/systray/xfce-tray-plugin.h
===================================================================
--- xfce4-panel/trunk/plugins/systray/xfce-tray-plugin.h	                        (rev 0)
+++ xfce4-panel/trunk/plugins/systray/xfce-tray-plugin.h	2007-09-02 11:47:54 UTC (rev 26037)
@@ -0,0 +1,42 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+ 
+#ifndef __XFCE_TRAY_PLUGIN_H__
+#define __XFCE_TRAY_PLUGIN_H__
+
+typedef struct _XfceTrayPlugin XfceTrayPlugin;
+
+struct _XfceTrayPlugin
+{
+    /* panel plugin */
+    XfcePanelPlugin *panel_plugin;
+    
+    /* tray manager */
+    XfceTrayManager *manager;
+    
+    /* widgets */
+    GtkWidget       *frame;
+    GtkWidget       *tray;
+    
+    /* properties */
+    guint            show_frame : 1;
+};
+
+
+#endif /* !__XFCE_TRAY_PLUGIN_H__ */


Property changes on: xfce4-panel/trunk/plugins/systray/xfce-tray-plugin.h
___________________________________________________________________
Name: keywords
   + Id

Added: xfce4-panel/trunk/plugins/systray/xfce-tray-widget.c
===================================================================
--- xfce4-panel/trunk/plugins/systray/xfce-tray-widget.c	                        (rev 0)
+++ xfce4-panel/trunk/plugins/systray/xfce-tray-widget.c	2007-09-02 11:47:54 UTC (rev 26037)
@@ -0,0 +1,655 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libxfce4panel/xfce-arrow-button.h>
+#include <libxfce4panel/xfce-panel-macros.h>
+
+#include "xfce-tray-manager.h"
+#include "xfce-tray-widget.h"
+
+#define XFCE_TRAY_WIDGET_BUTTON_SIZE          (16)
+#define XFCE_TRAY_WIDGET_SPACING              (1)
+#define XFCE_TRAY_WIDGET_OFFSCREEN            (-9999)
+#define XFCE_TRAY_WIDGET_IS_HORIZONTAL(obj)   ((obj)->arrow_position == GTK_ARROW_LEFT || (obj)->arrow_position == GTK_ARROW_RIGHT)
+#define XFCE_TRAY_WIDGET_IS_SOUTH_EAST(obj)   ((obj)->arrow_position == GTK_ARROW_RIGHT || (obj)->arrow_position == GTK_ARROW_DOWN)
+#define XFCE_TRAY_WIDGET_GET_ORIENTATION(obj) (XFCE_TRAY_WIDGET_IS_HORIZONTAL (obj) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL)
+#define XFCE_TRAY_WIDGET_SWAP_INT(x,y)        G_STMT_START{ gint __v = x; x = y; y = __v; }G_STMT_END
+
+
+
+/* prototypes */
+static void xfce_tray_widget_class_init       (XfceTrayWidgetClass *klass);
+static void xfce_tray_widget_init             (XfceTrayWidget      *tray);
+static void xfce_tray_widget_finalize         (GObject             *object);
+static void xfce_tray_widget_size_request     (GtkWidget           *widget, 
+                                               GtkRequisition      *requisition);
+static void xfce_tray_widget_size_allocate    (GtkWidget           *widget, 
+                                               GtkAllocation       *allocation);
+static void xfce_tray_widget_style_set        (GtkWidget           *widget,
+                                               GtkStyle            *previous_style);
+static void xfce_tray_widget_map              (GtkWidget           *widget);
+static gint xfce_tray_widget_expose_event     (GtkWidget           *widget, 
+                                               GdkEventExpose      *event);
+static void xfce_tray_widget_button_set_arrow (XfceTrayWidget      *tray);
+static void xfce_tray_widget_button_clicked   (GtkToggleButton     *button, 
+                                               XfceTrayWidget      *tray);
+static gint xfce_tray_widget_compare_function (gconstpointer        a, 
+                                               gconstpointer        b);
+static void xfce_tray_widget_icon_added       (XfceTrayManager     *manager, 
+                                               GtkWidget           *icon,
+                                               XfceTrayWidget      *tray);
+static void xfce_tray_widget_icon_removed     (XfceTrayManager     *manager, 
+                                               GtkWidget           *icon, 
+                                               XfceTrayWidget      *tray);
+
+
+
+struct _XfceTrayWidgetClass
+{
+    GtkContainerClass __parent__;
+};
+
+struct _XfceTrayWidget
+{
+    GtkContainer __parent__;
+    
+    /* tray manager of this tray */
+    XfceTrayManager  *manager;
+    
+    /* arrow toggle button */
+    GtkWidget        *button;
+    
+    /* all the icons packed in this box */
+    GSList           *childeren;
+    
+    /* counters for the icons in the list */
+    guint             n_childeren;
+    guint             n_hidden_childeren;
+    
+    /* whether hidden icons are visible */
+    guint             all_visible :    1;
+    
+    /* reqested icon size */
+    guint             req_child_size;
+    
+    /* properties */
+    guint             lines;
+    GtkArrowType      arrow_position;
+};
+
+
+
+static GObjectClass *xfce_tray_widget_parent_class;
+
+
+
+GType
+xfce_tray_widget_get_type (void)
+{
+    static GType type = G_TYPE_INVALID;
+
+    if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+        type = g_type_register_static_simple (GTK_TYPE_CONTAINER,
+                                              I_("XfceTrayWidget"),
+                                              sizeof (XfceTrayWidgetClass),
+                                              (GClassInitFunc) xfce_tray_widget_class_init,
+                                              sizeof (XfceTrayWidget),
+                                              (GInstanceInitFunc) xfce_tray_widget_init,
+                                              0);
+    }
+
+    return type;
+}
+
+
+
+static void
+xfce_tray_widget_class_init (XfceTrayWidgetClass *klass)
+{
+    GObjectClass      *gobject_class;
+    GtkWidgetClass    *gtkwidget_class;
+    GtkContainerClass *gtkcontainer_class;
+
+    /* determine the parent type class */
+    xfce_tray_widget_parent_class = g_type_class_peek_parent (klass);
+
+    gobject_class = G_OBJECT_CLASS (klass);
+    gobject_class->finalize = xfce_tray_widget_finalize;
+    
+    gtkwidget_class = GTK_WIDGET_CLASS (klass);
+    gtkwidget_class->size_request = xfce_tray_widget_size_request;
+    gtkwidget_class->size_allocate = xfce_tray_widget_size_allocate;
+    gtkwidget_class->style_set = xfce_tray_widget_style_set;
+    gtkwidget_class->expose_event = xfce_tray_widget_expose_event;
+    gtkwidget_class->map = xfce_tray_widget_map;
+    
+    gtkcontainer_class = GTK_CONTAINER_CLASS (klass);
+    gtkcontainer_class->add = NULL;
+    gtkcontainer_class->remove = NULL;
+}
+
+
+
+static void
+xfce_tray_widget_init (XfceTrayWidget *tray)
+{
+    GTK_WIDGET_SET_FLAGS (tray, GTK_NO_WINDOW);
+    
+    /* initialize */
+    tray->childeren = NULL;
+    tray->button = NULL;
+    tray->manager = NULL;
+    
+    tray->n_childeren = 0;
+    tray->n_hidden_childeren = 0;
+    
+    tray->all_visible = FALSE;
+    tray->req_child_size = 1;
+    
+    tray->lines = 1;
+    tray->arrow_position = GTK_ARROW_LEFT; 
+}
+
+
+
+static void
+xfce_tray_widget_finalize (GObject *object)
+{
+    XfceTrayWidget *tray = XFCE_TRAY_WIDGET (object);
+    
+    /* free the child list */
+    g_slist_free (tray->childeren);
+    
+    /* release the manager */
+    g_object_unref (G_OBJECT (tray->manager));
+    
+    G_OBJECT_CLASS (xfce_tray_widget_parent_class)->finalize (object);
+}
+
+
+
+static void
+xfce_tray_widget_size_request (GtkWidget      *widget,
+                               GtkRequisition *requisition)
+{
+    XfceTrayWidget *tray = XFCE_TRAY_WIDGET (widget);
+    gint            width, height, size;
+    gint            req_child_size, n_childeren;
+    gint            columns;
+    
+    /* get the requested sizes */
+    gtk_widget_get_size_request (widget, &width, &height);
+    
+    /* get the size we can not change */
+    size = (XFCE_TRAY_WIDGET_IS_HORIZONTAL (tray) ? height : width);
+    
+    /* calculate the requested child size */
+    req_child_size = (size - (XFCE_TRAY_WIDGET_SPACING * (tray->lines - 1))) / tray->lines;
+    
+    /* save the requested child size */
+    tray->req_child_size = req_child_size;
+    
+    /* number of icons in the tray */
+    n_childeren = tray->n_childeren;
+    if (!tray->all_visible)
+        n_childeren -= tray->n_hidden_childeren;
+    
+    /* number of columns in the tray */
+    columns = n_childeren / tray->lines;
+    if (n_childeren > (columns * tray->lines))
+        columns++;
+        
+    /* calculate the tray size we can set */
+    size = (req_child_size * columns) + (XFCE_TRAY_WIDGET_SPACING * MAX (columns - 1, 0));
+    
+    /* add the hidden button when visible */
+    if (tray->n_hidden_childeren > 0)
+    {
+        size += XFCE_TRAY_WIDGET_BUTTON_SIZE;
+        
+        /* space between the button and the icons */
+        if (columns > 0)
+            size += XFCE_TRAY_WIDGET_SPACING;
+    }
+    
+    /* set the other size */
+    if (XFCE_TRAY_WIDGET_IS_HORIZONTAL (tray))
+        width = size;
+    else
+        height = size;
+        
+    /* set your request width and height */
+    requisition->width = width;
+    requisition->height = height;
+}
+
+
+
+static void
+xfce_tray_widget_size_allocate (GtkWidget     *widget,
+                                GtkAllocation *allocation)
+{
+    XfceTrayWidget *tray = XFCE_TRAY_WIDGET (widget);
+    GSList         *li;
+    GtkWidget      *child;
+    GtkAllocation   child_allocation;
+    gint            n = 0, i = 0;
+    gint            x_offset = 0;
+    
+    /* set the widget allocation */
+    widget->allocation = *allocation;
+    
+    /* allocation for the arrow button */
+    if (tray->n_hidden_childeren > 0)
+    {
+        /* set the coordinates and default size */
+        child_allocation.x = allocation->x;
+        child_allocation.y = allocation->y;
+        child_allocation.width = child_allocation.height = XFCE_TRAY_WIDGET_BUTTON_SIZE;
+        
+        /* set the offset for the icons */
+        x_offset = XFCE_TRAY_WIDGET_BUTTON_SIZE + XFCE_TRAY_WIDGET_SPACING;
+        
+        /* position the button on the other side of the tray */
+        if (XFCE_TRAY_WIDGET_IS_SOUTH_EAST (tray))
+        {
+            /* set the coordinates to the other side of the tray */
+            if (XFCE_TRAY_WIDGET_IS_HORIZONTAL (tray))
+                child_allocation.x += allocation->width - XFCE_TRAY_WIDGET_BUTTON_SIZE;
+            else
+                child_allocation.y += allocation->height - XFCE_TRAY_WIDGET_BUTTON_SIZE;
+        }
+        
+        /* set the width or height to the allocated size */
+        if (XFCE_TRAY_WIDGET_IS_HORIZONTAL (tray))
+            child_allocation.height = allocation->height;
+        else
+            child_allocation.width = allocation->width;
+        
+        /* position the arrow button */
+        gtk_widget_size_allocate (tray->button, &child_allocation);
+    }
+    
+    /* position all the icons */
+    for (li = tray->childeren; li != NULL; li = li->next, i++)
+    {
+        /* get the child */
+        child = li->data;
+        
+        /* handle hidden icons */
+        if (!tray->all_visible && i < tray->n_hidden_childeren)
+        {
+            /* put the widget offscreen */
+            child_allocation.x = child_allocation.y = XFCE_TRAY_WIDGET_OFFSCREEN;
+        }
+        else
+        {
+            /* position of the child on the tray */
+            child_allocation.x = (tray->req_child_size + XFCE_TRAY_WIDGET_SPACING) * (n / tray->lines) + x_offset;
+            child_allocation.y = (tray->req_child_size + XFCE_TRAY_WIDGET_SPACING) * (n % tray->lines);
+            
+            /* increase counter */
+            n++;
+            
+            /* swap coordinates on a vertical panel */
+            if (!XFCE_TRAY_WIDGET_IS_HORIZONTAL (tray))
+                XFCE_TRAY_WIDGET_SWAP_INT (child_allocation.x, child_allocation.y);
+            
+            /* invert the icon order if the arrow button position is right or down */
+            if (tray->arrow_position == GTK_ARROW_RIGHT)
+                child_allocation.x = allocation->width - child_allocation.x - tray->req_child_size;
+            else if (tray->arrow_position == GTK_ARROW_DOWN)
+                child_allocation.y = allocation->height - child_allocation.y - tray->req_child_size;
+            
+            /* add the tray coordinates */
+            child_allocation.x += allocation->x + XFCE_TRAY_WIDGET_SPACING;
+            child_allocation.y += allocation->y + XFCE_TRAY_WIDGET_SPACING;
+        }        
+        
+        /* set the child width and height */
+        child_allocation.width = child_allocation.height = tray->req_child_size - 2 * XFCE_TRAY_WIDGET_SPACING;
+      
+        /* send the child allocation */
+        gtk_widget_size_allocate (child, &child_allocation);
+    }
+}
+
+
+
+static gint
+xfce_tray_widget_expose_event (GtkWidget      *widget,
+                               GdkEventExpose *event)
+{
+    XfceTrayWidget *tray = XFCE_TRAY_WIDGET (widget);
+    
+    /* expose the button, because it doesn't have its own window */
+    gtk_container_propagate_expose (GTK_CONTAINER (widget), tray->button, event);
+    
+    return FALSE;
+}
+
+
+
+static void
+xfce_tray_widget_style_set (GtkWidget *widget,
+                            GtkStyle  *previous_style)
+{
+    XfceTrayWidget *tray = XFCE_TRAY_WIDGET (widget);
+    GSList         *li;
+    
+    /* set the button style */
+    if (tray->button)
+        gtk_widget_set_style (tray->button, widget->style);
+        
+    /* send the style to all the childeren */
+    for (li = tray->childeren; li != NULL; li = li->next)
+        gtk_widget_set_style (GTK_WIDGET (li->data), widget->style);
+        
+    /* invoke the parent */
+    GTK_WIDGET_CLASS (xfce_tray_widget_parent_class)->style_set (widget, previous_style);
+}
+
+
+
+static void
+xfce_tray_widget_map (GtkWidget *widget)
+{
+    XfceTrayWidget *tray = XFCE_TRAY_WIDGET (widget);
+    
+    /* we've been mapped */
+    GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+    
+    /* create the arrow button (needs a mapped tray before the parent is set) */
+    tray->button = xfce_arrow_button_new (tray->arrow_position);
+    GTK_WIDGET_UNSET_FLAGS (tray->button, GTK_CAN_DEFAULT | GTK_CAN_FOCUS);
+    gtk_button_set_focus_on_click (GTK_BUTTON (tray->button), FALSE);
+    g_signal_connect (G_OBJECT (tray->button), "clicked", G_CALLBACK (xfce_tray_widget_button_clicked), tray);
+    gtk_widget_set_parent (tray->button, widget);
+    gtk_widget_show (tray->button);
+}
+
+
+
+static void
+xfce_tray_widget_button_set_arrow (XfceTrayWidget *tray)
+{
+    GtkArrowType arrow_type;
+    
+    /* get the origional arrow type */
+    arrow_type = tray->arrow_position;
+    
+    /* invert the arrow direction when the button is toggled */
+    if (tray->all_visible)
+    {
+        if (XFCE_TRAY_WIDGET_IS_HORIZONTAL (tray))
+            arrow_type = (arrow_type == GTK_ARROW_LEFT ? GTK_ARROW_RIGHT : GTK_ARROW_LEFT);
+        else
+            arrow_type = (arrow_type == GTK_ARROW_UP ? GTK_ARROW_DOWN : GTK_ARROW_UP);
+    }
+    
+    /* set the arrow type */
+    xfce_arrow_button_set_arrow_type (XFCE_ARROW_BUTTON (tray->button), arrow_type);
+}
+
+
+
+static void 
+xfce_tray_widget_button_clicked (GtkToggleButton *button, 
+                                 XfceTrayWidget        *tray)
+{
+    /* set the new visible state */
+    tray->all_visible = gtk_toggle_button_get_active (button);
+        
+    /* set the button arrow */
+    xfce_tray_widget_button_set_arrow (tray);
+    
+    /* update the tray */
+    gtk_widget_queue_resize (GTK_WIDGET (tray));
+}
+
+
+
+static gint
+xfce_tray_widget_compare_function (gconstpointer a,
+                                   gconstpointer b)
+{
+    gboolean     a_hidden, b_hidden;
+    const gchar *a_wmname, *b_wmname;
+    
+    /* get hidden state */
+    a_hidden = xfce_tray_manager_application_get_hidden (GTK_WIDGET (a));
+    b_hidden = xfce_tray_manager_application_get_hidden (GTK_WIDGET (b));
+    
+    /* sort hidden icons before visible ones */
+    if (a_hidden != b_hidden)
+        return (a_hidden ? -1 : 1);
+    
+    /* get the window names */
+    a_wmname = xfce_tray_manager_application_get_name (GTK_WIDGET (a));
+    b_wmname = xfce_tray_manager_application_get_name (GTK_WIDGET (b));
+    
+    /* return when one of them has no name */
+    if (G_UNLIKELY (!a_wmname || !b_wmname))
+        return (a_wmname == b_wmname ? 0 : (!a_wmname ? -1 : 1));
+        
+    return strcmp (a_wmname, b_wmname);
+}
+
+
+
+static void
+xfce_tray_widget_icon_added (XfceTrayManager *manager,
+                             GtkWidget       *icon,
+                             XfceTrayWidget  *tray)
+{
+    gboolean hidden;
+    
+    g_return_if_fail (XFCE_IS_TRAY_MANAGER (manager));
+    g_return_if_fail (XFCE_IS_TRAY_WIDGET (tray));
+    g_return_if_fail (GTK_IS_WIDGET (icon));
+    
+    /* add the icon to the list */
+    tray->childeren = g_slist_insert_sorted (tray->childeren, icon, xfce_tray_widget_compare_function);
+    
+    /* increase counter */
+    tray->n_childeren++;
+    
+    /* whether this icon could be hidden */
+    hidden = xfce_tray_manager_application_get_hidden (icon);
+    
+    /* increase hidden counter */
+    if (hidden)
+        tray->n_hidden_childeren++;
+        
+    /* show the icon */
+    gtk_widget_show (icon);
+    
+    /* set the parent window */
+    gtk_widget_set_parent (icon, GTK_WIDGET (tray));
+}
+
+
+
+static void
+xfce_tray_widget_icon_removed (XfceTrayManager *manager,
+                               GtkWidget       *icon,
+                               XfceTrayWidget  *tray)
+{
+    g_return_if_fail (XFCE_IS_TRAY_MANAGER (manager));
+    g_return_if_fail (XFCE_IS_TRAY_WIDGET (tray));
+    g_return_if_fail (GTK_IS_WIDGET (icon));
+    
+    /* decrease counter */
+    tray->n_childeren--;
+    
+    /* remove the child from the list */
+    tray->childeren = g_slist_remove (tray->childeren, icon);
+    
+    /* handle hidden icons */
+    if (xfce_tray_manager_application_get_hidden (icon))
+    {
+        /* decrease hidden counter */
+        tray->n_hidden_childeren--;
+        
+        /* collapse the hidden button */
+        if (tray->n_hidden_childeren == 0)
+            gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tray->button), FALSE);
+    }
+    
+    /* update the tray */
+    gtk_widget_queue_resize (GTK_WIDGET (tray));
+}
+
+
+
+GtkWidget *
+xfce_tray_widget_new_for_screen (GdkScreen     *screen,
+                                 GtkArrowType   arrow_position,
+                                 GError       **error)
+{
+    XfceTrayWidget  *tray = NULL;
+    XfceTrayManager *manager;
+    
+    g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+    g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+    
+    /* new tray manager */
+    manager = xfce_tray_manager_new ();
+        
+    /* register the manager for this screen */
+    if (G_LIKELY (xfce_tray_manager_register (manager, screen, error) == TRUE))
+    {
+        /* create a tray */
+        tray = g_object_new (XFCE_TYPE_TRAY_WIDGET, NULL);
+        
+        /* set the manager */
+        tray->manager = manager;
+        
+        /* set the orientations */
+        tray->arrow_position = arrow_position;
+        xfce_tray_manager_set_orientation (manager, XFCE_TRAY_WIDGET_GET_ORIENTATION (tray));
+        
+        /* manager signals */
+        g_signal_connect (G_OBJECT (manager), "tray-icon-added", G_CALLBACK (xfce_tray_widget_icon_added), tray);
+        g_signal_connect (G_OBJECT (manager), "tray-icon-removed", G_CALLBACK (xfce_tray_widget_icon_removed), tray);
+        //g_signal_connect (G_OBJECT (manager), "tray-message-sent", G_CALLBACK (xfce_tray_widget_message_sent), tray);
+        //g_signal_connect (G_OBJECT (manager), "tray-message-cancelled", G_CALLBACK (xfce_tray_widget_message_cancelled), tray);
+        //g_signal_connect (G_OBJECT (manager), "tray-lost-selection", G_CALLBACK (xfce_tray_widget_lost_selection), tray);
+    }
+    else
+    {
+        /* release the manager */
+        g_object_unref (G_OBJECT (manager));
+    }
+    
+    return GTK_WIDGET (tray);
+}
+
+
+
+void
+xfce_tray_widget_sort (XfceTrayWidget *tray)
+{
+    GSList *li;
+    guint   n_hidden_childeren = 0;
+    
+    /* sort the list */
+    tray->childeren = g_slist_sort (tray->childeren, xfce_tray_widget_compare_function);
+    
+    /* count the number of hidden items again */
+    for (li = tray->childeren; li != NULL; li = li->next)
+    {
+        /* increase counter or break (hidden items are in the beginning of the list) */
+        if (xfce_tray_manager_application_get_hidden (GTK_WIDGET (li->data)))
+            n_hidden_childeren++;
+        else
+            break;
+    }
+    
+    /* update if changed */
+    if (tray->n_hidden_childeren != n_hidden_childeren)
+    {
+        /* collapse the button if there are no hidden childeren */
+        if (n_hidden_childeren == 0)
+            gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tray->button), FALSE);
+        
+        /* set new value */
+        tray->n_hidden_childeren = n_hidden_childeren;
+        
+        /* update the tray */
+        gtk_widget_queue_resize (GTK_WIDGET (tray));        
+    }
+}
+
+
+
+XfceTrayManager *
+xfce_tray_widget_get_manager (XfceTrayWidget *tray)
+{
+    g_return_val_if_fail (XFCE_IS_TRAY_WIDGET (tray), NULL);
+    
+    return tray->manager;
+}
+
+
+
+void 
+xfce_tray_widget_set_arrow_position (XfceTrayWidget     *tray, 
+                                     GtkArrowType  arrow_position)
+{
+    g_return_if_fail (XFCE_IS_TRAY_WIDGET (tray));
+    
+    if (G_LIKELY (tray->arrow_position != arrow_position))
+    {
+        /* set property */
+        tray->arrow_position = arrow_position;
+        
+        /* set orientation of the manager */
+        xfce_tray_manager_set_orientation (tray->manager, XFCE_TRAY_WIDGET_GET_ORIENTATION (tray));
+        
+        /* set the arrow on the button */
+        xfce_tray_widget_button_set_arrow (tray);
+        
+        /* update the tray */
+        gtk_widget_queue_resize (GTK_WIDGET (tray));
+    }
+}
+
+
+                                             
+void         
+xfce_tray_widget_set_lines (XfceTrayWidget *tray,
+                            guint           lines)
+{
+    g_return_if_fail (XFCE_IS_TRAY_WIDGET (tray));
+    g_return_if_fail (lines >= 1);
+    
+    /* set property */
+    tray->lines = lines;
+}


Property changes on: xfce4-panel/trunk/plugins/systray/xfce-tray-widget.c
___________________________________________________________________
Name: keywords
   + Id

Added: xfce4-panel/trunk/plugins/systray/xfce-tray-widget.h
===================================================================
--- xfce4-panel/trunk/plugins/systray/xfce-tray-widget.h	                        (rev 0)
+++ xfce4-panel/trunk/plugins/systray/xfce-tray-widget.h	2007-09-02 11:47:54 UTC (rev 26037)
@@ -0,0 +1,49 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __XFCE_TRAY_WIDGET_H__
+#define __XFCE_TRAY_WIDGET_H__
+
+typedef struct _XfceTrayWidgetClass XfceTrayWidgetClass;
+typedef struct _XfceTrayWidget      XfceTrayWidget;
+
+#define XFCE_TYPE_TRAY_WIDGET            (xfce_tray_widget_get_type ())
+#define XFCE_TRAY_WIDGET(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_TRAY_WIDGET, XfceTrayWidget))
+#define XFCE_TRAY_WIDGET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_TRAY_WIDGET, XfceTrayWidgetClass))
+#define XFCE_IS_TRAY_WIDGET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_TRAY_WIDGET))
+#define XFCE_IS_TRAY_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_TRAY_WIDGET))
+#define XFCE_TRAY_WIDGET_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_TRAY_WIDGET, XfceTrayWidgetClass))
+
+GType            xfce_tray_widget_get_type           (void) G_GNUC_CONST G_GNUC_INTERNAL;
+
+GtkWidget       *xfce_tray_widget_new_for_screen     (GdkScreen       *screen, 
+                                                      GtkArrowType     arrow_position,
+                                                      GError         **error) G_GNUC_MALLOC G_GNUC_INTERNAL;
+                                                      
+void             xfce_tray_widget_sort               (XfceTrayWidget   *tray) G_GNUC_INTERNAL;
+                                                
+XfceTrayManager *xfce_tray_widget_get_manager        (XfceTrayWidget   *tray) G_GNUC_INTERNAL;
+
+void             xfce_tray_widget_set_arrow_position (XfceTrayWidget   *tray, 
+                                                      GtkArrowType     arrow_position) G_GNUC_INTERNAL;
+                                            
+void             xfce_tray_widget_set_lines          (XfceTrayWidget   *tray,
+                                                      guint            lines) G_GNUC_INTERNAL;
+
+#endif /* !__XFCE_TRAY_WIDGET_H__ */


Property changes on: xfce4-panel/trunk/plugins/systray/xfce-tray-widget.h
___________________________________________________________________
Name: keywords
   + Id

Modified: xfce4-panel/trunk/po/POTFILES.in
===================================================================
--- xfce4-panel/trunk/po/POTFILES.in	2007-09-01 21:36:32 UTC (rev 26036)
+++ xfce4-panel/trunk/po/POTFILES.in	2007-09-02 11:47:54 UTC (rev 26037)
@@ -33,7 +33,10 @@
 plugins/pager/pager.c
 plugins/separator/separator.c
 plugins/showdesktop/showdesktop.c
-plugins/systray/systray.c
+plugins/systray/xfce-tray-plugin.c
+plugins/systray/xfce-tray-dialogs.c
+plugins/systray/xfce-tray-widget.c
+plugins/systray/xfce-tray-manager.c
 plugins/tasklist/tasklist.c
 plugins/tasklist/tasklist-dialogs.c
 plugins/windowlist/windowlist.c

Modified: xfce4-panel/trunk/po/ar.po
===================================================================
--- xfce4-panel/trunk/po/ar.po	2007-09-01 21:36:32 UTC (rev 26036)
+++ xfce4-panel/trunk/po/ar.po	2007-09-02 11:47:54 UTC (rev 26037)
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: xfce4-panel\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-07-06 21:54+0200\n"
+"POT-Creation-Date: 2007-09-02 13:40+0200\n"
 "PO-Revision-Date: 2007-02-02 10:45+0200\n"
 "Last-Translator: Mohamed Magdy <alnokta at yahoo.com>\n"
 "Language-Team: Arabeyes Translation & Documentation <admin at arabeyes.org>\n"
@@ -55,40 +55,40 @@
 msgid "An item was unexpectedly removed: \"%s\"."
 msgstr "لقد ازيل عنصر بصورة غير متوقعة: \"%s\"."
 
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:594
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:602
 #, c-format
 msgid "Remove \"%s\"?"
 msgstr "ازل \"%s\"?"
 
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:608
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:616
 msgid ""
 "The item will be removed from the panel and its configuration will be lost."
 msgstr ""
 
 #. configure, hide by default
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:823
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:825
 msgid "Properties"
 msgstr "خصائص"
 
 #. about item, hide by default
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:840
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:842
 msgid "About"
 msgstr "حول"
 
 #. move
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:852
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:854
 msgid "Move"
 msgstr "انقل"
 
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:871
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:873
 msgid "Remove"
 msgstr "ازل"
 
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:888
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:890
 msgid "Add New Item"
 msgstr "أضف شيء جديد"
 
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:899 ../panel/panel.c:696
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:901 ../panel/panel.c:696
 #: ../mcs-plugin/xfce4-panel-manager.desktop.in.h:1
 msgid "Customize Panel"
 msgstr "خصص الشريط"
@@ -303,8 +303,10 @@
 msgstr "محرر"
 
 #. appearance settings
+#. appearance
 #. Button Layout
-#: ../panel/panel-dialogs.c:1427 ../plugins/clock/clock-dialog.c:481
+#: ../panel/panel-dialogs.c:1427 ../plugins/clock/clock-dialog.c:480
+#: ../plugins/systray/xfce-tray-dialogs.c:238
 #: ../plugins/tasklist/tasklist-dialogs.c:183
 #: ../plugins/windowlist/windowlist-dialog.c:190
 msgid "Appearance"
@@ -372,62 +374,64 @@
 msgid "Quit + Lock screen"
 msgstr "/_إغلاق الشاشة"
 
-#: ../plugins/clock/clock-dialog.c:346
+#: ../plugins/clock/clock-dialog.c:345
 msgid "Custom"
 msgstr ""
 
-#: ../plugins/clock/clock-dialog.c:400
+#: ../plugins/clock/clock-dialog.c:399
 #, fuzzy
 msgid "Display _seconds"
 msgstr "اعرض الثواني"
 
-#: ../plugins/clock/clock-dialog.c:409
+#: ../plugins/clock/clock-dialog.c:408
 msgid "Use 24-_hour clock"
 msgstr "استخدم ساعة ال 24"
 
-#: ../plugins/clock/clock-dialog.c:415
+#: ../plugins/clock/clock-dialog.c:414
 #, fuzzy
 msgid "Sho_w AM/PM"
 msgstr "اظهر صباحاً/مساء"
 
-#: ../plugins/clock/clock-dialog.c:424
+#: ../plugins/clock/clock-dialog.c:423
 msgid "True _binary clock"
 msgstr ""
 
 #. create dialog
-#: ../plugins/clock/clock-dialog.c:466
+#: ../plugins/clock/clock-dialog.c:465
 #: ../plugins/clock/clock.desktop.in.in.h:1
 msgid "Clock"
 msgstr "الساعة"
 
-#: ../plugins/clock/clock-dialog.c:491
+#: ../plugins/clock/clock-dialog.c:490
 msgid "Analog"
 msgstr "عقارب"
 
-#: ../plugins/clock/clock-dialog.c:492
+#: ../plugins/clock/clock-dialog.c:491
 msgid "Binary"
 msgstr ""
 
-#: ../plugins/clock/clock-dialog.c:493
+#: ../plugins/clock/clock-dialog.c:492
 msgid "Digital"
 msgstr "رقمية"
 
-#: ../plugins/clock/clock-dialog.c:494
+#: ../plugins/clock/clock-dialog.c:493
 #, fuzzy
 msgid "LCD"
 msgstr "لمبة"
 
-#: ../plugins/clock/clock-dialog.c:499 ../plugins/systray/systray.c:402
+#. show frame
+#: ../plugins/clock/clock-dialog.c:498
+#: ../plugins/systray/xfce-tray-dialogs.c:244
 msgid "Show _frame"
 msgstr ""
 
 #. tooltip settings
-#: ../plugins/clock/clock-dialog.c:506
+#: ../plugins/clock/clock-dialog.c:505
 msgid "Tooltip Format"
 msgstr ""
 
 #. clock settings
-#: ../plugins/clock/clock-dialog.c:532
+#: ../plugins/clock/clock-dialog.c:531
 msgid "Clock Options"
 msgstr "خيارات الساعة"
 
@@ -563,36 +567,36 @@
 msgid "Switch workspaces using the mouse wheel"
 msgstr ""
 
-#: ../plugins/separator/separator.c:397
+#: ../plugins/separator/separator.c:409
 #: ../plugins/separator/separator.desktop.in.in.h:2
 #, fuzzy
 msgid "Separator or Spacing"
 msgstr "فاصل"
 
-#: ../plugins/separator/separator.c:418
+#: ../plugins/separator/separator.c:430
 #, fuzzy
 msgid "Separator Style"
 msgstr "فاصل"
 
 #. space
-#: ../plugins/separator/separator.c:425
+#: ../plugins/separator/separator.c:437
 msgid "_Empty Space"
 msgstr ""
 
-#: ../plugins/separator/separator.c:434
+#: ../plugins/separator/separator.c:446
 msgid "_Expanding Empty Space"
 msgstr ""
 
-#: ../plugins/separator/separator.c:443
+#: ../plugins/separator/separator.c:455
 msgid "_Line"
 msgstr ""
 
-#: ../plugins/separator/separator.c:452
+#: ../plugins/separator/separator.c:464
 #, fuzzy
 msgid "_Handle"
 msgstr "موقع"
 
-#: ../plugins/separator/separator.c:461
+#: ../plugins/separator/separator.c:473
 msgid "_Dots"
 msgstr ""
 
@@ -604,20 +608,29 @@
 msgid "Hide windows and show desktop"
 msgstr "اخفي النوافذ واظهر سطح المكتب"
 
-#: ../plugins/systray/systray.c:69 ../plugins/systray/systray.c:84
+#. create a dialog
+#. create dialog
+#: ../plugins/systray/xfce-tray-plugin.c:71
+#: ../plugins/systray/xfce-tray-dialogs.c:224
+#: ../plugins/systray/systray.desktop.in.in.h:2
+msgid "System Tray"
+msgstr "صينية النظام"
+
+#: ../plugins/systray/xfce-tray-plugin.c:97
 msgid "There is already a system tray running on this screen"
 msgstr "هناك صينية نظام تعمل مسبقا على الشاشة"
 
-#: ../plugins/systray/systray.c:90
+#. applications
+#: ../plugins/systray/xfce-tray-dialogs.c:251
+#, fuzzy
+msgid "Hidden Applications"
+msgstr "إختر أمر"
+
+#: ../plugins/systray/xfce-tray-manager.c:431
 #, c-format
-msgid "Unable to register system tray: %s"
-msgstr "لم أتمكن من تسجيل صينية النظام: %s"
+msgid "Failed to acquire manager selection for screen %d"
+msgstr ""
 
-#: ../plugins/systray/systray.c:378
-#: ../plugins/systray/systray.desktop.in.in.h:2
-msgid "System Tray"
-msgstr "صينية النظام"
-
 #: ../plugins/tasklist/tasklist-dialogs.c:157
 #: ../plugins/tasklist/tasklist-dialogs.c:224
 #: ../plugins/tasklist/tasklist.desktop.in.in.h:2
@@ -805,102 +818,105 @@
 msgid "Xfce 4 Panel Manager"
 msgstr "مدير أشرطة اكسفس 4"
 
+#~ msgid "Unable to register system tray: %s"
+#~ msgstr "لم أتمكن من تسجيل صينية النظام: %s"
+
 #, fuzzy
-msgid ""
-"\n"
-" Xfce Panel %s\n"
-"\n"
-" Part of the Xfce Desktop Environment\n"
-" http://www.xfce.org\n"
-"\n"
-" Licensed under the GNU GPL.\n"
-"\n"
-msgstr ""
-"\n"
-"The Xfce Panel\n"
-"نسخة %s\n"
-"\n"
-"جزء من الواجهة الرسومية Xfce\n"
-"http://www.xfce.org\n"
-"\n"
-"Licensed under the GNU GPL.\n"
-"\n"
+#~ msgid ""
+#~ "\n"
+#~ " Xfce Panel %s\n"
+#~ "\n"
+#~ " Part of the Xfce Desktop Environment\n"
+#~ " http://www.xfce.org\n"
+#~ "\n"
+#~ " Licensed under the GNU GPL.\n"
+#~ "\n"
+#~ msgstr ""
+#~ "\n"
+#~ "The Xfce Panel\n"
+#~ "نسخة %s\n"
+#~ "\n"
+#~ "جزء من الواجهة الرسومية Xfce\n"
+#~ "http://www.xfce.org\n"
+#~ "\n"
+#~ "Licensed under the GNU GPL.\n"
+#~ "\n"
 
-msgid ""
-" Usage: %s [OPTIONS]\n"
-"\n"
-msgstr ""
-"الاستخدام: %s [OPTIONS]\n"
-"\n"
+#~ msgid ""
+#~ " Usage: %s [OPTIONS]\n"
+#~ "\n"
+#~ msgstr ""
+#~ "الاستخدام: %s [OPTIONS]\n"
+#~ "\n"
 
 #, fuzzy
-msgid "%A %d %B %Y"
-msgstr "%A, %d %B %Y"
+#~ msgid "%A %d %B %Y"
+#~ msgstr "%A, %d %B %Y"
 
-msgid "Error in command \"%s\""
-msgstr "خطأ في الأمر \"%s\""
+#~ msgid "Error in command \"%s\""
+#~ msgstr "خطأ في الأمر \"%s\""
 
 #, fuzzy
-msgid "This item has not yet been configured"
-msgstr "ﻻ يحوي على خيرات أعداد"
+#~ msgid "This item has not yet been configured"
+#~ msgstr "ﻻ يحوي على خيرات أعداد"
 
-msgid "Default"
-msgstr "تلقائي"
+#~ msgid "Default"
+#~ msgstr "تلقائي"
 
-msgid "File management"
-msgstr "متصفح الملفات"
+#~ msgid "File management"
+#~ msgstr "متصفح الملفات"
 
-msgid "Utilities"
-msgstr "وسائل"
+#~ msgid "Utilities"
+#~ msgstr "وسائل"
 
-msgid "Games"
-msgstr "ألعاب"
+#~ msgid "Games"
+#~ msgstr "ألعاب"
 
-msgid "Help browser"
-msgstr "متصفح المساعدة"
+#~ msgid "Help browser"
+#~ msgstr "متصفح المساعدة"
 
-msgid "Multimedia"
-msgstr "وسائط متعددة"
+#~ msgid "Multimedia"
+#~ msgstr "وسائط متعددة"
 
-msgid "Network"
-msgstr "شبكة"
+#~ msgid "Network"
+#~ msgstr "شبكة"
 
-msgid "Graphics"
-msgstr "رسومية"
+#~ msgid "Graphics"
+#~ msgstr "رسومية"
 
-msgid "Printer"
-msgstr "طابعة"
+#~ msgid "Printer"
+#~ msgstr "طابعة"
 
-msgid "Productivity"
-msgstr "إنتاجية"
+#~ msgid "Productivity"
+#~ msgstr "إنتاجية"
 
-msgid "Office"
-msgstr "المكتب"
+#~ msgid "Office"
+#~ msgstr "المكتب"
 
-msgid "Sound"
-msgstr "صوت"
+#~ msgid "Sound"
+#~ msgstr "صوت"
 
-msgid "Terminal"
-msgstr "سطر اﻷوامر"
+#~ msgid "Terminal"
+#~ msgstr "سطر اﻷوامر"
 
-msgid "Development"
-msgstr "التطوير"
+#~ msgid "Development"
+#~ msgstr "التطوير"
 
-msgid "Select image file"
-msgstr "اختر ملف صورة"
+#~ msgid "Select image file"
+#~ msgstr "اختر ملف صورة"
 
-msgid "Select command"
-msgstr "إختر أمر"
+#~ msgid "Select command"
+#~ msgstr "إختر أمر"
 
-msgid "Other..."
-msgstr "آخر"
+#~ msgid "Other..."
+#~ msgstr "آخر"
 
-msgid "Select file"
-msgstr "إختر ملف"
+#~ msgid "Select file"
+#~ msgstr "إختر ملف"
 
 #, fuzzy
-msgid "_Draw Separator"
-msgstr "فاصل"
+#~ msgid "_Draw Separator"
+#~ msgstr "فاصل"
 
-msgid "_Expand"
-msgstr "_افرد"
+#~ msgid "_Expand"
+#~ msgstr "_افرد"

Modified: xfce4-panel/trunk/po/az.po
===================================================================
--- xfce4-panel/trunk/po/az.po	2007-09-01 21:36:32 UTC (rev 26036)
+++ xfce4-panel/trunk/po/az.po	2007-09-02 11:47:54 UTC (rev 26037)
@@ -7,7 +7,7 @@
 msgstr ""
 "Project-Id-Version: xfce4-panel 4.4.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-07-06 21:54+0200\n"
+"POT-Creation-Date: 2007-09-02 13:40+0200\n"
 "PO-Revision-Date: 2005-09-29 20:16+0900\n"
 "Last-Translator: Mətin Əmirov <metin at karegen.com>\n"
 "Language-Team: Azerbaijani <translation-team-az at lists.sourceforge.net>\n"
@@ -57,43 +57,43 @@
 msgid "An item was unexpectedly removed: \"%s\"."
 msgstr ""
 
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:594
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:602
 #, fuzzy, c-format
 msgid "Remove \"%s\"?"
 msgstr "Sil"
 
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:608
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:616
 msgid ""
 "The item will be removed from the panel and its configuration will be lost."
 msgstr ""
 
 #. configure, hide by default
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:823
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:825
 msgid "Properties"
 msgstr ""
 
 #. about item, hide by default
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:840
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:842
 msgid "About"
 msgstr ""
 
 #. move
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:852
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:854
 #, fuzzy
 msgid "Move"
 msgstr "Sil"
 
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:871
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:873
 #, fuzzy
 msgid "Remove"
 msgstr "Sil"
 
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:888
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:890
 #, fuzzy
 msgid "Add New Item"
 msgstr "Yeni üzv əlavə et"
 
-#: ../libxfce4panel/xfce-panel-plugin-iface.c:899 ../panel/panel.c:696
+#: ../libxfce4panel/xfce-panel-plugin-iface.c:901 ../panel/panel.c:696
 #: ../mcs-plugin/xfce4-panel-manager.desktop.in.h:1
 msgid "Customize Panel"
 msgstr ""
@@ -309,8 +309,10 @@
 msgstr "Editor"
 
 #. appearance settings
+#. appearance
 #. Button Layout
-#: ../panel/panel-dialogs.c:1427 ../plugins/clock/clock-dialog.c:481
+#: ../panel/panel-dialogs.c:1427 ../plugins/clock/clock-dialog.c:480
+#: ../plugins/systray/xfce-tray-dialogs.c:238
 #: ../plugins/tasklist/tasklist-dialogs.c:183
 #: ../plugins/windowlist/windowlist-dialog.c:190
 msgid "Appearance"
@@ -380,62 +382,64 @@
 msgid "Quit + Lock screen"
 msgstr "/Ekranı _qıfılla"
 
-#: ../plugins/clock/clock-dialog.c:346
+#: ../plugins/clock/clock-dialog.c:345
 msgid "Custom"
 msgstr ""
 
-#: ../plugins/clock/clock-dialog.c:400
+#: ../plugins/clock/clock-dialog.c:399
 msgid "Display _seconds"
 msgstr ""
 
-#: ../plugins/clock/clock-dialog.c:409
+#: ../plugins/clock/clock-dialog.c:408
 msgid "Use 24-_hour clock"
 msgstr ""
 
-#: ../plugins/clock/clock-dialog.c:415
+#: ../plugins/clock/clock-dialog.c:414
 #, fuzzy
 msgid "Sho_w AM/PM"
 msgstr "GƏ/GS"
 
-#: ../plugins/clock/clock-dialog.c:424
+#: ../plugins/clock/clock-dialog.c:423
 msgid "True _binary clock"
 msgstr ""
 
 #. create dialog
-#: ../plugins/clock/clock-dialog.c:466
+#: ../plugins/clock/clock-dialog.c:465
 #: ../plugins/clock/clock.desktop.in.in.h:1
 #, fuzzy
 msgid "Clock"
 msgstr "Qıfılla"
 
-#: ../plugins/clock/clock-dialog.c:491
+#: ../plugins/clock/clock-dialog.c:490
 msgid "Analog"
 msgstr "Analoq"
 
-#: ../plugins/clock/clock-dialog.c:492
+#: ../plugins/clock/clock-dialog.c:491
 msgid "Binary"
 msgstr ""
 
-#: ../plugins/clock/clock-dialog.c:493
+#: ../plugins/clock/clock-dialog.c:492
 msgid "Digital"
 msgstr "Dijital"
 
-#: ../plugins/clock/clock-dialog.c:494
+#: ../plugins/clock/clock-dialog.c:493
 #, fuzzy
 msgid "LCD"
 msgstr "LED"
 
-#: ../plugins/clock/clock-dialog.c:499 ../plugins/systray/systray.c