[Xfce4-commits] r26065 - in xfce4-panel/trunk: libxfce4panel plugins/launcher plugins/systray po

Nick Schermer nick at xfce.org
Mon Sep 10 14:04:49 CEST 2007


Author: nick
Date: 2007-09-10 12:04:49 +0000 (Mon, 10 Sep 2007)
New Revision: 26065

Modified:
   xfce4-panel/trunk/libxfce4panel/xfce-panel-plugin-iface.c
   xfce4-panel/trunk/plugins/launcher/launcher-dialog.c
   xfce4-panel/trunk/plugins/launcher/launcher-dialog.h
   xfce4-panel/trunk/plugins/launcher/launcher-exec.c
   xfce4-panel/trunk/plugins/launcher/launcher-exec.h
   xfce4-panel/trunk/plugins/launcher/launcher.c
   xfce4-panel/trunk/plugins/launcher/launcher.h
   xfce4-panel/trunk/plugins/systray/xfce-tray-widget.c
   xfce4-panel/trunk/po/am.po
   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:
Launcher:
* Finish arrow position code (Bug #1046 and Bug #2985).
* Code cleanups and fixes.

Libxfce4panel:
* Force plugins to use the panel size.

Po:
* Merge strings


Modified: xfce4-panel/trunk/libxfce4panel/xfce-panel-plugin-iface.c
===================================================================
--- xfce4-panel/trunk/libxfce4panel/xfce-panel-plugin-iface.c	2007-09-10 08:51:12 UTC (rev 26064)
+++ xfce4-panel/trunk/libxfce4panel/xfce-panel-plugin-iface.c	2007-09-10 12:04:49 UTC (rev 26065)
@@ -343,15 +343,35 @@
 _xfce_panel_plugin_signal_size (XfcePanelPlugin *plugin,
                                 gint             size)
 {
-    gboolean handled = FALSE;
+    gboolean       handled = FALSE;
+    GtkOrientation orientation;
+    gint           width, height;
 
     _panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
 
+    /* emit signal */
     g_signal_emit (G_OBJECT (plugin), xfce_panel_plugin_signals[SIZE_CHANGED], 0,
                    size, &handled);
 
     if (!handled)
+    {
+        /* size was not handled by the plugin, so we set it */
         gtk_widget_set_size_request (GTK_WIDGET (plugin), size, size);
+    }
+    else
+    {
+        /* get the orientation of the panel */
+        orientation = xfce_panel_plugin_get_orientation (plugin);
+
+        /* get the requested plugin size */
+        gtk_widget_get_size_request (GTK_WIDGET (plugin), &width, &height);
+
+        /* force the plugin size */
+        if (orientation == GTK_ORIENTATION_HORIZONTAL)
+            gtk_widget_set_size_request (GTK_WIDGET (plugin), width, size);
+        else
+            gtk_widget_set_size_request (GTK_WIDGET (plugin), size, height);
+    }
 }
 
 

Modified: xfce4-panel/trunk/plugins/launcher/launcher-dialog.c
===================================================================
--- xfce4-panel/trunk/plugins/launcher/launcher-dialog.c	2007-09-10 08:51:12 UTC (rev 26064)
+++ xfce4-panel/trunk/plugins/launcher/launcher-dialog.c	2007-09-10 12:04:49 UTC (rev 26065)
@@ -35,10 +35,11 @@
 #include "launcher.h"
 #include "launcher-dialog.h"
 
+
 enum
 {
-    COL_ICON = 0,
-    COL_TEXT
+    COLUMN_ICON = 0,
+    COLUMN_NAME
 };
 
 typedef struct _LauncherDialog LauncherDialog;
@@ -47,6 +48,12 @@
 {
     LauncherPlugin *launcher;
 
+    /* stored setting */
+    guint           stored_move_first : 1;
+
+    /* arrow position */
+    GtkWidget      *arrow_position;
+
     /* entries list */
     GtkWidget      *treeview;
     GtkListStore   *store;
@@ -80,7 +87,8 @@
 /**
  * Prototypes
  **/
-static gchar      *launcher_dialog_parse_exec                (const gchar           *exec) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+static void        launcher_dialog_g_list_swap               (GList                 *li_a,
+                                                              GList                 *li_b);
 static gboolean    launcher_dialog_read_desktop_file         (const gchar           *file,
                                                               LauncherEntry         *entry);
 static void        launcher_dialog_tree_drag_data_received   (GtkWidget             *widget,
@@ -99,7 +107,6 @@
                                                               guint                  info,
                                                               guint                  time,
                                                               LauncherDialog        *ld);
-static void        launcher_dialog_update_panel              (LauncherDialog        *ld);
 static void        launcher_dialog_save_entry                (GtkWidget             *entry,
                                                                LauncherDialog        *ld);
 static void        launcher_dialog_save_button               (GtkWidget             *button,
@@ -109,7 +116,6 @@
 static void        launcher_dialog_folder_chooser            (LauncherDialog        *ld);
 static void        launcher_dialog_command_chooser           (LauncherDialog        *ld);
 static void        launcher_dialog_icon_chooser              (LauncherDialog        *ld);
-static void        launcher_dialog_tree_free_store           (LauncherDialog        *ld);
 static void        launcher_dialog_tree_update_row           (LauncherDialog        *ld,
                                                               gint                   column);
 static void        launcher_dialog_tree_selection_changed    (LauncherDialog        *ld,
@@ -128,23 +134,19 @@
 /**
  * .Desktop entry
  **/
-static gchar *
-launcher_dialog_parse_exec (const gchar *exec)
+static void
+launcher_dialog_g_list_swap (GList *li_a,
+                             GList *li_b)
 {
-    gchar *command;
+    gpointer data;
 
-    /* quit if nothing is set */
-    if (exec == NULL)
-        return NULL;
-
-    /* expand enviorement variables like ~/ and ~user/ */
-    command = xfce_expand_variables (exec, NULL);
-
-    return command;
+    /* swap the data pointers */
+    data = li_a->data;
+    li_a->data = li_b->data;
+    li_b->data = data;
 }
 
 
-
 static gboolean
 launcher_dialog_read_desktop_file (const gchar   *path,
                                    LauncherEntry *entry)
@@ -203,7 +205,7 @@
         g_free (entry->exec);
 
         /* expand variables and store */
-        entry->exec = launcher_dialog_parse_exec (value);
+        entry->exec = value ? xfce_expand_variables (value, NULL) : NULL;
     }
 
     /* working directory */
@@ -247,13 +249,14 @@
     GtkTreeModel            *model;
     GtkTreeIter              iter_a;
     GtkTreeIter              iter_b;
-    GSList                  *file_list = NULL;
+    GSList                  *filenames = NULL;
     GSList                  *li;
-    gchar                   *file;
+    const gchar             *file;
     gboolean                 insert_before = FALSE;
+    gboolean                 update_icon = FALSE;
     gint                     i = 0;
     LauncherEntry           *entry;
-    GdkPixbuf               *icon = NULL;
+    GdkPixbuf               *pixbuf;
 
     /* get drop position in the tree */
     if (gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (ld->treeview),
@@ -289,48 +292,47 @@
                 break;
          }
 
-        /* we need to update the button icon if something was dropped on the first position */
+        /* we need to update the button icon afterwards */
         if (i == 0)
-            ld->launcher->icon_update_required = TRUE;
+            update_icon = TRUE;
 
         /* create list from selection data */
-        file_list = launcher_file_list_from_selection (selection_data);
+        filenames = launcher_utility_filenames_from_selection_data (selection_data);
     }
 
-    if (G_LIKELY (file_list != NULL))
+    if (G_LIKELY (filenames != NULL))
     {
-        for (li = file_list; li != NULL; li = li->next)
+        for (li = filenames; li != NULL; li = li->next)
         {
-            file = (gchar *) li->data;
+            file = li->data;
 
             /* create new entry */
-            entry = launcher_new_entry ();
+            entry = launcher_entry_new ();
 
             /* try to parse desktop file */
             if (G_LIKELY (launcher_dialog_read_desktop_file (file, entry) == TRUE))
             {
-                /* try to load the pixbuf */
-                icon = launcher_load_pixbuf (ld->treeview, entry->icon, TREE_ICON_SIZE, TRUE);
-
                 /* insert new row in store */
                 if (insert_before)
                     gtk_list_store_insert_before (ld->store, &iter_b, &iter_a);
                 else
                     gtk_list_store_insert_after (ld->store, &iter_b, &iter_a);
 
+                /* try to load the pixbuf */
+                pixbuf = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE);
+
                 /* set tree data */
                 gtk_list_store_set (ld->store, &iter_b,
-                                    COL_ICON, icon,
-                                    COL_TEXT, entry->name,
+                                    COLUMN_ICON, pixbuf,
+                                    COLUMN_NAME, entry->name,
                                     -1);
 
                 /* release pixbuf */
-                if (G_LIKELY (icon != NULL))
-                    g_object_unref (G_OBJECT (icon));
+                if (G_LIKELY (pixbuf != NULL))
+                    g_object_unref (G_OBJECT (pixbuf));
 
                 /* insert in list */
-                ld->launcher->entries = g_list_insert (ld->launcher->entries,
-                                                        entry, i);
+                ld->launcher->entries = g_list_insert (ld->launcher->entries, entry, i);
 
                 /* copy iter, so we add after last item */
                 iter_a = iter_b;
@@ -345,7 +347,7 @@
             else
             {
                 /* desktop file pasring failed, free new entry */
-                launcher_free_entry (entry, NULL);
+                launcher_entry_free (entry, NULL);
             }
         }
 
@@ -353,10 +355,10 @@
         gtk_tree_view_set_cursor (GTK_TREE_VIEW (ld->treeview), path, NULL, FALSE);
 
         /* update the panel */
-        launcher_dialog_update_panel (ld);
+        launcher_plugin_rebuild (ld->launcher, update_icon);
 
         /* cleanup */
-        g_slist_free_all (file_list);
+        launcher_free_filenames (filenames);
     }
 
     /* free path */
@@ -379,16 +381,16 @@
                                           guint             time,
                                           LauncherDialog   *ld)
 {
-    GSList *file_list = NULL;
-    GSList *li;
-    gchar  *file;
+    GSList   *filenames, *li;
+    gchar    *file;
+    gboolean  update_icon = FALSE;
 
     /* create list from all the uri list */
-    file_list = launcher_file_list_from_selection (selection_data);
+    filenames = launcher_utility_filenames_from_selection_data (selection_data);
 
-    if (G_LIKELY (file_list != NULL))
+    if (G_LIKELY (filenames != NULL))
     {
-        for (li = file_list; li != NULL; li = li->next)
+        for (li = filenames; li != NULL; li = li->next)
         {
             file = (gchar *) li->data;
 
@@ -399,14 +401,15 @@
                 launcher_dialog_update_entries (ld);
 
                 /* update the tree */
-                launcher_dialog_tree_update_row (ld, COL_TEXT);
-                launcher_dialog_tree_update_row (ld, COL_ICON);
-                
+                launcher_dialog_tree_update_row (ld, COLUMN_NAME);
+                launcher_dialog_tree_update_row (ld, COLUMN_ICON);
+
                 /* also update the panel button icon */
-                ld->launcher->icon_update_required = TRUE;
+                if (g_list_index (ld->launcher->entries, ld->entry) == 0)
+                    update_icon = TRUE;
 
                 /* update the panel */
-                launcher_dialog_update_panel (ld);
+                launcher_plugin_rebuild (ld->launcher, update_icon);
 
                 /* stop trying */
                 break;
@@ -414,7 +417,7 @@
         }
 
         /* cleanup */
-        g_slist_free_all (file_list);
+        launcher_free_filenames (filenames);
     }
 
     /* finish drag */
@@ -427,15 +430,6 @@
  * Properties update and save functions
  **/
 static void
-launcher_dialog_update_panel (LauncherDialog *ld)
-{
-    g_idle_add ((GSourceFunc) launcher_button_update, ld->launcher);
-    g_idle_add ((GSourceFunc) launcher_menu_prepare, ld->launcher);
-}
-
-
-
-static void
 launcher_dialog_save_entry (GtkWidget      *entry,
                             LauncherDialog *ld)
 {
@@ -459,7 +453,7 @@
         ld->entry->name = g_strdup (text);
 
         /* update tree, when triggered by widget */
-        launcher_dialog_tree_update_row (ld, COL_TEXT);
+        launcher_dialog_tree_update_row (ld, COLUMN_NAME);
     }
     else if (entry == ld->entry_comment)
     {
@@ -469,7 +463,7 @@
     else if (entry == ld->entry_exec)
     {
         g_free (ld->entry->exec);
-        ld->entry->exec = launcher_dialog_parse_exec (text);
+        ld->entry->exec = text ? xfce_expand_variables (text, NULL) : NULL;
     }
     else if (entry == ld->entry_path)
     {
@@ -478,7 +472,7 @@
     }
 
     /* update panel */
-    launcher_dialog_update_panel (ld);
+    launcher_plugin_rebuild (ld->launcher, FALSE);
 }
 
 
@@ -565,21 +559,24 @@
         gtk_widget_destroy (GTK_BIN (ld->entry_icon)->child);
 
     if (G_LIKELY (ld->entry->icon))
-        icon = launcher_load_pixbuf (ld->entry_icon, ld->entry->icon, CHOOSER_ICON_SIZE, FALSE);
+        icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->entry_icon), ld->entry->icon, LAUNCHER_CHOOSER_ICON_SIZE);
 
     /* create icon button */
     if (G_LIKELY (icon != NULL))
     {
+        /* create image from pixbuf */
         child = gtk_image_new_from_pixbuf (icon);
 
         /* release icon */
         g_object_unref (G_OBJECT (icon));
+
+        gtk_widget_set_size_request (child, LAUNCHER_CHOOSER_ICON_SIZE, LAUNCHER_CHOOSER_ICON_SIZE);
     }
     else
     {
         child = gtk_label_new (_("No icon"));
 
-        gtk_widget_set_size_request (child, -1, CHOOSER_ICON_SIZE);
+        gtk_widget_set_size_request (child, -1, LAUNCHER_CHOOSER_ICON_SIZE);
     }
 
     gtk_container_add (GTK_CONTAINER (ld->entry_icon), child);
@@ -756,6 +753,7 @@
     const gchar *name;
     GtkWidget   *chooser;
     gchar       *title;
+    gboolean     update_icon = FALSE;
 
     /* determine the name of the entry being edited */
     name = gtk_entry_get_text (GTK_ENTRY (ld->entry_name));
@@ -790,14 +788,14 @@
         launcher_dialog_update_icon (ld);
 
         /* update the icon column in the tree */
-        launcher_dialog_tree_update_row (ld, COL_ICON);
+        launcher_dialog_tree_update_row (ld, COLUMN_ICON);
 
         /* check if we need to update the icon button image */
         if (g_list_index (ld->launcher->entries, ld->entry) == 0)
-            ld->launcher->icon_update_required = TRUE;
+            update_icon = TRUE;
 
         /* update the panel widgets */
-        launcher_dialog_update_panel (ld);
+        launcher_plugin_rebuild (ld->launcher, update_icon);
     }
 
     /* destroy the chooser */
@@ -810,18 +808,6 @@
  * Tree functions
  **/
 static void
-launcher_dialog_tree_free_store (LauncherDialog *ld)
-{
-    /* clear the store */
-    gtk_list_store_clear (ld->store);
-
-    /* release the store */
-    g_object_unref (G_OBJECT (ld->store));
-}
-
-
-
-static void
 launcher_dialog_tree_update_row (LauncherDialog *ld,
                                  gint            column)
 {
@@ -835,13 +821,13 @@
     {
         switch (column)
         {
-            case COL_ICON:
+            case COLUMN_ICON:
                 /* load entry icon */
-                icon = launcher_load_pixbuf (ld->treeview, ld->entry->icon, TREE_ICON_SIZE, TRUE);
+                icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), ld->entry->icon, LAUNCHER_TREE_ICON_SIZE);
 
                 /* set new icon */
                 gtk_list_store_set (ld->store, &iter,
-                                    COL_ICON, icon,
+                                    COLUMN_ICON, icon,
                                     -1);
 
                 /* release icon */
@@ -850,10 +836,10 @@
 
                 break;
 
-            case COL_TEXT:
+            case COLUMN_NAME:
                 /* set new name */
                 gtk_list_store_set (ld->store, &iter,
-                                    COL_TEXT, ld->entry->name,
+                                    COLUMN_NAME, ld->entry->name,
                                     -1);
 
                 break;
@@ -925,9 +911,11 @@
     GtkTreeIter       iter_a;
     GtkTreeIter       iter_b;
     guint             position;
+    gint              list_length;
     GList            *li;
     GdkPixbuf        *icon = NULL;
     LauncherEntry    *entry;
+    gboolean          update_icon = FALSE;
 
     /* get the selected items in the treeview */
     selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ld->treeview));
@@ -945,9 +933,9 @@
         /* position of the item in the list */
         position = gtk_tree_path_get_indices (path)[0];
 
-        /* check if we need to update the icon button image*/
+        /* check if we need to update the icon button image */
         if (position == 1)
-            ld->launcher->icon_update_required = TRUE;
+            update_icon = TRUE;
 
         /* get previous path */
         if (G_LIKELY (gtk_tree_path_prev (path)))
@@ -960,7 +948,7 @@
 
             /* swap items in the list */
             li = g_list_nth (ld->launcher->entries, position);
-            launcher_g_list_swap (li, li->prev);
+            launcher_dialog_g_list_swap (li, li->prev);
         }
 
         /* release the path */
@@ -979,7 +967,7 @@
 
         /* check if we need to update the icon button image*/
         if (position == 0)
-            ld->launcher->icon_update_required = TRUE;
+            update_icon = TRUE;
 
         /* get next item in the list */
         gtk_tree_path_next (path);
@@ -992,7 +980,7 @@
 
             /* swap items in the list */
             li = g_list_nth (ld->launcher->entries, position);
-            launcher_g_list_swap (li, li->next);
+            launcher_dialog_g_list_swap (li, li->next);
         }
 
         /* release the path */
@@ -1004,16 +992,16 @@
     else if (button == ld->add)
     {
         /* create new entry */
-        entry = launcher_new_entry ();
+        entry = launcher_entry_new ();
 
         /* load new launcher icon */
-        icon = launcher_load_pixbuf (ld->treeview, entry->icon, TREE_ICON_SIZE, TRUE);
+        icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE);
 
         /* append new entry */
         gtk_list_store_insert_after (ld->store, &iter_b, &iter_a);
         gtk_list_store_set (ld->store, &iter_b,
-                            COL_ICON, icon,
-                            COL_TEXT, entry->name,
+                            COLUMN_ICON, icon,
+                            COLUMN_NAME, entry->name,
                             -1);
 
         /* release the pixbuf */
@@ -1036,6 +1024,9 @@
         /* cleanup */
         gtk_tree_path_free (path);
 
+        /* allow to set the arrow position */
+        gtk_widget_set_sensitive (ld->arrow_position, TRUE);
+
     }
     else if (button == ld->remove)
     {
@@ -1047,13 +1038,13 @@
 
         /* check if we need to update the icon button image*/
         if (position == 0)
-            ld->launcher->icon_update_required = TRUE;
+            update_icon = TRUE;
 
         /* lock */
         ld->updating = TRUE;
 
         /* remove active entry */
-        launcher_free_entry (ld->entry, ld->launcher);
+        launcher_entry_free (ld->entry, ld->launcher);
         ld->entry = NULL;
 
         /* remove row from store */
@@ -1062,8 +1053,11 @@
         /* unlock */
         ld->updating = FALSE;
 
+        /* list length */
+        list_length = g_list_length (ld->launcher->entries);
+
         /* select previous item, if last item was removed */
-        if (position >= g_list_length (ld->launcher->entries))
+        if (position >= list_length)
             gtk_tree_path_prev (path);
 
         /* select the new item (also updates treeview buttons) */
@@ -1071,14 +1065,32 @@
 
         /* cleanup */
         gtk_tree_path_free (path);
+
+        /* allow to set the arrow position */
+        gtk_widget_set_sensitive (ld->arrow_position, list_length > 1);
+
+        /* don't allow menu arrows */
+        if (list_length == 1 && ld->launcher->arrow_position == LAUNCHER_ARROW_INSIDE_BUTTON)
+            gtk_combo_box_set_active (GTK_COMBO_BOX (ld->arrow_position), LAUNCHER_ARROW_DEFAULT);
     }
 
     /* update panel */
-    launcher_dialog_update_panel (ld);
+    launcher_plugin_rebuild (ld->launcher, update_icon);
 }
 
 
 
+static void
+launcher_dialog_arrow_position_changed (GtkComboBox    *combo,
+                                        LauncherDialog *ld)
+{
+    ld->launcher->arrow_position = gtk_combo_box_get_active (combo);
+
+    launcher_plugin_rebuild (ld->launcher, TRUE);
+}
+
+
+
 /**
  * Launcher dialog widgets
  **/
@@ -1281,25 +1293,27 @@
     /* create tree view */
     ld->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (ld->store));
     gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (ld->treeview), FALSE);
+    gtk_tree_view_set_search_column (GTK_TREE_VIEW (ld->treeview), COLUMN_NAME);
+    gtk_tree_view_set_enable_search (GTK_TREE_VIEW (ld->treeview), TRUE);
+    gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (ld->treeview), TRUE);
     gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (ld->treeview), TRUE);
     gtk_container_add (GTK_CONTAINER (scroll), ld->treeview);
 
-    g_signal_connect_swapped (G_OBJECT (ld->treeview), "destroy",
-                              G_CALLBACK (launcher_dialog_tree_free_store), ld);
-
     /* create columns and cell renders */
     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_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
     gtk_tree_view_append_column (GTK_TREE_VIEW (ld->treeview), column);
 
     renderer = gtk_cell_renderer_pixbuf_new();
+    gtk_cell_renderer_set_fixed_size (renderer, LAUNCHER_TREE_ICON_SIZE, LAUNCHER_TREE_ICON_SIZE);
     gtk_tree_view_column_pack_start (column, renderer, FALSE);
-    gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", COL_ICON, NULL);
+    gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", COLUMN_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", COL_TEXT, NULL);
+    gtk_tree_view_column_set_attributes (column, renderer, "text", COLUMN_NAME, NULL);
     g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
 
     /* set selection change signal */
@@ -1316,14 +1330,13 @@
         if (G_LIKELY (entry && entry->name))
         {
             /* load icon */
-            icon = launcher_load_pixbuf (ld->treeview, entry->icon, TREE_ICON_SIZE, TRUE);
+            icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE);
 
             /* create new row and add the data */
             gtk_list_store_append (ld->store, &iter);
             gtk_list_store_set (ld->store, &iter,
-                                COL_ICON, icon,
-                                COL_TEXT, entry->name,
-                                -1);
+                                COLUMN_ICON, icon,
+                                COLUMN_NAME, entry->name, -1);
 
             /* release the pixbuf */
             if (G_LIKELY (icon))
@@ -1416,9 +1429,11 @@
  **/
 static void
 launcher_dialog_response (GtkWidget      *dialog,
-                            gint            response,
-                            LauncherDialog *ld)
+                          gint            response,
+                          LauncherDialog *ld)
 {
+    LauncherPlugin *launcher = ld->launcher;
+
     /* hide the dialog */
     gtk_widget_hide (dialog);
 
@@ -1426,44 +1441,43 @@
     ld->updating = TRUE;
     ld->entry = NULL;
 
-    /* remove link */
-    g_object_set_data (G_OBJECT (ld->launcher->plugin), "dialog", NULL);
+    /* cleanup the store */
+    gtk_list_store_clear (ld->store);
+    g_object_unref (G_OBJECT (ld->store));
 
+    /* the launcher dialog dataS */
+    g_object_set_data (G_OBJECT (launcher->panel_plugin), I_("launcher-dialog"), NULL);
+
     /* destroy the dialog */
     gtk_widget_destroy (dialog);
 
-    /* unlock plugin menu (do this before writing -> see hack in write function) */
-    xfce_panel_plugin_unblock_menu (ld->launcher->plugin);
+    /* unlock plugin menu */
+    xfce_panel_plugin_unblock_menu (launcher->panel_plugin);
 
-    /* revert settings made */
-    if (response == GTK_RESPONSE_CANCEL)
-    {
-        /* remove all entries from the list */
-        g_list_foreach (ld->launcher->entries,
-                        (GFunc) launcher_free_entry, ld->launcher);
+    /* restore move first */
+    launcher->move_first = ld->stored_move_first;
 
-        /* read last saved settings */
-        launcher_read (ld->launcher);
+    /* allow saving again */
+    launcher->plugin_can_save = TRUE;
 
-        /* if this is a newly created item, there is no saved data yet */
-        if (G_UNLIKELY (g_list_length (ld->launcher->entries) == 0))
-        {
-              ld->launcher->entries = g_list_append (ld->launcher->entries, 
-                                                     launcher_new_entry ());
-        }
-
-        /* update the panel again */
-        launcher_dialog_update_panel (ld);
-    }
-    else /* save changes */
+    if (response == GTK_RESPONSE_OK)
     {
         /* write new settings */
-        launcher_write (ld->launcher);
+        launcher_plugin_save (launcher);
     }
+    else /* revert changes */
+    {
+        /* remove all the entries */
+        g_list_foreach (launcher->entries, (GFunc) launcher_entry_free, launcher);
 
-    /* enable/disable auto sort again */
-    launcher_set_move_first (ld->launcher->move_first);
+        /* read the last saved settings */
+        launcher_plugin_read (launcher);
 
+        /* add new item if there are no entries yet */
+        if (G_UNLIKELY (g_list_length (launcher->entries) == 0))
+            launcher->entries = g_list_append (launcher->entries, launcher_entry_new ());
+    }
+
     /* free the panel structure */
     panel_slice_free (LauncherDialog, ld);
 }
@@ -1476,28 +1490,26 @@
     LauncherDialog *ld;
     GtkWidget      *dialog;
     GtkWidget      *dialog_vbox;
-    GtkWidget      *paned, *vbox;
-    GtkWidget      *widget;
+    GtkWidget      *paned, *vbox, *hbox;
+    GtkWidget      *widget, *label, *combo;
     GtkTreePath    *path;
 
     /* create new structure */
     ld = panel_slice_new0 (LauncherDialog);
 
+    /* init */
     ld->launcher = launcher;
+    ld->entry = g_list_first (launcher->entries)->data;
 
-    /* get first entry */
-    if (G_UNLIKELY (g_list_length (launcher->entries) == 0)) 
-    {
-        launcher->entries = g_list_append (launcher->entries, 
-                                           launcher_new_entry ());
-    }
-    ld->entry = launcher->entries->data;
+    /* prevent saving to be able to use the cancel button */
+    launcher->plugin_can_save = FALSE;
 
     /* lock right-click plugin menu */
-    xfce_panel_plugin_block_menu (launcher->plugin);
+    xfce_panel_plugin_block_menu (launcher->panel_plugin);
 
     /* disable the auto sort of the list, while working in properties */
-    launcher_set_move_first (FALSE);
+    ld->stored_move_first = launcher->move_first;
+    launcher->move_first = FALSE;
 
     /* create new dialog */
     dialog = xfce_titled_dialog_new_with_buttons (_("Program Launcher"),
@@ -1506,16 +1518,13 @@
                                                   GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                                   GTK_STOCK_OK, GTK_RESPONSE_OK,
                                                   NULL);
-
-    gtk_window_set_screen (GTK_WINDOW (dialog),
-                           gtk_widget_get_screen (GTK_WIDGET (launcher->plugin)));
-
+    gtk_window_set_screen (GTK_WINDOW (dialog), gtk_widget_get_screen (GTK_WIDGET (launcher->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);
 
     /* connect dialog to plugin, so we can destroy it when plugin is closed */
-    g_object_set_data (G_OBJECT (ld->launcher->plugin), "dialog", dialog);
+    g_object_set_data (G_OBJECT (ld->launcher->panel_plugin), "dialog", dialog);
 
     dialog_vbox = GTK_DIALOG (dialog)->vbox;
 
@@ -1527,6 +1536,27 @@
     vbox = gtk_vbox_new (FALSE, BORDER);
     gtk_paned_pack1 (GTK_PANED (paned), vbox, FALSE, FALSE);
 
+    /* arrow button position */
+    hbox = gtk_hbox_new (FALSE, BORDER);
+    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+    label = gtk_label_new_with_mnemonic (_("A_rrow:"));
+    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+    ld->arrow_position = combo = gtk_combo_box_new_text ();
+    gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
+    gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
+    gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Default"));
+    gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Left"));
+    gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Right"));
+    gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Top"));
+    gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Bottom"));
+    gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Inside Button"));
+    gtk_widget_set_sensitive (combo, g_list_length (launcher->entries) > 1);
+    gtk_combo_box_set_active (GTK_COMBO_BOX (combo), launcher->arrow_position);
+    g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (launcher_dialog_arrow_position_changed), ld);
+    gtk_widget_show (combo);
+
     /* add the entries list */
     widget = launcher_dialog_add_tree (ld);
     gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);

Modified: xfce4-panel/trunk/plugins/launcher/launcher-dialog.h
===================================================================
--- xfce4-panel/trunk/plugins/launcher/launcher-dialog.h	2007-09-10 08:51:12 UTC (rev 26064)
+++ xfce4-panel/trunk/plugins/launcher/launcher-dialog.h	2007-09-10 12:04:49 UTC (rev 26065)
@@ -21,6 +21,6 @@
 #ifndef __XFCE_PANEL_LAUNCHER_DIALOG_H__
 #define __XFCE_PANEL_LAUNCHER_DIALOG_H__
 
-void                    launcher_dialog_show                      (LauncherPlugin  *launcher) G_GNUC_INTERNAL;
+void launcher_dialog_show (LauncherPlugin *launcher) G_GNUC_INTERNAL;
 
 #endif /* !__XFCE_PANEL_LAUNCHER_DIALOG_H__ */

Modified: xfce4-panel/trunk/plugins/launcher/launcher-exec.c
===================================================================
--- xfce4-panel/trunk/plugins/launcher/launcher-exec.c	2007-09-10 08:51:12 UTC (rev 26064)
+++ xfce4-panel/trunk/plugins/launcher/launcher-exec.c	2007-09-10 12:04:49 UTC (rev 26065)
@@ -20,20 +20,22 @@
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
 #endif
-#ifdef HAVE_STRING_H
-#include <string.h>
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
 #endif
+
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
 #endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
 #endif
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
 #endif
 
 #ifndef WAIT_ANY
@@ -154,7 +156,7 @@
     elapsed = (((gdouble) now.tv_sec - tv_sec) * G_USEC_PER_SEC + (now.tv_usec - tv_usec)) / 1000.0;
 
     /* check if the timeout was reached */
-    if (elapsed >= STARTUP_TIMEOUT)
+    if (elapsed >= LAUNCHER_STARTUP_TIMEOUT)
     {
         /* abort the startup notification */
         sn_launcher_context_complete (startup_data->sn_launcher);
@@ -163,7 +165,7 @@
     }
 
     /* keep the startup timeout if not elapsed */
-    return (elapsed < STARTUP_TIMEOUT);
+    return (elapsed < LAUNCHER_STARTUP_TIMEOUT);
 }
 
 
@@ -211,7 +213,7 @@
       {
         /* get the child process state without hanging */
         ret = waitpid (WAIT_ANY, NULL, WNOHANG);
-        
+
         /* exit if there is nothing to wait for */
         if (ret == 0 || ret < 0)
           break;
@@ -487,7 +489,7 @@
             /* schedule a startup notification timeout */
             startup_data = panel_slice_new (LauncherStartupData);
             startup_data->sn_launcher = sn_launcher;
-            startup_data->timeout_id = g_timeout_add_full (G_PRIORITY_LOW, STARTUP_TIMEOUT,
+            startup_data->timeout_id = g_timeout_add_full (G_PRIORITY_LOW, LAUNCHER_STARTUP_TIMEOUT,
                                                            launcher_exec_startup_timeout,
                                                            startup_data, launcher_exec_startup_timeout_destroy);
             startup_data->watch_id = g_child_watch_add_full (G_PRIORITY_LOW, pid, launcher_exec_startup_watch,
@@ -547,7 +549,7 @@
         screen = gdk_screen_get_default ();
 
     /* maybe no command have been filed yet */
-    if (G_UNLIKELY (entry->exec == NULL))
+    if (G_UNLIKELY (entry->exec == NULL || *entry->exec == '\0'))
         return;
 
     /* check if the launcher supports (and needs) multiple instances */
@@ -583,13 +585,9 @@
 {
     GtkClipboard     *clipboard;
     gchar            *text = NULL;
-    GSList           *file_list = NULL;
+    GSList           *filenames;
     GtkSelectionData  selection_data;
 
-    /* maybe no command have been filed yet */
-    if (G_UNLIKELY (entry->exec == NULL))
-        return;
-
     /* get the clipboard */
     clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
 
@@ -605,26 +603,26 @@
 
         /* get clipboard text */
         if (G_LIKELY (clipboard))
-        text = gtk_clipboard_wait_for_text (clipboard);
+            text = gtk_clipboard_wait_for_text (clipboard);
     }
 
-    if (G_LIKELY (text != NULL))
+    if (G_LIKELY (text))
     {
         /* create some fake selection data */
         selection_data.data = (guchar *) text;
         selection_data.length = strlen (text);
 
         /* parse the filelist, this way we can handle 'copied' file from thunar */
-        file_list = launcher_file_list_from_selection (&selection_data);
+        filenames = launcher_utility_filenames_from_selection_data (&selection_data);
 
-        if (G_LIKELY (file_list != NULL))
+        if (G_LIKELY (filenames))
         {
             /* run the command with argument from clipboard */
-            launcher_exec_on_screen (screen, entry, file_list);
+            launcher_execute (screen, entry, filenames);
 
             /* cleanup */
-            g_slist_free_all (file_list);
-    }
+            launcher_free_filenames (filenames);
+        }
 
         /* cleanup */
         g_free (text);

Modified: xfce4-panel/trunk/plugins/launcher/launcher-exec.h
===================================================================
--- xfce4-panel/trunk/plugins/launcher/launcher-exec.h	2007-09-10 08:51:12 UTC (rev 26064)
+++ xfce4-panel/trunk/plugins/launcher/launcher-exec.h	2007-09-10 12:04:49 UTC (rev 26065)
@@ -20,10 +20,10 @@
 #ifndef __XFCE_PANEL_EXEC_H__
 #define __XFCE_PANEL_EXEC_H__
 
-void                    launcher_execute                     (GdkScreen             *screen,
-                                                              LauncherEntry         *entry,
-                                                              GSList                *file_list) G_GNUC_INTERNAL;
-void                    launcher_execute_from_clipboard      (GdkScreen             *screen,
-                                                              LauncherEntry         *entry)     G_GNUC_INTERNAL;
+void launcher_execute                (GdkScreen     *screen,
+                                      LauncherEntry *entry,
+                                      GSList        *file_list) G_GNUC_INTERNAL;
+void launcher_execute_from_clipboard (GdkScreen     *screen,
+                                      LauncherEntry *entry)     G_GNUC_INTERNAL;
 
 #endif /* !__XFCE_PANEL_EXEC_H__ */

Modified: xfce4-panel/trunk/plugins/launcher/launcher.c
===================================================================
--- xfce4-panel/trunk/plugins/launcher/launcher.c	2007-09-10 08:51:12 UTC (rev 26064)
+++ xfce4-panel/trunk/plugins/launcher/launcher.c	2007-09-10 12:04:49 UTC (rev 26065)
@@ -37,132 +37,95 @@
 #include "launcher-exec.h"
 #include "launcher-dialog.h"
 
-/**
- * Prototypes
- **/
-static void             launcher_g_list_move_first           (GList                 *li);
-static gboolean         launcher_theme_changed               (GSignalInvocationHint *ihint,
-                                                              guint                  n_param_values,
-                                                              const GValue          *param_values,
-                                                              LauncherPlugin        *launcher);
-static void             launcher_button_drag_data_received   (GtkWidget             *widget,
-                                                              GdkDragContext        *context,
-                                                              gint                   x,
-                                                              gint                   y,
-                                                              GtkSelectionData      *selection_data,
-                                                              guint                  info,
-                                                              guint                  time,
-                                                              LauncherPlugin        *launcher);
-static void             launcher_menu_drag_data_received     (GtkWidget             *widget,
-                                                              GdkDragContext        *context,
-                                                              gint                   x,
-                                                              gint                   y,
-                                                              GtkSelectionData      *selection_data,
-                                                              guint                  info,
-                                                              guint                  time,
-                                                              LauncherEntry         *entry);
-static void             launcher_button_clicked              (GtkWidget             *button,
-                                                              LauncherPlugin        *launcher);
-static void             launcher_button_state_changed        (GtkWidget             *button_a,
-                                                              GtkStateType           state,
-                                                              GtkWidget             *button_b);
-static gboolean         launcher_button_pressed              (LauncherPlugin        *launcher,
-                                                              GdkEventButton        *ev);
-static gboolean         launcher_button_released             (GtkWidget             *button,
-                                                              GdkEventButton        *ev,
-                                                              LauncherPlugin        *launcher);
-static gboolean         launcher_arrow_pressed               (LauncherPlugin        *launcher,
-                                                              GdkEventButton        *ev);
-static void             launcher_menu_item_activate          (GtkWidget             *mi,
-                                                              GList                 *li);
-static gboolean         launcher_menu_item_released          (GtkWidget             *mi,
-                                                              GdkEventButton        *ev,
-                                                              GList                 *li);
-static void             launcher_menu_position               (GtkMenu               *menu,
-                                                              gint                  *x,
-                                                              gint                  *y,
-                                                              gboolean              *push_in,
-                                                              GtkWidget             *button);
-static gboolean         launcher_menu_popup                  (LauncherPlugin        *launcher);
-static void             launcher_menu_deactivated            (LauncherPlugin        *launcher);
-static void             launcher_menu_update                 (LauncherPlugin        *launcher);
-static LauncherPlugin  *launcher_new                         (XfcePanelPlugin       *plugin) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-static GtkArrowType     launcher_calculate_floating_arrow    (LauncherPlugin        *launcher,
-                                                              XfceScreenPosition     position);
-static void             launcher_screen_position_changed     (LauncherPlugin        *launcher,
-                                                              XfceScreenPosition     position);
-static void             launcher_orientation_changed         (LauncherPlugin        *launcher,
-                                                              GtkOrientation         orientation);
-static gboolean         launcher_set_size                    (LauncherPlugin        *launcher,
-                                                              guint                  size);
-static void             launcher_free                        (LauncherPlugin        *launcher);
-static void             launcher_construct                   (XfcePanelPlugin       *plugin);
+/* prototypes */
+static gboolean        launcher_utility_icon_theme_changed          (GSignalInvocationHint *ihint,
+                                                                     guint                  n_param_values,
+                                                                     const GValue          *param_values,
+                                                                     LauncherPlugin        *launcher);
+static gboolean        launcher_icon_button_expose_event            (GtkWidget             *widget,
+                                                                     GdkEventExpose        *event,
+                                                                     LauncherPlugin        *launcher);
+static void            launcher_icon_button_set_icon                (LauncherPlugin        *launcher);
+#if LAUNCHER_NEW_TOOLTIP_API
+static gboolean        launcher_icon_button_query_tooltip           (GtkWidget             *widget,
+                                                                     gint                   x,
+                                                                     gint                   y,
+                                                                     gboolean               keyboard_mode,
+                                                                     GtkTooltip            *tooltip,
+                                                                     LauncherPlugin        *launcher);
+#else
+static void            launcher_icon_button_set_tooltip             (LauncherPlugin        *launcher);
+#endif
+static gboolean        launcher_icon_button_pressed                 (GtkWidget             *button,
+                                                                     GdkEventButton        *event,
+                                                                     LauncherPlugin        *launcher);
+static gboolean        launcher_icon_button_released                (GtkWidget             *button,
+                                                                     GdkEventButton        *event,
+                                                                     LauncherPlugin        *launcher);
+static void            launcher_icon_button_drag_data_received      (GtkWidget             *widget,
+                                                                     GdkDragContext        *context,
+                                                                     gint                   x,
+                                                                     gint                   y,
+                                                                     GtkSelectionData      *selection_data,
+                                                                     guint                  info,
+                                                                     guint                  time,
+                                                                     LauncherPlugin        *launcher);
+static gboolean        launcher_arrow_button_pressed                (GtkWidget             *button,
+                                                                     GdkEventButton        *event,
+                                                                     LauncherPlugin        *launcher);
+static void            launcher_button_state_changed                (GtkWidget             *button_a,
+                                                                     GtkStateType           state,
+                                                                     GtkWidget             *button_b);
+static gboolean        launcher_menu_item_released                  (GtkWidget             *mi,
+                                                                     GdkEventButton        *event,
+                                                                     LauncherPlugin        *launcher);
+static void            launcher_menu_position                       (GtkMenu               *menu,
+                                                                     gint                  *x,
+                                                                     gint                  *y,
+                                                                     gboolean              *push_in,
+                                                                     LauncherPlugin        *launcher);
+static void            launcher_menu_popup_destroyed                (gpointer               user_data);
+static gboolean        launcher_menu_popup                          (gpointer               user_data);
+static void            launcher_menu_deactivated                    (LauncherPlugin        *launcher);
+static void            launcher_menu_destroy                        (LauncherPlugin        *launcher);
+static void            launcher_menu_rebuild                        (LauncherPlugin        *launcher);
+static LauncherPlugin *launcher_plugin_new                          (XfcePanelPlugin       *plugin) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+static void            launcher_plugin_pack_buttons                 (LauncherPlugin        *launcher);
+static gchar          *launcher_plugin_read_entry                   (XfceRc                *rc,
+                                                                     const gchar           *name) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+static GtkArrowType    launcher_plugin_calculate_arrow_type         (XfcePanelPlugin       *panel_plugin);
+static void            launcher_plugin_screen_position_changed      (LauncherPlugin        *launcher);
+static void            launcher_plugin_orientation_changed          (LauncherPlugin        *launcher);
+static gboolean        launcher_plugin_set_size                     (LauncherPlugin        *launcher,
+                                                                     guint                  size);
+static void            launcher_plugin_free                         (LauncherPlugin        *launcher);
+static void            launcher_plugin_construct                    (XfcePanelPlugin       *plugin);
 
 
 
-/* global setting */
-static gboolean move_first = FALSE;
-
-
-
 /* register the plugin */
-XFCE_PANEL_PLUGIN_REGISTER_INTERNAL (launcher_construct);
+XFCE_PANEL_PLUGIN_REGISTER_INTERNAL (launcher_plugin_construct);
 
 
 
 /**
- * Utility functions
+ * Utility Functions
  **/
-void
-launcher_g_list_swap (GList *li_a,
-                          GList *li_b)
-{
-    gpointer data;
-
-    /* swap data between the items */
-    data = li_a->data;
-    li_a->data = li_b->data;
-    li_b->data = data;
-}
-
-
-
-static void
-launcher_g_list_move_first (GList *li)
-{
-    /* quit if we're not going to sort */
-    if (move_first == FALSE)
-        return;
-
-    /* swap items till we reached the beginning of the list */
-    while (li->prev != NULL)
-{
-        launcher_g_list_swap (li, li->prev);
-        li = li->prev;
-    }
-}
-
-
-
-/**
- * Miscelanious function
- **/
 static gboolean
-launcher_theme_changed (GSignalInvocationHint *ihint,
-                        guint                  n_param_values,
-                        const GValue          *param_values,
-                        LauncherPlugin        *launcher)
+launcher_utility_icon_theme_changed (GSignalInvocationHint *ihint,
+                                     guint                  n_param_values,
+                                     const GValue          *param_values,
+                                     LauncherPlugin        *launcher)
 {
     /* only update if we already have an image, this fails when the signal is connected */
     if (G_LIKELY (gtk_image_get_storage_type (GTK_IMAGE (launcher->image)) == GTK_IMAGE_EMPTY))
         return TRUE;
 
-    /* update the icon button */
-    launcher->icon_update_required = TRUE;
-    launcher_button_update (launcher);
+    /* update the button icon */
+    launcher_icon_button_set_icon (launcher);
 
     /* destroy the menu */
-    launcher_menu_prepare (launcher);
+    launcher_menu_destroy (launcher);
 
     /* keep hook alive */
     return TRUE;
@@ -170,281 +133,304 @@
 
 
 
-GdkPixbuf *
-launcher_load_pixbuf (GtkWidget   *widget,
-                      const gchar *icon_name,
-                      guint        size,
-                      gboolean     fallback)
+GSList *
+launcher_utility_filenames_from_selection_data (GtkSelectionData *selection_data)
 {
-    GdkPixbuf    *icon = NULL;
-    GdkPixbuf    *icon_scaled;
-    GtkIconTheme *icon_theme;
+    gchar  **uri_list;
+    GSList  *filenames = NULL;
+    gchar   *filename;
+    guint    i;
 
-    if (G_LIKELY (icon_name != NULL) &&
-          G_UNLIKELY (g_path_is_absolute (icon_name)))
+    /* check whether the retrieval worked */
+    if (G_LIKELY (selection_data->length > 0))
     {
-        /* load the icon from the file */
-        icon = exo_gdk_pixbuf_new_from_file_at_max_size (icon_name, size, size, TRUE, NULL);
-    }
-    else if (G_LIKELY (icon_name != NULL))
-    {
-        /* determine the appropriate icon theme */
-        if (G_LIKELY (gtk_widget_has_screen (widget)))
-            icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
-        else
-            icon_theme = gtk_icon_theme_get_default ();
+        /* split the received uri list */
+        uri_list = g_uri_list_extract_uris ((gchar *) selection_data->data);
 
-        /* try to load the named icon */
-        icon = gtk_icon_theme_load_icon (icon_theme, icon_name, size, 0, NULL);
-    }
+        if (G_LIKELY (uri_list))
+        {
+            /* walk though the list */
+            for (i = 0; uri_list[i] != NULL; i++)
+            {
+                /* convert the uri to a filename */
+                filename = g_filename_from_uri (uri_list[i], NULL, NULL);
 
-    /* scale down the icon (function above is a convenience function) */
-    if (G_LIKELY (icon != NULL))
-    {
-        /* scale down the icon if required */
-        icon_scaled = exo_gdk_pixbuf_scale_down (icon, TRUE, size, size);
-        g_object_unref (G_OBJECT (icon));
-        icon = icon_scaled;
+                /* prepend the filename */
+                if (G_LIKELY (filename))
+                    filenames = g_slist_prepend (filenames, filename);
+            }
+
+            /* cleanup */
+            g_strfreev (uri_list);
+
+            /* reverse the list */
+            filenames = g_slist_reverse (filenames);
+        }
     }
-    else if (fallback) /* create empty pixbuf */
-    {
-        /* this is a transparent pixbuf, used for tree convenience */
-        icon = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, size, size);
-        gdk_pixbuf_fill (icon, 0x00000000);
-    }
 
-    return icon;
+    return filenames;
 }
 
 
 
-void
-launcher_set_move_first (gboolean activate)
+GdkPixbuf *
+launcher_utility_load_pixbuf (GdkScreen   *screen,
+                              const gchar *name,
+                              guint        size)
 {
-    /* set the value of the move first boolean */
-    move_first = activate;
-}
+    GdkPixbuf    *pixbuf = NULL;
+    GdkPixbuf    *scaled;
+    GtkIconTheme *theme;
 
+    if (G_LIKELY (name))
+    {
+        if (g_path_is_absolute (name))
+        {
+            /* load the icon from the file */
+            pixbuf = exo_gdk_pixbuf_new_from_file_at_max_size (name, size, size, TRUE, NULL);
+        }
+        else
+        {
+            /* determine the appropriate icon theme */
+            if (G_LIKELY (screen))
+                theme = gtk_icon_theme_get_for_screen (screen);
+            else
+                theme = gtk_icon_theme_get_default ();
 
+            /* try to load the named icon */
+            pixbuf = gtk_icon_theme_load_icon (theme, name, size, 0, NULL);
 
-/**
- * Drag and Drop
- **/
-static void
-launcher_button_drag_data_received (GtkWidget        *widget,
-                                    GdkDragContext   *context,
-                                    gint              x,
-                                    gint              y,
-                                    GtkSelectionData *selection_data,
-                                    guint             info,
-                                    guint             time,
-                                    LauncherPlugin   *launcher)
-{
-    /* run the 'entry' dnd with first item from the list */
-    launcher_menu_drag_data_received (widget, context, x, y,
-                                      selection_data, info, time,
-                                      g_list_first (launcher->entries)->data);
+            if (G_LIKELY (pixbuf))
+            {
+                /* scale down the icon if required */
+                scaled = exo_gdk_pixbuf_scale_down (pixbuf, TRUE, size, size);
+                g_object_unref (G_OBJECT (pixbuf));
+                pixbuf = scaled;
+            }
+        }
+    }
+
+    return pixbuf;
 }
 
 
 
-static void
-launcher_menu_drag_data_received (GtkWidget        *widget,
-                                  GdkDragContext   *context,
-                                  gint              x,
-                                  gint              y,
-                                  GtkSelectionData *selection_data,
-                                  guint             info,
-                                  guint             time,
-                                  LauncherEntry    *entry)
+#if LAUNCHER_NEW_TOOLTIP_API
+static gboolean
+launcher_utility_query_tooltip (GtkWidget     *widget,
+                                gint           x,
+                                gint           y,
+                                gboolean       keyboard_mode,
+                                GtkTooltip    *tooltip,
+                                LauncherEntry *entry)
 {
-    GSList *file_list = NULL;
+    gchar     *string;
+    GdkPixbuf *pixbuf;
 
-    /* create list from all the uri list */
-    file_list = launcher_file_list_from_selection (selection_data);
-
-    if (G_LIKELY (file_list != NULL))
+    /* create tooltip text */
+    if (G_LIKELY (entry && entry->name))
     {
-        launcher_execute (gtk_widget_get_screen (widget), entry, file_list);
+        if (entry->comment)
+            string = g_strdup_printf ("<b>%s</b>\n%s", entry->name, entry->comment);
+        else
+            string = g_strdup_printf ("%s", entry->name);
 
+        /* set the markup tooltip */
+        gtk_tooltip_set_markup (tooltip, string);
+
         /* cleanup */
-        g_slist_free_all (file_list);
+        g_free (string);
+
+        if (G_LIKELY (entry->icon))
+        {
+            /* try to load an pixbuf */
+            pixbuf = launcher_utility_load_pixbuf (gtk_widget_get_screen (widget), entry->icon,
+                                                   LAUNCHER_TOOLTIP_SIZE);
+
+            if (G_LIKELY (pixbuf))
+            {
+                /* set the tooltip icon */
+                gtk_tooltip_set_icon (tooltip, pixbuf);
+
+                /* releases */
+                g_object_unref (G_OBJECT (pixbuf));
+            }
+        }
+
+        /* show the tooltip */
+        return TRUE;
     }
 
-    /* finish drag */
-    gtk_drag_finish (context, TRUE, FALSE, time);
+    /* nothing to show */
+    return FALSE;
 }
+#endif
 
 
 
-GSList *
-launcher_file_list_from_selection (GtkSelectionData *selection_data)
+/**
+ * Icon Button Functions
+ **/
+static gboolean
+launcher_icon_button_expose_event (GtkWidget      *widget,
+                                   GdkEventExpose *event,
+                                   LauncherPlugin *launcher)
 {
-    gchar  **uri_list;
-    GSList  *file_list = NULL;
-    gchar   *filename;
-    guint    i;
+    gint         x, y, w;
+    GtkArrowType arrow_type;
 
-    /* check whether the retrieval worked */
-    if (G_LIKELY (selection_data->length > 0))
+    /* only show the arrow when the arrow button is hidden */
+    if (launcher->arrow_position == LAUNCHER_ARROW_INSIDE_BUTTON)
     {
-        /* split the received uri list */
-        uri_list = g_uri_list_extract_uris ((gchar *) selection_data->data);
+        /* calculate the width of the arrow */
+        w = widget->allocation.width / 3;
 
-        /* walk though the list */
-        for (i = 0; uri_list[i] != NULL; i++)
+        /* get the arrow type */
+        arrow_type = xfce_arrow_button_get_arrow_type (XFCE_ARROW_BUTTON (launcher->arrow_button));
+
+        /* start coordinates */
+        x = widget->allocation.x;
+        y = widget->allocation.y;
+
+        /* calculate the position based on the arrow type */
+        switch (arrow_type)
         {
-            /* escape the ascii-encoded uri */
-            filename = g_filename_from_uri (uri_list[i], NULL, NULL);
+            case GTK_ARROW_UP:
+                /* north east */
+                x += (widget->allocation.width - w);
+                break;
 
-            /* append the uri, if uri -> filename conversion failed */
-            if (G_UNLIKELY (filename == NULL))
-                filename = g_strdup (uri_list[i]);
+            case GTK_ARROW_DOWN:
+                /* south west */
+                y += (widget->allocation.height - w);
+                break;
 
-            /* append the filename */
-            file_list = g_slist_append (file_list, filename);
+            case GTK_ARROW_RIGHT:
+                /* south east */
+                x += (widget->allocation.width - w);
+                y += (widget->allocation.height - w);
+                break;
+
+            default:
+                /* north west */
+                break;
         }
 
-        /* cleanup */
-        g_strfreev (uri_list);
+        /* paint the arrow */
+        gtk_paint_arrow (widget->style, widget->window,
+                         GTK_WIDGET_STATE (widget), GTK_SHADOW_IN,
+                         &(event->area), widget, "launcher_button",
+                         arrow_type, TRUE, x, y, w, w);
     }
 
-    return file_list;
+    return FALSE;
 }
 
 
 
-/**
- * (Icon) Button Functions
- **/
-gboolean
-launcher_button_update (LauncherPlugin *launcher)
+static void
+launcher_icon_button_set_icon (LauncherPlugin *launcher)
 {
-    GdkPixbuf     *icon;
+    GdkPixbuf     *pixbuf;
     LauncherEntry *entry;
-    guint          size;
-    gchar         *tooltip = NULL;
+    GdkScreen     *screen;
 
-    /* safety check */
-    if (G_UNLIKELY (g_list_length (launcher->entries) == 0))
-        return FALSE;
-
-    /* get first entry */
+    /* get the first entry in the list */
     entry = g_list_first (launcher->entries)->data;
 
-    /* check if we really need to update the button icon */
-    if (launcher->icon_update_required == FALSE)
-        goto updatetooltip;
+    /* get widget screen */
+    screen = gtk_widget_get_screen (launcher->image);
 
-    /* reset button update */
-    launcher->icon_update_required = FALSE;
+    /* try to load the file */
+    pixbuf = launcher_utility_load_pixbuf (screen, entry->icon, launcher->image_size);
 
-    /* calculate icon size */
-    size = xfce_panel_plugin_get_size (XFCE_PANEL_PLUGIN (launcher->plugin))
-           - 2 - 2 * MAX (launcher->iconbutton->style->xthickness,
-                          launcher->iconbutton->style->ythickness);
-
-    /* load the pixbuf, we use the fallback image here because else
-     * the theme signal fails when xfce-mcs-manager restarts */
-    icon = launcher_load_pixbuf (launcher->iconbutton, entry->icon, size, TRUE);
-
-    /* set the new button icon */
-    if (G_LIKELY (icon != NULL))
+    if (G_LIKELY (pixbuf))
     {
-        gtk_image_set_from_pixbuf (GTK_IMAGE (launcher->image), icon);
-
-        /* release the icon */
-        g_object_unref (G_OBJECT (icon));
+        /* set the image and release the pixbuf */
+        gtk_image_set_from_pixbuf (GTK_IMAGE (launcher->image), pixbuf);
+        g_object_unref (G_OBJECT (pixbuf));
     }
     else
     {
-        /* clear image if no (valid) icon is set */
+        /* clear the image */
         gtk_image_clear (GTK_IMAGE (launcher->image));
     }
-
-updatetooltip:
-
-    /* create tooltip text */
-    if (G_LIKELY (entry->name))
-    {
-        if (entry->comment)
-            tooltip = g_strdup_printf ("%s\n%s", entry->name, entry->comment);
-        else
-            tooltip = g_strdup_printf ("%s", entry->name);
-    }
-
-    /* set the tooltip */
-    gtk_tooltips_set_tip (launcher->tips, launcher->iconbutton,
-                          tooltip, NULL);
-
-    /* free string */
-    if (G_LIKELY (tooltip))
-        g_free (tooltip);
-
-    return FALSE;
 }
 
 
 
-static void
-launcher_button_state_changed (GtkWidget    *button_a,
-                               GtkStateType  state,
-                               GtkWidget    *button_b)
+#if LAUNCHER_NEW_TOOLTIP_API
+static gboolean
+launcher_icon_button_query_tooltip (GtkWidget      *widget,
+                                    gint            x,
+                                    gint            y,
+                                    gboolean        keyboard_mode,
+                                    GtkTooltip     *tooltip,
+                                    LauncherPlugin *launcher)
 {
-    if (GTK_WIDGET_STATE (button_b) != GTK_WIDGET_STATE (button_a) &&
-        GTK_WIDGET_STATE (button_a) != GTK_STATE_INSENSITIVE)
-    {
-        /* sync the button states */
-        gtk_widget_set_state (button_b, GTK_WIDGET_STATE (button_a));
-    }
+    /* don't show tooltips on a menu button */
+    if (launcher->arrow_position == LAUNCHER_ARROW_INSIDE_BUTTON)
+       return FALSE;
+
+    return launcher_utility_query_tooltip (widget, x, y, keyboard_mode, tooltip,
+                                           g_list_first (launcher->entries)->data);
 }
 
 
 
+#else
 static void
-launcher_button_clicked (GtkWidget      *button,
-                         LauncherPlugin *launcher)
+launcher_icon_button_set_tooltip (LauncherPlugin *launcher)
 {
     LauncherEntry *entry;
+    gchar         *string = NULL;
 
-    /* remove popup timeout */
-    if (launcher->popup_timeout_id)
+    /* get first entry */
+    entry = g_list_first (launcher->entries)->data;
+
+    /* create tooltip text */
+    if (G_LIKELY (entry->name && launcher->arrow_position != LAUNCHER_ARROW_INSIDE_BUTTON))
     {
-        g_source_remove (launcher->popup_timeout_id);
-        launcher->popup_timeout_id = 0;
+        if (entry->comment)
+            string = g_strdup_printf ("%s\n%s", entry->name, entry->comment);
+        else
+            string = g_strdup_printf ("%s", entry->name);
     }
 
-    /* get first entry */
-    entry = g_list_first (launcher->entries)->data;
+    /* set the tooltip */
+    gtk_tooltips_set_tip (launcher->tips, launcher->icon_button, string, NULL);
 
-    /* execute command */
-    launcher_execute (gtk_widget_get_screen (button), entry, NULL);
+    /* cleanup */
+    g_free (string);
 }
+#endif
 
 
 
 static gboolean
-launcher_button_pressed (LauncherPlugin  *launcher,
-                         GdkEventButton  *ev)
+launcher_icon_button_pressed (GtkWidget      *button,
+                              GdkEventButton *event,
+                              LauncherPlugin *launcher)
 {
     guint modifiers;
 
-    modifiers = gtk_accelerator_get_default_mod_mask ();
+    /* get the default accelerator modifier mask */
+    modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
 
-    /* exit if control is pressed, or pressed != button 1 */
-    if (G_LIKELY (ev->button != 1) ||
-        (ev->button == 1 && (ev->state & modifiers) == GDK_CONTROL_MASK))
-    {
+    /* exit if another button then 1 is pressed or control is hold */
+    if (event->button != 1 || modifiers == GDK_CONTROL_MASK)
         return FALSE;
-    }
 
-    /* start new popup timeout */
-    if (launcher->popup_timeout_id == 0)
+    /* popup the menu or start the popup timeout */
+    if (launcher->arrow_position == LAUNCHER_ARROW_INSIDE_BUTTON)
     {
+        launcher_menu_popup (launcher);
+    }
+    else if (launcher->popup_timeout_id == 0 && g_list_length (launcher->entries) > 1)
+    {
         launcher->popup_timeout_id =
-            g_timeout_add (MENU_POPUP_DELAY,
-                           (GSourceFunc) launcher_menu_popup,
-                           launcher);
+            g_timeout_add_full (G_PRIORITY_DEFAULT, LAUNCHER_POPUP_DELAY, launcher_menu_popup,
+                                launcher, launcher_menu_popup_destroyed);
     }
 
     return FALSE;
@@ -453,25 +439,31 @@
 
 
 static gboolean
-launcher_button_released (GtkWidget       *button,
-                          GdkEventButton  *ev,
-                          LauncherPlugin  *launcher)
+launcher_icon_button_released (GtkWidget      *button,
+                               GdkEventButton *event,
+                               LauncherPlugin *launcher)
 {
     LauncherEntry *entry;
+    GdkScreen     *screen;
 
-    /* stop the timeout (from button press) if it's still running */
-    if (launcher->popup_timeout_id > 0)
-    {
+    /* remove the timeout */
+    if (G_LIKELY (launcher->popup_timeout_id > 0))
         g_source_remove (launcher->popup_timeout_id);
-        launcher->popup_timeout_id = 0;
-    }
 
-    /* if button is 2, start command with arg from clipboard */
-    if (ev->button == 2)
+    /* only accept click in the button and don't respond on multiple clicks */
+    if (GTK_BUTTON (button)->in_button && launcher->arrow_position != LAUNCHER_ARROW_INSIDE_BUTTON)
     {
+        /* get the first launcher entry */
         entry = g_list_first (launcher->entries)->data;
 
-        launcher_execute_from_clipboard (gtk_widget_get_screen (button), entry);
+        /* get the widget screen */
+        screen = gtk_widget_get_screen (button);
+
+        /* execute the command on button 1 and 2 */
+        if (event->button == 1)
+            launcher_execute (screen, entry, NULL);
+        else if (event->button == 2)
+            launcher_execute_from_clipboard (screen, entry);
     }
 
     return FALSE;
@@ -479,71 +471,125 @@
 
 
 
-/**
- * Arrow button functions
- **/
-static gboolean
-launcher_arrow_pressed (LauncherPlugin  *launcher,
-                        GdkEventButton  *ev)
+static void
+launcher_icon_button_drag_data_received (GtkWidget        *widget,
+                                         GdkDragContext   *context,
+                                         gint              x,
+                                         gint              y,
+                                         GtkSelectionData *selection_data,
+                                         guint             info,
+                                         guint             time,
+                                         LauncherPlugin   *launcher)
 {
-    /* only popup on 1st button */
-    if (G_UNLIKELY (ev->button != 1))
-        return FALSE;
+    GSList        *filenames;
+    LauncherEntry *entry;
 
-    /* popup menu */
-    launcher_menu_popup (launcher);
+    /* execute */
+    if (launcher->arrow_position != LAUNCHER_ARROW_INSIDE_BUTTON)
+    {
+        /* create filenames list from all the uris */
+        filenames = launcher_utility_filenames_from_selection_data (selection_data);
 
-    return FALSE;
+        if (G_LIKELY (filenames))
+        {
+            /* get entry */
+            entry = g_list_first (launcher->entries)->data;
+
+            /* execute the entry with the filenames */
+            launcher_execute (gtk_widget_get_screen (widget), entry, filenames);
+
+            /* cleanup */
+            launcher_free_filenames (filenames);
+        }
+    }
+
+    /* finish drag */
+    gtk_drag_finish (context, TRUE, FALSE, time);
 }
 
 
 
+/**
+ * Arrow Button Functions
+ **/
 static gboolean
-launcher_arrow_drag_motion (GtkToggleButton *button,
-                            GdkDragContext  *drag_context,
-                            gint             x,
-                            gint             y,
-                            guint            time,
-                            LauncherPlugin  *launcher)
+launcher_arrow_button_pressed (GtkWidget      *button,
+                               GdkEventButton *event,
+                               LauncherPlugin *launcher)
 {
-    /* we need to popup the menu to allow a drop in a menu item, but
-     * since there is no good way to do this (because the pointer is grabbed)
-     * we do nothing... */
-    return TRUE;
+    /* only popup on 1st button */
+    if (event->button == 1)
+        launcher_menu_popup (launcher);
+
+    return FALSE;
 }
 
 
 
 /**
- * Menu functions
+ * Global Button Functions
  **/
 static void
-launcher_menu_item_activate (GtkWidget     *mi,
-                             GList         *li)
+launcher_button_state_changed (GtkWidget    *button_a,
+                               GtkStateType  state,
+                               GtkWidget    *button_b)
 {
-    /* execute command */
-    launcher_execute (gtk_widget_get_screen (mi), li->data, NULL);
-
-    /* reorder list, if needed */
-    launcher_g_list_move_first (li);
+    if (GTK_WIDGET_STATE (button_b) != GTK_WIDGET_STATE (button_a)
+        && GTK_WIDGET_STATE (button_a) != GTK_STATE_INSENSITIVE)
+    {
+        /* sync the button states */
+        gtk_widget_set_state (button_b, GTK_WIDGET_STATE (button_a));
+    }
 }
 
 
 
+/**
+ * Menu Functions
+ **/
 static gboolean
 launcher_menu_item_released (GtkWidget      *mi,
-                             GdkEventButton *ev,
-                             GList          *li)
+                             GdkEventButton *event,
+                             LauncherPlugin *launcher)
 {
-    if (ev->button == 2)
+    GdkScreen     *screen;
+    gint           i;
+    LauncherEntry *entry;
+
+    /* get the widget screen */
+    screen = gtk_widget_get_screen (mi);
+
+    /* get the item number */
+    i = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (mi), I_("entry-number")));
+
+    /* get the entry from the list */
+    entry = g_list_nth_data (launcher->entries, i);
+
+    if (G_LIKELY (entry))
     {
-        /* execute command with arg from clipboard */
-        launcher_execute_from_clipboard (gtk_widget_get_screen (mi), li->data);
+        if (event->button == 1)
+            launcher_execute (screen, entry, NULL);
+        else if (event->button == 2)
+            launcher_execute_from_clipboard (screen, entry);
 
-        /* reorder list, if needed */
-        launcher_g_list_move_first (li);
+        /* move the item to the first position in the list */
+        if (G_UNLIKELY (launcher->move_first && i > 0))
+        {
+            /* remove from the list */
+            launcher->entries = g_list_remove (launcher->entries, entry);
 
-        return TRUE;
+            /* insert in first position */
+            launcher->entries = g_list_prepend (launcher->entries, entry);
+
+            /* destroy the menu */
+            launcher_menu_destroy (launcher);
+
+            /* rebuild the icon button */
+            launcher_icon_button_set_icon (launcher);
+#if !LAUNCHER_NEW_TOOLTIP_API
+            launcher_icon_button_set_tooltip (launcher);
+#endif
+        }
     }
 
     return FALSE;
@@ -552,98 +598,75 @@
 
 
 static void
-launcher_menu_position (GtkMenu   *menu,
-                        gint      *x,
-                        gint      *y,
-                        gboolean  *push_in,
-                        GtkWidget *button)
+launcher_menu_position (GtkMenu        *menu,
+                        gint           *x,
+                        gint           *y,
+                        gboolean       *push_in,
+                        LauncherPlugin *launcher)
 {
-    GtkWidget      *widget;
+    GtkWidget      *widget = GTK_WIDGET (launcher->panel_plugin);
     GtkRequisition  req;
-    GdkScreen      *screen;
-    GdkRectangle    geom;
-    gint            num;
 
     if (!GTK_WIDGET_REALIZED (GTK_WIDGET (menu)))
         gtk_widget_realize (GTK_WIDGET (menu));
 
     gtk_widget_size_request (GTK_WIDGET (menu), &req);
-
-    widget = button->parent->parent;
     gdk_window_get_origin (widget->window, x, y);
 
-    widget = button->parent;
-
-    switch (xfce_arrow_button_get_arrow_type (XFCE_ARROW_BUTTON (button)))
+    switch (xfce_arrow_button_get_arrow_type (XFCE_ARROW_BUTTON (launcher->arrow_button)))
     {
         case GTK_ARROW_UP:
-            *x += widget->allocation.x;
-            *y += widget->allocation.y - req.height;
+            *y -= req.height;
             break;
 
         case GTK_ARROW_DOWN:
-            *x += widget->allocation.x;
-            *y += widget->allocation.y + widget->allocation.height;
+            *y += widget->allocation.height;
             break;
 
         case GTK_ARROW_LEFT:
-            *x += widget->allocation.x - req.width;
-            *y += widget->allocation.y - req.height
-                  + widget->allocation.height;
+            *x -= req.width;
             break;
 
         default: /* GTK_ARROW_RIGHT and GTK_ARROW_NONE */
-            *x += widget->allocation.x + widget->allocation.width;
-            *y += widget->allocation.y - req.height
-                  + widget->allocation.height;
+            *x += widget->allocation.width;
             break;
     }
+}
 
-    screen = gtk_widget_get_screen (widget);
 
-    num = gdk_screen_get_monitor_at_window (screen, widget->window);
 
-    gdk_screen_get_monitor_geometry (screen, num, &geom);
+static void
+launcher_menu_popup_destroyed (gpointer user_data)
+{
+    LauncherPlugin *launcher = user_data;
 
-    if (*x > geom.x + geom.width - req.width)
-        *x = geom.x + geom.width - req.width;
-    if (*x < geom.x)
-        *x = geom.x;
-
-    if (*y > geom.y + geom.height - req.height)
-        *y = geom.y + geom.height - req.height;
-    if (*y < geom.y)
-        *y = geom.y;
+    launcher->popup_timeout_id = 0;
 }
 
 
 
 static gboolean
-launcher_menu_popup (LauncherPlugin *launcher)
+launcher_menu_popup (gpointer user_data)
 {
-    /* stop timeout if needed */
-    if (launcher->popup_timeout_id > 0)
-    {
-        g_source_remove (launcher->popup_timeout_id);
-        launcher->popup_timeout_id = 0;
-    }
+    LauncherPlugin *launcher = user_data;
 
-    /* check if menu is needed, or it needs an update */
-    if (g_list_length (launcher->entries) <= 1)
-        return FALSE;
-    else if (launcher->menu == NULL)
-        launcher_menu_update (launcher);
+    GDK_THREADS_ENTER ();
 
+    /* check if the menu exists, if not, rebuild it */
+    if (launcher->menu == NULL)
+        launcher_menu_rebuild (launcher);
+
     /* toggle the arrow button */
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (launcher->arrowbutton), TRUE);
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (launcher->arrow_button), TRUE);
 
     /* popup menu */
     gtk_menu_popup (GTK_MENU (launcher->menu), NULL, NULL,
                     (GtkMenuPositionFunc) launcher_menu_position,
-                    launcher->arrowbutton, 0,
-                    gtk_get_current_event_time ());
+                    launcher, 1, gtk_get_current_event_time ());
 
-    return TRUE;
+    GDK_THREADS_LEAVE ();
+
+    return FALSE;
 }
 
 
@@ -652,544 +675,673 @@
 launcher_menu_deactivated (LauncherPlugin *launcher)
 {
     /* deactivate arrow button */
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (launcher->arrowbutton), FALSE);
-
-    /* rebuild menu and button */
-    if (move_first)
-    {
-        launcher->icon_update_required = TRUE;
-        g_idle_add ((GSourceFunc) launcher_button_update, launcher);
-
-        g_idle_add ((GSourceFunc) launcher_menu_prepare, launcher);
-    }
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (launcher->arrow_button), FALSE);
 }
 
 
 
-gboolean
-launcher_menu_prepare (LauncherPlugin *launcher)
+static void
+launcher_menu_destroy (LauncherPlugin *launcher)
 {
     if (launcher->menu != NULL)
     {
-        g_signal_emit_by_name (G_OBJECT (launcher->menu), "deactivate");
+        /* destroy the menu and null the variable */
         gtk_widget_destroy (launcher->menu);
         launcher->menu = NULL;
+
+        /* deactivate arrow button */
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (launcher->arrow_button), FALSE);
     }
 
-    /* show or hide the arrow button */
-    if (g_list_length (launcher->entries) <= 1)
-        gtk_widget_hide (launcher->arrowbutton);
+    /* set the visibility of the arrow button */
+    if (launcher->arrow_position == LAUNCHER_ARROW_INSIDE_BUTTON ||
+        g_list_length (launcher->entries) < 2)
+    {
+        gtk_widget_hide (launcher->arrow_button);
+    }
     else
-        gtk_widget_show (launcher->arrowbutton);
-
-    return FALSE;
+    {
+        gtk_widget_show (launcher->arrow_button);
+    }
 }
 
 
 
 static void
-launcher_menu_update (LauncherPlugin *launcher)
+launcher_menu_rebuild (LauncherPlugin *launcher)
 {
+    GdkScreen     *screen;
     GList         *li;
+    guint          n = 0;
+    LauncherEntry *entry;
     GtkWidget     *mi, *image;
-    GdkPixbuf     *icon;
-    LauncherEntry *entry;
+    GdkPixbuf     *pixbuf;
 
-    /* destroy the old menu, if needed */
-    if (G_UNLIKELY (launcher->menu != NULL))
-        launcher_menu_prepare (launcher);
+    /* destroy the old menu */
+    if (G_UNLIKELY (launcher->menu))
+        launcher_menu_destroy (launcher);
 
     /* create new menu */
     launcher->menu = gtk_menu_new ();
 
-    /* make sure the menu popups up in right screen */
-    gtk_menu_set_screen (GTK_MENU (launcher->menu),
-                         gtk_widget_get_screen (GTK_WIDGET (launcher->plugin)));
+    /* get the plugin screen */
+    screen = gtk_widget_get_screen (GTK_WIDGET (launcher->panel_plugin));
 
-    /* append all entries, except first one */
-    for (li = g_list_nth (launcher->entries, 1); li != NULL; li = li->next)
+    /* set the menu screen */
+    gtk_menu_set_screen (GTK_MENU (launcher->menu), screen);
+
+    /* walk through the entries */
+    for (li = launcher->entries; li != NULL; li = li->next, n++)
     {
+        /* skip the first entry when the arrow is visible */
+        if (n == 0 && launcher->arrow_position != LAUNCHER_ARROW_INSIDE_BUTTON)
+            continue;
+
         entry = li->data;
 
-        /* create new menu item */
+        /* create menu item */
         mi = gtk_image_menu_item_new_with_label (entry->name ? entry->name : _("New Item"));
+        gtk_menu_shell_prepend (GTK_MENU_SHELL (launcher->menu), mi);
         gtk_widget_show (mi);
-        gtk_menu_shell_prepend (GTK_MENU_SHELL (launcher->menu), mi);
 
-        /* load and set menu icon */
-        icon = launcher_load_pixbuf (launcher->iconbutton, entry->icon, MENU_ICON_SIZE, FALSE);
-
-        if (G_LIKELY (icon != NULL))
+        /* try to set an image */
+        if (G_LIKELY (entry->icon))
         {
-            image = gtk_image_new_from_pixbuf (icon);
-            gtk_widget_show (image);
-            gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
+            /* load pixbuf */
+            pixbuf = launcher_utility_load_pixbuf (screen, entry->icon, LAUNCHER_MENU_SIZE);
 
-            /* release pixbuf */
-            g_object_unref (G_OBJECT (icon));
+            if (G_LIKELY (pixbuf))
+            {
+                /* set image */
+                image = gtk_image_new_from_pixbuf (pixbuf);
+                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
+                gtk_widget_show (image);
+
+                /* release reference */
+                g_object_unref (G_OBJECT (pixbuf));
+            }
         }
 
+        /* set entries list number */
+        g_object_set_data (G_OBJECT (mi), I_("entry-number"), GINT_TO_POINTER (n));
+
         /* connect signals */
-        g_signal_connect (G_OBJECT (mi), "activate",
-                          G_CALLBACK (launcher_menu_item_activate), li);
+        g_signal_connect (G_OBJECT (mi), "button-release-event", G_CALLBACK (launcher_menu_item_released), launcher);
+#if LAUNCHER_NEW_TOOLTIP_API
+        g_object_set (G_OBJECT (mi), "has-tooltip", TRUE, NULL);
+        g_signal_connect (G_OBJECT (mi), "query-tooltip", G_CALLBACK (launcher_utility_query_tooltip), entry);
+#endif
 
-        g_signal_connect (G_OBJECT (mi), "button-release-event",
-                          G_CALLBACK (launcher_menu_item_released), li);
-
         /* dnd support */
-        gtk_drag_dest_set (mi, GTK_DEST_DEFAULT_ALL,
-                           drop_targets, G_N_ELEMENTS (drop_targets),
-                           GDK_ACTION_COPY);
+        gtk_drag_dest_set (mi, GTK_DEST_DEFAULT_ALL, drop_targets, G_N_ELEMENTS (drop_targets), GDK_ACTION_COPY);
 
-        g_signal_connect (G_OBJECT (mi), "drag-data-received",
-                          G_CALLBACK (launcher_menu_drag_data_received), entry);
-
+#if !LAUNCHER_NEW_TOOLTIP_API
         /* set tooltip */
-        if (G_LIKELY (entry->comment))
+        if (entry->comment)
             gtk_tooltips_set_tip (launcher->tips, mi, entry->comment, NULL);
+#endif
     }
 
     /* connect deactivate signal */
-    g_signal_connect_swapped (G_OBJECT (launcher->menu), "deactivate",
-                                G_CALLBACK (launcher_menu_deactivated), launcher);
+    g_signal_connect_swapped (G_OBJECT (launcher->menu), "deactivate", G_CALLBACK (launcher_menu_deactivated), launcher);
 }
 
 
 
 /**
- * Save and load settings
+ * Entry Functions
  **/
-static gchar *
-launcher_read_entry (XfceRc      *rc,
-                         const gchar *name)
+LauncherEntry *
+launcher_entry_new (void)
 {
-    const gchar *temp;
-    gchar       *value = NULL;
+    LauncherEntry *entry;
 
-    temp = xfce_rc_read_entry (rc, name, NULL);
-    if (G_LIKELY (temp != NULL && *temp != '\0'))
-        value = g_strdup (temp);
+    /* allocate structure */
+    entry = panel_slice_new0 (LauncherEntry);
 
-    return value;
+    /* set some default values */
+    entry->name    = g_strdup (_("New Item"));
+    entry->comment = NULL;
+    entry->icon    = g_strdup ("applications-other");
+
+    /* fill others */
+    entry->exec     = NULL;
+    entry->path     = NULL;
+    entry->terminal = FALSE;
+#ifdef HAVE_LIBSTARTUP_NOTIFICATION
+    entry->startup  = FALSE;
+#endif
+
+    return entry;
 }
 
 
 
 void
-launcher_read (LauncherPlugin *launcher)
+launcher_entry_free (LauncherEntry  *entry,
+                     LauncherPlugin *launcher)
 {
-    gchar         *file;
-    gchar          group[10];
-    XfceRc        *rc;
-    guint          i;
-    LauncherEntry *entry;
+    /* remove from the list */
+    if (G_LIKELY (launcher))
+        launcher->entries = g_list_remove (launcher->entries, entry);
 
-    /* get rc file name, create it if needed */
-    file = xfce_panel_plugin_lookup_rc_file (launcher->plugin);
+    /* free variables */
+    g_free (entry->name);
+    g_free (entry->comment);
+    g_free (entry->path);
+    g_free (entry->icon);
+    g_free (entry->exec);
 
-    if (G_UNLIKELY (file == NULL))
-        return;
+    /* free structure */
+    panel_slice_free (LauncherEntry, entry);
+}
 
-    /* open rc, read-only */
-    rc = xfce_rc_simple_open (file, TRUE);
-    g_free (file);
 
-    if (G_UNLIKELY (rc == NULL))
-        return;
 
-    /* read global settings */
-    xfce_rc_set_group (rc, "Global");
+/**
+ * Panel Plugin Functions
+ **/
+static LauncherPlugin*
+launcher_plugin_new (XfcePanelPlugin *plugin)
+{
+    LauncherPlugin *launcher;
+    gpointer        klass;
 
-    launcher->move_first = xfce_rc_read_bool_entry (rc, "MoveFirst", FALSE);
+    /* create launcher structure */
+    launcher = panel_slice_new0 (LauncherPlugin);
 
-    for (i = 0; i < 100 /* arbitrary */; ++i)
-    {
-        /* create group name */
-        g_snprintf (group, sizeof (group), "Entry %d", i);
+    /* init */
+    launcher->panel_plugin = plugin;
+    launcher->menu = NULL;
+    launcher->plugin_can_save = TRUE;
 
-        /* break if no more entries found */
-        if (xfce_rc_has_group (rc, group) == FALSE)
-            break;
+#if !LAUNCHER_NEW_TOOLTIP_API
+    /* create tooltips */
+    launcher->tips = gtk_tooltips_new ();
+    exo_gtk_object_ref_sink (GTK_OBJECT (launcher->tips));
+#endif
 
-        /* set the group */
-        xfce_rc_set_group (rc, group);
+    /* create widgets */
+    launcher->box = xfce_hvbox_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
+    gtk_container_add (GTK_CONTAINER (plugin), launcher->box);
+    gtk_widget_show (launcher->box);
 
-        /* create new entry structure */
-        entry = panel_slice_new0 (LauncherEntry);
+    launcher->icon_button = xfce_create_panel_button ();
+    gtk_box_pack_start (GTK_BOX (launcher->box), launcher->icon_button, TRUE, TRUE, 0);
+    gtk_widget_show (launcher->icon_button);
 
-        /* read all the entry settings */
-        entry->name = launcher_read_entry (rc, "Name");
-        entry->comment = launcher_read_entry (rc, "Comment");
-        entry->icon = launcher_read_entry (rc, "Icon");
-        entry->exec = launcher_read_entry (rc, "Exec");
-        entry->path = launcher_read_entry (rc, "Path");
+    launcher->image = gtk_image_new ();
+    gtk_container_add (GTK_CONTAINER (launcher->icon_button), launcher->image);
+    gtk_widget_show (launcher->image);
 
-        entry->terminal = xfce_rc_read_bool_entry (rc, "Terminal", FALSE);
-#ifdef HAVE_LIBSTARTUP_NOTIFICATION
-        entry->startup = xfce_rc_read_bool_entry (rc, "StartupNotify", FALSE);
+    launcher->arrow_button = xfce_arrow_button_new (GTK_ARROW_UP);
+    GTK_WIDGET_UNSET_FLAGS (launcher->arrow_button, GTK_CAN_DEFAULT | GTK_CAN_FOCUS);
+    gtk_box_pack_start (GTK_BOX (launcher->box), launcher->arrow_button, FALSE, FALSE, 0);
+    gtk_button_set_relief (GTK_BUTTON (launcher->arrow_button), GTK_RELIEF_NONE);
+    gtk_button_set_focus_on_click (GTK_BUTTON (launcher->arrow_button), FALSE);
+
+    /* hook for icon themes changes */
+    klass = g_type_class_ref (GTK_TYPE_ICON_THEME);
+    launcher->theme_timeout_id =
+        g_signal_add_emission_hook (g_signal_lookup ("changed", GTK_TYPE_ICON_THEME),
+                                    0, (GSignalEmissionHook) launcher_utility_icon_theme_changed,
+                                    launcher, NULL);
+    g_type_class_unref (klass);
+
+    /* icon button signals */
+    g_signal_connect (G_OBJECT (launcher->icon_button), "state-changed",
+                      G_CALLBACK (launcher_button_state_changed), launcher->arrow_button);
+    g_signal_connect (G_OBJECT (launcher->icon_button), "button-press-event",
+                      G_CALLBACK (launcher_icon_button_pressed), launcher);
+    g_signal_connect (G_OBJECT (launcher->icon_button), "button-release-event",
+                      G_CALLBACK (launcher_icon_button_released), launcher);
+    g_signal_connect (G_OBJECT (launcher->icon_button), "drag-data-received",
+                      G_CALLBACK (launcher_icon_button_drag_data_received), launcher);
+    g_signal_connect_after (G_OBJECT (launcher->image), "expose-event",
+                            G_CALLBACK (launcher_icon_button_expose_event), launcher);
+
+#if LAUNCHER_NEW_TOOLTIP_API
+    g_object_set (G_OBJECT (launcher->icon_button), "has-tooltip", TRUE, NULL);
+    g_signal_connect (G_OBJECT (launcher->icon_button), "query-tooltip",
+                      G_CALLBACK (launcher_icon_button_query_tooltip), launcher);
 #endif
-        /* append the entry */
-        launcher->entries = g_list_append (launcher->entries, entry);
-    }
 
-    /* close the rc file */
-    xfce_rc_close (rc);
-}
+    /* arrow button signals */
+    g_signal_connect (G_OBJECT (launcher->arrow_button), "state-changed",
+                      G_CALLBACK (launcher_button_state_changed), launcher->icon_button);
+    g_signal_connect (G_OBJECT (launcher->arrow_button), "button-press-event",
+                      G_CALLBACK (launcher_arrow_button_pressed), launcher);
 
+    /* set drag destinations */
+    gtk_drag_dest_set (launcher->icon_button, GTK_DEST_DEFAULT_ALL,
+                       drop_targets, G_N_ELEMENTS (drop_targets),
+                       GDK_ACTION_COPY);
+    gtk_drag_dest_set (launcher->arrow_button, GTK_DEST_DEFAULT_ALL,
+                       drop_targets, G_N_ELEMENTS (drop_targets),
+                       GDK_ACTION_COPY);
 
+    /* read the user settings */
+    launcher_plugin_read (launcher);
 
-void
-launcher_write (LauncherPlugin *launcher)
-{
-    gchar          *file;
-    gchar         **groups;
-    gchar           group[10];
-    XfceRc         *rc;
-    GList          *li;
-    guint           i = 0, n;
-    guint           block;
-    LauncherEntry  *entry;
+    /* add new entry if the list is empty */
+    if (G_UNLIKELY (g_list_length (launcher->entries) == 0))
+        launcher->entries = g_list_prepend (launcher->entries, launcher_entry_new ());
 
-    /* HACK:
-     * sometimes the panel emits a save signal, this is cool, unless we're working
-     * in the properties dialog. This because the cancel button won't work then. */
-    block = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (launcher->plugin),
-                                                "xfce-panel-plugin-block"));
-    if (G_UNLIKELY (block > 0))
-        return;
+    /* set the arrow direction */
+    launcher_plugin_screen_position_changed (launcher);
 
-    /* get rc file name, create it if needed */
-    file = xfce_panel_plugin_save_location (launcher->plugin, TRUE);
+    /* set the buttons in the correct position */
+    launcher_plugin_pack_buttons (launcher);
 
-    if (G_UNLIKELY (file == NULL))
-        return;
+    /* change the visiblity of the arrow button */
+    launcher_menu_destroy (launcher);
 
-    /* open rc, read/write */
-    rc = xfce_rc_simple_open (file, FALSE);
-    g_free (file);
+#if !LAUNCHER_NEW_TOOLTIP_API
+    /* set the button tooltip */
+    launcher_icon_button_set_tooltip (launcher);
+#endif
 
-    if (G_UNLIKELY (rc == NULL))
-        return;
+    return launcher;
+}
 
-    /* retreive all the groups in the config file */
-    groups = xfce_rc_get_groups (rc);
 
-    /* remove all the groups
-     * note: you can use g_unlink to remove the file, but first you need some
-     * stdio library and some benchmarking showed this is almost 2x faster for
-     * 'normal' situations */
-    for (n = 0; groups[n] != NULL; ++n)
-        xfce_rc_delete_group (rc, groups[n], TRUE);
 
-    /* cleanup */
-    g_strfreev (groups);
+void
+launcher_plugin_rebuild (LauncherPlugin *launcher,
+                         gboolean        update_icon)
+{
+    /* pack buttons again */
+    launcher_plugin_pack_buttons (launcher);
 
-    /* save global launcher settings */
-    xfce_rc_set_group (rc, "Global");
+    /* size */
+    launcher_plugin_set_size (launcher, xfce_panel_plugin_get_size (launcher->panel_plugin));
 
-    xfce_rc_write_bool_entry (rc, "MoveFirst", launcher->move_first);
+#if !LAUNCHER_NEW_TOOLTIP_API
+    /* update tooltip */
+    launcher_icon_button_set_tooltip (launcher);
+#endif
 
-    /* save all the entries */
-    for (li = launcher->entries; li != NULL; li = li->next, ++i)
-    {
-        entry = li->data;
+    if (update_icon)
+        launcher_icon_button_set_icon (launcher);
 
-        /* set entry group */
-        g_snprintf (group, sizeof (group), "Entry %d", i);
-        xfce_rc_set_group (rc, group);
+    /* destroy menu */
+    launcher_menu_destroy (launcher);
+}
 
-        /* write entry settings */
-        if (G_LIKELY (entry->name))
-            xfce_rc_write_entry (rc, "Name", entry->name);
 
-        if (G_LIKELY (entry->comment))
-            xfce_rc_write_entry (rc, "Comment", entry->comment);
 
-        if (G_LIKELY (entry->icon))
-            xfce_rc_write_entry (rc, "Icon", entry->icon);
+static void
+launcher_plugin_pack_buttons (LauncherPlugin *launcher)
+{
+    GtkOrientation orientation;
+    guint          position = launcher->arrow_position;
+    gint           box_position, width = -1, height = -1;
 
-        if (G_LIKELY (entry->exec))
-            xfce_rc_write_entry (rc, "Exec", entry->exec);
+    if (position == LAUNCHER_ARROW_DEFAULT)
+    {
+        /* get the current panel orientation */
+        orientation = xfce_panel_plugin_get_orientation (launcher->panel_plugin);
 
-        if (G_LIKELY (entry->path))
-            xfce_rc_write_entry (rc, "Path", entry->path);
+        /* get the arrow position in the default layout */
+        if (orientation == GTK_ORIENTATION_HORIZONTAL)
+            position = LAUNCHER_ARROW_RIGHT;
+        else
+            position = LAUNCHER_ARROW_BOTTOM;
+    }
+    else if (position == LAUNCHER_ARROW_INSIDE_BUTTON)
+    {
+        /* nothing to arrange */
+        return;
+    }
 
-        xfce_rc_write_bool_entry (rc, "Terminal", entry->terminal);
-#ifdef HAVE_LIBSTARTUP_NOTIFICATION
-        xfce_rc_write_bool_entry (rc, "StartupNotify", entry->startup);
-#endif
+    /* set the arrow button position in the box */
+    box_position = (position == LAUNCHER_ARROW_LEFT || position == LAUNCHER_ARROW_TOP) ? 0 : -1;
+    gtk_box_reorder_child (GTK_BOX (launcher->box), launcher->arrow_button, box_position);
+
+    /* set the arrow button size and box orientation */
+    if (position == LAUNCHER_ARROW_LEFT || position == LAUNCHER_ARROW_RIGHT)
+    {
+        orientation = GTK_ORIENTATION_HORIZONTAL;
+        width = LAUNCHER_ARROW_SIZE;
     }
+    else
+    {
+        orientation = GTK_ORIENTATION_VERTICAL;
+        height = LAUNCHER_ARROW_SIZE;
+    }
 
-    /* close the rc file */
-    xfce_rc_close (rc);
+    gtk_widget_set_size_request (launcher->arrow_button, width, height);
+    xfce_hvbox_set_orientation (XFCE_HVBOX (launcher->box), orientation);
+
+    /* set the visibility of the arrow button */
+    if (g_list_length (launcher->entries) > 1)
+        gtk_widget_show (launcher->arrow_button);
+    else
+        gtk_widget_hide (launcher->arrow_button);
 }
 
 
 
-LauncherEntry *
-launcher_new_entry (void)
+static gchar *
+launcher_plugin_read_entry (XfceRc      *rc,
+                            const gchar *name)
 {
-    LauncherEntry *entry;
+    const gchar *temp;
+    gchar       *value = NULL;
 
-    /* create new entry slice */
-    entry = panel_slice_new0 (LauncherEntry);
+    temp = xfce_rc_read_entry (rc, name, NULL);
+    if (G_LIKELY (temp != NULL && *temp != '\0'))
+        value = g_strdup (temp);
 
-    /* set some default values */
-    entry->name    = g_strdup (_("New Item"));
-    entry->comment = NULL; /* _("This item has not yet been configured")); */
-    entry->icon    = g_strdup ("applications-other");
-
-    /* fill others */
-    entry->exec     = NULL;
-    entry->path     = NULL;
-    entry->terminal = FALSE;
-#ifdef HAVE_LIBSTARTUP_NOTIFICATION
-    entry->startup  = FALSE;
-#endif
-
-    return entry;
+    return value;
 }
 
 
 
-/**
- * Plugin create function and signal handling
- **/
-static LauncherPlugin*
-launcher_new (XfcePanelPlugin *plugin)
+void
+launcher_plugin_read (LauncherPlugin *launcher)
 {
-    LauncherPlugin     *launcher;
-    LauncherEntry      *entry;
-    GtkWidget          *box;
-    XfceScreenPosition  position;
-    gpointer            klass;
+    gchar         *file;
+    gchar          group[10];
+    XfceRc        *rc;
+    guint          i;
+    LauncherEntry *entry;
 
-    /* get panel information */
-    position = xfce_panel_plugin_get_screen_position (plugin);
+    /* get rc file name, create it if needed */
+    file = xfce_panel_plugin_lookup_rc_file ( launcher->panel_plugin);
+    if (G_LIKELY (file))
+    {
+        /* open config file, read-only */
+        rc = xfce_rc_simple_open (file, TRUE);
 
-    launcher = panel_slice_new0 (LauncherPlugin);
+        /* cleanup */
+        g_free (file);
 
-    /* link plugin */
-    launcher->plugin = plugin;
+        if (G_LIKELY (rc))
+        {
+            /* read global settings */
+            xfce_rc_set_group (rc, "Global");
 
-    /* defaults */
-    launcher->menu = NULL;
+            launcher->move_first = xfce_rc_read_bool_entry (rc, "MoveFirst", FALSE);
+            launcher->arrow_position = xfce_rc_read_int_entry (rc, "ArrowPosition", 0);
 
-    /* create tooltips */
-    launcher->tips = gtk_tooltips_new ();
-    exo_gtk_object_ref_sink (GTK_OBJECT (launcher->tips));
+            for (i = 0; i < 100 /* arbitrary */; ++i)
+            {
+                /* create group name */
+                g_snprintf (group, sizeof (group), "Entry %d", i);
 
-    /* create widgets */
-    box = xfce_hvbox_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
-    gtk_container_add (GTK_CONTAINER (plugin), box);
-    gtk_widget_show (box);
+                /* break if no more entries found */
+                if (xfce_rc_has_group (rc, group) == FALSE)
+                    break;
 
-    launcher->iconbutton = xfce_create_panel_button ();
-    gtk_widget_show (launcher->iconbutton);
-    gtk_box_pack_start (GTK_BOX (box), launcher->iconbutton, TRUE, TRUE, 0);
+                /* set the group */
+                xfce_rc_set_group (rc, group);
 
-    gtk_drag_dest_set (launcher->iconbutton, GTK_DEST_DEFAULT_ALL,
-                       drop_targets, G_N_ELEMENTS (drop_targets),
-                       GDK_ACTION_COPY);
+                /* create new entry structure */
+                entry = panel_slice_new0 (LauncherEntry);
 
-    launcher->image = gtk_image_new ();
-    gtk_widget_show (launcher->image);
-    gtk_container_add (GTK_CONTAINER (launcher->iconbutton), launcher->image);
+                /* read all the entry settings */
+                entry->name = launcher_plugin_read_entry (rc, "Name");
+                entry->comment = launcher_plugin_read_entry (rc, "Comment");
+                entry->icon = launcher_plugin_read_entry (rc, "Icon");
+                entry->exec = launcher_plugin_read_entry (rc, "Exec");
+                entry->path = launcher_plugin_read_entry (rc, "Path");
 
-    launcher->arrowbutton = xfce_arrow_button_new (GTK_ARROW_UP);
-    GTK_WIDGET_UNSET_FLAGS (launcher->arrowbutton, GTK_CAN_DEFAULT|GTK_CAN_FOCUS);
-    gtk_box_pack_start (GTK_BOX (box), launcher->arrowbutton, FALSE, FALSE, 0);
-    gtk_widget_set_size_request (launcher->arrowbutton, ARROW_WIDTH, ARROW_WIDTH);
-    gtk_button_set_relief (GTK_BUTTON (launcher->arrowbutton), GTK_RELIEF_NONE);
-    gtk_button_set_focus_on_click (GTK_BUTTON (launcher->arrowbutton), FALSE);
+                entry->terminal = xfce_rc_read_bool_entry (rc, "Terminal", FALSE);
+#ifdef HAVE_LIBSTARTUP_NOTIFICATION
+                entry->startup = xfce_rc_read_bool_entry (rc, "StartupNotify", FALSE);
+#endif
+                /* prepend the entry */
+                launcher->entries = g_list_prepend (launcher->entries, entry);
+            }
 
-    gtk_drag_dest_set (launcher->arrowbutton, GTK_DEST_DEFAULT_ALL,
-                       drop_targets, G_N_ELEMENTS (drop_targets),
-                       GDK_ACTION_COPY);
+            /* reverse the list */
+            launcher->entries = g_list_reverse (launcher->entries);
 
-    /* signals for button state sync */
-    g_signal_connect (G_OBJECT (launcher->iconbutton), "state-changed",
-                      G_CALLBACK (launcher_button_state_changed), launcher->arrowbutton);
-    g_signal_connect (G_OBJECT (launcher->arrowbutton), "state-changed",
-                      G_CALLBACK (launcher_button_state_changed), launcher->iconbutton);
+            /* close the rc file */
+            xfce_rc_close (rc);
+        }
+    }
+}
 
-    /* hook for icon themes changes */
-    klass = g_type_class_ref (GTK_TYPE_ICON_THEME);
-    launcher->theme_timeout_id = g_signal_add_emission_hook (g_signal_lookup ("changed", GTK_TYPE_ICON_THEME),
-                                                             0, (GSignalEmissionHook) launcher_theme_changed,
-                                                             launcher, NULL);
-    g_type_class_unref (klass);
 
-    /* icon button signals */
-    g_signal_connect (G_OBJECT (launcher->iconbutton), "clicked",
-                      G_CALLBACK (launcher_button_clicked), launcher);
 
-    g_signal_connect_swapped (G_OBJECT (launcher->iconbutton), "button-press-event",
-                              G_CALLBACK (launcher_button_pressed), launcher);
+void
+launcher_plugin_save (LauncherPlugin *launcher)
+{
+    gchar          *file;
+    gchar         **groups;
+    gchar           group[10];
+    XfceRc         *rc;
+    GList          *li;
+    guint           i;
+    LauncherEntry  *entry;
 
-    g_signal_connect (G_OBJECT (launcher->iconbutton), "button-release-event",
-                      G_CALLBACK (launcher_button_released), launcher);
+    /* check if it's allowed to save */
+    if (G_UNLIKELY (launcher->plugin_can_save == FALSE))
+        return;
 
-    g_signal_connect (G_OBJECT (launcher->iconbutton), "drag-data-received",
-                      G_CALLBACK (launcher_button_drag_data_received), launcher);
+    /* get rc file name, create it if needed */
+    file = xfce_panel_plugin_save_location ( launcher->panel_plugin, TRUE);
+    if (G_LIKELY (file))
+    {
+        /* open the config file, writable */
+        rc = xfce_rc_simple_open (file, FALSE);
 
-    /* this signal with update the button (show icon) when the button is realizde */
-    launcher->icon_update_required = TRUE;
-    g_signal_connect_swapped (G_OBJECT (launcher->iconbutton), "realize",
-                              G_CALLBACK (launcher_button_update), launcher);
+        /* cleanup */
+        g_free (file);
 
-    /* arrow button signals */
-    g_signal_connect_swapped (G_OBJECT (launcher->arrowbutton), "button-press-event",
-                              G_CALLBACK (launcher_arrow_pressed), launcher);
+        if (G_LIKELY (rc))
+        {
+            /* retreive all the groups in the config file */
+            groups = xfce_rc_get_groups (rc);
+            if (G_LIKELY (groups))
+            {
+                /* remove all the groups */
+                for (i = 0; groups[i] != NULL; i++)
+                    xfce_rc_delete_group (rc, groups[i], TRUE);
 
-    g_signal_connect (G_OBJECT (launcher->arrowbutton), "drag-motion",
-                      G_CALLBACK (launcher_arrow_drag_motion), launcher);
+                /* cleanup */
+                g_strfreev (groups);
+            }
 
-    /* read the user settings */
-    launcher_read (launcher);
+            /* save global launcher settings */
+            xfce_rc_set_group (rc, "Global");
+            xfce_rc_write_bool_entry (rc, "MoveFirst", launcher->move_first);
+            xfce_rc_write_int_entry (rc, "ArrowPosition", launcher->arrow_position);
 
-    /* set move_first boolean */
-    launcher_set_move_first (launcher->move_first);
+            /* save all the entries */
+            for (li = launcher->entries, i = 0; li != NULL; li = li->next, i++)
+            {
+                entry = li->data;
 
-    /* append new entry if no entries loaded */
-    if (G_UNLIKELY (g_list_length (launcher->entries) == 0))
-    {
-          entry = launcher_new_entry ();
+                /* create group name */
+                g_snprintf (group, sizeof (group), "Entry %d", i);
 
-          launcher->entries = g_list_append (launcher->entries, entry);
-    }
+                /* set entry group */
+                xfce_rc_set_group (rc, group);
 
-    /* set arrow position */
-    launcher_screen_position_changed (launcher, position);
+                /* write entry settings */
+                if (G_LIKELY (entry->name))
+                    xfce_rc_write_entry (rc, "Name", entry->name);
+                if (G_LIKELY (entry->comment))
+                    xfce_rc_write_entry (rc, "Comment", entry->comment);
+                if (G_LIKELY (entry->icon))
+                    xfce_rc_write_entry (rc, "Icon", entry->icon);
+                if (G_LIKELY (entry->exec))
+                    xfce_rc_write_entry (rc, "Exec", entry->exec);
+                if (G_LIKELY (entry->path))
+                    xfce_rc_write_entry (rc, "Path", entry->path);
+                xfce_rc_write_bool_entry (rc, "Terminal", entry->terminal);
+#ifdef HAVE_LIBSTARTUP_NOTIFICATION
+                xfce_rc_write_bool_entry (rc, "StartupNotify", entry->startup);
+#endif
+            }
 
-    /* prepare the menu */
-    launcher_menu_prepare (launcher);
-
-    return launcher;
+            /* close the rc file */
+            xfce_rc_close (rc);
+        }
+    }
 }
 
 
 
 static GtkArrowType
-launcher_calculate_floating_arrow (LauncherPlugin     *launcher,
-                                   XfceScreenPosition  position)
+launcher_plugin_calculate_arrow_type (XfcePanelPlugin *panel_plugin)
 {
-    gint          mon, x, y;
-    GdkScreen    *screen;
-    GdkRectangle  geom;
+    XfceScreenPosition  position;
+    GdkScreen          *screen;
+    GdkRectangle        geom;
+    gint                mon, x, y;
 
-    if (!GTK_WIDGET_REALIZED (launcher->iconbutton))
-    {
-        if (xfce_screen_position_is_horizontal (position))
-            return GTK_ARROW_UP;
-        else
-            return GTK_ARROW_LEFT;
-    }
+    g_return_val_if_fail (GTK_WIDGET_REALIZED (panel_plugin), GTK_ARROW_UP);
 
-    screen = gtk_widget_get_screen (launcher->iconbutton);
-    mon = gdk_screen_get_monitor_at_window (screen, launcher->iconbutton->window);
-    gdk_screen_get_monitor_geometry (screen, mon, &geom);
-    gdk_window_get_root_origin (launcher->iconbutton->window, &x, &y);
+    /* get the plugin position */
+    position = xfce_panel_plugin_get_screen_position (panel_plugin);
 
-    if (xfce_screen_position_is_horizontal (position))
+    /* get the arrow direction */
+    switch (position)
     {
-        if (y > geom.y + geom.height / 2)
-            return GTK_ARROW_UP;
-        else
+        /* top */
+        case XFCE_SCREEN_POSITION_NW_H:
+        case XFCE_SCREEN_POSITION_N:
+        case XFCE_SCREEN_POSITION_NE_H:
             return GTK_ARROW_DOWN;
-    }
-    else
-    {
-        if (x > geom.x + geom.width / 2)
+
+        /* left */
+        case XFCE_SCREEN_POSITION_NW_V:
+        case XFCE_SCREEN_POSITION_W:
+        case XFCE_SCREEN_POSITION_SW_V:
+            return GTK_ARROW_RIGHT;
+
+        /* right */
+        case XFCE_SCREEN_POSITION_NE_V:
+        case XFCE_SCREEN_POSITION_E:
+        case XFCE_SCREEN_POSITION_SE_V:
             return GTK_ARROW_LEFT;
-        else
-            return GTK_ARROW_RIGHT;
+
+        /* bottom */
+        case XFCE_SCREEN_POSITION_SW_H:
+        case XFCE_SCREEN_POSITION_S:
+        case XFCE_SCREEN_POSITION_SE_H:
+            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 ((y < (geom.y + geom.height / 2)) ? GTK_ARROW_DOWN : GTK_ARROW_UP);
+            else
+                return ((x < (geom.x + geom.width / 2)) ? GTK_ARROW_RIGHT : GTK_ARROW_LEFT);
     }
 }
 
 
 
 static void
-launcher_screen_position_changed (LauncherPlugin     *launcher,
-                                  XfceScreenPosition  position)
+launcher_plugin_screen_position_changed (LauncherPlugin *launcher)
 {
-    GtkArrowType type;
+    GtkArrowType arrow_type;
 
-    if (xfce_screen_position_is_bottom (position))
-        type = GTK_ARROW_UP;
-    else if (xfce_screen_position_is_top (position))
-        type = GTK_ARROW_DOWN;
-    else if (xfce_screen_position_is_left (position))
-        type = GTK_ARROW_RIGHT;
-    else if (xfce_screen_position_is_right (position))
-        type = GTK_ARROW_LEFT;
-    else /* floating */
-        type = launcher_calculate_floating_arrow (launcher, position);
+    /* get the arrow type */
+    arrow_type = launcher_plugin_calculate_arrow_type (launcher->panel_plugin);
 
     /* set the arrow direction */
-    xfce_arrow_button_set_arrow_type (XFCE_ARROW_BUTTON (launcher->arrowbutton), type);
+    xfce_arrow_button_set_arrow_type (XFCE_ARROW_BUTTON (launcher->arrow_button), arrow_type);
 }
 
 
 
 static void
-launcher_orientation_changed (LauncherPlugin  *launcher,
-                              GtkOrientation   orientation)
+launcher_plugin_orientation_changed (LauncherPlugin *launcher)
 {
-    /* noting yet */
+    /* set the arrow direction */
+    launcher_plugin_screen_position_changed (launcher);
+
+    /* reorder the boxes again */
+    launcher_plugin_pack_buttons (launcher);
 }
 
 
 
 static gboolean
-launcher_set_size (LauncherPlugin  *launcher,
-                       guint            size)
+launcher_plugin_set_size (LauncherPlugin  *launcher,
+                          guint            size)
 {
-    /* set fixed button size */
-    gtk_widget_set_size_request (launcher->iconbutton, size, size);
+    gint            width = size, height = size;
+    GtkOrientation  orientation;
+    GtkWidget      *widget = launcher->icon_button;
 
-    /* reload the icon button */
-    if (GTK_WIDGET_REALIZED (launcher->iconbutton))
+    if (g_list_length (launcher->entries) > 1)
     {
-        launcher->icon_update_required = TRUE;
-        launcher_button_update (launcher);
-    }
+        /* get the orientation of the panel */
+        orientation = xfce_panel_plugin_get_orientation (launcher->panel_plugin);
 
-    return TRUE;
-}
+        switch (launcher->arrow_position)
+        {
+            case LAUNCHER_ARROW_DEFAULT:
+                if (orientation == GTK_ORIENTATION_HORIZONTAL)
+                    width += LAUNCHER_ARROW_SIZE;
+                else
+                    height += LAUNCHER_ARROW_SIZE;
 
+                break;
 
+            case LAUNCHER_ARROW_LEFT:
+            case LAUNCHER_ARROW_RIGHT:
+                if (orientation == GTK_ORIENTATION_HORIZONTAL)
+                    width += LAUNCHER_ARROW_SIZE;
+                else
+                    height -= LAUNCHER_ARROW_SIZE;
 
-void
-launcher_free_entry (LauncherEntry  *entry,
-                     LauncherPlugin *launcher)
-{
-    /* remove from the list */
-    if (G_LIKELY (launcher != NULL))
-        launcher->entries = g_list_remove (launcher->entries, entry);
+                break;
 
-    /* free variables */
-    g_free (entry->name);
-    g_free (entry->comment);
-    g_free (entry->path);
-    g_free (entry->icon);
-    g_free (entry->exec);
+            case LAUNCHER_ARROW_TOP:
+            case LAUNCHER_ARROW_BOTTOM:
+                if (orientation == GTK_ORIENTATION_HORIZONTAL)
+                    width -= LAUNCHER_ARROW_SIZE;
+                else
+                    height += LAUNCHER_ARROW_SIZE;
 
-    /* free structure */
-    panel_slice_free (LauncherEntry, entry);
+                break;
+
+            default:
+                /* nothing to do for a hidden arrow button */
+                break;
+        }
+    }
+
+    /* calculate the image size inside the button */
+    launcher->image_size = MIN (width, height);
+    launcher->image_size -= 2 + 2 * MAX (widget->style->xthickness, widget->style->ythickness);
+
+    /* set the plugin size */
+    gtk_widget_set_size_request (GTK_WIDGET (launcher->panel_plugin), width, height);
+
+    /* update the icon button */
+    launcher_icon_button_set_icon (launcher);
+
+    /* we handled the size */
+    return TRUE;
 }
 
 
 
 static void
-launcher_free (LauncherPlugin *launcher)
+launcher_plugin_free (LauncherPlugin  *launcher)
 {
     GtkWidget *dialog;
 
-    /* check if we still need to destroy the dialog */
-    dialog = g_object_get_data (G_OBJECT (launcher->plugin), "dialog");
+    /* check if we still need to destroy the properties dialog */
+    dialog = g_object_get_data (G_OBJECT (launcher->panel_plugin), I_("launcher-dialog"));
     if (G_UNLIKELY (dialog != NULL))
-        gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
+        gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
 
     /* stop timeout */
     if (G_UNLIKELY (launcher->popup_timeout_id))
@@ -1204,12 +1356,13 @@
         gtk_widget_destroy (launcher->menu);
 
     /* remove the entries */
-    g_list_foreach (launcher->entries,
-                    (GFunc) launcher_free_entry, launcher);
+    g_list_foreach (launcher->entries, (GFunc) launcher_entry_free, launcher);
     g_list_free (launcher->entries);
 
+#if !LAUNCHER_NEW_TOOLTIP_API
     /* release the tooltips */
     g_object_unref (G_OBJECT (launcher->tips));
+#endif
 
     /* free launcher structure */
     panel_slice_free (LauncherPlugin, launcher);
@@ -1218,30 +1371,29 @@
 
 
 static void
-launcher_construct (XfcePanelPlugin *plugin)
+launcher_plugin_construct (XfcePanelPlugin *plugin)
 {
-    LauncherPlugin *launcher = launcher_new (plugin);
+    LauncherPlugin *launcher;
 
-    xfce_panel_plugin_add_action_widget (plugin, launcher->iconbutton);
-    xfce_panel_plugin_add_action_widget (plugin, launcher->arrowbutton);
+    /* create the plugin */
+    launcher = launcher_plugin_new (plugin);
+
+    /* set the action widgets and show configure */
+    xfce_panel_plugin_add_action_widget (plugin, launcher->icon_button);
+    xfce_panel_plugin_add_action_widget (plugin, launcher->arrow_button);
     xfce_panel_plugin_menu_show_configure (plugin);
 
     /* connect signals */
     g_signal_connect_swapped (G_OBJECT (plugin), "screen-position-changed",
-                              G_CALLBACK (launcher_screen_position_changed), launcher);
-
+                              G_CALLBACK (launcher_plugin_screen_position_changed), launcher);
     g_signal_connect_swapped (G_OBJECT (plugin), "orientation-changed",
-                              G_CALLBACK (launcher_orientation_changed), launcher);
-
+                              G_CALLBACK (launcher_plugin_orientation_changed), launcher);
     g_signal_connect_swapped (G_OBJECT (plugin), "size-changed",
-                              G_CALLBACK (launcher_set_size), launcher);
-
+                              G_CALLBACK (launcher_plugin_set_size), launcher);
+    g_signal_connect_swapped (G_OBJECT (plugin), "save",
+                              G_CALLBACK (launcher_plugin_save), launcher);
     g_signal_connect_swapped (G_OBJECT (plugin), "free-data",
-                      G_CALLBACK (launcher_free), launcher);
-
-    g_signal_connect_swapped (G_OBJECT (plugin), "save",
-                              G_CALLBACK (launcher_write), launcher);
-
+                              G_CALLBACK (launcher_plugin_free), launcher);
     g_signal_connect_swapped (G_OBJECT (plugin), "configure-plugin",
                               G_CALLBACK (launcher_dialog_show), launcher);
 }

Modified: xfce4-panel/trunk/plugins/launcher/launcher.h
===================================================================
--- xfce4-panel/trunk/plugins/launcher/launcher.h	2007-09-10 08:51:12 UTC (rev 26064)
+++ xfce4-panel/trunk/plugins/launcher/launcher.h	2007-09-10 12:04:49 UTC (rev 26065)
@@ -25,17 +25,24 @@
 #include <exo/exo.h>
 #include <libxfce4panel/xfce-panel-plugin.h>
 
-#define STARTUP_TIMEOUT   (30 * 1000)
-#define ARROW_WIDTH       16
-#define MENU_ICON_SIZE    24
-#define MENU_POPUP_DELAY  225
-#define BORDER            8
-#define TREE_ICON_SIZE    24
-#define CHOOSER_ICON_SIZE 48
+#define BORDER                     (8)
+#define LAUNCHER_NEW_TOOLTIP_API   (GTK_CHECK_VERSION (2,11,6))
+#define LAUNCHER_ARROW_SIZE        (16)
+#define LAUNCHER_POPUP_DELAY       (225)
+#define LAUNCHER_TOOLTIP_SIZE      (32)
+#define LAUNCHER_MENU_SIZE	       (24)
+#define LAUNCHER_STARTUP_TIMEOUT   (30 * 1000)
+#define LAUNCHER_TREE_ICON_SIZE    (24)
+#define LAUNCHER_CHOOSER_ICON_SIZE (48)
 
-#define g_free_null(mem)          g_free (mem); mem = NULL
-#define g_slist_free_all(list)    g_slist_foreach (list, (GFunc) g_free, NULL); g_slist_free (list)
 
+/* frequently used code */
+#define launcher_free_filenames(list) G_STMT_START{ \
+    g_slist_foreach (list, (GFunc) g_free, NULL); \
+    g_slist_free (list); \
+    }G_STMT_END
+
+
 typedef struct _LauncherEntry  LauncherEntry;
 typedef struct _LauncherPlugin LauncherPlugin;
 
@@ -55,48 +62,63 @@
 
 struct _LauncherPlugin
 {
-    /* globals */
-    XfcePanelPlugin *plugin;
-    GtkTooltips     *tips;
+    /* panel plugin */
+    XfcePanelPlugin *panel_plugin;
+
+    /* whether saving is allowed */
+    guint            plugin_can_save : 1;
+    gint             image_size;
+
+    /* list of launcher entries */
     GList           *entries;
 
-    /* cpu saver */
-    guint            icon_update_required : 1;
-
     /* panel widgets */
-    GtkWidget       *arrowbutton;
-    GtkWidget       *iconbutton;
+    GtkWidget       *box;
+    GtkWidget       *icon_button;
+    GtkWidget       *arrow_button;
     GtkWidget       *image;
     GtkWidget       *menu;
+#if !LAUNCHER_NEW_TOOLTIP_API
+    GtkTooltips     *tips;
+#endif
 
-    /* global settings */
-    guint            move_first : 1;
-
-    /* timeouts */
+    /* event source ids */
     guint            popup_timeout_id;
     guint            theme_timeout_id;
+
+    /* settings */
+    guint            move_first : 1;
+    guint            arrow_position;
 };
 
+enum
+{
+    LAUNCHER_ARROW_DEFAULT = 0,
+    LAUNCHER_ARROW_LEFT,
+    LAUNCHER_ARROW_RIGHT,
+    LAUNCHER_ARROW_TOP,
+    LAUNCHER_ARROW_BOTTOM,
+    LAUNCHER_ARROW_INSIDE_BUTTON
+};
+
 /* target types for dropping in the launcher plugin */
 static const GtkTargetEntry drop_targets[] =
 {
     { "text/uri-list", 0, 0, },
 };
 
-void                     launcher_g_list_swap                (GList              *li_a,
-                                                              GList              *li_b)           G_GNUC_INTERNAL;
-GdkPixbuf               *launcher_load_pixbuf                (GtkWidget          *widget,
-                                                              const gchar        *icon_name,
-                                                              guint               size,
-                                                              gboolean            fallback)       G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-void                     launcher_set_move_first             (gboolean            activate)       G_GNUC_INTERNAL;
-GSList                  *launcher_file_list_from_selection   (GtkSelectionData   *selection_data) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-gboolean                 launcher_button_update              (LauncherPlugin     *launcher)       G_GNUC_INTERNAL;
-gboolean                 launcher_menu_prepare               (LauncherPlugin     *launcher)       G_GNUC_INTERNAL;
-void                     launcher_read                       (LauncherPlugin     *launcher)       G_GNUC_INTERNAL;
-void                     launcher_write                      (LauncherPlugin     *launcher)       G_GNUC_INTERNAL;
-void                     launcher_free_entry                 (LauncherEntry      *entry,
-                                                              LauncherPlugin     *launcher)       G_GNUC_INTERNAL;
-LauncherEntry           *launcher_new_entry                  (void)                               G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
 
+
+GSList        *launcher_utility_filenames_from_selection_data (GtkSelectionData *selection_data) G_GNUC_MALLOC G_GNUC_INTERNAL;
+GdkPixbuf     *launcher_utility_load_pixbuf                   (GdkScreen        *screen,
+                                                               const gchar      *name,
+                                                               guint             size) G_GNUC_MALLOC G_GNUC_INTERNAL;
+LauncherEntry *launcher_entry_new                             (void) G_GNUC_MALLOC G_GNUC_INTERNAL;
+void           launcher_entry_free                            (LauncherEntry    *entry,
+                                                               LauncherPlugin   *launcher) G_GNUC_INTERNAL;
+void           launcher_plugin_rebuild                        (LauncherPlugin   *launcher,
+                                                               gboolean          update_icon) G_GNUC_INTERNAL;
+void           launcher_plugin_read                           (LauncherPlugin   *launcher) G_GNUC_INTERNAL;
+void           launcher_plugin_save                           (LauncherPlugin   *launcher) G_GNUC_INTERNAL;
+
 #endif /* !__XFCE_PANEL_LAUNCHER_H__ */

Modified: xfce4-panel/trunk/plugins/systray/xfce-tray-widget.c
===================================================================
--- xfce4-panel/trunk/plugins/systray/xfce-tray-widget.c	2007-09-10 08:51:12 UTC (rev 26064)
+++ xfce4-panel/trunk/plugins/systray/xfce-tray-widget.c	2007-09-10 12:04:49 UTC (rev 26065)
@@ -51,21 +51,21 @@
 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, 
+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     *