[Xfce4-commits] <xfce4-panel:devel> Initial launcher code

Nick Schermer nick at xfce.org
Tue Aug 11 20:26:38 CEST 2009


Updating branch refs/heads/devel
         to f5e0af0b8761c436c58d85feb7c4ee95f277a180 (commit)
       from a07574610ac7a98de9f768e0ec6a1bcf02292b06 (commit)

commit f5e0af0b8761c436c58d85feb7c4ee95f277a180
Author: Nick Schermer <nick at xfce.org>
Date:   Sat Feb 7 01:56:07 2009 +0100

    Initial launcher code

 panel-preferences.desktop.in           |    3 +-
 panel/panel-window.c                   |    9 +-
 plugins/launcher/launcher-dialog.c     |   52 ++-
 plugins/launcher/launcher-dialog.glade |   19 +-
 plugins/launcher/launcher.c            | 1465 +++++++++-----------------------
 plugins/launcher/launcher.h            |   88 +--
 6 files changed, 453 insertions(+), 1183 deletions(-)

diff --git a/panel-preferences.desktop.in b/panel-preferences.desktop.in
index b59f3be..6ab4bfd 100644
--- a/panel-preferences.desktop.in
+++ b/panel-preferences.desktop.in
@@ -9,6 +9,5 @@ Categories=X-XFCE;Settings;DesktopSettings;
 OnlyShowIn=XFCE;
 Terminal=false
 StartupNotify=true
-_GenericName=Panel Preferences
-_Name=Xfce 4 Panel Preferences
+_Name=Panel Preferences
 _Comment=Customize the Xfce Panel
diff --git a/panel/panel-window.c b/panel/panel-window.c
index cfed99e..87532c1 100644
--- a/panel/panel-window.c
+++ b/panel/panel-window.c
@@ -70,11 +70,10 @@ static void panel_window_struts_update (PanelWindow  *window, gint x, gint y, gi
 static void panel_window_set_colormap (PanelWindow *window);
 static void panel_window_get_position (PanelWindow *window, gint *root_x, gint *root_y);
 static void panel_window_set_borders (PanelWindow *window);
-static void panel_window_set_autohide (PanelWindow *window, gboolean     autohide);
+static void panel_window_set_autohide (PanelWindow *window, gboolean autohide);
 static void panel_window_menu_quit (gpointer boolean);
 static void panel_window_menu_deactivate (GtkMenu *menu, PanelWindow *window);
 static void panel_window_menu_popup (PanelWindow *window);
-
 static void panel_window_set_plugin_active_panel (GtkWidget *widget, gpointer user_data);
 static void panel_window_set_plugin_background_alpha (GtkWidget *widget, gpointer user_data);
 static void panel_window_set_plugin_size (GtkWidget *widget, gpointer user_data);
@@ -235,7 +234,7 @@ panel_window_class_init (PanelWindowClass *klass)
   gtkwidget_class->size_request = panel_window_size_request;
   gtkwidget_class->size_allocate = panel_window_size_allocate;
   gtkwidget_class->screen_changed = panel_window_screen_changed;
-
+  
   g_object_class_install_property (gobject_class,
                                    PROP_HORIZONTAL,
                                    g_param_spec_boolean ("horizontal", NULL, NULL,
@@ -305,7 +304,9 @@ panel_window_class_init (PanelWindowClass *klass)
   g_object_class_install_property (gobject_class,
                                    PROP_SNAP_EDGE,
                                    g_param_spec_uint ("snap-edge", NULL, NULL,
-                                                      PANEL_SNAP_EGDE_NONE, PANEL_SNAP_EGDE_S, PANEL_SNAP_EGDE_NONE,
+                                                      PANEL_SNAP_EGDE_NONE, 
+                                                      PANEL_SNAP_EGDE_S, 
+                                                      PANEL_SNAP_EGDE_NONE,
                                                       EXO_PARAM_READWRITE));
 
   /* initialize the atoms */
diff --git a/plugins/launcher/launcher-dialog.c b/plugins/launcher/launcher-dialog.c
index aff625b..c0456dc 100644
--- a/plugins/launcher/launcher-dialog.c
+++ b/plugins/launcher/launcher-dialog.c
@@ -42,6 +42,13 @@ typedef struct
 }
 LauncherPluginDialog;
 
+enum
+{
+  COL_ADD_ICON,
+  COL_ADD_NAME,
+  COL_ADD_FILENAME
+};
+
 
 
 static gboolean
@@ -66,7 +73,7 @@ launcher_dialog_add_visible_function (GtkTreeModel *model,
   text_casefolded = g_utf8_casefold (normalized, -1);
   g_free (normalized);
 
-  gtk_tree_model_get (model, iter, 0, &name, -1);
+  gtk_tree_model_get (model, iter, COL_ADD_NAME, &name, -1);
   if (G_LIKELY (name != NULL))
     {
       /* casefold the name */
@@ -97,13 +104,25 @@ launcher_dialog_add_store_insert (gpointer filename,
 {
   GtkListStore *store = GTK_LIST_STORE (user_data);
   GtkTreeIter   iter;
+  const gchar  *icon_name;
 
   panel_return_if_fail (XFCE_IS_MENU_ITEM (item));
   panel_return_if_fail (GTK_IS_LIST_STORE (user_data));
+  
+  /* TODO get rid of this and support absolute paths too */
+  icon_name = xfce_menu_item_get_icon_name (item);
+  if (icon_name != NULL
+      && (g_path_is_absolute (icon_name)
+          || !gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), icon_name)))
+    icon_name = NULL;
 
   /* insert the item */
   gtk_list_store_append (store, &iter);
-  gtk_list_store_set (store, &iter, 0, xfce_menu_item_get_name (item), -1);
+  gtk_list_store_set (store, &iter,
+                      COL_ADD_ICON, icon_name,
+                      COL_ADD_NAME, xfce_menu_item_get_name (item), 
+                      COL_ADD_FILENAME, xfce_menu_item_get_filename (item),
+                      -1);
 }
 
 
@@ -332,8 +351,31 @@ launcher_dialog_add_response (GtkWidget            *widget,
                               gint                  response_id,
                               LauncherPluginDialog *dialog)
 {
+  GObject          *treeview, *store;
+  GtkTreeSelection *selection;
+  GtkTreeModel     *model;
+  GtkTreeIter       iter;
+  gchar            *filename;
+
   panel_return_if_fail (GTK_IS_DIALOG (widget));
   panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (dialog->plugin));
+  
+  if (response_id != 0)
+    {
+      /* set the selected item in the treeview */
+      treeview = gtk_builder_get_object (dialog->builder, "add-treeview");
+      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+      if (gtk_tree_selection_get_selected (selection, &model, &iter))
+        {
+          gtk_tree_model_get (model, &iter, COL_ADD_FILENAME, &filename, -1);
+          
+          g_free (filename);
+        }
+    }
+  
+  /* empty the store */
+  store = gtk_builder_get_object (dialog->builder, "add-store");
+  gtk_list_store_clear (GTK_LIST_STORE (store));
 
   /* hide the dialog, since it's owned by gtkbuilder */
   gtk_widget_hide (widget);
@@ -406,7 +448,7 @@ launcher_dialog_show (LauncherPlugin *plugin)
       g_signal_connect (G_OBJECT (object), "delete-event", G_CALLBACK (exo_noop_true), NULL);
 
       object = gtk_builder_get_object (builder, "add-store");
-      gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (object), 0, GTK_SORT_ASCENDING);
+      gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (object), COL_ADD_NAME, GTK_SORT_ASCENDING);
 
       /* setup search filter in the add dialog */
       object = gtk_builder_get_object (builder, "add-store-filter");
@@ -414,6 +456,10 @@ launcher_dialog_show (LauncherPlugin *plugin)
       gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (object), launcher_dialog_add_visible_function, entry, NULL);
       g_signal_connect_swapped (G_OBJECT (entry), "changed", G_CALLBACK (gtk_tree_model_filter_refilter), object);
 
+      /* setup the icon size */
+      object = gtk_builder_get_object (builder, "addrenderericon");
+      g_object_set (G_OBJECT (object), "stock-size", GTK_ICON_SIZE_DND, NULL);
+
       /* show the dialog */
       gtk_widget_show (GTK_WIDGET (window));
     }
diff --git a/plugins/launcher/launcher-dialog.glade b/plugins/launcher/launcher-dialog.glade
index 0740111..ad98233 100644
--- a/plugins/launcher/launcher-dialog.glade
+++ b/plugins/launcher/launcher-dialog.glade
@@ -31,8 +31,12 @@
   </object>
   <object class="GtkListStore" id="add-store">
     <columns>
+      <!-- column-name icon -->
+      <column type="gchararray"/>
       <!-- column-name name -->
       <column type="gchararray"/>
+      <!-- column-name filename -->
+      <column type="gchararray"/>
     </columns>
   </object>
   <object class="GtkTreeModelFilter" id="add-store-filter">
@@ -267,6 +271,7 @@
                     <child>
                       <object class="GtkComboBox" id="arrow-position">
                         <property name="visible">True</property>
+                        <property name="model">arrow-position-store</property>
                         <property name="button_sensitivity">on</property>
                         <child>
                           <object class="GtkCellRendererText" id="cellrenderertext1"/>
@@ -351,7 +356,6 @@
   </object>
   <object class="XfceTitledDialog" id="dialog-editor">
     <property name="title" translatable="yes">Edit Custom Launcher</property>
-    <property name="modal">True</property>
     <property name="window_position">center-on-parent</property>
     <property name="destroy_with_parent">True</property>
     <property name="icon_name">applications-other</property>
@@ -637,7 +641,6 @@
   </object>
   <object class="XfceTitledDialog" id="dialog-add">
     <property name="title" translatable="yes">Add New Entry</property>
-    <property name="modal">True</property>
     <property name="window_position">center-on-parent</property>
     <property name="default_width">400</property>
     <property name="default_height">400</property>
@@ -703,11 +706,17 @@
                     <property name="enable_search">False</property>
                     <child>
                       <object class="GtkTreeViewColumn" id="treeviewcolumn1">
-                        <property name="title">Icon</property>
+                        <property name="spacing">2</property>
                         <child>
-                          <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                          <object class="GtkCellRendererPixbuf" id="addrenderericon"/>
                           <attributes>
-                            <attribute name="text">0</attribute>
+                            <attribute name="icon-name">0</attribute>
+                          </attributes>
+                        </child>
+                        <child>
+                          <object class="GtkCellRendererText" id="addrenderername"/>
+                          <attributes>
+                            <attribute name="text">1</attribute>
                           </attributes>
                         </child>
                       </object>
diff --git a/plugins/launcher/launcher.c b/plugins/launcher/launcher.c
index 1b94842..7c64ba7 100644
--- a/plugins/launcher/launcher.c
+++ b/plugins/launcher/launcher.c
@@ -19,25 +19,14 @@
 #include <config.h>
 #endif
 
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-
 #include <exo/exo.h>
+#include <xfconf/xfconf.h>
 #include <libxfce4util/libxfce4util.h>
 #include <libxfce4ui/libxfce4ui.h>
 
 #include "launcher.h"
 #include "launcher-dialog.h"
 
-#define MENU_POPUP_DELAY  (225)
-#define ARROW_BUTTON_SIZE (16)
-#define TOOLTIP_ICON_SIZE (32)
-#define MENU_ICON_SIZE    (24)
-
 
 
 static void launcher_plugin_construct (XfcePanelPlugin *panel_plugin);
@@ -47,33 +36,58 @@ static gboolean launcher_plugin_size_changed (XfcePanelPlugin *panel_plugin, gin
 static void launcher_plugin_save (XfcePanelPlugin *panel_plugin);
 static void launcher_plugin_configure_plugin (XfcePanelPlugin *panel_plugin);
 static void launcher_plugin_screen_position_changed (XfcePanelPlugin *panel_plugin, gint position);
-static void launcher_plugin_execute_string_append_quoted (GString *string, const gchar *unquoted);
-static gchar *launcher_plugin_execute_parse_command (LauncherPluginEntry *entry, GSList *file_list);
-static void launcher_plugin_execute (GdkScreen *screen, LauncherPluginEntry *entry, GSList *file_list);
-static void launcher_plugin_execute_from_clipboard (GdkScreen *screen, LauncherPluginEntry *entry);
-static void launcher_plugin_icon_theme_changed (GtkIconTheme *icon_theme, LauncherPlugin *plugin);
-static void launcher_plugin_update_icon (LauncherPlugin *plugin);
-static void launcher_plugin_reorder_buttons (LauncherPlugin *plugin);
-static gboolean launcher_plugin_read (LauncherPlugin *plugin);
+
 static void launcher_plugin_button_state_changed (GtkWidget *button_a, GtkStateType state, GtkWidget *button_b);
-static gboolean launcher_plugin_query_tooltip (GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip *tooltip, LauncherPluginEntry *entry);
-static gboolean launcher_plugin_icon_button_pressed (GtkWidget *button, GdkEventButton *event, LauncherPlugin *plugin);
-static gboolean launcher_plugin_icon_button_released (GtkWidget *button, GdkEventButton *event, LauncherPlugin *plugin);
-static void launcher_plugin_icon_button_drag_data_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint drag_time, LauncherPlugin *plugin);
+static gboolean launcher_plugin_button_press_event (GtkWidget *button, GdkEventButton *event, LauncherPlugin *plugin);
+static gboolean launcher_plugin_button_release_event (GtkWidget *button, GdkEventButton *event, LauncherPlugin *plugin);
 static gboolean launcher_plugin_icon_button_query_tooltip (GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip *tooltip, LauncherPlugin *plugin);
-static gboolean launcher_plugin_arrow_button_pressed (GtkWidget *button, GdkEventButton *event, LauncherPlugin *plugin);
-static gboolean launcher_plugin_menu_popup (gpointer user_data);
-static void launcher_plugin_menu_popup_destroyed (gpointer user_data);
-static void launcher_plugin_menu_deactivate (GtkWidget *menu, LauncherPlugin *plugin);
-static void launcher_plugin_menu_destroy (LauncherPlugin *plugin);
-static void launcher_plugin_menu_build (LauncherPlugin *plugin);
-static gboolean launcher_plugin_menu_item_released (GtkMenuItem *menu_item, GdkEventButton *event, LauncherPluginEntry *entry);
-static LauncherPluginEntry *launcher_plugin_entry_new_default (void);
-static void launcher_plugin_entry_free (LauncherPluginEntry *entry);
+static void launcher_plugin_button_drag_data_received (GtkWidget *widget,GdkDragContext *context, gint x,gint y,GtkSelectionData *selection_data, guint info, guint drag_time, LauncherPlugin *plugin);
+
+static void launcher_plugin_entries_load (LauncherPlugin *plugin);
+static gboolean launcher_plugin_entry_query_tooltip (GtkWidget *widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip *tooltip, LauncherEntry *entry);
+static LauncherEntry *launcher_plugin_entry_new_from_filename (const gchar *filename);
+static void launcher_plugin_entry_free (LauncherEntry *entry);
+
+static gboolean launcher_plugin_entry_exec_on_screen (LauncherEntry *entry, GdkScreen *screen, GSList *uri_list);
+static void launcher_plugin_entry_exec (LauncherEntry *entry, GdkScreen *screen, GSList *uri_list);
+static void launcher_plugin_entry_exec_from_clipboard (LauncherEntry *entry, GdkScreen *screen);
+static void launcher_plugin_exec_append_quoted (GString *string, const gchar *unquoted);
+static gboolean launcher_plugin_exec_parse (LauncherEntry *entry, GSList *uri_list, gboolean terminal, gint *argc, gchar ***argv, GError **error);
+
 
 
+struct _LauncherPluginClass
+{
+  XfcePanelPluginClass __parent__;
+};
+
+struct _LauncherPlugin
+{
+  XfcePanelPlugin __parent__;
+
+  XfconfChannel *channel;
 
-static GQuark launcher_plugin_quark = 0;
+  GtkWidget *box;
+  GtkWidget *button;
+  GtkWidget *arrow;
+  GtkWidget *image;
+
+  GSList *items;
+
+  guint disable_tooltips : 1;
+};
+
+struct _LauncherEntry
+{
+  gchar *filename;
+  gchar *name;
+  gchar *comment;
+  gchar *exec;
+  gchar *path;
+  gchar *icon;
+  guint terminal : 1;
+  guint startup_notify : 1;
+};
 
 
 
@@ -99,9 +113,6 @@ launcher_plugin_class_init (LauncherPluginClass *klass)
   plugin_class->save = launcher_plugin_save;
   plugin_class->configure_plugin = launcher_plugin_configure_plugin;
   plugin_class->screen_position_changed = launcher_plugin_screen_position_changed;
-
-  /* initialize the quark */
-  launcher_plugin_quark = g_quark_from_static_string ("xfce-launcher-plugin");
 }
 
 
@@ -109,72 +120,11 @@ launcher_plugin_class_init (LauncherPluginClass *klass)
 static void
 launcher_plugin_init (LauncherPlugin *plugin)
 {
-  GdkScreen *screen;
-
   /* initialize xfconf */
   xfconf_init (NULL);
 
-  /* initialize variables */
-  plugin->entries = NULL;
-  plugin->menu = NULL;
-  plugin->popup_timeout_id = 0;
-  plugin->move_first = FALSE;
-  plugin->disable_tooltips = FALSE;
-  plugin->show_labels = FALSE; /* TODO */
-  plugin->arrow_position = ARROW_POS_DEFAULT;
-
   /* show the configure menu item */
   xfce_panel_plugin_menu_show_configure (XFCE_PANEL_PLUGIN (plugin));
-
-  /* create the dialog widgets */
-  plugin->box = xfce_hvbox_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
-  gtk_container_add (GTK_CONTAINER (plugin), plugin->box);
-  gtk_widget_show (plugin->box);
-
-  plugin->icon_button = xfce_panel_create_button ();
-  gtk_box_pack_start (GTK_BOX (plugin->box), plugin->icon_button, TRUE, TRUE, 0);
-  xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), plugin->icon_button);
-  gtk_widget_show (plugin->icon_button);
-
-  plugin->image = xfce_scaled_image_new ();
-  gtk_container_add (GTK_CONTAINER (plugin->icon_button), plugin->image);
-  gtk_widget_show (plugin->image);
-
-  plugin->arrow_button = xfce_arrow_button_new (GTK_ARROW_UP);
-  gtk_box_pack_start (GTK_BOX (plugin->box), plugin->arrow_button, FALSE, FALSE, 0);
-  xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), plugin->arrow_button);
-  GTK_WIDGET_UNSET_FLAGS (plugin->arrow_button, GTK_CAN_DEFAULT | GTK_CAN_FOCUS);
-  gtk_button_set_relief (GTK_BUTTON (plugin->arrow_button), GTK_RELIEF_NONE);
-  gtk_button_set_focus_on_click (GTK_BUTTON (plugin->arrow_button), FALSE);
-
-  /* signals */
-  g_signal_connect (G_OBJECT (plugin->icon_button), "state-changed",
-                    G_CALLBACK (launcher_plugin_button_state_changed), plugin->arrow_button);
-  g_signal_connect (G_OBJECT (plugin->arrow_button), "state-changed",
-                    G_CALLBACK (launcher_plugin_button_state_changed), plugin->icon_button);
-
-  g_signal_connect (G_OBJECT (plugin->icon_button), "button-press-event",
-                    G_CALLBACK (launcher_plugin_icon_button_pressed), plugin);
-  g_signal_connect (G_OBJECT (plugin->icon_button), "button-release-event",
-                    G_CALLBACK (launcher_plugin_icon_button_released), plugin);
-
-  gtk_drag_dest_set (plugin->icon_button, 0, drop_targets, /* TODO check flags */
-                     G_N_ELEMENTS (drop_targets), GDK_ACTION_COPY);
-  g_signal_connect (G_OBJECT (plugin->icon_button), "drag-data-received",
-                    G_CALLBACK (launcher_plugin_icon_button_drag_data_received), plugin);
-
-  g_signal_connect (G_OBJECT (plugin->arrow_button), "button-press-event",
-                    G_CALLBACK (launcher_plugin_arrow_button_pressed), plugin);
-
-  g_object_set (G_OBJECT (plugin->icon_button), "has-tooltip", TRUE, NULL);
-  g_signal_connect (G_OBJECT (plugin->icon_button), "query-tooltip",
-                    G_CALLBACK (launcher_plugin_icon_button_query_tooltip), plugin);
-
-  /* store and monitor the icon theme */
-  screen = gtk_widget_get_screen (GTK_WIDGET (plugin));
-  plugin->icon_theme = screen ? gtk_icon_theme_get_for_screen (screen) : gtk_icon_theme_get_default ();
-  g_signal_connect (G_OBJECT (plugin->icon_theme), "changed",
-                    G_CALLBACK (launcher_plugin_icon_theme_changed), plugin);
 }
 
 
@@ -185,10 +135,6 @@ launcher_plugin_property_changed (XfconfChannel  *channel,
                                   const GValue   *value,
                                   LauncherPlugin *plugin)
 {
-  guint                nth;
-  gchar               *property;
-  LauncherPluginEntry *entry;
-
   panel_return_if_fail (XFCONF_IS_CHANNEL (channel));
   panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin));
   panel_return_if_fail (plugin->channel == channel);
@@ -197,68 +143,15 @@ launcher_plugin_property_changed (XfconfChannel  *channel,
     {
       plugin->disable_tooltips = g_value_get_boolean (value);
     }
-  else if (exo_str_is_equal (property_name, "/move-first"))
+  else if (exo_str_is_equal (property_name, "/entries"))
     {
-      plugin->move_first = g_value_get_boolean (value);
-    }
-  else if (exo_str_is_equal (property_name, "/show-labels"))
-    {
-      plugin->show_labels = g_value_get_boolean (value);
-    }
-  else if (exo_str_is_equal (property_name, "/arrow-position"))
-    {
-      plugin->arrow_position = MIN (g_value_get_uint (value), ARROW_POS_MAX);
-    }
-  else if (sscanf (property_name, "/entries/entry-%u/%a[a-z]", &nth, &property) == 2)
-    {
-      /* lookup the launcher entry */
-      entry = g_list_nth_data (plugin->entries, nth);
-      if (G_LIKELY (entry))
-        {
-          if (exo_str_is_equal (property, "name"))
-            {
-              g_free (entry->name);
-              entry->name = g_value_dup_string (value);
-
-              if (nth > 0 || plugin->show_labels)
-                launcher_plugin_rebuild (plugin, FALSE);
-            }
-          else if (exo_str_is_equal (property, "comment"))
-            {
-              g_free (entry->comment);
-              entry->comment = g_value_dup_string (value);
-            }
-          else if (exo_str_is_equal (property, "icon"))
-            {
-              g_free (entry->icon);
-              entry->icon = g_value_dup_string (value);
+      /* free entries */
+      g_slist_foreach (plugin->entries, (GFunc) launcher_plugin_entry_free, NULL);
+      g_slist_free (plugin->entries);
+      plugin->entries = NULL;
 
-              launcher_plugin_rebuild (plugin, (nth == 0));
-            }
-          else if (exo_str_is_equal (property, "command"))
-            {
-              g_free (entry->exec);
-              entry->exec = g_value_dup_string (value);
-            }
-          else if (exo_str_is_equal (property, "working-directory"))
-            {
-              g_free (entry->path);
-              entry->path = g_value_dup_string (value);
-            }
-          else if (exo_str_is_equal (property, "terminal"))
-            {
-              entry->terminal = g_value_get_boolean (value);
-            }
-#ifdef HAVE_LIBSTARTUP_NOTIFICATION
-          else if (exo_str_is_equal (property, "startup-notify"))
-            {
-              entry->startup_notify = g_value_get_boolean (value);
-            }
-#endif
-        }
-
-      /* cleanup */
-      g_free (property);
+      /* load the new entries */
+      launcher_plugin_entries_load (plugin);
     }
 }
 
@@ -267,46 +160,55 @@ launcher_plugin_property_changed (XfconfChannel  *channel,
 static void
 launcher_plugin_construct (XfcePanelPlugin *panel_plugin)
 {
-  LauncherPlugin      *plugin = XFCE_LAUNCHER_PLUGIN (panel_plugin);
-  const gchar * const *filenames;
-  guint                i;
+  LauncherPlugin *plugin = XFCE_LAUNCHER_PLUGIN (panel_plugin);
+  GtkWidget     *widget;
 
   /* open the xfconf channel */
   plugin->channel = xfce_panel_plugin_xfconf_channel_new (panel_plugin);
   g_signal_connect (G_OBJECT (plugin->channel), "property-changed",
                     G_CALLBACK (launcher_plugin_property_changed), plugin);
 
-  /* read the plugin configuration */
-  if (launcher_plugin_read (plugin) == FALSE)
-    {
-      /* try to build a launcher from the passed arguments */
-      filenames = xfce_panel_plugin_get_arguments (panel_plugin);
-      if (filenames)
-        {
-          /* try to add all the passed filenames */
-          for (i = 0; filenames[i] != NULL; i++)
-            {
-                /* TODO */
-                g_message ("TODO %s", filenames[i]);
-            }
-        }
+  /* create the dialog widgets */
+  plugin->box = xfce_hvbox_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
+  gtk_container_add (GTK_CONTAINER (plugin), plugin->box);
+  gtk_widget_show (plugin->box);
 
-      /* create a new launcher if there are still no entries */
-      if (plugin->entries == NULL)
-        plugin->entries = g_list_prepend (plugin->entries, launcher_plugin_entry_new_default ());
-    }
+  plugin->button = widget = xfce_panel_create_button ();
+  gtk_box_pack_start (GTK_BOX (plugin->box), widget, TRUE, TRUE, 0);
+  xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), widget);
+  gtk_widget_set_has_tooltip (widget, TRUE);
+  gtk_widget_show (widget);
+  g_signal_connect (G_OBJECT (widget), "button-press-event",
+                    G_CALLBACK (launcher_plugin_button_press_event), plugin);
+  g_signal_connect (G_OBJECT (widget), "button-release-event",
+                    G_CALLBACK (launcher_plugin_button_release_event), plugin);
+  g_signal_connect (G_OBJECT (widget), "query-tooltip",
+                    G_CALLBACK (launcher_plugin_button_query_tooltip), plugin);
+  g_signal_connect (G_OBJECT (widget), "drag-data-received",
+                    G_CALLBACK (launcher_plugin_button_drag_data_received), plugin);
+
+  plugin->image = xfce_scaled_image_new ();
+  gtk_container_add (GTK_CONTAINER (plugin->icon_button), plugin->image);
+  gtk_widget_show (plugin->image);
 
-  /* set the arrow direction */
-  launcher_plugin_screen_position_changed (panel_plugin, 0 /* TODO */);
+  plugin->arrow = xfce_arrow_button_new (GTK_ARROW_UP);
+  gtk_box_pack_start (GTK_BOX (plugin->box), plugin->arrow, FALSE, FALSE, 0);
+  xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), plugin->arrow);
+  GTK_WIDGET_UNSET_FLAGS (plugin->arrow, GTK_CAN_DEFAULT | GTK_CAN_FOCUS);
+  gtk_button_set_relief (GTK_BUTTON (plugin->arrow), GTK_RELIEF_NONE);
+  gtk_button_set_focus_on_click (GTK_BUTTON (plugin->arrow), FALSE);
 
-  /* set the buttons in the correct position */
-  launcher_plugin_reorder_buttons (plugin);
+  /* sync button states */
+  g_signal_connect (G_OBJECT (plugin->button), "state-changed",
+                    G_CALLBACK (launcher_plugin_button_state_changed), plugin->arrow);
+  g_signal_connect (G_OBJECT (plugin->arrow), "state-changed",
+                    G_CALLBACK (launcher_plugin_button_state_changed), plugin->button);
 
-  /* change the visiblity of the arrow button */
-  launcher_plugin_menu_destroy (plugin);
+  /* load global settings */
+  plugin->disable_tooltips = xfconf_channel_get_bool (plugin->channel, "/disable-tooltips", FALSE);
 
-  /* update the icon */
-  launcher_plugin_update_icon (plugin);
+  /* load the entries */
+  launcher_plugin_entries_load (plugin);
 }
 
 
@@ -322,17 +224,9 @@ launcher_plugin_free_data (XfcePanelPlugin *panel_plugin)
   /* shutdown xfconf */
   xfconf_shutdown ();
 
-  /* stop popup timeout */
-  if (G_UNLIKELY (plugin->popup_timeout_id))
-    g_source_remove (plugin->popup_timeout_id);
-
-  /* destroy the popup menu */
-  if (plugin->menu)
-    gtk_widget_destroy (plugin->menu);
-
-  /* remove the entries */
-  g_list_foreach (plugin->entries, (GFunc) launcher_plugin_entry_free, NULL);
-  g_list_free (plugin->entries);
+  /* free entries */
+  g_slist_foreach (plugin->entries, (GFunc) launcher_plugin_entry_free, NULL);
+  g_slist_free (plugin->entries);
 }
 
 
@@ -341,14 +235,7 @@ static void
 launcher_plugin_orientation_changed (XfcePanelPlugin *panel_plugin,
                                      GtkOrientation   orientation)
 {
-  /* update the arrow direction */
-  launcher_plugin_screen_position_changed (panel_plugin, 0 /* TODO */);
 
-  /* reorder the buttons */
-  launcher_plugin_reorder_buttons (XFCE_LAUNCHER_PLUGIN (panel_plugin));
-
-  /* update the plugin size */
-  launcher_plugin_size_changed (panel_plugin, xfce_panel_plugin_get_size (panel_plugin));
 }
 
 
@@ -357,48 +244,6 @@ static gboolean
 launcher_plugin_size_changed (XfcePanelPlugin *panel_plugin,
                               gint             size)
 {
-  LauncherPlugin *plugin = XFCE_LAUNCHER_PLUGIN (panel_plugin);
-  gint            width, height;
-  GtkOrientation  orientation;
-
-  /* init size */
-  width = height = size;
-
-  if (plugin->arrow_position != ARROW_POS_INSIDE_BUTTON
-      && LIST_HAS_TWO_OR_MORE_ENTRIES (plugin->entries))
-    {
-      /* get the orientation of the panel */
-      orientation = xfce_panel_plugin_get_orientation (panel_plugin);
-
-      switch (plugin->arrow_position)
-        {
-          case ARROW_POS_DEFAULT:
-            if (orientation == GTK_ORIENTATION_HORIZONTAL)
-              width += ARROW_BUTTON_SIZE;
-            else
-              height += ARROW_BUTTON_SIZE;
-            break;
-
-          case ARROW_POS_LEFT:
-          case ARROW_POS_RIGHT:
-            if (orientation == GTK_ORIENTATION_HORIZONTAL)
-              width += ARROW_BUTTON_SIZE;
-            else
-              height -= ARROW_BUTTON_SIZE;
-            break;
-
-          default:
-            if (orientation == GTK_ORIENTATION_HORIZONTAL)
-              width -= ARROW_BUTTON_SIZE;
-            else
-              height += ARROW_BUTTON_SIZE;
-            break;
-        }
-    }
-
-  /* set the size */
-  gtk_widget_set_size_request (GTK_WIDGET (panel_plugin), width, height);
-
   return TRUE;
 }
 
@@ -407,63 +252,30 @@ launcher_plugin_size_changed (XfcePanelPlugin *panel_plugin,
 static void
 launcher_plugin_save (XfcePanelPlugin *panel_plugin)
 {
-  LauncherPlugin      *plugin = XFCE_LAUNCHER_PLUGIN (panel_plugin);
-  gchar                buf[100];
-  GList               *li;
-  guint                i;
-  LauncherPluginEntry *entry;
+  LauncherPlugin  *plugin = XFCE_LAUNCHER_PLUGIN (panel_plugin);
+  gchar         **filenames;
+  guint           i, length;
+  GSList          *li;
+  LauncherEntry  *entry;
 
   /* save the global settings */
-  xfconf_channel_set_bool (plugin->channel, "/move-first", plugin->move_first);
   xfconf_channel_set_bool (plugin->channel, "/disable-tooltips", plugin->disable_tooltips);
-  xfconf_channel_set_bool (plugin->channel, "/show-labels", plugin->show_labels);
-  xfconf_channel_set_uint (plugin->channel, "/arrow-position", plugin->arrow_position);
 
-  for (li = plugin->entries, i = 0; li != NULL; li = li->next, i++)
+  length = g_slist_length (plugin->entries);
+  if (G_LIKELY (length > 0))
     {
-      entry = li->data;
-
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/name", i);
-      if (G_LIKELY (entry->name))
-        xfconf_channel_set_string (plugin->channel, buf, entry->name);
-      else
-        xfconf_channel_reset_property (plugin->channel, buf, FALSE);
-
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/comment", i);
-      if (entry->comment)
-        xfconf_channel_set_string (plugin->channel, buf, entry->comment);
-      else
-        xfconf_channel_reset_property (plugin->channel, buf, FALSE);
-
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/icon", i);
-      if (G_LIKELY (entry->icon))
-        xfconf_channel_set_string (plugin->channel, buf, entry->icon);
-      else
-        xfconf_channel_reset_property (plugin->channel, buf, FALSE);
-
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/command", i);
-      if (G_LIKELY (entry->exec))
-        xfconf_channel_set_string (plugin->channel, buf, entry->exec);
-      else
-        xfconf_channel_reset_property (plugin->channel, buf, FALSE);
+      /* create the array with filenames */
+      filenames = g_new0 (gchar *, length + 1);
+      for (li = plugin->entries, i = 0; li != NULL; li = li->next)
+        if (G_LIKELY ((entry = li->data) != NULL))
+          filenames[i++] = entry->filename;
 
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/working-directory", i);
-      if (entry->path)
-        xfconf_channel_set_string (plugin->channel, buf, entry->path);
-      else
-        xfconf_channel_reset_property (plugin->channel, buf, FALSE);
-
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/terminal", i);
-      xfconf_channel_set_bool (plugin->channel, buf, entry->terminal);
+      /* store the list of filenames */
+      xfconf_channel_set_string_list (plugin->channel, "/entries", filenames);
 
-#ifdef HAVE_LIBSTARTUP_NOTIFICATION
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/startup-notify", i);
-      xfconf_channel_set_bool (plugin->channel, buf, entry->startup_notify);
-#endif
+      /* cleanup */
+      g_free (filenames);
     }
-
-  /* store the number of launchers */
-  xfconf_channel_set_uint (plugin->channel, "/entries", i);
 }
 
 
@@ -481,913 +293,402 @@ static void
 launcher_plugin_screen_position_changed (XfcePanelPlugin *panel_plugin,
                                          gint             position)
 {
-  GtkArrowType    arrow_type;
-  LauncherPlugin *plugin = XFCE_LAUNCHER_PLUGIN (panel_plugin);
-
-  /* get the arrow type */
-  arrow_type = xfce_panel_plugin_arrow_type (panel_plugin);
-
-  /* set the arrow direction */
-  xfce_arrow_button_set_arrow_type (XFCE_ARROW_BUTTON (plugin->arrow_button), arrow_type);
 
-  /* destroy the menu to update the popup menu order */
-  launcher_plugin_menu_destroy (plugin);
 }
 
 
 
 static void
-launcher_plugin_execute_string_append_quoted (GString     *string,
-                                              const gchar *unquoted)
+launcher_plugin_button_state_changed (GtkWidget    *button_a,
+                                      GtkStateType  state,
+                                      GtkWidget    *button_b)
 {
-  gchar *quoted;
-
-  quoted = g_shell_quote (unquoted);
-  g_string_append (string, quoted);
-  g_free (quoted);
+  if (GTK_WIDGET_STATE (button_a) != GTK_WIDGET_STATE (button_b)
+      && GTK_WIDGET_STATE (button_a) != GTK_STATE_INSENSITIVE)
+    gtk_widget_set_state (button_b, GTK_WIDGET_STATE (button_a));
 }
 
 
 
-static gchar *
-launcher_plugin_execute_parse_command (LauncherPluginEntry *entry,
-                                       GSList              *file_list)
+static gboolean
+launcher_plugin_button_press_event (GtkWidget      *button,
+                                    GdkEventButton *event,
+                                    LauncherPlugin *plugin)
 {
-  GString     *cmd = g_string_sized_new (50);
-  const gchar *p;
-  gchar       *tmp;
-  GSList      *li;
-
-  /* parse the execute command */
-  for (p = entry->exec; *p != '\0'; ++p)
-    {
-      if (p[0] == '%' && p[1] != '\0')
-        {
-          switch (*++p)
-            {
-              /* a single filename or url */
-              case 'u':
-              case 'f':
-                if (file_list != NULL)
-                  launcher_plugin_execute_string_append_quoted (cmd, (gchar *) file_list->data);
-                break;
-
-              /* a list of filenames or urls */
-              case 'U':
-              case 'F':
-                for (li = file_list; li != NULL; li = li->next)
-                  {
-                    if (G_LIKELY (li != file_list))
-                      g_string_append_c (cmd, ' ');
-
-                    launcher_plugin_execute_string_append_quoted (cmd, (gchar *) li->data);
-                  }
-                break;
-
-              /* directory containing the file that would be passed in a %f field */
-              case 'd':
-                if (file_list != NULL)
-                  {
-                    tmp = g_path_get_dirname ((gchar *) file_list->data);
-                    if (tmp != NULL)
-                      {
-                        launcher_plugin_execute_string_append_quoted (cmd, tmp);
-                        g_free (tmp);
-                      }
-                  }
-                break;
-
-              /* list of directories containing the files that would be passed in to a %F field */
-              case 'D':
-                for (li = file_list; li != NULL; li = li->next)
-                  {
-                    tmp = g_path_get_dirname (li->data);
-                    if (tmp != NULL)
-                      {
-                        if (G_LIKELY (li != file_list))
-                          g_string_append_c (cmd, ' ');
-
-                        launcher_plugin_execute_string_append_quoted (cmd, tmp);
-                        g_free (tmp);
-                      }
-                  }
-                break;
-
-              /* a single filename (without path) */
-              case 'n':
-                if (file_list != NULL)
-                  {
-                    tmp = g_path_get_basename ((gchar *) file_list->data);
-                    if (tmp != NULL)
-                      {
-                        launcher_plugin_execute_string_append_quoted (cmd, tmp);
-                        g_free (tmp);
-                      }
-                  }
-                break;
-
-              /* a list of filenames (without paths) */
-              case 'N':
-                for (li = file_list; li != NULL; li = li->next)
-                  {
-                    tmp = g_path_get_basename (li->data);
-                    if (tmp != NULL)
-                      {
-                        if (G_LIKELY (li != file_list))
-                          g_string_append_c (cmd, ' ');
-
-                        launcher_plugin_execute_string_append_quoted (cmd, tmp);
-                        g_free (tmp);
-                      }
-                  }
-                break;
-
-              /* the icon name used in the panel */
-              case 'i':
-                if (G_LIKELY (entry->icon != NULL))
-                  {
-                    g_string_append (cmd, "--icon ");
-                    launcher_plugin_execute_string_append_quoted (cmd, entry->icon);
-                  }
-                break;
-
-              /* the 'translated' name of the application */
-              case 'c':
-                if (G_LIKELY (entry->name != NULL))
-                  launcher_plugin_execute_string_append_quoted (cmd, entry->name);
-                break;
-
-              /* percentage character */
-              case '%':
-                g_string_append_c (cmd, '%');
-                break;
-            }
-        }
-      else
-        {
-          g_string_append_c (cmd, *p);
-        }
-    }
-
-  /* return the command */
-  return g_string_free (cmd, FALSE);
+  panel_return_val_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin), FALSE);
+  panel_return_val_if_fail (plugin->entries != NULL, FALSE);
+  
+  /* do nothing on anything else then a single click */
+  if (event->type != GDK_BUTTON_PRESS)
+    return FALSE;
+    
+    
 }
 
 
 
-static void
-launcher_plugin_execute (GdkScreen           *screen,
-                         LauncherPluginEntry *entry,
-                         GSList              *file_list)
+static gboolean
+launcher_plugin_button_release_event (GtkWidget      *button,
+                                      GdkEventButton *event,
+                                      LauncherPlugin *plugin)
 {
-  GSList   *li, fake;
-  gboolean  succeed = TRUE;
-  gchar    *command_line;
-  gboolean  startup_notify;
-  GError   *error = NULL;
-
-  /* set the startup notification boolean */
-#ifdef HAVE_LIBSTARTUP_NOTIFICATION
-  startup_notify = entry->startup_notify;
-#else
-  startup_notify = FALSE;
-#endif
-
-  /* leave when no command has been set */
-  if (G_UNLIKELY (entry->exec == NULL || *entry->exec == '\0'))
-    return;
-
-  /* make sure we've set a screen */
-  if (G_UNLIKELY (screen == NULL))
-    screen = gdk_screen_get_default ();
-
-  /* check if we have multiple files to launches */
-  if (file_list != NULL && LIST_HAS_TWO_OR_MORE_ENTRIES (file_list)
-       && !(strstr (entry->exec, "%F") || strstr (entry->exec, "%U")))
-    {
-      /* fake an empty list */
-      fake.next = NULL;
-
-      /* run a new instance for each file in the list */
-      for (li = file_list; li != NULL && succeed; li = li->next)
-        {
-          /* point to data */
-          fake.data = li->data;
-
-          /* parse the command and execute the command */
-          command_line = launcher_plugin_execute_parse_command (entry, &fake);
-          succeed = xfce_execute_on_screen (screen, command_line, entry->terminal, startup_notify, &error);
-          g_free (command_line);
-        }
-    }
+  panel_return_val_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin), FALSE);
+  panel_return_val_if_fail (plugin->entries != NULL, FALSE);
+  
+  if (event->button == 1)
+    launcher_plugin_entry_exec (entry, gtk_widget_get_screen (button), NULL);
+  else if (event->button == 2)
+    launcher_plugin_entry_exec_from_clipboard (entry, gtk_widget_get_screen (button));
   else
-    {
-      /* parse the command and execute the command */
-      command_line = launcher_plugin_execute_parse_command (entry, file_list);
-      succeed = xfce_execute_on_screen (screen, command_line, entry->terminal, startup_notify, &error);
-      g_free (command_line);
-    }
-
-  if (G_UNLIKELY (succeed == FALSE))
-    {
-      g_message ("Failed to execute: %s", error->message);
-      g_error_free (error);
-    }
-}
-
-
-
-static void
-launcher_plugin_execute_from_clipboard (GdkScreen           *screen,
-                                        LauncherPluginEntry *entry)
-{
-  GtkClipboard     *clipboard;
-  gchar            *text = NULL;
-  GSList           *filenames;
-  GtkSelectionData  selection_data;
-
-  /* get the primary clipboard text */
-  clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
-  if (G_LIKELY (clipboard))
-    text = gtk_clipboard_wait_for_text (clipboard);
-
-  /* try other clipboard if this one was empty */
-  if (text == NULL)
-    {
-      /* get the secondary clipboard text */
-      clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
-      if (G_LIKELY (clipboard))
-        text = gtk_clipboard_wait_for_text (clipboard);
-    }
-
-  if (G_LIKELY (text))
-    {
-      /* create some fake selection data */
-      selection_data.data = (guchar *) text;
-      selection_data.length = 1;
-
-      /* parse the filelist, this way we can handle 'copied' file from thunar */
-      filenames = launcher_plugin_filenames_from_selection_data (&selection_data);
-      if (G_LIKELY (filenames))
-        {
-          /* run the command with filenames from the clipboard */
-          launcher_plugin_execute (screen, entry, filenames);
-
-          /* cleanup */
-          launcher_plugin_filenames_free (filenames);
-        }
-
-      /* cleanup */
-      g_free (text);
-    }
+    return TRUE;
+    
+  return FALSE;
 }
 
 
 
-static void
-launcher_plugin_icon_theme_changed (GtkIconTheme   *icon_theme,
-                                    LauncherPlugin *plugin)
+static gboolean
+launcher_plugin_icon_button_query_tooltip (GtkWidget      *widget,
+                                           gint            x,
+                                           gint            y,
+                                           gboolean        keyboard_mode,
+                                           GtkTooltip     *tooltip,
+                                           LauncherPlugin *plugin)
 {
-  panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin));
-  panel_return_if_fail (GTK_IS_ICON_THEME (icon_theme));
-
-  /* set the new icon theme */
-  plugin->icon_theme = icon_theme;
+  panel_return_val_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin), FALSE);
+  panel_return_val_if_fail (plugin->entries != NULL, FALSE);
 
-  /* update the button icon */
-  launcher_plugin_update_icon (plugin);
+  /* check if we show tooltips */
+  if (plugin->entries == NULL || plugin->entries->data == NULL
+      || plugin->disable_tooltips)
+    return FALSE;
 
-  /* destroy the menu */
-  launcher_plugin_menu_destroy (plugin);
+  return launcher_plugin_entry_query_tooltip (widget, x, y, keyboard_mode,
+                                              tooltip, plugin->entries->data);
 }
 
 
 
-static void
-launcher_plugin_update_icon (LauncherPlugin *plugin)
+static void 
+launcher_plugin_button_drag_data_received (GtkWidget        *widget,
+                                           GdkDragContext   *context, 
+                                           gint              x,
+                                           gint              y,
+                                           GtkSelectionData *selection_data, 
+                                           guint             info, 
+                                           guint             drag_time, 
+                                           LauncherPlugin   *plugin)
 {
-  LauncherPluginEntry *entry;
-
   panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin));
   panel_return_if_fail (plugin->entries != NULL);
 
-  /* get the first entry */
-  entry = plugin->entries->data;
-
-  if (g_path_is_absolute (entry->icon))
-    xfce_scaled_image_set_from_file (XFCE_SCALED_IMAGE (plugin->image), entry->icon);
-  else
-    xfce_scaled_image_set_from_icon_name (XFCE_SCALED_IMAGE (plugin->image), entry->icon);
-}
-
-
-
-void
-launcher_plugin_rebuild (LauncherPlugin *plugin,
-                         gboolean        update_icon)
-{
-  panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin));
-
-  /* destroy the popup menu */
-  launcher_plugin_menu_destroy (plugin);
-
-  /* reorder the buttons */
-  launcher_plugin_reorder_buttons (plugin);
-
-  /* update the size */
-  launcher_plugin_size_changed (XFCE_PANEL_PLUGIN (plugin),
-                                xfce_panel_plugin_get_size (XFCE_PANEL_PLUGIN (plugin)));
-
-  /* update the icon if needed */
-  if (update_icon)
-    launcher_plugin_update_icon (plugin);
+  gtk_drag_finish (context, TRUE, FALSE, drag_time);
 }
 
 
 
 static void
-launcher_plugin_reorder_buttons (LauncherPlugin *plugin)
+launcher_plugin_entries_load (LauncherPlugin *plugin)
 {
-  GtkOrientation         orientation;
-  LauncherPluginArrowPos arrow_position = plugin->arrow_position;
+  gchar        **filenames;
+  guint          i;
+  LauncherEntry *entry;
 
   panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin));
 
-  if (arrow_position == ARROW_POS_DEFAULT)
+  /* get the list of launcher filenames */
+  filenames = xfconf_channel_get_string_list (plugin->channel, "/entries");
+  if (G_LIKELY (filenames != NULL))
     {
-      /* get the plugin orientation */
-      orientation = xfce_panel_plugin_get_orientation (XFCE_PANEL_PLUGIN (plugin));
+      /* try to load all the entries */
+      for (i = 0; filenames[i] != NULL; i++)
+        {
+          entry = launcher_plugin_entry_from_filename (filenames[i]);
+          if (G_LIKELY (entry != NULL))
+            launcher->entries = g_slist_append (launcher->entries, entry);
+        }
 
-      if (orientation == GTK_ORIENTATION_HORIZONTAL)
-        arrow_position = ARROW_POS_RIGHT;
-      else
-        arrow_position = ARROW_POS_BOTTOM;
-    }
-  else if (arrow_position == ARROW_POS_INSIDE_BUTTON)
-    {
-      /* nothing to pack */
-      return;
+      /* cleanup */
+      g_strfreev (filenames);
     }
-
-  /* set the position of the arrow button in the box */
-  gtk_box_reorder_child (GTK_BOX (plugin->box), plugin->arrow_button,
-                         (arrow_position == ARROW_POS_LEFT
-                          || arrow_position == ARROW_POS_TOP) ? 0 : -1);
-
-  /* set the hxbox orientation */
-  if (arrow_position == ARROW_POS_LEFT || arrow_position == ARROW_POS_RIGHT)
-    orientation = GTK_ORIENTATION_HORIZONTAL;
-  else
-    orientation = GTK_ORIENTATION_VERTICAL;
-
-  xfce_hvbox_set_orientation (XFCE_HVBOX (plugin->box), orientation);
 }
 
 
 
 static gboolean
-launcher_plugin_read (LauncherPlugin *plugin)
+launcher_plugin_entry_query_tooltip (GtkWidget     *widget,
+                                     gint           x,
+                                     gint           y,
+                                     gboolean       keyboard_mode,
+                                     GtkTooltip    *tooltip,
+                                     LauncherEntry *entry)
 {
-  guint                i, n_entries;
-  gchar                buf[100];
-  LauncherPluginEntry *entry;
+  gchar *markup;
 
-  panel_return_val_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin), FALSE);
-  panel_return_val_if_fail (XFCONF_IS_CHANNEL (plugin->channel), FALSE);
+  panel_return_val_if_fail (entry != NULL, FALSE);
 
-  /* read global settings */
-  plugin->move_first = xfconf_channel_get_bool (plugin->channel, "/move-first", FALSE);
-  plugin->disable_tooltips = xfconf_channel_get_bool (plugin->channel, "/disable-tooltips", FALSE);
-  plugin->show_labels = xfconf_channel_get_bool (plugin->channel, "/show-labels", FALSE);
-  plugin->arrow_position = MIN (xfconf_channel_get_uint (plugin->channel, "/arrow-position", ARROW_POS_DEFAULT),
-                                ARROW_POS_MAX);
+  /* require atleast an entry name */
+  if (!IS_STRING (entry->name))
+    return FALSE;
 
-  /* number of launcher entries */
-  n_entries = xfconf_channel_get_uint (plugin->channel, "/entries", 0);
-  for (i = 0; i < n_entries; i++)
+  if (IS_STRING (entry->comment))
     {
-      entry = g_slice_new (LauncherPluginEntry);
-
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/name", i);
-      entry->name = xfconf_channel_get_string (plugin->channel, buf, NULL);
-
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/comment", i);
-      entry->comment = xfconf_channel_get_string (plugin->channel, buf, NULL);
-
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/icon", i);
-      entry->icon = xfconf_channel_get_string (plugin->channel, buf, NULL);
-
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/command", i);
-      entry->exec = xfconf_channel_get_string (plugin->channel, buf, NULL);
-
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/working-directory", i);
-      entry->path = xfconf_channel_get_string (plugin->channel, buf, NULL);
-
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/terminal", i);
-      entry->terminal = xfconf_channel_get_bool (plugin->channel, buf, FALSE);
-
-#ifdef HAVE_LIBSTARTUP_NOTIFICATION
-      g_snprintf (buf, sizeof (buf), "/entries/entry-%d/startup-notify", i);
-      entry->startup_notify = xfconf_channel_get_bool (plugin->channel, buf, FALSE);
-#endif
-
-      /* prepend the entry */
-      plugin->entries = g_list_prepend (plugin->entries, entry);
+      markup = g_strdup_printf ("<b>%s</b>\n%s", entry->name, entry->comment);
+      gtk_tooltip_set_markup (tooltip, markup);
+      g_free (markup);
     }
-
-  /* reverse the order of the list */
-  plugin->entries = g_list_reverse (plugin->entries);
-
-  return (plugin->entries != NULL);
-}
-
-
-
-GSList *
-launcher_plugin_filenames_from_selection_data (GtkSelectionData *selection_data)
-{
-  gchar  **uri_list;
-  GSList  *filenames = NULL;
-  gchar   *file;
-  guint    i;
-
-  /* check whether the retrieval worked */
-  if (G_LIKELY (selection_data->length > 0))
-    {
-      /* split the received uri list */
-      uri_list = g_uri_list_extract_uris ((gchar *) selection_data->data);
-      if (G_LIKELY (uri_list))
-        {
-          /* walk though the list */
-          for (i = 0; uri_list[i] != NULL; i++)
-            {
-              /* convert the uri to a filename */
-              file = g_filename_from_uri (uri_list[i], NULL, NULL);
-
-              /* prepend the filename */
-              if (G_LIKELY (file))
-                filenames = g_slist_prepend (filenames, file);
-            }
-
-          /* cleanup */
-          g_strfreev (uri_list);
-
-          /* reverse the list */
-          filenames = g_slist_reverse (filenames);
-      }
-  }
-
-  return filenames;
-}
-
-
-
-GdkPixbuf *
-launcher_plugin_load_pixbuf (const gchar  *name,
-                             gint          size,
-                             GtkIconTheme *icon_theme)
-{
-  GdkPixbuf *pixbuf, *scaled;
-
-  panel_return_val_if_fail (size > 0, NULL);
-  panel_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL);
-
-  /* return null if there is no name */
-  if (G_UNLIKELY (name == NULL || *name == '\0'))
-    return NULL;
-
-  /* load the icon from a file or the icon theme */
-  if (g_path_is_absolute (name))
+  else
     {
-      pixbuf = exo_gdk_pixbuf_new_from_file_at_max_size (name, size, size, TRUE, NULL);
+      gtk_tooltip_set_text (tooltip, entry->name);
     }
-  else
+
+  if (G_LIKELY (entry->icon))
     {
-      pixbuf = gtk_icon_theme_load_icon (icon_theme, name, size, 0, NULL);
-      if (G_LIKELY (pixbuf))
-        {
-          scaled = exo_gdk_pixbuf_scale_down (pixbuf, TRUE, size, size);
-          g_object_unref (G_OBJECT (pixbuf));
-          pixbuf = scaled;
-        }
+      /* TODO pixbuf with cache */
     }
 
-  return pixbuf;
+  return TRUE;
 }
 
 
 
-static gboolean
-launcher_plugin_query_tooltip (GtkWidget           *widget,
-                               gint                 x,
-                               gint                 y,
-                               gboolean             keyboard_mode,
-                               GtkTooltip          *tooltip,
-                               LauncherPluginEntry *entry)
+static LauncherEntry *
+launcher_plugin_entry_new_from_filename (const gchar *filename)
 {
-  gchar        *string;
-  GdkPixbuf    *pixbuf;
-  GtkIconTheme *icon_theme;
-  GdkScreen    *screen;
+  LauncherEntry *entry = NULL;
+  XfceRc        *rc;
 
-  if (G_LIKELY (entry && entry->name))
-    {
-      /* create tooltip label */
-      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 and cleanup */
-      gtk_tooltip_set_markup (tooltip, string);
-      g_free (string);
-
-      if (G_LIKELY (entry->icon))
-        {
-          /* get the icon theme */
-          screen = gtk_widget_get_screen (widget);
-          icon_theme = gtk_icon_theme_get_for_screen (screen);
+  panel_return_val_if_fail (filename != NULL, NULL);
+  panel_return_val_if_fail (g_path_is_absolute (filename), NULL);
 
-          /* try to load a pixbuf */
-          pixbuf = launcher_plugin_load_pixbuf (entry->icon, TOOLTIP_ICON_SIZE, icon_theme);
-          if (G_LIKELY (pixbuf))
-            {
-              /* set the tooltip icon and release it */
-              gtk_tooltip_set_icon (tooltip, pixbuf);
-              g_object_unref (G_OBJECT (pixbuf));
-            }
-        }
-
-      /* show the tooltip */
-      return TRUE;
+  rc = xfce_rc_simple_open (filename, TRUE);
+  if (G_LIKELY (rc != NULL))
+    {
+      /* allocate a new entry */
+      entry = g_slice_new0 (LauncherEntry);
+
+      /* set group */
+      xfce_rc_set_group (rc, "Desktop Entry");
+
+      /* set entry values */
+      entry->filename = g_strdup (filename);
+      entry->name = g_strdup (xfce_rc_read_entry (rc, "Name", NULL));
+      entry->comment = g_strdup (xfce_rc_read_entry (rc, "Comment", NULL));
+      entry->exec = g_strdup (xfce_rc_read_entry_untranslated (rc, "Exec", NULL));
+      entry->icon = g_strdup (xfce_rc_read_entry_untranslated (rc, "Icon", NULL));
+      entry->path = g_strdup (xfce_rc_read_entry_untranslated (rc, "Path", NULL));
+      entry->terminal = xfce_rc_read_bool_entry (rc, "Terminal", FALSE);
+      entry->startup_notify = xfce_rc_read_bool_entry (rc, "StartupNotify", FALSE);
+
+      /* close */
+      xfce_rc_close (rc);
     }
 
-  /* nothing to show */
-  return FALSE;
+  return entry;
 }
 
 
 
 static void
-launcher_plugin_button_state_changed (GtkWidget    *button_a,
-                                      GtkStateType  state,
-                                      GtkWidget    *button_b)
+launcher_plugin_entry_free (LauncherEntry *entry)
 {
-  /* sync the button states */
-  if (GTK_WIDGET_STATE (button_b) != GTK_WIDGET_STATE (button_a)
-      && GTK_WIDGET_STATE (button_a) != GTK_STATE_INSENSITIVE)
-    gtk_widget_set_state (button_b, GTK_WIDGET_STATE (button_a));
-}
-
-
-
-static gboolean
-launcher_plugin_icon_button_pressed (GtkWidget      *button,
-                                     GdkEventButton *event,
-                                     LauncherPlugin *plugin)
-{
-  guint modifiers;
+  panel_return_if_fail (entry != NULL);
 
-  panel_return_val_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin), FALSE);
-
-  /* get the default accelerator modifier mask */
-  modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
-
-  /* leave when button 1 is not pressed, shift if hold */
-  if (event->button != 1 || modifiers == GDK_CONTROL_MASK)
-    return FALSE;
-
-  /* popup the menu or start the popup timeout */
-  if (plugin->arrow_position == ARROW_POS_INSIDE_BUTTON)
-    launcher_plugin_menu_popup (plugin);
-  else if (plugin->popup_timeout_id == 0
-           && LIST_HAS_TWO_OR_MORE_ENTRIES (plugin->entries))
-    plugin->popup_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, MENU_POPUP_DELAY,
-                                                   launcher_plugin_menu_popup, plugin,
-                                                   launcher_plugin_menu_popup_destroyed);
+  g_free (entry->filename);
+  g_free (entry->name);
+  g_free (entry->comment);
+  g_free (entry->exec);
+  g_free (entry->icon);
+  g_free (entry->path);
 
-  return FALSE;
+  g_slice_free (LauncherEntry, entry);
 }
 
 
 
 static gboolean
-launcher_plugin_icon_button_released (GtkWidget      *button,
-                                      GdkEventButton *event,
-                                      LauncherPlugin *plugin)
-{
-  LauncherPluginEntry *entry;
-  GdkScreen           *screen;
-
-  panel_return_val_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin), FALSE);
-  panel_return_val_if_fail (plugin->entries != NULL, FALSE);
-
-  /* remove a delayout popup timeout */
-  if (G_LIKELY (plugin->popup_timeout_id != 0))
-    g_source_remove (plugin->popup_timeout_id);
-
-  /* only accept click in the button and don't respond on multiple clicks */
-  if (GTK_BUTTON (button)->in_button
-      && plugin->arrow_position != ARROW_POS_INSIDE_BUTTON)
+launcher_plugin_entry_exec_on_screen (LauncherEntry *entry,
+                                      GdkScreen     *screen,
+                                      GSList        *uri_list)
+{
+  GError    *error = NULL;
+  gchar    **argv;
+  gboolean   succeed = FALSE;
+  
+  /* parse the execute command */
+  if (launcher_plugin_exec_parse (entry, uri_list, entry->terminal,
+                                  NULL, &argv, &error))
     {
-      /* get the first launcher entry */
-      entry = plugin->entries->data;
-
-      /* get the widget screen */
-      screen = gtk_widget_get_screen (button);
-
-      /* execute the command on button 1 and 2 */
-      if (event->button == 1)
-        launcher_plugin_execute (screen, entry, NULL);
-      else if (event->button == 2)
-        launcher_plugin_execute_from_clipboard (screen, entry);
+      /* launch the command on the screen */
+      succeed = xfce_execute_argv_on_screen (screen, entry->path, argv, NULL,
+                                             G_SPAWN_SEARCH_PATH, entry->startup_notify,
+                                             entry->icon, &error);
+                                             
+      /* cleanup */
+      g_strfreev (argv);
     }
-
-  return FALSE;
+    
+  if (G_UNLIKELY (succeed == FALSE))
+    {
+      /* TODO */
+      g_message ("Failed to launch.... (%s)", error->message);
+      g_error_free (error);
+    }
+    
+  return succeed;
 }
 
 
 
 static void
-launcher_plugin_icon_button_drag_data_received (GtkWidget        *widget,
-                                                GdkDragContext   *context,
-                                                gint              x,
-                                                gint              y,
-                                                GtkSelectionData *selection_data,
-                                                guint             info,
-                                                guint             drag_time,
-                                                LauncherPlugin   *plugin)
+launcher_plugin_entry_exec (LauncherEntry *entry,
+                            GdkScreen     *screen,
+                            GSList        *uri_list)
 {
-  GSList *filenames;
-
-  panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin));
-  panel_return_if_fail (plugin->entries != NULL);
-
-  /* leave when arrow is inside the button */
-  if (plugin->arrow_position == ARROW_POS_INSIDE_BUTTON)
+  GSList   *li, fake;
+  gboolean  proceed = TRUE;
+  
+  panel_return_if_fail (entry != NULL);
+  
+  /* leave when there is nothing to execute */
+  if (!IS_STRING (entry->exec))
     return;
-
-  /* get the filenames from the selection data */
-  filenames = launcher_plugin_filenames_from_selection_data (selection_data);
-  if (G_LIKELY (filenames))
+  
+  if (G_UNLIKELY (uri_list != NULL
+      && g_strstr (entry->exec, "%F") == NULL
+      && g_strstr (entry->exec, "%U") == NULL))
     {
-      /* execute */
-      launcher_plugin_execute (gtk_widget_get_screen (widget), plugin->entries->data, filenames);
-
-      /* cleanup */
-      launcher_plugin_filenames_free (filenames);
+      fake.next = NULL;
+      
+      /* run an instance for each file, break on the first error */
+      for (li = uri_list; li != NULL && proceed; li = li->next)
+        {
+          fake.data = li->data;
+          proceed = launcher_plugin_entry_exec_on_screen (entry, screen, &fake);
+        }
+    }
+  else
+    {
+      launcher_plugin_entry_exec_on_screen (entry, screen, uri_list);
     }
-
-  /* finish the drag */
-  gtk_drag_finish (context, TRUE, FALSE, drag_time);
-}
-
-
-
-static gboolean
-launcher_plugin_icon_button_query_tooltip (GtkWidget      *widget,
-                                           gint            x,
-                                           gint            y,
-                                           gboolean        keyboard_mode,
-                                           GtkTooltip     *tooltip,
-                                           LauncherPlugin *plugin)
-{
-  panel_return_val_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin), FALSE);
-  panel_return_val_if_fail (plugin->entries != NULL, FALSE);
-
-  /* don't show tooltips on a menu button or when tooltips are disabled */
-  if (plugin->disable_tooltips
-      || plugin->arrow_position == ARROW_POS_INSIDE_BUTTON)
-    return FALSE;
-
-  /* run the tooltip query function */
-  return launcher_plugin_query_tooltip (widget, x, y, keyboard_mode, tooltip, plugin->entries->data);
-}
-
-
-
-static gboolean
-launcher_plugin_arrow_button_pressed (GtkWidget      *button,
-                                      GdkEventButton *event,
-                                      LauncherPlugin *plugin)
-{
-  panel_return_val_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin), FALSE);
-
-  /* only popup when button 1 is pressed */
-  if (event->button == 1)
-    launcher_plugin_menu_popup (plugin);
-
-  return FALSE;
-}
-
-
-
-static gboolean
-launcher_plugin_menu_popup (gpointer user_data)
-{
-  LauncherPlugin *plugin = XFCE_LAUNCHER_PLUGIN (user_data);
-
-  /* build the menu */
-  if (G_UNLIKELY (plugin->menu == NULL))
-    launcher_plugin_menu_build (plugin);
-
-  GDK_THREADS_ENTER ();
-
-  /* toggle the arrow button */
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->arrow_button), TRUE);
-
-  /* popup the menu */
-  gtk_menu_popup (GTK_MENU (plugin->menu), NULL, NULL,
-                  xfce_panel_plugin_position_menu,
-                  XFCE_PANEL_PLUGIN (plugin), 1,
-                  gtk_get_current_event_time ());
-
-  GDK_THREADS_LEAVE ();
-
-  return FALSE;
-}
-
-
-
-static void
-launcher_plugin_menu_popup_destroyed (gpointer user_data)
-{
-  XFCE_LAUNCHER_PLUGIN (user_data)->popup_timeout_id = 0;
 }
 
 
 
 static void
-launcher_plugin_menu_deactivate (GtkWidget      *menu,
-                                 LauncherPlugin *plugin)
+launcher_plugin_entry_exec_from_clipboard (LauncherEntry *entry,
+                                           GdkScreen     *screen)
 {
-  panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin));
-  panel_return_if_fail (plugin->menu == menu);
-
-  /* deactivate the arrow button */
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->arrow_button), FALSE);
+  panel_return_if_fail (entry != NULL);
+  
+  /* TODO */
 }
 
 
 
 static void
-launcher_plugin_menu_destroy (LauncherPlugin *plugin)
+launcher_plugin_exec_append_quoted (GString     *string,
+                                    const gchar *unquoted)
 {
-  panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin));
-
-  if (G_LIKELY (plugin->menu != NULL))
-    {
-      /* destroy the menu and null the variable */
-      gtk_widget_destroy (plugin->menu);
-      plugin->menu = NULL;
-
-      /* deactivate arrow button */
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->arrow_button), FALSE);
-    }
+  gchar *quoted;
 
-  /* set the visibility of the arrow button */
-  if (plugin->arrow_position == ARROW_POS_INSIDE_BUTTON
-      || LIST_HAS_ONE_ENTRY (plugin->entries))
-    gtk_widget_hide (plugin->arrow_button);
-  else
-    gtk_widget_show (plugin->arrow_button);
+  quoted = g_shell_quote (unquoted);
+  g_string_append (string, quoted);
+  g_free (quoted);
 }
 
 
 
-static void
-launcher_plugin_menu_build (LauncherPlugin *plugin)
-{
-  GList               *li;
-  guint                n;
-  LauncherPluginEntry *entry;
-  GtkWidget           *mi, *image;
-  GdkScreen           *screen;
-  GdkPixbuf           *pixbuf;
-  GtkArrowType         arrow_type;
+static gboolean
+launcher_plugin_exec_parse (LauncherEntry   *entry,
+                            GSList          *uri_list,
+                            gboolean         terminal,
+                            gint            *argc,
+                            gchar         ***argv,
+                            GError         **error)
+{
+  GString     *string;
+  const gchar *p;
+  gboolean     result;
+  GSList      *li;
+  gchar       *filename;
 
-  panel_return_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin));
-  panel_return_if_fail (plugin->menu == NULL);
+  panel_return_val_if_fail (entry != NULL, FALSE);
+  panel_return_val_if_fail (IS_STRING (entry->exec), FALSE);
 
-  /* create a new menu */
-  plugin->menu = gtk_menu_new ();
-  screen = gtk_widget_get_screen (GTK_WIDGET (plugin));
-  gtk_menu_set_screen (GTK_MENU (plugin->menu), screen);
-  g_signal_connect (G_OBJECT (plugin->menu), "deactivate", G_CALLBACK (launcher_plugin_menu_deactivate), plugin);
+  /* allocate an empty string */
+  string = g_string_sized_new (100);
 
-  /* get the arrow type from the button for the menu direction */
-  arrow_type = xfce_arrow_button_get_arrow_type (XFCE_ARROW_BUTTON (plugin->arrow_button));
+  /* prepend terminal command if required */
+  if (G_UNLIKELY (terminal))
+    g_string_append (string, "exo-open --launch TerminalEmulator ");
 
-  /* walk through the entries */
-  for (li = plugin->entries, n = 0; li != NULL; li = li->next, n++)
+  for (p = exec; *p != '\0'; ++p)
     {
-      /* skip the first entry when the arrow is visible */
-      if (n == 0 && plugin->arrow_position != ARROW_POS_INSIDE_BUTTON)
-        continue;
-
-      entry = li->data;
-
-      /* create menu item */
-      mi = gtk_image_menu_item_new_with_label (entry->name ? entry->name : _("New Item"));
-      g_object_set_qdata (G_OBJECT (mi), launcher_plugin_quark, plugin);
-      g_object_set (G_OBJECT (mi), "has-tooltip", TRUE, NULL);
-      gtk_widget_show (mi);
-
-      /* depending on the menu position we append or prepend */
-      if (arrow_type == GTK_ARROW_DOWN)
-        gtk_menu_shell_append (GTK_MENU_SHELL (plugin->menu), mi);
-      else
-        gtk_menu_shell_prepend (GTK_MENU_SHELL (plugin->menu), mi);
-
-      /* connect signals */
-      g_signal_connect (G_OBJECT (mi), "button-release-event", G_CALLBACK (launcher_plugin_menu_item_released), entry);
-
-      if (plugin->disable_tooltips == FALSE)
-        g_signal_connect (G_OBJECT (mi), "query-tooltip", G_CALLBACK (launcher_plugin_query_tooltip), entry);
-
-      /* try to set an image */
-      if (G_LIKELY (entry->icon))
+      if (p[0] == '%' && p[1] != '\0')
         {
-          /* load pixbuf */
-          pixbuf = launcher_plugin_load_pixbuf (entry->icon, MENU_ICON_SIZE, plugin->icon_theme);
-          if (G_LIKELY (pixbuf))
+          switch (*++p)
             {
-              /* 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));
-            }
-        }
-    }
-}
-
-
+              case 'f':
+              case 'F':
+                for (li = uri_list; li != NULL; li = li->next)
+                  {
+                    filename = g_filename_from_uri ((const gchar *) li->data, NULL, NULL);
+                    if (G_LIKELY (filename != NULL))
+                      launcher_plugin_exec_append_quoted (string, filename);
+                    g_free (filename);
+
+                    if (*p == 'f')
+                      break;
+                    if (li->next != NULL)
+                      g_string_insert_c (string, -1, ' ');
+                  }
+                break;
 
-static gboolean
-launcher_plugin_menu_item_released (GtkMenuItem         *menu_item,
-                                    GdkEventButton      *event,
-                                    LauncherPluginEntry *entry)
-{
-  LauncherPlugin *plugin;
-  GdkScreen      *screen;
+              case 'u':
+              case 'U':
+                for (li = uri_list; li != NULL; li = li->next)
+                  {
+                    launcher_plugin_exec_append_quoted (string, (const gchar *) li->data);
 
-  /* get the plugin */
-  plugin = g_object_get_qdata (G_OBJECT (menu_item), launcher_plugin_quark);
-  panel_return_val_if_fail (XFCE_IS_LAUNCHER_PLUGIN (plugin), FALSE);
+                    if (*p == 'u')
+                      break;
+                    if (li->next != NULL)
+                      g_string_insert_c (string, -1, ' ');
+                  }
+                break;
 
-  /* get the current screen */
-  screen = gtk_widget_get_screen (GTK_WIDGET (plugin));
+              case 'i':
+                if (IS_STRING (entry->icon))
+                  {
+                    g_string_append (string, "--icon ");
+                    launcher_plugin_exec_append_quoted (string, entry->icon);
+                  }
+                break;
 
-  if (event->button != 2)
-    launcher_plugin_execute (screen, entry, NULL);
-  else
-    launcher_plugin_execute_from_clipboard (screen, entry);
+              case 'c':
+                if (IS_STRING (entry->name))
+                  launcher_plugin_exec_append_quoted (string, entry->name);
+                break;
 
-  /* move the item to the first position if enabled */
-  if (G_UNLIKELY (plugin->move_first))
-    {
-      /* remove the item to the first place */
-      plugin->entries = g_list_remove (plugin->entries, entry);
-      plugin->entries = g_list_prepend (plugin->entries, entry);
+              case 'k':
+                if (IS_STRING (entry->filename))
+                  launcher_plugin_exec_append_quoted (string, entry->filename);
+                break;
 
-      /* destroy the menu and update the icon */
-      launcher_plugin_menu_destroy (plugin);
-      launcher_plugin_update_icon (plugin);
+              case '%':
+                g_string_insert_c (string, -1, '%');
+                break;
+            }
+        }
+      else
+        {
+          g_string_insert_c (string, -1, *p);
+        }
     }
 
-  return FALSE;
-}
-
-
-
-static LauncherPluginEntry *
-launcher_plugin_entry_new_default (void)
-{
-  LauncherPluginEntry *entry;
-
-  /* allocate */
-  entry = g_slice_new0 (LauncherPluginEntry);
-  entry->name = g_strdup (_("New Item"));
-  entry->icon = g_strdup ("applications-other");
-
-  return entry;
-}
-
-
-
-static void
-launcher_plugin_entry_free (LauncherPluginEntry *entry)
-{
-  /* free data */
-  g_free (entry->name);
-  g_free (entry->comment);
-  g_free (entry->path);
-  g_free (entry->icon);
-  g_free (entry->exec);
+  result = g_shell_parse_argv (string->str, argc, argv, error);
+  g_string_free (string, TRUE);
 
-  /* free structure */
-  g_slice_free (LauncherPluginEntry, entry);
+  return result;
 }
diff --git a/plugins/launcher/launcher.h b/plugins/launcher/launcher.h
index 211063a..b87023d 100644
--- a/plugins/launcher/launcher.h
+++ b/plugins/launcher/launcher.h
@@ -19,15 +19,13 @@
 #define __LAUNCHER_H__
 
 #include <gtk/gtk.h>
-#include <xfconf/xfconf.h>
 #include <libxfce4panel/libxfce4panel.h>
 
 G_BEGIN_DECLS
 
 typedef struct _LauncherPluginClass    LauncherPluginClass;
 typedef struct _LauncherPlugin         LauncherPlugin;
-typedef struct _LauncherPluginEntry    LauncherPluginEntry;
-typedef enum   _LauncherPluginArrowPos LauncherPluginArrowPos;
+typedef struct _LauncherEntry          LauncherEntry;
 
 #define XFCE_TYPE_LAUNCHER_PLUGIN            (launcher_plugin_get_type ())
 #define XFCE_LAUNCHER_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_LAUNCHER_PLUGIN, LauncherPlugin))
@@ -36,92 +34,8 @@ typedef enum   _LauncherPluginArrowPos LauncherPluginArrowPos;
 #define XFCE_IS_LAUNCHER_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_LAUNCHER_PLUGIN))
 #define XFCE_LAUNCHER_PLUGIN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_LAUNCHER_PLUGIN, LauncherPluginClass))
 
-#define LIST_HAS_ONE_ENTRY(list)             ((list) != NULL && (list)->next == NULL)
-#define LIST_HAS_TWO_OR_MORE_ENTRIES(list)   ((list) != NULL && (list)->next != NULL)
-#define launcher_plugin_filenames_free(list) G_STMT_START { \
-                                             g_slist_foreach (list, (GFunc) g_free, NULL); \
-                                             g_slist_free (list); \
-                                             } G_STMT_END
-
-enum _LauncherPluginArrowPos
-{
-  ARROW_POS_DEFAULT,
-  ARROW_POS_LEFT,
-  ARROW_POS_RIGHT,
-  ARROW_POS_TOP,
-  ARROW_POS_BOTTOM,
-  ARROW_POS_INSIDE_BUTTON,
-
-  ARROW_POS_MIN = ARROW_POS_DEFAULT,
-  ARROW_POS_MAX = ARROW_POS_INSIDE_BUTTON
-};
-
-struct _LauncherPluginClass
-{
-  XfcePanelPluginClass __parent__;
-};
-
-struct _LauncherPlugin
-{
-  XfcePanelPlugin __parent__;
-
-  /* xfconf channel */
-  XfconfChannel          *channel;
-
-  /* settings */
-  guint                   move_first : 1;
-  guint                   disable_tooltips : 1;
-  guint                   show_labels : 1;
-  LauncherPluginArrowPos  arrow_position;
-
-  /* list of entries in the launcher */
-  GList                  *entries;
-
-  /* store the icon theme */
-  GtkIconTheme           *icon_theme;
-
-  /* plugin widgets */
-  GtkWidget              *box;
-  GtkWidget              *icon_button;
-  GtkWidget              *arrow_button;
-  GtkWidget              *image;
-  GtkWidget              *menu;
-
-  /* delayout menu popup */
-  guint                   popup_timeout_id;
-};
-
-struct _LauncherPluginEntry
-{
-  gchar *name;
-  gchar *comment;
-  gchar *exec;
-  gchar *icon;
-  gchar *path;
-
-  guint  terminal : 1;
-#ifdef HAVE_LIBSTARTUP_NOTIFICATION
-  guint  startup_notify : 1;
-#endif
-};
-
-/* target types for dropping in the launcher plugin */
-static const GtkTargetEntry drop_targets[] =
-{
-  { (gchar *) "text/uri-list", 0, 0, },
-  { (gchar *) "STRING",	       0, 0 },
-  { (gchar *) "UTF8_STRING",   0, 0 },
-  { (gchar *) "text/plain",    0, 0 },
-};
-
 GType      launcher_plugin_get_type (void) G_GNUC_CONST;
 
-void       launcher_plugin_rebuild (LauncherPlugin *plugin, gboolean update_icon);
-
-GSList    *launcher_plugin_filenames_from_selection_data (GtkSelectionData *selection_data);
-
-GdkPixbuf *launcher_plugin_load_pixbuf (const gchar *name, gint size, GtkIconTheme *icon_theme);
-
 G_END_DECLS
 
 #endif /* !__LAUNCHER_H__ */



More information about the Xfce4-commits mailing list