[Xfce4-commits] <xfce4-panel:master> Improve code for external plugins.

Nick Schermer noreply at xfce.org
Sun Jul 11 16:54:01 CEST 2010


Updating branch refs/heads/master
         to 13f5459a4a1a75746a5adf19fa9dedd3bd956477 (commit)
       from 779963eda47275f740fc6e97e0741348ef612788 (commit)

commit 13f5459a4a1a75746a5adf19fa9dedd3bd956477
Author: Nick Schermer <nick at xfce.org>
Date:   Thu Jun 17 19:08:44 2010 +0200

    Improve code for external plugins.
    
    Split the base of the external plugin code in three pieces:
    PanelPluginExternal as abstract object to handle the child
    monitoring and access-point for the panel and
    PanelPluginExternal{46,Wrapper} to handle the dbus or socket
    communication. This drop a lot of duplicated code.
    
    Also improve handling of external plugins during a child
    crash; we now wait until the child is terminated before
    we launch the new proccess and also handle restarts of a
    child (requested by the panel) without bothering the
    user.

 common/panel-dbus.h                                |   24 +-
 libxfce4panel/xfce-panel-macros-46.h               |   64 +-
 libxfce4panel/xfce-panel-macros.h                  |    2 -
 libxfce4panel/xfce-panel-plugin-provider.h         |   25 +-
 panel/Makefile.am                                  |   10 +-
 panel/panel-application.c                          |    2 +-
 panel/panel-base-window.c                          |    8 -
 panel/panel-dbus-service.c                         |    1 +
 panel/panel-dialogs.c                              |   32 -
 panel/panel-dialogs.h                              |    3 -
 panel/panel-module.c                               |    4 +-
 panel/panel-plugin-external-46.c                   |  902 +++----------------
 panel/panel-plugin-external-46.h                   |    6 -
 ...xml => panel-plugin-external-wrapper-infos.xml} |   10 +-
 panel/panel-plugin-external-wrapper.c              |  376 ++++++++
 panel/panel-plugin-external-wrapper.h              |   47 +
 panel/panel-plugin-external.c                      |  941 +++++++++-----------
 panel/panel-plugin-external.h                      |   71 ++-
 panel/panel-preferences-dialog.c                   |  105 ++-
 panel/panel-window.c                               |    9 -
 po/POTFILES.in                                     |    1 +
 wrapper/Makefile.am                                |    2 +-
 wrapper/main.c                                     |  116 ++-
 23 files changed, 1272 insertions(+), 1489 deletions(-)

diff --git a/common/panel-dbus.h b/common/panel-dbus.h
index 32d8c39..77412de 100644
--- a/common/panel-dbus.h
+++ b/common/panel-dbus.h
@@ -26,36 +26,20 @@
 #define PANEL_DBUS_WRAPPER_PATH      PANEL_DBUS_PATH "/Wrapper/%d"
 #define PANEL_DBUS_WRAPPER_INTERFACE PANEL_DBUS_INTERFACE ".Wrapper"
 
-/* internal signals send over dbus */
-#define SIGNAL_SET_SIZE                 "a"
-#define SIGNAL_SET_ORIENTATION          "b"
-#define SIGNAL_SET_SCREEN_POSITION      "c"
-#define SIGNAL_SET_LOCKED               "d"
-#define SIGNAL_SAVE                     "e"
-#define SIGNAL_SHOW_CONFIGURE           "f"
-#define SIGNAL_SHOW_ABOUT               "g"
-#define SIGNAL_REMOVED                  "h"
-#define SIGNAL_WRAPPER_SET_SENSITIVE    "i"
-#define SIGNAL_WRAPPER_BACKGROUND_ALPHA "j"
-#define SIGNAL_WRAPPER_QUIT             "k"
-#define SIGNAL_WRAPPER_BACKGROUND_COLOR "l"
-#define SIGNAL_WRAPPER_BACKGROUND_IMAGE "m"
-#define SIGNAL_WRAPPER_BACKGROUND_UNSET "n"
-
 /* special types for dbus communication */
-#define PANEL_TYPE_DBUS_SET_MESSAGE \
+#define PANEL_TYPE_DBUS_SET_PROPERTY \
   dbus_g_type_get_struct ("GValueArray", \
-                          G_TYPE_STRING, \
+                          G_TYPE_UINT, \
                           G_TYPE_VALUE, \
                           G_TYPE_INVALID)
 
 #define PANEL_TYPE_DBUS_SET_SIGNAL \
   dbus_g_type_get_collection ("GPtrArray", \
-                              PANEL_TYPE_DBUS_SET_MESSAGE)
+                              PANEL_TYPE_DBUS_SET_PROPERTY)
 
 enum
 {
-  DBUS_SET_PROPERTY,
+  DBUS_SET_TYPE,
   DBUS_SET_VALUE
 };
 
diff --git a/libxfce4panel/xfce-panel-macros-46.h b/libxfce4panel/xfce-panel-macros-46.h
index 47e25f6..3c28106 100644
--- a/libxfce4panel/xfce-panel-macros-46.h
+++ b/libxfce4panel/xfce-panel-macros-46.h
@@ -38,22 +38,6 @@ G_BEGIN_DECLS
  * Macros to register old external panel plugins that are compiled as executables.
  **/
 
-enum /*< skip >*/
-{
-  PANEL_CLIENT_EVENT_REMOVED,
-  PANEL_CLIENT_EVENT_SAVE,
-  PANEL_CLIENT_EVENT_SET_BACKGROUND_ALPHA,
-  PANEL_CLIENT_EVENT_SET_LOCKED,
-  PANEL_CLIENT_EVENT_SET_ORIENTATION,
-  PANEL_CLIENT_EVENT_SET_SCREEN_POSITION,
-  PANEL_CLIENT_EVENT_SET_SENSITIVE,
-  PANEL_CLIENT_EVENT_SET_SIZE,
-  PANEL_CLIENT_EVENT_SHOW_ABOUT,
-  PANEL_CLIENT_EVENT_SHOW_CONFIGURE,
-  PANEL_CLIENT_EVENT_QUIT,
-  PANEL_CLIENT_EVENT_SET_BG_COLOR,
-  PANEL_CLIENT_EVENT_UNSET_BG
-};
 
 /*< private >*/
 #define _PANEL_CLIENT_EVENT_ATOM "XFCE4_PANEL_PLUGIN_46"
@@ -284,6 +268,7 @@ enum /*< skip >*/
   static const gchar     *_xpp_bg_image = NULL; \
   static cairo_pattern_t *_xpp_bg_image_cache = NULL; \
   static gboolean         _xpp_debug = FALSE; \
+  static gint             _xpp_retval = PLUGIN_EXIT_FAILURE; \
   \
   static void \
   _xpp_quit_main_loop (void) \
@@ -302,9 +287,9 @@ enum /*< skip >*/
                      GdkEventClient  *event, \
                      XfcePanelPlugin *xpp) \
   { \
-    XfcePanelPluginProvider *provider = XFCE_PANEL_PLUGIN_PROVIDER (xpp); \
-    gint                     value; \
-    gint                     message; \
+    XfcePanelPluginProvider          *provider = XFCE_PANEL_PLUGIN_PROVIDER (xpp); \
+    gint                              value; \
+    XfcePanelPluginProviderPropType   type; \
     \
     g_return_val_if_fail (XFCE_IS_PANEL_PLUGIN (xpp), TRUE); \
     g_return_val_if_fail (GTK_IS_PLUG (plug), TRUE); \
@@ -313,58 +298,60 @@ enum /*< skip >*/
     \
     if (event->message_type == _xpp_atom) \
       { \
-        message = event->data.s[0]; \
+        type = event->data.s[0]; \
         value = event->data.s[1]; \
         \
-        switch (message) \
+        switch (type) \
           { \
-          case PANEL_CLIENT_EVENT_REMOVED: \
+          case PROVIDER_PROP_TYPE_ACTION_REMOVED: \
             xfce_panel_plugin_provider_removed (provider); \
             break; \
             \
-          case PANEL_CLIENT_EVENT_SAVE: \
+          case PROVIDER_PROP_TYPE_ACTION_SAVE: \
             xfce_panel_plugin_provider_save (provider); \
             break; \
             \
-          case PANEL_CLIENT_EVENT_SET_BACKGROUND_ALPHA: \
+          case PROVIDER_PROP_TYPE_SET_BACKGROUND_ALPHA: \
             _xpp_alpha = value / 100.00; \
             if (_xpp_composited) \
               gtk_widget_queue_draw (plug); \
             break; \
             \
-          case PANEL_CLIENT_EVENT_SET_LOCKED: \
+          case PROVIDER_PROP_TYPE_SET_LOCKED: \
             xfce_panel_plugin_provider_set_locked (provider, !!value); \
             break; \
             \
-          case PANEL_CLIENT_EVENT_SET_ORIENTATION: \
+          case PROVIDER_PROP_TYPE_SET_ORIENTATION: \
             xfce_panel_plugin_provider_set_orientation (provider, value); \
             break; \
             \
-          case PANEL_CLIENT_EVENT_SET_SCREEN_POSITION: \
+          case PROVIDER_PROP_TYPE_SET_SCREEN_POSITION: \
             xfce_panel_plugin_provider_set_screen_position (provider, value); \
             break; \
             \
-          case PANEL_CLIENT_EVENT_SET_SENSITIVE: \
+          case PROVIDER_PROP_TYPE_SET_SENSITIVE: \
             gtk_widget_set_sensitive (plug, !!value); \
             break; \
             \
-          case PANEL_CLIENT_EVENT_SET_SIZE: \
+          case PROVIDER_PROP_TYPE_SET_SIZE: \
             xfce_panel_plugin_provider_set_size (provider, value); \
             break; \
             \
-          case PANEL_CLIENT_EVENT_SHOW_ABOUT: \
+          case PROVIDER_PROP_TYPE_ACTION_SHOW_ABOUT: \
             xfce_panel_plugin_provider_show_about (provider); \
             break; \
             \
-          case PANEL_CLIENT_EVENT_SHOW_CONFIGURE: \
+          case PROVIDER_PROP_TYPE_ACTION_SHOW_CONFIGURE: \
             xfce_panel_plugin_provider_show_configure (provider); \
             break; \
             \
-          case PANEL_CLIENT_EVENT_QUIT: \
+          case PROVIDER_PROP_TYPE_ACTION_QUIT_FOR_RESTART: \
+            _xpp_retval = PLUGIN_EXIT_SUCCESS_AND_RESTART; \
+          case PROVIDER_PROP_TYPE_ACTION_QUIT: \
             _xpp_quit_main_loop (); \
             break; \
             \
-          case PANEL_CLIENT_EVENT_SET_BG_COLOR: \
+          case PROVIDER_PROP_TYPE_SET_BACKGROUND_COLOR: \
             _xpp_bg_color.red = event->data.s[1]; \
             _xpp_bg_color.green = event->data.s[2]; \
             _xpp_bg_color.blue = event->data.s[3]; \
@@ -372,13 +359,13 @@ enum /*< skip >*/
             gtk_widget_queue_draw (plug); \
             break; \
             \
-          case PANEL_CLIENT_EVENT_UNSET_BG: \
+          case PROVIDER_PROP_TYPE_ACTION_BACKGROUND_UNSET: \
             _xpp_bg_style = 0; \
             gtk_widget_queue_draw (plug); \
             break; \
             \
           default: \
-            g_warning ("Received unknow client event %d", message); \
+            g_warning ("Received unknow client event %u", type); \
             break; \
           } \
         \
@@ -562,7 +549,7 @@ enum /*< skip >*/
     if (G_UNLIKELY (argc < PLUGIN_ARGV_ARGUMENTS)) \
       { \
         g_critical ("Not enough arguments are passed to the plugin"); \
-        return PLUGIN_EXIT_FAILURE; \
+        return PLUGIN_EXIT_ARGUMENTS_FAILED; \
       } \
     \
     if (G_UNLIKELY (preinit_func != NULL)) \
@@ -630,13 +617,16 @@ enum /*< skip >*/
     \
     gtk_main (); \
     \
+    if (_xpp_retval != PLUGIN_EXIT_SUCCESS_AND_RESTART) \
+      _xpp_retval = PLUGIN_EXIT_SUCCESS; \
+    \
     if (_xpp_bg_image_cache != NULL) \
       cairo_pattern_destroy (_xpp_bg_image_cache); \
     \
     if (GTK_IS_WIDGET (plug)) \
       gtk_widget_destroy (plug); \
     \
-    return PLUGIN_EXIT_SUCCESS; \
+    return _xpp_retval; \
   }
 
 
diff --git a/libxfce4panel/xfce-panel-macros.h b/libxfce4panel/xfce-panel-macros.h
index b8acf26..75ac35e 100644
--- a/libxfce4panel/xfce-panel-macros.h
+++ b/libxfce4panel/xfce-panel-macros.h
@@ -61,8 +61,6 @@ G_BEGIN_DECLS
  * Macros to register panel plugin types and custom types inside panel plugins.
  **/
 
-
-
 /**
  * XfcePanelTypeModule:
  *
diff --git a/libxfce4panel/xfce-panel-plugin-provider.h b/libxfce4panel/xfce-panel-plugin-provider.h
index 141f450..cf82e3a 100644
--- a/libxfce4panel/xfce-panel-plugin-provider.h
+++ b/libxfce4panel/xfce-panel-plugin-provider.h
@@ -92,14 +92,37 @@ typedef enum /*< skip >*/
 }
 XfcePanelPluginProviderSignal;
 
+/* properties to the plugin; with a value or as an action */
+typedef enum /*< skip >*/
+{
+  PROVIDER_PROP_TYPE_SET_SIZE,                /* gint */
+  PROVIDER_PROP_TYPE_SET_ORIENTATION,         /* GtkOrientation (as gint) */
+  PROVIDER_PROP_TYPE_SET_SCREEN_POSITION,     /* XfceScreenPosition (as gint) */
+  PROVIDER_PROP_TYPE_SET_BACKGROUND_ALPHA,    /* gdouble */
+  PROVIDER_PROP_TYPE_SET_LOCKED,              /* gboolean */
+  PROVIDER_PROP_TYPE_SET_SENSITIVE,           /* gboolean */
+  PROVIDER_PROP_TYPE_SET_BACKGROUND_COLOR,    /* string, wrapper only */
+  PROVIDER_PROP_TYPE_SET_BACKGROUND_IMAGE,    /* string, wrapper only */
+  PROVIDER_PROP_TYPE_ACTION_REMOVED,          /* none */
+  PROVIDER_PROP_TYPE_ACTION_SAVE,             /* none */
+  PROVIDER_PROP_TYPE_ACTION_QUIT,             /* none */
+  PROVIDER_PROP_TYPE_ACTION_QUIT_FOR_RESTART, /* none */
+  PROVIDER_PROP_TYPE_ACTION_BACKGROUND_UNSET, /* none */
+  PROVIDER_PROP_TYPE_ACTION_SHOW_CONFIGURE,   /* none */
+  PROVIDER_PROP_TYPE_ACTION_SHOW_ABOUT        /* none */
+}
+XfcePanelPluginProviderPropType;
+
 /* plugin exit values */
 enum
 {
   PLUGIN_EXIT_SUCCESS = 0,
   PLUGIN_EXIT_FAILURE,
+  PLUGIN_EXIT_ARGUMENTS_FAILED,
   PLUGIN_EXIT_PREINIT_FAILED,
   PLUGIN_EXIT_CHECK_FAILED,
-  PLUGIN_EXIT_NO_PROVIDER
+  PLUGIN_EXIT_NO_PROVIDER,
+  PLUGIN_EXIT_SUCCESS_AND_RESTART
 };
 
 /* argument handling in plugin and wrapper */
diff --git a/panel/Makefile.am b/panel/Makefile.am
index 906217a..4adb915 100644
--- a/panel/Makefile.am
+++ b/panel/Makefile.am
@@ -17,7 +17,7 @@ xfce4_panel_built_sources = \
 	panel-dbus-client-infos.h \
 	panel-marshal.c \
 	panel-marshal.h \
-	panel-plugin-external-infos.h \
+	panel-plugin-external-wrapper-infos.h \
 	panel-preferences-dialog-ui.h
 
 xfce4_panel_SOURCES = \
@@ -43,6 +43,8 @@ xfce4_panel_SOURCES = \
 	panel-module-factory.h \
 	panel-plugin-external.c \
 	panel-plugin-external.h \
+	panel-plugin-external-wrapper.c \
+	panel-plugin-external-wrapper.h \
 	panel-plugin-external-46.c \
 	panel-plugin-external-46.h \
 	panel-preferences-dialog.c \
@@ -97,8 +99,8 @@ panel-dbus-service-infos.h: $(srcdir)/panel-dbus-service-infos.xml Makefile
 panel-dbus-client-infos.h: $(srcdir)/panel-dbus-service-infos.xml Makefile
 	$(AM_V_GEN) dbus-binding-tool --mode=glib-client $< > $@
 
-panel-plugin-external-infos.h: $(srcdir)/panel-plugin-external-infos.xml Makefile
-	$(AM_V_GEN) dbus-binding-tool --prefix=panel_plugin_external --mode=glib-server $< > $@
+panel-plugin-external-wrapper-infos.h: $(srcdir)/panel-plugin-external-wrapper-infos.xml Makefile
+	$(AM_V_GEN) dbus-binding-tool --prefix=panel_plugin_external_wrapper --mode=glib-server $< > $@
 
 panel-preferences-dialog-ui.h: $(srcdir)/panel-preferences-dialog.glade Makefile
 	$(AM_V_GEN) exo-csource --static --strip-comments --strip-content --name=panel_preferences_dialog_ui $< >$@
@@ -120,7 +122,7 @@ endif
 
 EXTRA_DIST = \
 	panel-dbus-service-infos.xml \
-	panel-plugin-external-infos.xml \
+	panel-plugin-external-wrapper-infos.xml \
 	panel-preferences-dialog.glade \
 	panel-marshal.list
 
diff --git a/panel/panel-application.c b/panel/panel-application.c
index b49c2b5..5120c3a 100644
--- a/panel/panel-application.c
+++ b/panel/panel-application.c
@@ -624,7 +624,7 @@ panel_application_plugin_insert (PanelApplication  *application,
    * realizing for 4.6 panel plugins */
   if (PANEL_BASE_WINDOW (window)->background_style == PANEL_BG_STYLE_IMAGE
       && PANEL_IS_PLUGIN_EXTERNAL_46 (provider))
-    panel_plugin_external_46_set_background_image (PANEL_PLUGIN_EXTERNAL_46 (provider),
+    panel_plugin_external_set_background_image (PANEL_PLUGIN_EXTERNAL (provider),
         PANEL_BASE_WINDOW (window)->background_image);
 
   /* add the item to the panel */
diff --git a/panel/panel-base-window.c b/panel/panel-base-window.c
index 7c42872..5638b8f 100644
--- a/panel/panel-base-window.c
+++ b/panel/panel-base-window.c
@@ -782,9 +782,6 @@ panel_base_window_set_plugin_background_alpha (GtkWidget *widget,
   if (PANEL_IS_PLUGIN_EXTERNAL (widget))
     panel_plugin_external_set_background_alpha (PANEL_PLUGIN_EXTERNAL (widget),
         PANEL_BASE_WINDOW (user_data)->background_alpha);
-  else if (PANEL_IS_PLUGIN_EXTERNAL_46 (widget))
-    panel_plugin_external_46_set_background_alpha (PANEL_PLUGIN_EXTERNAL_46 (widget),
-        PANEL_BASE_WINDOW (user_data)->background_alpha);
 }
 
 
@@ -804,8 +801,6 @@ panel_base_window_set_plugin_background_color (GtkWidget *widget,
 
   if (PANEL_IS_PLUGIN_EXTERNAL (widget))
     panel_plugin_external_set_background_color (PANEL_PLUGIN_EXTERNAL (widget), color);
-  else if (PANEL_IS_PLUGIN_EXTERNAL_46 (widget))
-    panel_plugin_external_46_set_background_color (PANEL_PLUGIN_EXTERNAL_46 (widget), color);
 }
 
 
@@ -820,9 +815,6 @@ panel_base_window_set_plugin_background_image (GtkWidget *widget,
   if (PANEL_IS_PLUGIN_EXTERNAL (widget))
     panel_plugin_external_set_background_image (PANEL_PLUGIN_EXTERNAL (widget),
         PANEL_BASE_WINDOW (user_data)->background_image);
-  else if (PANEL_IS_PLUGIN_EXTERNAL_46 (widget))
-    panel_plugin_external_46_set_background_image (PANEL_PLUGIN_EXTERNAL_46 (widget),
-        PANEL_BASE_WINDOW (user_data)->background_image);
 }
 
 
diff --git a/panel/panel-dbus-service.c b/panel/panel-dbus-service.c
index d2ce717..cb4a481 100644
--- a/panel/panel-dbus-service.c
+++ b/panel/panel-dbus-service.c
@@ -301,6 +301,7 @@ panel_dbus_service_plugin_event_result (XfcePanelPluginProvider *prev_provider,
               lnext = li->next;
               provider = li->data;
               event->plugins = g_slist_delete_link (event->plugins, li);
+              new_handle = 0;
 
               /* maybe the plugin has been destroyed */
               if (!XFCE_PANEL_PLUGIN_PROVIDER (provider))
diff --git a/panel/panel-dialogs.c b/panel/panel-dialogs.c
index 32f017f..14596e9 100644
--- a/panel/panel-dialogs.c
+++ b/panel/panel-dialogs.c
@@ -190,35 +190,3 @@ panel_dialogs_kiosk_warning (void)
 
   return locked;
 }
-
-
-
-gboolean
-panel_dialogs_restart_plugin (GtkWindow   *parent,
-                              const gchar *plugin_name)
-{
-  GtkWidget *dialog;
-  gint       response;
-
-  panel_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), FALSE);
-  panel_return_val_if_fail (plugin_name != NULL, FALSE);
-
-  dialog = gtk_message_dialog_new (parent,
-                                   GTK_DIALOG_DESTROY_WITH_PARENT,
-                                   GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
-                                   _("Plugin \"%s\" unexpectedly left the panel, do you want to restart it?"),
-                                   plugin_name);
-  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), _("The plugin restarted more than once in "
-                                            "the last %d seconds. If you press Execute the panel will try to restart "
-                                            "the plugin otherwise it will be permanently removed from the panel."),
-                                            PANEL_PLUGIN_AUTO_RESTART);
-  gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_EXECUTE, GTK_RESPONSE_OK,
-                          GTK_STOCK_REMOVE, GTK_RESPONSE_CLOSE, NULL);
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
-
-  response = gtk_dialog_run (GTK_DIALOG (dialog));
-  gtk_widget_destroy (dialog);
-
-  return (response == GTK_RESPONSE_OK);
-}
diff --git a/panel/panel-dialogs.h b/panel/panel-dialogs.h
index 253e344..e5be385 100644
--- a/panel/panel-dialogs.h
+++ b/panel/panel-dialogs.h
@@ -30,9 +30,6 @@ gint     panel_dialogs_choose_panel   (PanelApplication *application);
 
 gboolean panel_dialogs_kiosk_warning  (void);
 
-gboolean panel_dialogs_restart_plugin (GtkWindow        *parent,
-                                       const gchar      *plugin_name);
-
 G_END_DECLS
 
 #endif /* !__PANEL_DIALOGS_H__ */
diff --git a/panel/panel-module.c b/panel/panel-module.c
index 4df39b5..bb9b428 100644
--- a/panel/panel-module.c
+++ b/panel/panel-module.c
@@ -31,7 +31,7 @@
 
 #include <panel/panel-module.h>
 #include <panel/panel-module-factory.h>
-#include <panel/panel-plugin-external.h>
+#include <panel/panel-plugin-external-wrapper.h>
 #include <panel/panel-plugin-external-46.h>
 
 #define PANEL_PLUGINS_LIB_DIR LIBDIR G_DIR_SEPARATOR_S "panel-plugins"
@@ -461,7 +461,7 @@ panel_module_new_plugin (PanelModule  *module,
        * preinit_func which is not supported for internal plugins */
 
     case WRAPPER:
-      plugin = panel_plugin_external_new (module, unique_id, arguments);
+      plugin = panel_plugin_external_wrapper_new (module, unique_id, arguments);
       break;
 
     case EXTERNAL_46:
diff --git a/panel/panel-plugin-external-46.c b/panel/panel-plugin-external-46.c
index 2e7c030..b5b81cd 100644
--- a/panel/panel-plugin-external-46.c
+++ b/panel/panel-plugin-external-46.c
@@ -43,105 +43,36 @@
 
 #include <panel/panel-module.h>
 #include <panel/panel-plugin-external-46.h>
+#include <panel/panel-plugin-external.h>
 #include <panel/panel-window.h>
 #include <panel/panel-dialogs.h>
 
 
 
-static void         panel_plugin_external_46_provider_init            (XfcePanelPluginProviderInterface *iface);
-static void         panel_plugin_external_46_finalize                 (GObject                          *object);
-static void         panel_plugin_external_46_get_property             (GObject                          *object,
-                                                                       guint                             prop_id,
-                                                                       GValue                           *value,
-                                                                       GParamSpec                       *pspec);
-static void         panel_plugin_external_46_set_property             (GObject                          *object,
-                                                                       guint                             prop_id,
-                                                                       const GValue                     *value,
-                                                                       GParamSpec                       *pspec);
-static void         panel_plugin_external_46_realize                  (GtkWidget                        *widget);
-static void         panel_plugin_external_46_unrealize                (GtkWidget                        *widget);
-static gboolean     panel_plugin_external_46_client_event             (GtkWidget                        *widget,
-                                                                       GdkEventClient                   *event);
-static gboolean     panel_plugin_external_46_plug_removed             (GtkSocket                        *socket);
-static void         panel_plugin_external_46_plug_added               (GtkSocket                        *socket);
-static void         panel_plugin_external_46_send_client_event        (PanelPluginExternal46            *external,
-                                                                       GdkEventClient                   *event);
-static void         panel_plugin_external_46_send_client_event_simple (PanelPluginExternal46            *external,
-                                                                       gint                              message,
-                                                                       gint                              value);
-static void         panel_plugin_external_46_queue_add                (PanelPluginExternal46            *external,
-                                                                       gint                              message,
-                                                                       gint                              value);
-static const gchar *panel_plugin_external_46_get_name                 (XfcePanelPluginProvider          *provider);
-static gint         panel_plugin_external_46_get_unique_id            (XfcePanelPluginProvider          *provider);
-static void         panel_plugin_external_46_set_size                 (XfcePanelPluginProvider          *provider,
-                                                                       gint                              size);
-static void         panel_plugin_external_46_set_orientation          (XfcePanelPluginProvider          *provider,
-                                                                       GtkOrientation                    orientation);
-static void         panel_plugin_external_46_set_screen_position      (XfcePanelPluginProvider          *provider,
-                                                                       XfceScreenPosition                screen_position);
-static void         panel_plugin_external_46_save                     (XfcePanelPluginProvider          *provider);
-static gboolean     panel_plugin_external_46_get_show_configure       (XfcePanelPluginProvider          *provider);
-static void         panel_plugin_external_46_show_configure           (XfcePanelPluginProvider          *provider);
-static gboolean     panel_plugin_external_46_get_show_about           (XfcePanelPluginProvider          *provider);
-static void         panel_plugin_external_46_show_about               (XfcePanelPluginProvider          *provider);
-static void         panel_plugin_external_46_removed                  (XfcePanelPluginProvider          *provider);
-static gboolean     panel_plugin_external_46_remote_event             (XfcePanelPluginProvider          *provider,
-                                                                       const gchar                      *name,
-                                                                       const GValue                     *value,
-                                                                       guint                            *handler_id);
-static void         panel_plugin_external_46_set_locked               (XfcePanelPluginProvider          *provider,
-                                                                       gboolean                          locked);
-static void         panel_plugin_external_46_set_sensitive            (PanelPluginExternal46            *external);
-static void         panel_plugin_external_46_child_watch              (GPid                              pid,
-                                                                       gint                              status,
-                                                                       gpointer                          user_data);
-static void         panel_plugin_external_46_child_watch_destroyed    (gpointer                          user_data);
+static void       panel_plugin_external_46_finalize       (GObject              *object);
+static gboolean   panel_plugin_external_46_client_event   (GtkWidget            *widget,
+                                                           GdkEventClient       *event);
+static gchar    **panel_plugin_external_46_get_argv       (PanelPluginExternal  *external,
+                                                           gchar               **arguments);
+static void       panel_plugin_external_46_set_properties (PanelPluginExternal  *external,
+                                                           GSList               *properties);
+static gboolean   panel_plugin_external_46_remote_event   (PanelPluginExternal  *external,
+                                                           const gchar          *name,
+                                                           const GValue         *value,
+                                                           guint                *handle);
 
 
 
 struct _PanelPluginExternal46Class
 {
-  GtkSocketClass __parent__;
+  PanelPluginExternalClass __parent__;
 };
 
 struct _PanelPluginExternal46
 {
-  GtkSocket  __parent__;
+  PanelPluginExternal __parent__;
 
-  gint              unique_id;
-
-  /* startup arguments */
-  gchar           **arguments;
-
-  PanelModule      *module;
-
-  guint             plug_embedded : 1;
-
-  /* client-event queue */
-  GSList           *queue;
-
-  /* auto restart timer */
-  GTimer           *restart_timer;
-
-  /* some info we receive on startup */
-  guint             show_configure : 1;
-  guint             show_about : 1;
-
-  /* background image location */
-  gchar            *background_image;
-
-  /* child watch data */
-  GPid              pid;
-  guint             watch_id;
-};
-
-enum
-{
-  PROP_0,
-  PROP_MODULE,
-  PROP_UNIQUE_ID,
-  PROP_ARGUMENTS
+  gchar *background_image;
 };
 
 
@@ -150,55 +81,27 @@ static GdkAtom panel_atom = GDK_NONE;
 
 
 
-G_DEFINE_TYPE_WITH_CODE (PanelPluginExternal46, panel_plugin_external_46, GTK_TYPE_SOCKET,
-  G_IMPLEMENT_INTERFACE (XFCE_TYPE_PANEL_PLUGIN_PROVIDER, panel_plugin_external_46_provider_init))
+G_DEFINE_TYPE (PanelPluginExternal46, panel_plugin_external_46, PANEL_TYPE_PLUGIN_EXTERNAL)
 
 
 
 static void
 panel_plugin_external_46_class_init (PanelPluginExternal46Class *klass)
 {
-  GObjectClass   *gobject_class;
-  GtkWidgetClass *gtkwidget_class;
-  GtkSocketClass *gtksocket_class;
+  GObjectClass             *gobject_class;
+  GtkWidgetClass           *gtkwidget_class;
+  PanelPluginExternalClass *plugin_external_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->finalize = panel_plugin_external_46_finalize;
-  gobject_class->set_property = panel_plugin_external_46_set_property;
-  gobject_class->get_property = panel_plugin_external_46_get_property;
 
   gtkwidget_class = GTK_WIDGET_CLASS (klass);
-  gtkwidget_class->realize = panel_plugin_external_46_realize;
-  gtkwidget_class->unrealize = panel_plugin_external_46_unrealize;
   gtkwidget_class->client_event = panel_plugin_external_46_client_event;
 
-  gtksocket_class = GTK_SOCKET_CLASS (klass);
-  gtksocket_class->plug_removed = panel_plugin_external_46_plug_removed;
-  gtksocket_class->plug_added = panel_plugin_external_46_plug_added;
-
-  g_object_class_install_property (gobject_class,
-                                   PROP_UNIQUE_ID,
-                                   g_param_spec_int ("unique-id",
-                                                     NULL, NULL,
-                                                     -1, G_MAXINT, -1,
-                                                     EXO_PARAM_READWRITE
-                                                     | G_PARAM_CONSTRUCT_ONLY));
-
-  g_object_class_install_property (gobject_class,
-                                   PROP_MODULE,
-                                   g_param_spec_object ("module",
-                                                        NULL, NULL,
-                                                        PANEL_TYPE_MODULE,
-                                                        EXO_PARAM_READWRITE
-                                                        | G_PARAM_CONSTRUCT_ONLY));
-
-  g_object_class_install_property (gobject_class,
-                                   PROP_ARGUMENTS,
-                                   g_param_spec_boxed ("arguments",
-                                                       NULL, NULL,
-                                                       G_TYPE_STRV,
-                                                       EXO_PARAM_READWRITE
-                                                       | G_PARAM_CONSTRUCT_ONLY));
+  plugin_external_class = PANEL_PLUGIN_EXTERNAL_CLASS (klass);
+  plugin_external_class->get_argv = panel_plugin_external_46_get_argv;
+  plugin_external_class->set_properties = panel_plugin_external_46_set_properties;
+  plugin_external_class->remote_event = panel_plugin_external_46_remote_event;
 
   panel_atom = gdk_atom_intern_static_string (_PANEL_CLIENT_EVENT_ATOM);
 }
@@ -208,39 +111,7 @@ panel_plugin_external_46_class_init (PanelPluginExternal46Class *klass)
 static void
 panel_plugin_external_46_init (PanelPluginExternal46 *external)
 {
-  external->unique_id = -1;
-  external->module = NULL;
-  external->queue = NULL;
-  external->arguments = NULL;
-  external->plug_embedded = FALSE;
-  external->restart_timer = NULL;
-  external->show_configure = FALSE;
-  external->show_about = FALSE;
   external->background_image = NULL;
-
-  /* signal to pass gtk_widget_set_sensitive() changes to the remote window */
-  g_signal_connect (G_OBJECT (external), "notify::sensitive",
-      G_CALLBACK (panel_plugin_external_46_set_sensitive), NULL);
-}
-
-
-
-static void
-panel_plugin_external_46_provider_init (XfcePanelPluginProviderInterface *iface)
-{
-  iface->get_name = panel_plugin_external_46_get_name;
-  iface->get_unique_id = panel_plugin_external_46_get_unique_id;
-  iface->set_size = panel_plugin_external_46_set_size;
-  iface->set_orientation = panel_plugin_external_46_set_orientation;
-  iface->set_screen_position = panel_plugin_external_46_set_screen_position;
-  iface->save = panel_plugin_external_46_save;
-  iface->get_show_configure = panel_plugin_external_46_get_show_configure;
-  iface->show_configure = panel_plugin_external_46_show_configure;
-  iface->get_show_about = panel_plugin_external_46_get_show_about;
-  iface->show_about = panel_plugin_external_46_show_about;
-  iface->removed = panel_plugin_external_46_removed;
-  iface->remote_event = panel_plugin_external_46_remote_event;
-  iface->set_locked = panel_plugin_external_46_set_locked;
 }
 
 
@@ -249,208 +120,20 @@ static void
 panel_plugin_external_46_finalize (GObject *object)
 {
   PanelPluginExternal46 *external = PANEL_PLUGIN_EXTERNAL_46 (object);
-  GSList                *li;
 
-  if (external->watch_id != 0)
-    {
-      /* remove the child watch and don't leave zomies */
-      g_source_remove (external->watch_id);
-      g_child_watch_add (external->pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
-    }
-
-  if (external->queue != NULL)
-    {
-      for (li = external->queue; li != NULL; li = li->next)
-        g_slice_free (GdkEventClient, li->data);
-      g_slist_free (external->queue);
-    }
-
-  g_strfreev (external->arguments);
   g_free (external->background_image);
 
-  if (external->restart_timer != NULL)
-    g_timer_destroy (external->restart_timer);
-
-  g_object_unref (G_OBJECT (external->module));
-
   (*G_OBJECT_CLASS (panel_plugin_external_46_parent_class)->finalize) (object);
 }
 
 
 
-static void
-panel_plugin_external_46_get_property (GObject    *object,
-                                       guint       prop_id,
-                                       GValue     *value,
-                                       GParamSpec *pspec)
-{
-  PanelPluginExternal46 *external = PANEL_PLUGIN_EXTERNAL_46 (object);
-
-  switch (prop_id)
-    {
-    case PROP_UNIQUE_ID:
-      g_value_set_int (value, external->unique_id);
-      break;
-
-    case PROP_ARGUMENTS:
-      g_value_set_boxed (value, external->arguments);
-      break;
-
-    case PROP_MODULE:
-      g_value_set_object (value, external->module);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-
-
-static void
-panel_plugin_external_46_set_property (GObject      *object,
-                                       guint         prop_id,
-                                       const GValue *value,
-                                       GParamSpec   *pspec)
-{
-  PanelPluginExternal46 *external = PANEL_PLUGIN_EXTERNAL_46 (object);
-
-  switch (prop_id)
-    {
-    case PROP_UNIQUE_ID:
-      external->unique_id = g_value_get_int (value);
-      break;
-
-    case PROP_ARGUMENTS:
-      external->arguments = g_value_dup_boxed (value);
-      break;
-
-    case PROP_MODULE:
-      external->module = g_value_dup_object (value);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-
-
-static void
-panel_plugin_external_46_realize (GtkWidget *widget)
-{
-  PanelPluginExternal46  *external = PANEL_PLUGIN_EXTERNAL_46 (widget);
-  gchar                 **argv;
-  GError                 *error = NULL;
-  gboolean                succeed;
-  gchar                  *socket_id, *unique_id;
-  GPid                    pid;
-  guint                   argc = PLUGIN_ARGV_ARGUMENTS;
-  guint                   i;
-
-  panel_return_if_fail (external->pid == 0);
-  panel_return_if_fail (!external->plug_embedded);
-
-  /* realize the socket first */
-  (*GTK_WIDGET_CLASS (panel_plugin_external_46_parent_class)->realize) (widget);
-
-  /* get the socket id and unique id in a string */
-  socket_id = g_strdup_printf ("%u", gtk_socket_get_id (GTK_SOCKET (widget)));
-  unique_id = g_strdup_printf ("%d", external->unique_id);
-
-  /* add the number of arguments to the argc count */
-  if (G_UNLIKELY (external->arguments != NULL))
-    argc += g_strv_length (external->arguments);
-
-  /* setup the basic argv */
-  argv = g_new0 (gchar *, argc + 1);
-  argv[PLUGIN_ARGV_0] = (gchar *) panel_module_get_filename (external->module);
-  argv[PLUGIN_ARGV_FILENAME] = (gchar *) ""; /* unused, for wrapper only */
-  argv[PLUGIN_ARGV_UNIQUE_ID] = unique_id;
-  argv[PLUGIN_ARGV_SOCKET_ID] = socket_id;
-  argv[PLUGIN_ARGV_NAME] = (gchar *) panel_module_get_name (external->module);
-  argv[PLUGIN_ARGV_DISPLAY_NAME] = (gchar *) panel_module_get_display_name (external->module);
-  argv[PLUGIN_ARGV_COMMENT] = (gchar *) panel_module_get_comment (external->module);
-
-  if (external->background_image != NULL)
-    argv[PLUGIN_ARGV_BACKGROUND_IMAGE] = (gchar *) external->background_image;
-  else
-    argv[PLUGIN_ARGV_BACKGROUND_IMAGE] = (gchar *) "";
-
-  /* append the arguments */
-  if (G_UNLIKELY (external->arguments != NULL))
-    for (i = 0; external->arguments[i] != NULL; i++)
-      argv[i + PLUGIN_ARGV_ARGUMENTS] = external->arguments[i];
-
-  /* spawn the proccess */
-  succeed = gdk_spawn_on_screen (gtk_widget_get_screen (widget),
-                                 NULL, argv, NULL,
-                                 G_SPAWN_DO_NOT_REAP_CHILD, NULL,
-                                 NULL, &pid, &error);
-
-  panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL46,
-               "plugin=%s, unique-id=%s. socked-id=%s, argc=%d, pid=%d",
-               argv[PLUGIN_ARGV_0], unique_id,
-               socket_id, argc, pid);
-
-  if (G_LIKELY (succeed))
-    {
-      /* watch the child */
-      external->pid = pid;
-      external->watch_id = g_child_watch_add_full (G_PRIORITY_LOW, pid,
-                                                   panel_plugin_external_46_child_watch, external,
-                                                   panel_plugin_external_46_child_watch_destroyed);
-    }
-  else
-    {
-      g_critical ("Failed to spawn plugin: %s", error->message);
-      g_error_free (error);
-    }
-
-  g_free (argv);
-  g_free (socket_id);
-  g_free (unique_id);
-}
-
-
-
-static void
-panel_plugin_external_46_unrealize (GtkWidget *widget)
-{
-  PanelPluginExternal46 *external = PANEL_PLUGIN_EXTERNAL_46 (widget);
-
-  /* the plug is not embedded anymore */
-  external->plug_embedded = FALSE;
-
-  panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL46,
-               "plugin %s-%d unrealized, quiting GtkPlug",
-               panel_module_get_name (external->module),
-               external->unique_id);
-
-  if (external->watch_id != 0)
-    {
-      /* remove the child watch so we don't leave zomies */
-      g_source_remove (external->watch_id);
-      g_child_watch_add (external->pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
-      external->pid = 0;
-    }
-
-  /* quit the plugin */
-  panel_plugin_external_46_send_client_event_simple (external, PANEL_CLIENT_EVENT_QUIT, FALSE);
-
-  (*GTK_WIDGET_CLASS (panel_plugin_external_46_parent_class)->unrealize) (widget);
-}
-
-
-
 static gboolean
 panel_plugin_external_46_client_event (GtkWidget      *widget,
                                        GdkEventClient *event)
 {
-  PanelPluginExternal46 *external = PANEL_PLUGIN_EXTERNAL_46 (widget);
-  gint                   provider_signal;
+  PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (widget);
+  gint                 provider_signal;
 
   if (event->message_type == panel_atom)
     {
@@ -481,409 +164,170 @@ panel_plugin_external_46_client_event (GtkWidget      *widget,
 
 
 
-static gboolean
-panel_plugin_external_46_plug_removed (GtkSocket *socket)
+static gchar **
+panel_plugin_external_46_get_argv (PanelPluginExternal  *external,
+                                   gchar               **arguments)
 {
-  PanelPluginExternal46 *external = PANEL_PLUGIN_EXTERNAL_46 (socket);
-  GtkWidget           *window;
-
-  panel_return_val_if_fail (PANEL_IS_MODULE (external->module), FALSE);
-
-  /* leave when the plugin was already removed */
-  if (!external->plug_embedded)
-    return FALSE;
-
-  /* plug has been removed */
-  external->plug_embedded = FALSE;
+  PanelPluginExternal46  *external46 = PANEL_PLUGIN_EXTERNAL_46 (external);
+  guint                  i, argc = PLUGIN_ARGV_ARGUMENTS;
+  gchar                 **argv;
 
-  /* unrealize and hide the socket */
-  gtk_widget_unrealize (GTK_WIDGET (socket));
-  gtk_widget_hide (GTK_WIDGET (socket));
+  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external), NULL);
+  panel_return_val_if_fail (PANEL_IS_MODULE (external->module), NULL);
+  panel_return_val_if_fail (GTK_IS_SOCKET (external), NULL);
 
-  if (external->watch_id != 0)
-    {
-      /* remove the child watch so we don't leave zomies */
-      g_source_remove (external->watch_id);
-      g_child_watch_add (external->pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
-    }
+  /* add the number of arguments to the argc count */
+  if (G_UNLIKELY (arguments != NULL))
+    argc += g_strv_length (arguments);
 
-  window = gtk_widget_get_toplevel (GTK_WIDGET (socket));
-  panel_return_val_if_fail (PANEL_IS_WINDOW (window), FALSE);
+  /* setup the basic argv */
+  argv = g_new0 (gchar *, argc + 1);
+  argv[PLUGIN_ARGV_0] = g_strdup (panel_module_get_filename (external->module));
+  argv[PLUGIN_ARGV_FILENAME] = g_strdup (""); /* unused, for wrapper only */
+  argv[PLUGIN_ARGV_UNIQUE_ID] = g_strdup_printf ("%d", external->unique_id);;
+  argv[PLUGIN_ARGV_SOCKET_ID] = g_strdup_printf ("%u", gtk_socket_get_id (GTK_SOCKET (external)));;
+  argv[PLUGIN_ARGV_NAME] = g_strdup (panel_module_get_name (external->module));
+  argv[PLUGIN_ARGV_DISPLAY_NAME] = g_strdup (panel_module_get_display_name (external->module));
+  argv[PLUGIN_ARGV_COMMENT] = g_strdup (panel_module_get_comment (external->module));
+
+  if (external46->background_image != NULL)
+    argv[PLUGIN_ARGV_BACKGROUND_IMAGE] = g_strdup (external46->background_image);
+  else
+    argv[PLUGIN_ARGV_BACKGROUND_IMAGE] = g_strdup ("");
 
-  if (external->restart_timer == NULL
-      || g_timer_elapsed (external->restart_timer, NULL) > PANEL_PLUGIN_AUTO_RESTART)
+  /* append the arguments */
+  if (G_UNLIKELY (arguments != NULL))
     {
-      g_message ("Plugin %s-%d has been automatically restarted after crash.",
-                 panel_module_get_name (external->module),
-                 external->unique_id);
+      for (i = 0; arguments[i] != NULL; i++)
+        argv[i + PLUGIN_ARGV_ARGUMENTS] = g_strdup (arguments[i]);
     }
-  else if (!panel_dialogs_restart_plugin (GTK_WINDOW (window),
-               panel_module_get_display_name (external->module)))
-    {
-      /* cleanup the plugin configuration (in panel-application) */
-      xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (external),
-                                              PROVIDER_SIGNAL_REMOVE_PLUGIN);
 
-      /* self destruction */
-      gtk_widget_destroy (GTK_WIDGET (socket));
-
-      return FALSE;
-    }
-
-  /* create or reset the retart timer */
-  if (external->restart_timer == NULL)
-    external->restart_timer = g_timer_new ();
-  else
-    g_timer_reset (external->restart_timer);
-
-  /* send panel information to the plugin (queued until realize) */
-  panel_window_set_povider_info (PANEL_WINDOW (window), GTK_WIDGET (external));
-
-  /* show the socket again (realize will spawn the plugin) */
-  gtk_widget_show (GTK_WIDGET (socket));
-
-  return TRUE;
+  return argv;
 }
 
 
 
 static void
-panel_plugin_external_46_plug_added (GtkSocket *socket)
+panel_plugin_external_46_set_properties (PanelPluginExternal *external,
+                                         GSList              *properties)
 {
-  PanelPluginExternal46 *external = PANEL_PLUGIN_EXTERNAL_46 (socket);
+  PanelPluginExternal46 *external46 = PANEL_PLUGIN_EXTERNAL_46 (external);
   GSList                *li;
-  GdkEventClient        *event;
-
-  /* plug has been added */
-  external->plug_embedded = TRUE;
-
-  panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL46,
-               "plugin %d has been embedded, %d events in queue",
-               external->unique_id, g_slist_length (external->queue));
+  GdkEventClient         event;
+  PluginProperty        *property;
+  GdkColor               color = { 0, };
+  GdkWindow             *window;
 
-  /* send all the messages in the queue */
-  if (external->queue != NULL)
-    {
-      external->queue = g_slist_reverse (external->queue);
-      for (li = external->queue; li != NULL; li = li->next)
-        {
-          event = li->data;
-          panel_plugin_external_46_send_client_event (external, event);
-          g_slice_free (GdkEventClient, event);
-        }
-
-      g_slist_free (external->queue);
-      external->queue = NULL;
-    }
-}
-
-
-
-static void
-panel_plugin_external_46_send_client_event (PanelPluginExternal46 *external,
-                                            GdkEventClient        *event)
-{
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external));
   panel_return_if_fail (panel_atom != GDK_NONE);
   panel_return_if_fail (GDK_IS_WINDOW (GTK_WIDGET (external)->window));
+  panel_return_if_fail (PANEL_IS_MODULE (external->module));
 
-  /* complete event information */
-  event->type = GDK_CLIENT_EVENT;
-  event->window = GTK_WIDGET (external)->window;
-  event->send_event = TRUE;
-  event->message_type = panel_atom;
-
-  gdk_error_trap_push ();
-  gdk_event_send_client_message ((GdkEvent *) event,
-      GDK_WINDOW_XID (gtk_socket_get_plug_window (GTK_SOCKET (external))));
-  gdk_flush ();
-  if (gdk_error_trap_pop () != 0)
-    g_warning ("Failed to send client event %d", event->data.s[0]);
-}
-
-
-
-static void
-panel_plugin_external_46_send_client_event_simple (PanelPluginExternal46 *external,
-                                                   gint                   message,
-                                                   gint                   value)
-{
-  GdkEventClient event;
-
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external));
-
-  /* set event data */
+  /* initial event information */
+  event.type = GDK_CLIENT_EVENT;
+  event.window = GTK_WIDGET (external)->window;
+  event.send_event = TRUE;
+  event.message_type = panel_atom;
   event.data_format = 16;
-  event.data.s[0] = message;
-  event.data.s[1] = value;
-  event.data.s[2] = 0;
 
-  panel_plugin_external_46_send_client_event (external, &event);
-}
-
-
-
-static void
-panel_plugin_external_46_queue_add (PanelPluginExternal46 *external,
-                                    gint                   message,
-                                    gint                   value)
-{
-  GdkEventClient *event;
-
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external));
+  gdk_error_trap_push ();
 
-  if (external->plug_embedded)
+  for (li = properties; li != NULL; li = li->next)
     {
-      /* directly send the message */
-      panel_plugin_external_46_send_client_event_simple (external, message, value);
-    }
-  else
-    {
-      /* queue the message until the plug is embedded */
-      event = g_slice_new0 (GdkEventClient);
-      event->data_format = 16;
-      event->data.s[0] = message;
-      event->data.s[1] = value;
-
-      external->queue = g_slist_prepend (external->queue, event);
-    }
-}
-
-
-
-static const gchar *
-panel_plugin_external_46_get_name (XfcePanelPluginProvider *provider)
-{
-  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider), NULL);
-  panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider), NULL);
-
-  return panel_module_get_name (PANEL_PLUGIN_EXTERNAL_46 (provider)->module);
-}
-
-
-
-static gint
-panel_plugin_external_46_get_unique_id (XfcePanelPluginProvider *provider)
-{
-  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider), -1);
-  panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider), -1);
-
-  return PANEL_PLUGIN_EXTERNAL_46 (provider)->unique_id;
-}
-
-
-
-static void
-panel_plugin_external_46_set_size (XfcePanelPluginProvider *provider,
-                                   gint                     size)
-{
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider));
-  panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
-
-  panel_plugin_external_46_queue_add (PANEL_PLUGIN_EXTERNAL_46 (provider),
-                                      PANEL_CLIENT_EVENT_SET_SIZE,
-                                      size);
-}
-
-
-
-static void
-panel_plugin_external_46_set_orientation (XfcePanelPluginProvider *provider,
-                                          GtkOrientation           orientation)
-{
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider));
-  panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
-
-  panel_plugin_external_46_queue_add (PANEL_PLUGIN_EXTERNAL_46 (provider),
-                                      PANEL_CLIENT_EVENT_SET_ORIENTATION,
-                                      orientation);
-}
-
-
-
-static void
-panel_plugin_external_46_set_screen_position (XfcePanelPluginProvider *provider,
-                                              XfceScreenPosition       screen_position)
-{
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider));
-  panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
-
-  panel_plugin_external_46_queue_add (PANEL_PLUGIN_EXTERNAL_46 (provider),
-                                      PANEL_CLIENT_EVENT_SET_SCREEN_POSITION,
-                                      screen_position);
-}
-
-
-
-static void
-panel_plugin_external_46_save (XfcePanelPluginProvider *provider)
-{
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider));
-  panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
-
-  panel_plugin_external_46_queue_add (PANEL_PLUGIN_EXTERNAL_46 (provider),
-                                      PANEL_CLIENT_EVENT_SAVE,
-                                      FALSE);
-}
-
-
-
-static gboolean
-panel_plugin_external_46_get_show_configure (XfcePanelPluginProvider *provider)
-{
-  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider), FALSE);
-  panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider), FALSE);
-
-  return PANEL_PLUGIN_EXTERNAL_46 (provider)->show_configure;
-}
+      property = li->data;
 
+      event.data.s[0] = property->type;
 
+      switch (property->type)
+        {
+        case PROVIDER_PROP_TYPE_SET_SIZE:
+        case PROVIDER_PROP_TYPE_SET_ORIENTATION:
+        case PROVIDER_PROP_TYPE_SET_SCREEN_POSITION:
+          event.data.s[1] = g_value_get_int (&property->value);
+          break;
 
-static void
-panel_plugin_external_46_show_configure (XfcePanelPluginProvider *provider)
-{
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider));
-  panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
-
-  panel_plugin_external_46_queue_add (PANEL_PLUGIN_EXTERNAL_46 (provider),
-                                      PANEL_CLIENT_EVENT_SHOW_CONFIGURE,
-                                      FALSE);
-}
-
+        case PROVIDER_PROP_TYPE_SET_BACKGROUND_ALPHA:
+          event.data.s[1] = g_value_get_double (&property->value) * 100.00;
+          break;
 
+        case PROVIDER_PROP_TYPE_SET_LOCKED:
+        case PROVIDER_PROP_TYPE_SET_SENSITIVE:
+          event.data.s[1] = g_value_get_boolean (&property->value);
+          break;
 
-static gboolean
-panel_plugin_external_46_get_show_about (XfcePanelPluginProvider *provider)
-{
-  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider), FALSE);
-  panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider), FALSE);
+        case PROVIDER_PROP_TYPE_SET_BACKGROUND_COLOR:
+          if (gdk_color_parse (g_value_get_string (&property->value), &color))
+            {
+              event.data.s[1] = color.red;
+              event.data.s[2] = color.green;
+              event.data.s[3] = color.blue;
+              event.data.s[4] = 0;
+            }
+          break;
 
-  return PANEL_PLUGIN_EXTERNAL_46 (provider)->show_about;
-}
+        case PROVIDER_PROP_TYPE_SET_BACKGROUND_IMAGE:
+          panel_plugin_external_46_set_background_image (external46, g_value_get_string (&property->value));
 
+          /* ask to restart the child */
+          panel_plugin_external_restart (external);
 
+          /* stop handling other properties */
+          goto bailout;
 
-static void
-panel_plugin_external_46_show_about (XfcePanelPluginProvider *provider)
-{
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider));
-  panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
+        case PROVIDER_PROP_TYPE_ACTION_REMOVED:
+        case PROVIDER_PROP_TYPE_ACTION_SAVE:
+        case PROVIDER_PROP_TYPE_ACTION_QUIT:
+        case PROVIDER_PROP_TYPE_ACTION_QUIT_FOR_RESTART:
+        case PROVIDER_PROP_TYPE_ACTION_BACKGROUND_UNSET:
+        case PROVIDER_PROP_TYPE_ACTION_SHOW_CONFIGURE:
+        case PROVIDER_PROP_TYPE_ACTION_SHOW_ABOUT:
+          event.data.s[1] = 0;
+          break;
 
-  panel_plugin_external_46_queue_add (PANEL_PLUGIN_EXTERNAL_46 (provider),
-                                      PANEL_CLIENT_EVENT_SHOW_ABOUT,
-                                      FALSE);
-}
+        default:
+          g_critical ("Received unknown plugin property %u for %s-%d",
+                      property->type, panel_module_get_name (external->module),
+                      external->unique_id);
+          goto bailout;
+        }
 
+      window = gtk_socket_get_plug_window (GTK_SOCKET (external));
+      panel_return_if_fail (GDK_IS_WINDOW (window));
+      gdk_event_send_client_message ((GdkEvent *) &event, GDK_WINDOW_XID (window));
+    }
 
+  bailout:
 
-static void
-panel_plugin_external_46_removed (XfcePanelPluginProvider *provider)
-{
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider));
-  panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
+  gdk_flush ();
 
-  panel_plugin_external_46_queue_add (PANEL_PLUGIN_EXTERNAL_46 (provider),
-                                      PANEL_CLIENT_EVENT_REMOVED,
-                                      FALSE);
+  if (gdk_error_trap_pop () != 0)
+    {
+      g_critical ("Failed to send client messages for %s-%d",
+                  panel_module_get_name (external->module),
+                  external->unique_id);
+    }
 }
 
 
 
 static gboolean
-panel_plugin_external_46_remote_event (XfcePanelPluginProvider *provider,
-                                       const gchar             *name,
-                                       const GValue            *value,
-                                       guint                   *handle)
+panel_plugin_external_46_remote_event (PanelPluginExternal *external,
+                                       const gchar         *name,
+                                       const GValue        *value,
+                                       guint               *handle)
 {
-  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider), TRUE);
-  panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider), TRUE);
+  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external), TRUE);
+  panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (external), TRUE);
 
   g_warning ("Plugin %s is compiled as an Xfce 4.6 binary. It needs to be "
              "ported to the new library plugin framework to be able to use "
-             "remote events.", panel_plugin_external_46_get_name (provider));
+             "remote events.", panel_module_get_name (external->module));
 
   return TRUE;
 }
 
 
 
-static void
-panel_plugin_external_46_set_locked (XfcePanelPluginProvider *provider,
-                                     gboolean                 locked)
-{
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (provider));
-  panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
-
-  panel_plugin_external_46_queue_add (PANEL_PLUGIN_EXTERNAL_46 (provider),
-                                      PANEL_CLIENT_EVENT_SET_LOCKED,
-                                      locked);
-}
-
-
-
-static void
-panel_plugin_external_46_set_sensitive (PanelPluginExternal46 *external)
-{
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external));
-
-  panel_plugin_external_46_queue_add (external,
-                                      PANEL_CLIENT_EVENT_SET_SENSITIVE,
-                                      GTK_WIDGET_IS_SENSITIVE (external));
-}
-
-
-
-static void
-panel_plugin_external_46_child_watch (GPid     pid,
-                                      gint     status,
-                                      gpointer user_data)
-{
-  PanelPluginExternal46 *external = PANEL_PLUGIN_EXTERNAL_46 (user_data);
-
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external));
-  panel_return_if_fail (external->pid == pid);
-
-  /* only handle our exit status if the plugin exited normally */
-  if (WIFEXITED (status))
-    {
-      /* extract our return value from the status */
-      switch (WEXITSTATUS (status))
-        {
-        case PLUGIN_EXIT_SUCCESS:
-          break;
-
-        case PLUGIN_EXIT_FAILURE:
-        case PLUGIN_EXIT_PREINIT_FAILED:
-        case PLUGIN_EXIT_CHECK_FAILED:
-        case PLUGIN_EXIT_NO_PROVIDER:
-          panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL46,
-                       "plugin exited with status %d. Removing from "
-                       "configuration.", WEXITSTATUS (status));
-
-          /* cleanup the plugin configuration (in panel-application) */
-          xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (external),
-                                                  PROVIDER_SIGNAL_REMOVE_PLUGIN);
-
-          /* wait until everything is settled */
-          exo_gtk_object_destroy_later (GTK_OBJECT (external));
-          break;
-
-        }
-    }
-
-  g_spawn_close_pid (pid);
-}
-
-
-
-static void
-panel_plugin_external_46_child_watch_destroyed (gpointer user_data)
-{
-  PANEL_PLUGIN_EXTERNAL_46 (user_data)->watch_id = 0;
-}
-
-
-
 GtkWidget *
 panel_plugin_external_46_new (PanelModule  *module,
                               gint          unique_id,
@@ -901,83 +345,11 @@ panel_plugin_external_46_new (PanelModule  *module,
 
 
 void
-panel_plugin_external_46_set_background_alpha (PanelPluginExternal46 *external,
-                                               gdouble              alpha)
-{
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external));
-
-  panel_plugin_external_46_queue_add (external,
-                                      PANEL_CLIENT_EVENT_SET_BACKGROUND_ALPHA,
-                                      rint (alpha * 100.0));
-}
-
-
-
-void
-panel_plugin_external_46_set_background_color (PanelPluginExternal46 *external,
-                                               const GdkColor        *color)
-{
-  GdkEventClient *event;
-
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external));
-
-  event = g_slice_new0 (GdkEventClient);
-
-  if (color != NULL)
-    {
-      event->data_format = 16;
-      event->data.s[0] = PANEL_CLIENT_EVENT_SET_BG_COLOR;
-      event->data.s[1] = color->red;
-      event->data.s[2] = color->green;
-      event->data.s[3] = color->blue;
-      event->data.s[4] = 0;
-    }
-  else
-    {
-      event->data_format = 16;
-      event->data.s[0] = PANEL_CLIENT_EVENT_UNSET_BG;
-    }
-
-  if (external->plug_embedded)
-    {
-      /* directly send the event */
-      panel_plugin_external_46_send_client_event (external, event);
-      g_slice_free (GdkEventClient, event);
-    }
-  else
-    {
-      /* queue the event until the plug is embedded */
-      external->queue = g_slist_prepend (external->queue, event);
-    }
-}
-
-
-void
 panel_plugin_external_46_set_background_image (PanelPluginExternal46 *external,
                                                const gchar           *image)
 {
-  GtkWidget *window;
-
-  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external));
+  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
 
-  /* store new file location */
   g_free (external->background_image);
   external->background_image = g_strdup (image);
-
-  /* restart the plugin if a process is already running */
-  if (external->plug_embedded)
-    {
-      panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL46,
-                   "going to restart plugin %d for background image change",
-                   external->unique_id);
-
-      gtk_widget_unrealize (GTK_WIDGET (external));
-      gtk_widget_hide (GTK_WIDGET (external));
-
-      window = gtk_widget_get_toplevel (GTK_WIDGET (external));
-      panel_return_if_fail (PANEL_IS_WINDOW (window));
-      panel_window_set_povider_info (PANEL_WINDOW (window), GTK_WIDGET (external));
-
-      gtk_widget_show (GTK_WIDGET (external));
-    }
 }
diff --git a/panel/panel-plugin-external-46.h b/panel/panel-plugin-external-46.h
index 4b2ae26..5cadde8 100644
--- a/panel/panel-plugin-external-46.h
+++ b/panel/panel-plugin-external-46.h
@@ -42,12 +42,6 @@ GtkWidget *panel_plugin_external_46_new                  (PanelModule
                                                           gint                    unique_id,
                                                           gchar                 **arguments) G_GNUC_MALLOC;
 
-void       panel_plugin_external_46_set_background_alpha (PanelPluginExternal46  *external,
-                                                          gdouble                 alpha);
-
-void       panel_plugin_external_46_set_background_color (PanelPluginExternal46  *external,
-                                                          const GdkColor         *color);
-
 void       panel_plugin_external_46_set_background_image (PanelPluginExternal46  *external,
                                                           const gchar            *image);
 
diff --git a/panel/panel-plugin-external-infos.xml b/panel/panel-plugin-external-wrapper-infos.xml
similarity index 76%
rename from panel/panel-plugin-external-infos.xml
rename to panel/panel-plugin-external-wrapper-infos.xml
index 454a02f..e2d4680 100644
--- a/panel/panel-plugin-external-infos.xml
+++ b/panel/panel-plugin-external-wrapper-infos.xml
@@ -4,18 +4,16 @@
   -->
   <interface name="org.xfce.Panel.Wrapper">
     <annotation name="org.freedesktop.DBus.GLib.CSymbol"
-                value="panel_plugin_external_dbus" />
+                value="panel_plugin_external_wrapper_dbus" />
     <annotation name="org.freedesktop.DBus.GLib.ClientCSymbol"
                 value="wrapper_dbus" />
 
     <!--
-      s : property : Name of the property to set on the wrapper. This is used
-                     for both panel values (no reply required) and plugin
-                     event (require a reply from the plugin).
-      v : value    : GValue with the value for the property.
+      i : unsigned integer : enum from XfcePanelPluginProviderPropType.
+      v : value            : GValue with the value for the property.
     -->
     <signal name="Set">
-      <arg name="values" type="a(sv)" />
+      <arg name="values" type="a(uv)" />
     </signal>
 
     <!--
diff --git a/panel/panel-plugin-external-wrapper.c b/panel/panel-plugin-external-wrapper.c
new file mode 100644
index 0000000..daf3153
--- /dev/null
+++ b/panel/panel-plugin-external-wrapper.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2008-2009 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#include <exo/exo.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <libxfce4util/libxfce4util.h>
+
+#include <common/panel-private.h>
+#include <common/panel-dbus.h>
+#include <common/panel-debug.h>
+
+#include <libxfce4panel/libxfce4panel.h>
+#include <libxfce4panel/xfce-panel-plugin-provider.h>
+
+#include <panel/panel-module.h>
+#include <panel/panel-plugin-external.h>
+#include <panel/panel-plugin-external-wrapper.h>
+#include <panel/panel-window.h>
+#include <panel/panel-dialogs.h>
+#include <panel/panel-marshal.h>
+
+
+
+#define WRAPPER_BIN LIBEXECDIR G_DIR_SEPARATOR_S "panel" G_DIR_SEPARATOR_S "wrapper"
+
+
+
+static GObject   *panel_plugin_external_wrapper_constructor              (GType                           type,
+                                                                          guint                           n_construct_params,
+                                                                          GObjectConstructParam          *construct_params);
+static void       panel_plugin_external_wrapper_set_properties           (PanelPluginExternal            *external,
+                                                                          GSList                         *properties);
+static gchar    **panel_plugin_external_wrapper_get_argv                 (PanelPluginExternal            *external,
+                                                                          gchar                         **arguments);
+static gboolean   panel_plugin_external_wrapper_remote_event             (PanelPluginExternal            *external,
+                                                                          const gchar                    *name,
+                                                                          const GValue                   *value,
+                                                                          guint                          *handle);
+static gboolean   panel_plugin_external_wrapper_dbus_provider_signal     (PanelPluginExternalWrapper     *external,
+                                                                          XfcePanelPluginProviderSignal   provider_signal,
+                                                                          GError                        **error);
+static gboolean   panel_plugin_external_wrapper_dbus_remote_event_result (PanelPluginExternalWrapper     *external,
+                                                                          guint                           handle,
+                                                                          gboolean                        result,
+                                                                          GError                        **error);
+
+
+
+/* include the dbus glue generated by dbus-binding-tool */
+#include <panel/panel-plugin-external-wrapper-infos.h>
+
+
+
+struct _PanelPluginExternalWrapperClass
+{
+  PanelPluginExternalClass __parent__;
+};
+
+struct _PanelPluginExternalWrapper
+{
+  PanelPluginExternal __parent__;
+};
+
+enum
+{
+  SET,
+  REMOTE_EVENT,
+  REMOTE_EVENT_RESULT,
+  LAST_SIGNAL
+};
+
+
+
+static guint external_signals[LAST_SIGNAL];
+
+
+
+G_DEFINE_TYPE (PanelPluginExternalWrapper, panel_plugin_external_wrapper, PANEL_TYPE_PLUGIN_EXTERNAL)
+
+
+
+static void
+panel_plugin_external_wrapper_class_init (PanelPluginExternalWrapperClass *klass)
+{
+  GObjectClass             *gobject_class;
+  PanelPluginExternalClass *plugin_external_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->constructor = panel_plugin_external_wrapper_constructor;
+
+  plugin_external_class = PANEL_PLUGIN_EXTERNAL_CLASS (klass);
+  plugin_external_class->get_argv = panel_plugin_external_wrapper_get_argv;
+  plugin_external_class->set_properties = panel_plugin_external_wrapper_set_properties;
+  plugin_external_class->remote_event = panel_plugin_external_wrapper_remote_event;
+
+  external_signals[SET] =
+    g_signal_new (g_intern_static_string ("set"),
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL,
+                  g_cclosure_marshal_VOID__BOXED,
+                  G_TYPE_NONE, 1,
+                  PANEL_TYPE_DBUS_SET_SIGNAL);
+
+  external_signals[REMOTE_EVENT] =
+    g_signal_new (g_intern_static_string ("remote-event"),
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL,
+                  _panel_marshal_VOID__STRING_BOXED_UINT,
+                  G_TYPE_NONE, 3,
+                  G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_UINT);
+
+  external_signals[REMOTE_EVENT_RESULT] =
+    g_signal_new (g_intern_static_string ("remote-event-result"),
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL,
+                  _panel_marshal_VOID__UINT_BOOLEAN,
+                  G_TYPE_NONE, 2,
+                  G_TYPE_UINT, G_TYPE_BOOLEAN);
+
+  /* add dbus type info for plugins */
+  dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
+      &dbus_glib_panel_plugin_external_wrapper_object_info);
+}
+
+
+
+static void
+panel_plugin_external_wrapper_init (PanelPluginExternalWrapper *external)
+{
+}
+
+
+
+static GObject *
+panel_plugin_external_wrapper_constructor (GType                  type,
+                                           guint                  n_construct_params,
+                                           GObjectConstructParam *construct_params)
+{
+  GObject         *object;
+  gchar           *path;
+  DBusGConnection *connection;
+  GError          *error = NULL;
+
+  object = G_OBJECT_CLASS (panel_plugin_external_wrapper_parent_class)->constructor (type,
+                                                                                     n_construct_params,
+                                                                                     construct_params);
+
+  connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+  if (G_LIKELY (connection != NULL))
+    {
+      /* register the object in dbus, the wrapper will monitor this object */
+      panel_return_val_if_fail (PANEL_PLUGIN_EXTERNAL (object)->unique_id != -1, NULL);
+      path = g_strdup_printf (PANEL_DBUS_WRAPPER_PATH, PANEL_PLUGIN_EXTERNAL (object)->unique_id);
+      dbus_g_connection_register_g_object (connection, path, object);
+      panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL, "register dbus path %s", path);
+      g_free (path);
+
+      dbus_g_connection_unref (connection);
+    }
+  else
+    {
+      g_critical ("Failed to get D-Bus session bus: %s", error->message);
+      g_error_free (error);
+    }
+
+  return object;
+}
+
+
+
+static gchar **
+panel_plugin_external_wrapper_get_argv (PanelPluginExternal   *external,
+                                        gchar               **arguments)
+{
+  guint   i, argc = PLUGIN_ARGV_ARGUMENTS;
+  gchar **argv;
+
+  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL_WRAPPER (external), NULL);
+  panel_return_val_if_fail (PANEL_IS_MODULE (external->module), NULL);
+  panel_return_val_if_fail (GTK_IS_SOCKET (external), NULL);
+
+  /* add the number of arguments to the argc count */
+  if (G_UNLIKELY (arguments != NULL))
+    argc += g_strv_length (arguments);
+
+  /* setup the basic argv */
+  argv = g_new0 (gchar *, argc + 1);
+  argv[PLUGIN_ARGV_0] = g_strdup (WRAPPER_BIN);
+  argv[PLUGIN_ARGV_FILENAME] = g_strdup (panel_module_get_filename (external->module));
+  argv[PLUGIN_ARGV_UNIQUE_ID] = g_strdup_printf ("%d", external->unique_id);;
+  argv[PLUGIN_ARGV_SOCKET_ID] = g_strdup_printf ("%u", gtk_socket_get_id (GTK_SOCKET (external)));;
+  argv[PLUGIN_ARGV_NAME] = g_strdup (panel_module_get_name (external->module));
+  argv[PLUGIN_ARGV_DISPLAY_NAME] = g_strdup (panel_module_get_display_name (external->module));
+  argv[PLUGIN_ARGV_COMMENT] = g_strdup (panel_module_get_comment (external->module));
+  argv[PLUGIN_ARGV_BACKGROUND_IMAGE] = g_strdup (""); /* unused, for 4.6 plugins only */
+
+  /* append the arguments */
+  if (G_UNLIKELY (arguments != NULL))
+    {
+      for (i = 0; arguments[i] != NULL; i++)
+        argv[i + PLUGIN_ARGV_ARGUMENTS] = g_strdup (arguments[i]);
+    }
+
+  return argv;
+}
+
+
+
+static void
+panel_plugin_external_wrapper_set_properties (PanelPluginExternal *external,
+                                              GSList              *properties)
+{
+  GPtrArray      *array;
+  GValue          message = { 0, };
+  PluginProperty *property;
+  GSList         *li;
+  guint           i;
+
+  array = g_ptr_array_sized_new (1);
+
+  g_value_init (&message, PANEL_TYPE_DBUS_SET_PROPERTY);
+  g_value_take_boxed (&message, dbus_g_type_specialized_construct (G_VALUE_TYPE (&message)));
+
+  /* put properties in a dbus-suitable array for the wrapper */
+  for (li = properties; li != NULL; li = li->next)
+    {
+      property = li->data;
+
+      dbus_g_type_struct_set (&message,
+                              DBUS_SET_TYPE, property->type,
+                              DBUS_SET_VALUE, &property->value,
+                              G_MAXUINT);
+
+      g_ptr_array_add (array, g_value_dup_boxed (&message));
+    }
+
+  /* send array to the wrapper */
+  g_signal_emit (G_OBJECT (external), external_signals[SET], 0, array);
+
+  for (i = 0; i < array->len; i++)
+    g_value_array_free (g_ptr_array_index (array, i));
+  g_ptr_array_free (array, TRUE);
+  g_value_unset (&message);
+}
+
+
+
+static gboolean
+panel_plugin_external_wrapper_remote_event (PanelPluginExternal *external,
+                                            const gchar         *name,
+                                            const GValue        *value,
+                                            guint               *handle)
+{
+  static guint  handle_counter = 0;
+  GValue        dummy_value = { 0, };
+  const GValue *real_value = value;
+
+  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL_WRAPPER (external), TRUE);
+  panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (external), TRUE);
+  panel_return_val_if_fail (value == NULL || G_IS_VALUE (value), FALSE);
+
+  if (G_UNLIKELY (handle_counter > G_MAXUINT - 2))
+    handle_counter = 0;
+  *handle = ++handle_counter;
+
+  if (value == NULL)
+    {
+      /* we send a dummy value over dbus */
+      g_value_init (&dummy_value, G_TYPE_UCHAR);
+      g_value_set_uchar (&dummy_value, '\0');
+      real_value = &dummy_value;
+    }
+
+  g_signal_emit (G_OBJECT (external), external_signals[REMOTE_EVENT], 0,
+                 name, real_value, *handle);
+
+  if (real_value != value)
+    g_value_unset (&dummy_value);
+
+  return TRUE;
+}
+
+
+
+static gboolean
+panel_plugin_external_wrapper_dbus_provider_signal (PanelPluginExternalWrapper     *external,
+                                                    XfcePanelPluginProviderSignal   provider_signal,
+                                                    GError                        **error)
+{
+  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external), FALSE);
+  panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (external), FALSE);
+
+  switch (provider_signal)
+    {
+    case PROVIDER_SIGNAL_SHOW_CONFIGURE:
+      PANEL_PLUGIN_EXTERNAL (external)->show_configure = TRUE;
+      break;
+
+    case PROVIDER_SIGNAL_SHOW_ABOUT:
+      PANEL_PLUGIN_EXTERNAL (external)->show_about = TRUE;
+      break;
+
+    default:
+      /* other signals are handled in panel-applications.c */
+      xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (external),
+                                              provider_signal);
+      break;
+    }
+
+  return TRUE;
+}
+
+
+
+static gboolean
+panel_plugin_external_wrapper_dbus_remote_event_result (PanelPluginExternalWrapper  *external,
+                                                        guint                        handle,
+                                                        gboolean                     result,
+                                                        GError                     **error)
+{
+  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external), FALSE);
+
+  g_signal_emit (G_OBJECT (external), external_signals[REMOTE_EVENT_RESULT], 0,
+                 handle, result);
+
+  return TRUE;
+}
+
+
+
+GtkWidget *
+panel_plugin_external_wrapper_new (PanelModule  *module,
+                                   gint          unique_id,
+                                   gchar       **arguments)
+{
+  panel_return_val_if_fail (PANEL_IS_MODULE (module), NULL);
+  panel_return_val_if_fail (unique_id != -1, NULL);
+
+  return g_object_new (PANEL_TYPE_PLUGIN_EXTERNAL_WRAPPER,
+                       "module", module,
+                       "unique-id", unique_id,
+                       "arguments", arguments, NULL);
+}
diff --git a/panel/panel-plugin-external-wrapper.h b/panel/panel-plugin-external-wrapper.h
new file mode 100644
index 0000000..eaa3ee9
--- /dev/null
+++ b/panel/panel-plugin-external-wrapper.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008-2010 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __PANEL_PLUGIN_EXTERNAL_WRAPPER_H__
+#define __PANEL_PLUGIN_EXTERNAL_WRAPPER_H__
+
+#include <gtk/gtk.h>
+#include <libxfce4panel/libxfce4panel.h>
+#include <libxfce4panel/xfce-panel-plugin-provider.h>
+#include <panel/panel-module.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PanelPluginExternalWrapperClass PanelPluginExternalWrapperClass;
+typedef struct _PanelPluginExternalWrapper      PanelPluginExternalWrapper;
+
+#define PANEL_TYPE_PLUGIN_EXTERNAL_WRAPPER            (panel_plugin_external_wrapper_get_type ())
+#define PANEL_PLUGIN_EXTERNAL_WRAPPER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_PLUGIN_EXTERNAL_WRAPPER, PanelPluginExternalWrapper))
+#define PANEL_PLUGIN_EXTERNAL_WRAPPER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PANEL_TYPE_PLUGIN_EXTERNAL_WRAPPER, PanelPluginExternalWrapperClass))
+#define PANEL_IS_PLUGIN_EXTERNAL_WRAPPER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PANEL_TYPE_PLUGIN_EXTERNAL_WRAPPER))
+#define PANEL_IS_PLUGIN_EXTERNAL_WRAPPER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_PLUGIN_EXTERNAL_WRAPPER))
+#define PANEL_PLUGIN_EXTERNAL_WRAPPER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PANEL_TYPE_PLUGIN_EXTERNAL_WRAPPER, PanelPluginExternalWrapperClass))
+
+GType      panel_plugin_external_wrapper_get_type (void) G_GNUC_CONST;
+
+GtkWidget *panel_plugin_external_wrapper_new      (PanelModule  *module,
+                                                   gint          unique_id,
+                                                   gchar       **arguments) G_GNUC_MALLOC;
+
+G_END_DECLS
+
+#endif /* !__PANEL_PLUGIN_EXTERNAL_WRAPPER_H__ */
diff --git a/panel/panel-plugin-external.c b/panel/panel-plugin-external.c
index 55ed76a..271e3b7 100644
--- a/panel/panel-plugin-external.c
+++ b/panel/panel-plugin-external.c
@@ -23,6 +23,9 @@
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
 #ifdef HAVE_SYS_WAIT_H
 #include <sys/wait.h>
 #endif
@@ -32,6 +35,8 @@
 #include <gdk/gdkx.h>
 #include <libxfce4util/libxfce4util.h>
 
+#include <dbus/dbus-glib.h>
+
 #include <common/panel-private.h>
 #include <common/panel-dbus.h>
 #include <common/panel-debug.h>
@@ -41,113 +46,88 @@
 
 #include <panel/panel-module.h>
 #include <panel/panel-plugin-external.h>
+#include <panel/panel-plugin-external-46.h>
 #include <panel/panel-window.h>
 #include <panel/panel-dialogs.h>
-#include <panel/panel-marshal.h>
-
-
-
-#define WRAPPER_BIN LIBEXECDIR G_DIR_SEPARATOR_S "panel" G_DIR_SEPARATOR_S "wrapper"
-
-
-
-static void         panel_plugin_external_provider_init            (XfcePanelPluginProviderInterface  *iface);
-static GObject     *panel_plugin_external_constructor              (GType                              type,
-                                                                    guint                              n_construct_params,
-                                                                    GObjectConstructParam             *construct_params);
-static void         panel_plugin_external_finalize                 (GObject                           *object);
-static void         panel_plugin_external_get_property             (GObject                           *object,
-                                                                    guint                              prop_id,
-                                                                    GValue                            *value,
-                                                                    GParamSpec                        *pspec);
-static void         panel_plugin_external_set_property             (GObject                           *object,
-                                                                    guint                              prop_id,
-                                                                    const GValue                      *value,
-                                                                    GParamSpec                        *pspec);
-static void         panel_plugin_external_realize                  (GtkWidget                         *widget);
-static void         panel_plugin_external_unrealize                (GtkWidget                         *widget);
-static gboolean     panel_plugin_external_plug_removed             (GtkSocket                         *socket);
-static void         panel_plugin_external_plug_added               (GtkSocket                         *socket);
-static gboolean     panel_plugin_external_dbus_provider_signal     (PanelPluginExternal               *external,
-                                                                    XfcePanelPluginProviderSignal      provider_signal,
-                                                                    GError                           **error);
-static gboolean     panel_plugin_external_dbus_remote_event_result (PanelPluginExternal               *external,
-                                                                    guint                              handle,
-                                                                    gboolean                           result,
-                                                                    GError                           **error);
-static void         panel_plugin_external_dbus_set                 (PanelPluginExternal               *external,
-                                                                    gboolean                           force);
-static void         panel_plugin_external_queue_add                (PanelPluginExternal               *external,
-                                                                    gboolean                           force,
-                                                                    const gchar                       *property,
-                                                                    const GValue                      *value);
-static void         panel_plugin_external_queue_add_noop           (PanelPluginExternal               *external,
-                                                                    gboolean                           force,
-                                                                    const gchar                       *property);
-static const gchar *panel_plugin_external_get_name                 (XfcePanelPluginProvider           *provider);
-static gint         panel_plugin_external_get_unique_id            (XfcePanelPluginProvider           *provider);
-static void         panel_plugin_external_set_size                 (XfcePanelPluginProvider           *provider,
-                                                                    gint                               size);
-static void         panel_plugin_external_set_orientation          (XfcePanelPluginProvider           *provider,
-                                                                    GtkOrientation                     orientation);
-static void         panel_plugin_external_set_screen_position      (XfcePanelPluginProvider           *provider,
-                                                                    XfceScreenPosition                 screen_position);
-static void         panel_plugin_external_save                     (XfcePanelPluginProvider           *provider);
-static gboolean     panel_plugin_external_get_show_configure       (XfcePanelPluginProvider           *provider);
-static void         panel_plugin_external_show_configure           (XfcePanelPluginProvider           *provider);
-static gboolean     panel_plugin_external_get_show_about           (XfcePanelPluginProvider           *provider);
-static void         panel_plugin_external_show_about               (XfcePanelPluginProvider           *provider);
-static void         panel_plugin_external_removed                  (XfcePanelPluginProvider           *provider);
-static gboolean     panel_plugin_external_remote_event             (XfcePanelPluginProvider           *provider,
-                                                                    const gchar                       *name,
-                                                                    const GValue                      *value,
-                                                                    guint                             *handler_id);
-static void         panel_plugin_external_set_locked               (XfcePanelPluginProvider           *provider,
-                                                                    gboolean                           locked);
-static void         panel_plugin_external_set_sensitive            (PanelPluginExternal               *external);
-static void         panel_plugin_external_child_watch              (GPid                               pid,
-                                                                    gint                               status,
-                                                                    gpointer                           user_data);
-static void         panel_plugin_external_child_watch_destroyed    (gpointer                           user_data);
-
-
-
-/* include the dbus glue generated by dbus-binding-tool */
-#include <panel/panel-plugin-external-infos.h>
-
-
-
-struct _PanelPluginExternalClass
-{
-  GtkSocketClass __parent__;
-};
 
-struct _PanelPluginExternal
-{
-  GtkSocket  __parent__;
 
-  gint              unique_id;
 
+static void         panel_plugin_external_provider_init           (XfcePanelPluginProviderInterface *iface);
+static void         panel_plugin_external_finalize                (GObject                          *object);
+static void         panel_plugin_external_get_property            (GObject                          *object,
+                                                                   guint                             prop_id,
+                                                                   GValue                           *value,
+                                                                   GParamSpec                       *pspec);
+static void         panel_plugin_external_set_property            (GObject                          *object,
+                                                                   guint                             prop_id,
+                                                                   const GValue                     *value,
+                                                                   GParamSpec                       *pspec);
+static void         panel_plugin_external_realize                 (GtkWidget                        *widget);
+static void         panel_plugin_external_unrealize               (GtkWidget                        *widget);
+static void         panel_plugin_external_plug_added              (GtkSocket                        *socket);
+static gboolean     panel_plugin_external_plug_removed            (GtkSocket                        *socket);
+static gboolean     panel_plugin_external_child_ask_restart       (PanelPluginExternal              *external);
+static void         panel_plugin_external_child_spawn             (PanelPluginExternal              *external);
+static gboolean     panel_plugin_external_child_respawn           (gpointer                          user_data);
+static void         panel_plugin_external_child_respawn_destroyed (gpointer                          user_data);
+static void         panel_plugin_external_child_watch             (GPid                              pid,
+                                                                   gint                              status,
+                                                                   gpointer                          user_data);
+static void         panel_plugin_external_child_watch_destroyed   (gpointer                          user_data);
+static void         panel_plugin_external_queue_free              (PanelPluginExternal              *external);
+static void         panel_plugin_external_queue_send_to_child     (PanelPluginExternal              *external);
+static void         panel_plugin_external_queue_add               (PanelPluginExternal              *external,
+                                                                   XfcePanelPluginProviderPropType   type,
+                                                                   const GValue                     *value);
+static void         panel_plugin_external_queue_add_action        (PanelPluginExternal              *external,
+                                                                   XfcePanelPluginProviderPropType   type);
+static const gchar *panel_plugin_external_get_name                (XfcePanelPluginProvider          *provider);
+static gint         panel_plugin_external_get_unique_id           (XfcePanelPluginProvider          *provider);
+static void         panel_plugin_external_set_size                (XfcePanelPluginProvider          *provider,
+                                                                   gint                              size);
+static void         panel_plugin_external_set_orientation         (XfcePanelPluginProvider          *provider,
+                                                                   GtkOrientation                    orientation);
+static void         panel_plugin_external_set_screen_position     (XfcePanelPluginProvider          *provider,
+                                                                   XfceScreenPosition                screen_position);
+static void         panel_plugin_external_save                    (XfcePanelPluginProvider          *provider);
+static gboolean     panel_plugin_external_get_show_configure      (XfcePanelPluginProvider          *provider);
+static void         panel_plugin_external_show_configure          (XfcePanelPluginProvider          *provider);
+static gboolean     panel_plugin_external_get_show_about          (XfcePanelPluginProvider          *provider);
+static void         panel_plugin_external_show_about              (XfcePanelPluginProvider          *provider);
+static void         panel_plugin_external_removed                 (XfcePanelPluginProvider          *provider);
+static gboolean     panel_plugin_external_remote_event            (XfcePanelPluginProvider          *provider,
+                                                                   const gchar                      *name,
+                                                                   const GValue                     *value,
+                                                                   guint                            *handler_id);
+static void         panel_plugin_external_set_locked              (XfcePanelPluginProvider          *provider,
+                                                                   gboolean                          locked);
+static void         panel_plugin_external_set_sensitive           (PanelPluginExternal              *external);
+
+
+
+#define PANEL_PLUGIN_EXTERNAL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PANEL_TYPE_PLUGIN_EXTERNAL, PanelPluginExternalPrivate))
+
+
+
+struct _PanelPluginExternalPrivate
+{
   /* startup arguments */
-  gchar           **arguments;
-
-  PanelModule      *module;
+  gchar     **arguments;
 
-  guint             plug_embedded : 1;
+  guint       embedded : 1;
 
   /* dbus message queue */
-  GPtrArray        *queue;
+  GSList     *queue;
 
   /* auto restart timer */
-  GTimer           *restart_timer;
-
-  /* some info received over dbus on startup */
-  guint             show_configure : 1;
-  guint             show_about : 1;
+  GTimer     *restart_timer;
 
   /* child watch data */
-  GPid              pid;
-  guint             watch_id;
+  GPid        pid;
+  guint       watch_id;
+
+  /* delayed spawning */
+  guint       spawn_timeout_id;
 };
 
 enum
@@ -158,21 +138,9 @@ enum
   PROP_ARGUMENTS
 };
 
-enum
-{
-  SET,
-  REMOTE_EVENT,
-  REMOTE_EVENT_RESULT,
-  LAST_SIGNAL
-};
-
-
 
-static guint external_signals[LAST_SIGNAL];
 
-
-
-G_DEFINE_TYPE_WITH_CODE (PanelPluginExternal, panel_plugin_external, GTK_TYPE_SOCKET,
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (PanelPluginExternal, panel_plugin_external, GTK_TYPE_SOCKET,
   G_IMPLEMENT_INTERFACE (XFCE_TYPE_PANEL_PLUGIN_PROVIDER, panel_plugin_external_provider_init))
 
 
@@ -184,8 +152,9 @@ panel_plugin_external_class_init (PanelPluginExternalClass *klass)
   GtkWidgetClass *gtkwidget_class;
   GtkSocketClass *gtksocket_class;
 
+  g_type_class_add_private (klass, sizeof (PanelPluginExternalPrivate));
+
   gobject_class = G_OBJECT_CLASS (klass);
-  gobject_class->constructor = panel_plugin_external_constructor;
   gobject_class->finalize = panel_plugin_external_finalize;
   gobject_class->set_property = panel_plugin_external_set_property;
   gobject_class->get_property = panel_plugin_external_get_property;
@@ -195,35 +164,8 @@ panel_plugin_external_class_init (PanelPluginExternalClass *klass)
   gtkwidget_class->unrealize = panel_plugin_external_unrealize;
 
   gtksocket_class = GTK_SOCKET_CLASS (klass);
-  gtksocket_class->plug_removed = panel_plugin_external_plug_removed;
   gtksocket_class->plug_added = panel_plugin_external_plug_added;
-
-  external_signals[SET] =
-    g_signal_new (g_intern_static_string ("set"),
-                  G_TYPE_FROM_CLASS (gobject_class),
-                  G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                  g_cclosure_marshal_VOID__BOXED,
-                  G_TYPE_NONE, 1,
-                  PANEL_TYPE_DBUS_SET_SIGNAL);
-
-  external_signals[REMOTE_EVENT] =
-    g_signal_new (g_intern_static_string ("remote-event"),
-                  G_TYPE_FROM_CLASS (gobject_class),
-                  G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                  _panel_marshal_VOID__STRING_BOXED_UINT,
-                  G_TYPE_NONE, 3,
-                  G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_UINT);
-
-  external_signals[REMOTE_EVENT_RESULT] =
-    g_signal_new (g_intern_static_string ("remote-event-result"),
-                  G_TYPE_FROM_CLASS (gobject_class),
-                  G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                  _panel_marshal_VOID__UINT_BOOLEAN,
-                  G_TYPE_NONE, 2,
-                  G_TYPE_UINT, G_TYPE_BOOLEAN);
+  gtksocket_class->plug_removed = panel_plugin_external_plug_removed;
 
   g_object_class_install_property (gobject_class,
                                    PROP_UNIQUE_ID,
@@ -248,10 +190,6 @@ panel_plugin_external_class_init (PanelPluginExternalClass *klass)
                                                        G_TYPE_STRV,
                                                        EXO_PARAM_READWRITE
                                                        | G_PARAM_CONSTRUCT_ONLY));
-
-  /* add dbus type info for plugins */
-  dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
-      &dbus_glib_panel_plugin_external_object_info);
 }
 
 
@@ -259,14 +197,18 @@ panel_plugin_external_class_init (PanelPluginExternalClass *klass)
 static void
 panel_plugin_external_init (PanelPluginExternal *external)
 {
-  external->unique_id = -1;
+  external->priv = PANEL_PLUGIN_EXTERNAL_GET_PRIVATE (external);
   external->module = NULL;
-  external->arguments = NULL;
-  external->queue = NULL;
-  external->restart_timer = NULL;
-  external->plug_embedded = FALSE;
   external->show_configure = FALSE;
   external->show_about = FALSE;
+  external->unique_id = -1;
+
+  external->priv->arguments = NULL;
+  external->priv->queue = NULL;
+  external->priv->restart_timer = NULL;
+  external->priv->embedded = FALSE;
+  external->priv->pid = 0;
+  external->priv->spawn_timeout_id = 0;
 
   /* signal to pass gtk_widget_set_sensitive() changes to the remote window */
   g_signal_connect (G_OBJECT (external), "notify::sensitive",
@@ -295,65 +237,27 @@ panel_plugin_external_provider_init (XfcePanelPluginProviderInterface *iface)
 
 
 
-static GObject *
-panel_plugin_external_constructor (GType                  type,
-                                   guint                  n_construct_params,
-                                   GObjectConstructParam *construct_params)
-{
-  GObject         *object;
-  gchar           *path;
-  DBusGConnection *connection;
-  GError          *error = NULL;
-
-  object = G_OBJECT_CLASS (panel_plugin_external_parent_class)->constructor (type,
-                                                                             n_construct_params,
-                                                                             construct_params);
-
-  connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
-  if (G_LIKELY (connection != NULL))
-    {
-      /* register the object in dbus, the wrapper will monitor this object */
-      panel_return_val_if_fail (PANEL_PLUGIN_EXTERNAL (object)->unique_id != -1, NULL);
-      path = g_strdup_printf (PANEL_DBUS_WRAPPER_PATH, PANEL_PLUGIN_EXTERNAL (object)->unique_id);
-      dbus_g_connection_register_g_object (connection, path, object);
-      panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL, "register dbus path %s", path);
-      g_free (path);
-
-      dbus_g_connection_unref (connection);
-    }
-  else
-    {
-      g_critical ("Failed to get D-Bus session bus: %s", error->message);
-      g_error_free (error);
-    }
-
-  return object;
-}
-
-
-
 static void
 panel_plugin_external_finalize (GObject *object)
 {
   PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (object);
 
-  if (external->watch_id != 0)
-    {
-      /* remove the child watch and don't leave zomies */
-      g_source_remove (external->watch_id);
-      g_child_watch_add (external->pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
-    }
+  if (external->priv->spawn_timeout_id != 0)
+    g_source_remove (external->priv->spawn_timeout_id);
 
-  if (external->queue != NULL)
+  if (external->priv->watch_id != 0)
     {
-      g_ptr_array_foreach (external->queue, (GFunc) g_value_array_free, NULL);
-      g_ptr_array_free (external->queue, TRUE);
+      /* remove the child watch and don't leave zombies */
+      g_source_remove (external->priv->watch_id);
+      g_child_watch_add (external->priv->pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
     }
 
-  g_strfreev (external->arguments);
+  panel_plugin_external_queue_free (external);
 
-  if (external->restart_timer != NULL)
-    g_timer_destroy (external->restart_timer);
+  g_strfreev (external->priv->arguments);
+
+  if (external->priv->restart_timer != NULL)
+    g_timer_destroy (external->priv->restart_timer);
 
   g_object_unref (G_OBJECT (external->module));
 
@@ -377,7 +281,7 @@ panel_plugin_external_get_property (GObject    *object,
       break;
 
     case PROP_ARGUMENTS:
-      g_value_set_boxed (value, external->arguments);
+      g_value_set_boxed (value, external->priv->arguments);
       break;
 
     case PROP_MODULE:
@@ -407,7 +311,7 @@ panel_plugin_external_set_property (GObject      *object,
       break;
 
     case PROP_ARGUMENTS:
-      external->arguments = g_value_dup_boxed (value);
+      external->priv->arguments = g_value_dup_boxed (value);
       break;
 
     case PROP_MODULE:
@@ -425,73 +329,18 @@ panel_plugin_external_set_property (GObject      *object,
 static void
 panel_plugin_external_realize (GtkWidget *widget)
 {
-  PanelPluginExternal  *external = PANEL_PLUGIN_EXTERNAL (widget);
-  gchar               **argv;
-  GError               *error = NULL;
-  gboolean              succeed;
-  gchar                *socket_id, *unique_id;
-  guint                 i;
-  guint                 argc = PLUGIN_ARGV_ARGUMENTS;
-  GPid                  pid;
-
-  panel_return_if_fail (external->pid == 0);
-  panel_return_if_fail (!external->plug_embedded);
+  PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (widget);
 
   /* realize the socket first */
   (*GTK_WIDGET_CLASS (panel_plugin_external_parent_class)->realize) (widget);
 
-  /* get the socket id and unique id in a string */
-  socket_id = g_strdup_printf ("%u", gtk_socket_get_id (GTK_SOCKET (widget)));
-  unique_id = g_strdup_printf ("%d", external->unique_id);
-
-  /* add the number of arguments to the argc count */
-  if (G_UNLIKELY (external->arguments != NULL))
-    argc += g_strv_length (external->arguments);
-
-  /* setup the basic argv */
-  argv = g_new0 (gchar *, argc + 1);
-  argv[PLUGIN_ARGV_0] = (gchar *) WRAPPER_BIN;
-  argv[PLUGIN_ARGV_FILENAME] = (gchar *) panel_module_get_filename (external->module);
-  argv[PLUGIN_ARGV_UNIQUE_ID] = unique_id;
-  argv[PLUGIN_ARGV_SOCKET_ID] = socket_id;
-  argv[PLUGIN_ARGV_NAME] = (gchar *) panel_module_get_name (external->module);
-  argv[PLUGIN_ARGV_DISPLAY_NAME] = (gchar *) panel_module_get_display_name (external->module);
-  argv[PLUGIN_ARGV_COMMENT] = (gchar *) panel_module_get_comment (external->module);
-  argv[PLUGIN_ARGV_BACKGROUND_IMAGE] = (gchar *) ""; /* unused, for 4.6 plugins only */
-
-  /* append the arguments */
-  if (G_UNLIKELY (external->arguments != NULL))
-    for (i = 0; external->arguments[i] != NULL; i++)
-      argv[i + PLUGIN_ARGV_ARGUMENTS] = external->arguments[i];
-
-  /* spawn the proccess */
-  succeed = gdk_spawn_on_screen (gtk_widget_get_screen (widget),
-                                 NULL, argv, NULL,
-                                 G_SPAWN_DO_NOT_REAP_CHILD, NULL,
-                                 NULL, &pid, &error);
-
-  panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL,
-               "library=%s, unique-id=%s. socked-id=%s, argc=%d, pid=%d",
-               argv[PLUGIN_ARGV_FILENAME], unique_id,
-               socket_id, argc, pid);
-
-  if (G_LIKELY (succeed))
+  if (external->priv->pid == 0)
     {
-      /* watch the child */
-      external->pid = pid;
-      external->watch_id = g_child_watch_add_full (G_PRIORITY_LOW, pid,
-                                                   panel_plugin_external_child_watch, external,
-                                                   panel_plugin_external_child_watch_destroyed);
+      if (external->priv->spawn_timeout_id != 0)
+        g_source_remove (external->priv->spawn_timeout_id);
+      
+      panel_plugin_external_child_spawn (external);
     }
-  else
-    {
-      g_critical ("Failed to spawn the xfce4-panel-wrapper: %s", error->message);
-      g_error_free (error);
-    }
-
-  g_free (argv);
-  g_free (socket_id);
-  g_free (unique_id);
 }
 
 
@@ -501,23 +350,17 @@ panel_plugin_external_unrealize (GtkWidget *widget)
 {
   PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (widget);
 
-  /* the plug is not embedded anymore */
-  external->plug_embedded = FALSE;
-
-  if (external->watch_id != 0)
+  /* ask the child to quit */
+  if (external->priv->pid != 0)
     {
-      /* remove the child watch so we don't leave zomies */
-      g_source_remove (external->watch_id);
-      g_child_watch_add (external->pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
-      external->pid = 0;
+      if (external->priv->embedded)
+        panel_plugin_external_queue_add_action (external, PROVIDER_PROP_TYPE_ACTION_QUIT);
+      else
+        kill (external->priv->pid, SIGTERM);
     }
 
-  /* quit the plugin */
-  panel_plugin_external_queue_add_noop (PANEL_PLUGIN_EXTERNAL (widget),
-                                        TRUE, SIGNAL_WRAPPER_QUIT);
-
   panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL,
-               "Plugin %s-%d unrealized, quiting wrapper",
+               "%s-%d: plugin unrealized; quiting child",
                panel_module_get_name (external->module),
                external->unique_id);
 
@@ -526,65 +369,115 @@ panel_plugin_external_unrealize (GtkWidget *widget)
 
 
 
+static void
+panel_plugin_external_plug_added (GtkSocket *socket)
+{
+  PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (socket);
+
+  external->priv->embedded = TRUE;
+
+  panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL,
+               "%s-%d: child is embedded; %d properties in queue",
+               panel_module_get_name (external->module),
+               external->unique_id,
+               g_slist_length (external->priv->queue));
+
+  /* send queue to wrapper */
+  panel_plugin_external_queue_send_to_child (external);
+}
+
+
+
 static gboolean
 panel_plugin_external_plug_removed (GtkSocket *socket)
 {
   PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (socket);
-  GtkWidget           *window;
 
-  /* leave when the plugin was already removed */
-  if (!external->plug_embedded)
-    return FALSE;
+  external->priv->embedded = FALSE;
+
+  panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL,
+               "%s-%d: child is unembedded",
+               panel_module_get_name (external->module),
+               external->unique_id);
 
-  /* plug has been removed */
-  external->plug_embedded = FALSE;
+  return TRUE;
+}
 
-  /* unrealize and hide the socket */
-  gtk_widget_unrealize (GTK_WIDGET (socket));
-  gtk_widget_hide (GTK_WIDGET (socket));
 
-  if (external->watch_id != 0)
-    {
-      /* remove the child watch so we don't leave zomies */
-      g_source_remove (external->watch_id);
-      g_child_watch_add (external->pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
-      external->pid = 0;
-    }
 
-  window = gtk_widget_get_toplevel (GTK_WIDGET (socket));
-  panel_return_val_if_fail (PANEL_IS_WINDOW (window), FALSE);
+static gboolean
+panel_plugin_external_child_ask_restart_dialog (GtkWindow   *parent,
+                                                const gchar *plugin_name)
+{
+  GtkWidget *dialog;
+  gint       response;
+
+  panel_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), FALSE);
+  panel_return_val_if_fail (plugin_name != NULL, FALSE);
+
+  dialog = gtk_message_dialog_new (parent,
+                                   GTK_DIALOG_DESTROY_WITH_PARENT,
+                                   GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
+                                   _("Plugin \"%s\" unexpectedly left the panel, do you want to restart it?"),
+                                   plugin_name);
+  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), _("The plugin restarted more than once in "
+                                            "the last %d seconds. If you press Execute the panel will try to restart "
+                                            "the plugin otherwise it will be permanently removed from the panel."),
+                                            PANEL_PLUGIN_AUTO_RESTART);
+  gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_EXECUTE, GTK_RESPONSE_OK,
+                          GTK_STOCK_REMOVE, GTK_RESPONSE_CLOSE, NULL);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
+
+  response = gtk_dialog_run (GTK_DIALOG (dialog));
+  gtk_widget_destroy (dialog);
+
+  return (response == GTK_RESPONSE_OK);
+}
 
-  if (external->restart_timer == NULL
-      || g_timer_elapsed (external->restart_timer, NULL) > PANEL_PLUGIN_AUTO_RESTART)
+
+
+static gboolean
+panel_plugin_external_child_ask_restart (PanelPluginExternal *external)
+{
+  GtkWidget *toplevel;
+
+  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external), FALSE);
+
+  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (external));
+  panel_return_val_if_fail (PANEL_IS_WINDOW (toplevel), FALSE);
+
+  if (external->priv->restart_timer == NULL
+      || g_timer_elapsed (external->priv->restart_timer, NULL) > PANEL_PLUGIN_AUTO_RESTART)
     {
       g_message ("Plugin %s-%d has been automatically restarted after crash.",
                  panel_module_get_name (external->module),
                  external->unique_id);
     }
-  else if (!panel_dialogs_restart_plugin (GTK_WINDOW (window),
+  else if (!panel_plugin_external_child_ask_restart_dialog (GTK_WINDOW (toplevel),
                panel_module_get_display_name (external->module)))
     {
-      /* cleanup the plugin configuration (in panel-application) */
+      if (external->priv->watch_id != 0)
+        {
+          /* remove the child watch and don't leave zombies */
+          g_source_remove (external->priv->watch_id);
+          g_child_watch_add (external->priv->pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
+          external->priv->watch_id = 0;
+        }
+
+      /* cleanup the plugin configuration (in PanelApplication) and
+       * destroy the plugin */
       xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (external),
                                               PROVIDER_SIGNAL_REMOVE_PLUGIN);
 
-      /* self destruction */
-      gtk_widget_destroy (GTK_WIDGET (socket));
-
       return FALSE;
     }
 
-  /* create or reset the retart timer */
-  if (external->restart_timer == NULL)
-    external->restart_timer = g_timer_new ();
+  /* create or reset the restart timer */
+  if (external->priv->restart_timer == NULL)
+    external->priv->restart_timer = g_timer_new ();
   else
-    g_timer_reset (external->restart_timer);
-
-  /* send panel information to the plugin (queued until realize) */
-  panel_window_set_povider_info (PANEL_WINDOW (window), GTK_WIDGET (external));
-
-  /* show the socket again (realize will spawn the plugin) */
-  gtk_widget_show (GTK_WIDGET (socket));
+    g_timer_reset (external->priv->restart_timer);
 
   return TRUE;
 }
@@ -592,123 +485,243 @@ panel_plugin_external_plug_removed (GtkSocket *socket)
 
 
 static void
-panel_plugin_external_plug_added (GtkSocket *socket)
+panel_plugin_external_child_spawn (PanelPluginExternal *external)
 {
-  PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (socket);
+  gchar    **argv;
+  GError    *error = NULL;
+  gboolean   succeed;
+  GPid       pid;
 
-  /* plug has been added */
-  external->plug_embedded = TRUE;
+  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
+  panel_return_if_fail (GTK_WIDGET_REALIZED (external));
+
+  /* set plugin specific arguments */
+  argv = (*PANEL_PLUGIN_EXTERNAL_GET_CLASS (external)->get_argv) (external, external->priv->arguments);
+
+  /* spawn the proccess */
+  succeed = gdk_spawn_on_screen (gtk_widget_get_screen (GTK_WIDGET (external)),
+                                 NULL, argv, NULL,
+                                 G_SPAWN_DO_NOT_REAP_CHILD, NULL,
+                                 NULL, &pid, &error);
 
   panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL,
-               "%d has been embedded, %d values in queue",
-               external->unique_id,
-               external->queue != NULL ? external->queue->len : 0);
+               "%s-%s: child spawned; pid=%d, socket-id=%s",
+               panel_module_get_name (external->module),
+               argv[PLUGIN_ARGV_UNIQUE_ID], pid, argv[PLUGIN_ARGV_SOCKET_ID]);
 
-  if (external->queue != NULL)
-    panel_plugin_external_dbus_set (external, FALSE);
+  if (G_LIKELY (succeed))
+    {
+      /* watch the child */
+      external->priv->pid = pid;
+      external->priv->watch_id = g_child_watch_add_full (G_PRIORITY_LOW, pid,
+                                                         panel_plugin_external_child_watch, external,
+                                                         panel_plugin_external_child_watch_destroyed);
+    }
+  else
+    {
+      g_critical ("Failed to spawn the xfce4-panel-wrapper: %s", error->message);
+      g_error_free (error);
+    }
+
+  g_strfreev (argv);
 }
 
 
 
 static gboolean
-panel_plugin_external_dbus_provider_signal (PanelPluginExternal            *external,
-                                            XfcePanelPluginProviderSignal   provider_signal,
-                                            GError                        **error)
+panel_plugin_external_child_respawn (gpointer user_data)
 {
+  PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (user_data);
+  GtkWidget           *window;
+
   panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external), FALSE);
-  panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (external), FALSE);
 
-  switch (provider_signal)
+  /* abort startup if the plugin is not realized */
+  if (!GTK_WIDGET_REALIZED (external))
+    return FALSE;
+
+  /* delay startup if the old child is still embedded */
+  if (external->priv->embedded)
+    return TRUE;
+
+  panel_plugin_external_queue_free (external);
+
+  window = gtk_widget_get_toplevel (GTK_WIDGET (external));
+  panel_return_val_if_fail (PANEL_IS_WINDOW (window), FALSE);
+  panel_window_set_povider_info (PANEL_WINDOW (window), GTK_WIDGET (external));
+
+  panel_plugin_external_child_spawn (external);
+
+  /* stop timeout */
+  return FALSE;
+}
+
+
+
+static void
+panel_plugin_external_child_respawn_destroyed (gpointer user_data)
+{
+  PANEL_PLUGIN_EXTERNAL (user_data)->priv->spawn_timeout_id = 0;
+}
+
+
+
+static void
+panel_plugin_external_child_watch (GPid     pid,
+                                   gint     status,
+                                   gpointer user_data)
+{
+  PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (user_data);
+  gboolean             auto_restart = FALSE;
+
+  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
+  panel_return_if_fail (external->priv->pid == pid);
+
+  external->priv->pid = 0;
+
+  panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL,
+               "%s-%d: child exited with status %d",
+               panel_module_get_name (external->module),
+               external->unique_id, status);
+
+  if (WIFEXITED (status))
     {
-    case PROVIDER_SIGNAL_SHOW_CONFIGURE:
-      external->show_configure = TRUE;
-      break;
+      /* extract our return value from the status */
+      switch (WEXITSTATUS (status))
+        {
+        case PLUGIN_EXIT_SUCCESS:
+          /* normal exit, do not try to restart */
+          goto close_pid;
 
-    case PROVIDER_SIGNAL_SHOW_ABOUT:
-      external->show_about = TRUE;
-      break;
+        case PLUGIN_EXIT_SUCCESS_AND_RESTART:
+          /* the panel asked for a restart, so do not bother the user */
+          auto_restart = TRUE;
+          break;
 
-    default:
-      /* other signals are handled in panel-applications.c */
-      xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (external),
-                                              provider_signal);
-      break;
+        case PLUGIN_EXIT_FAILURE:
+          /* do nothing, maybe we try to restart */
+          break;
+
+        case PLUGIN_EXIT_ARGUMENTS_FAILED:
+        case PLUGIN_EXIT_PREINIT_FAILED:
+        case PLUGIN_EXIT_CHECK_FAILED:
+        case PLUGIN_EXIT_NO_PROVIDER:
+          g_warning ("Plugin %s-%d exited with status %d, removing from panel configuration",
+                     panel_module_get_name (external->module),
+                     external->unique_id, WEXITSTATUS (status));
+
+          /* cleanup the plugin configuration (in PanelApplication) */
+          xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (external),
+                                                  PROVIDER_SIGNAL_REMOVE_PLUGIN);
+
+          /* wait until everything is settled before we destroy */
+          exo_gtk_object_destroy_later (GTK_OBJECT (external));
+          goto close_pid;
+        }
+    }
+  else if (WIFSIGNALED (status))
+    {
+      switch (WTERMSIG (status))
+        {
+        case SIGUSR1:
+          /* the panel asked for a restart, so do not bother the user */
+          auto_restart = TRUE;
+          break;
+        }
     }
 
-  return TRUE;
+  if (GTK_WIDGET_REALIZED (external)
+      && external->priv->spawn_timeout_id == 0
+      && (auto_restart || panel_plugin_external_child_ask_restart (external)))
+    {
+       panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL,
+                    "%s-%d: scheduled a respawn of the child",
+                    panel_module_get_name (external->module), external->unique_id);
+
+       /* schedule a restart timeout */
+       external->priv->spawn_timeout_id = g_timeout_add_full (G_PRIORITY_LOW, 100, panel_plugin_external_child_respawn,
+                                                              external, panel_plugin_external_child_respawn_destroyed);
+    }
+
+close_pid:
+  g_spawn_close_pid (pid);
 }
 
 
 
-static gboolean
-panel_plugin_external_dbus_remote_event_result (PanelPluginExternal  *external,
-                                                guint                 handle,
-                                                gboolean              result,
-                                                GError              **error)
+static void
+panel_plugin_external_child_watch_destroyed (gpointer user_data)
 {
-  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external), FALSE);
+  if (PANEL_IS_PLUGIN_EXTERNAL (user_data))
+    PANEL_PLUGIN_EXTERNAL (user_data)->priv->watch_id = 0;
+}
 
-  g_signal_emit (G_OBJECT (external), external_signals[REMOTE_EVENT_RESULT], 0,
-                 handle, result);
 
-  return TRUE;
+
+static void
+panel_plugin_external_queue_free (PanelPluginExternal *external)
+{
+  PluginProperty *property;
+  GSList         *li;
+
+  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
+
+  for (li = external->priv->queue; li != NULL; li = li->next)
+    {
+      property = li->data;
+      g_value_unset (&property->value);
+      g_slice_free (PluginProperty, property);
+    }
+
+  g_slist_free (external->priv->queue);
+  external->priv->queue = NULL;
 }
 
 
 
 static void
-panel_plugin_external_dbus_set (PanelPluginExternal *external,
-                                gboolean             force)
+panel_plugin_external_queue_send_to_child (PanelPluginExternal *external)
 {
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
-  panel_return_if_fail (external->queue != NULL);
 
-  if (force || external->plug_embedded)
+  if (external->priv->queue != NULL)
     {
-      g_signal_emit (G_OBJECT (external), external_signals[SET], 0,
-                     external->queue);
+      external->priv->queue = g_slist_reverse (external->priv->queue);
+
+      (*PANEL_PLUGIN_EXTERNAL_GET_CLASS (external)->set_properties) (external, external->priv->queue);
 
-      g_ptr_array_foreach (external->queue, (GFunc) g_value_array_free, NULL);
-      g_ptr_array_free (external->queue, TRUE);
-      external->queue = NULL;
+      panel_plugin_external_queue_free (external);
     }
 }
 
 
 
 static void
-panel_plugin_external_queue_add (PanelPluginExternal *external,
-                                 gboolean             force,
-                                 const gchar         *property,
-                                 const GValue        *value)
+panel_plugin_external_queue_add (PanelPluginExternal             *external,
+                                 XfcePanelPluginProviderPropType  type,
+                                 const GValue                    *value)
 {
-  GValue message = { 0, };
+  PluginProperty *prop;
 
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
   panel_return_if_fail (G_TYPE_CHECK_VALUE (value));
 
-  if (external->queue == NULL)
-    external->queue = g_ptr_array_sized_new (1);
-
-  g_value_init (&message, PANEL_TYPE_DBUS_SET_MESSAGE);
-  g_value_take_boxed (&message, dbus_g_type_specialized_construct (G_VALUE_TYPE (&message)));
-
-  dbus_g_type_struct_set (&message,
-                          DBUS_SET_PROPERTY, property,
-                          DBUS_SET_VALUE, value,
-                          G_MAXUINT);
+  prop = g_slice_new0 (PluginProperty);
+  prop->type = type;
+  g_value_init (&prop->value, G_VALUE_TYPE (value));
+  g_value_copy (value, &prop->value);
 
-  g_ptr_array_add (external->queue, g_value_get_boxed (&message));
+  external->priv->queue = g_slist_prepend (external->priv->queue, prop);
 
-  panel_plugin_external_dbus_set (external, force);
+  if (external->priv->embedded)
+    panel_plugin_external_queue_send_to_child (external);
 }
 
 
 
 static void
-panel_plugin_external_queue_add_noop (PanelPluginExternal *external,
-                                      gboolean             force,
-                                      const gchar         *property)
+panel_plugin_external_queue_add_action (PanelPluginExternal             *external,
+                                        XfcePanelPluginProviderPropType  type)
 {
   GValue value = { 0, };
 
@@ -716,7 +729,7 @@ panel_plugin_external_queue_add_noop (PanelPluginExternal *external,
 
   /* add to queue with noop boolean */
   g_value_init (&value, G_TYPE_BOOLEAN);
-  panel_plugin_external_queue_add (external, force, property, &value);
+  panel_plugin_external_queue_add (external, type, &value);
   g_value_unset (&value);
 }
 
@@ -757,8 +770,7 @@ panel_plugin_external_set_size (XfcePanelPluginProvider *provider,
   g_value_set_int (&value, size);
 
   panel_plugin_external_queue_add (PANEL_PLUGIN_EXTERNAL (provider),
-                                   FALSE, SIGNAL_SET_SIZE,
-                                   &value);
+                                   PROVIDER_PROP_TYPE_SET_SIZE, &value);
 
   g_value_unset (&value);
 }
@@ -774,12 +786,11 @@ panel_plugin_external_set_orientation (XfcePanelPluginProvider *provider,
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
   panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
 
-  g_value_init (&value, G_TYPE_UINT);
-  g_value_set_uint (&value, orientation);
+  g_value_init (&value, G_TYPE_INT);
+  g_value_set_int (&value, orientation);
 
   panel_plugin_external_queue_add (PANEL_PLUGIN_EXTERNAL (provider),
-                                   FALSE, SIGNAL_SET_ORIENTATION,
-                                   &value);
+                                   PROVIDER_PROP_TYPE_SET_ORIENTATION, &value);
 
   g_value_unset (&value);
 }
@@ -795,12 +806,11 @@ panel_plugin_external_set_screen_position (XfcePanelPluginProvider *provider,
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
   panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
 
-  g_value_init (&value, G_TYPE_UINT);
-  g_value_set_uint (&value, screen_position);
+  g_value_init (&value, G_TYPE_INT);
+  g_value_set_int (&value, screen_position);
 
   panel_plugin_external_queue_add (PANEL_PLUGIN_EXTERNAL (provider),
-                                   FALSE, SIGNAL_SET_SCREEN_POSITION,
-                                   &value);
+                                   PROVIDER_PROP_TYPE_SET_SCREEN_POSITION, &value);
 
   g_value_unset (&value);
 }
@@ -813,9 +823,8 @@ panel_plugin_external_save (XfcePanelPluginProvider *provider)
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
   panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
 
-  /* send signal to wrapper */
-  panel_plugin_external_queue_add_noop (PANEL_PLUGIN_EXTERNAL (provider),
-                                        FALSE, SIGNAL_SAVE);
+  panel_plugin_external_queue_add_action (PANEL_PLUGIN_EXTERNAL (provider),
+                                          PROVIDER_PROP_TYPE_ACTION_SAVE);
 }
 
 
@@ -837,9 +846,8 @@ panel_plugin_external_show_configure (XfcePanelPluginProvider *provider)
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
   panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
 
-  /* send signal to wrapper */
-  panel_plugin_external_queue_add_noop (PANEL_PLUGIN_EXTERNAL (provider),
-                                        FALSE, SIGNAL_SHOW_CONFIGURE);
+  panel_plugin_external_queue_add_action (PANEL_PLUGIN_EXTERNAL (provider),
+                                          PROVIDER_PROP_TYPE_ACTION_SHOW_CONFIGURE);
 }
 
 
@@ -861,9 +869,8 @@ panel_plugin_external_show_about (XfcePanelPluginProvider *provider)
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
   panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
 
-  /* send signal to wrapper */
-  panel_plugin_external_queue_add_noop (PANEL_PLUGIN_EXTERNAL (provider),
-                                        FALSE, SIGNAL_SHOW_ABOUT);
+  panel_plugin_external_queue_add_action (PANEL_PLUGIN_EXTERNAL (provider),
+                                          PROVIDER_PROP_TYPE_ACTION_SHOW_ABOUT);
 }
 
 
@@ -874,9 +881,8 @@ panel_plugin_external_removed (XfcePanelPluginProvider *provider)
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider));
   panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
 
-  /* send signal to wrapper */
-  panel_plugin_external_queue_add_noop (PANEL_PLUGIN_EXTERNAL (provider),
-                                        FALSE, SIGNAL_REMOVED);
+  panel_plugin_external_queue_add_action (PANEL_PLUGIN_EXTERNAL (provider),
+                                          PROVIDER_PROP_TYPE_ACTION_REMOVED);
 }
 
 
@@ -887,33 +893,8 @@ panel_plugin_external_remote_event (XfcePanelPluginProvider *provider,
                                     const GValue            *value,
                                     guint                   *handle)
 {
-  static guint  handle_counter = 0;
-  GValue        dummy_value = { 0, };
-  const GValue *real_value = value;
-
-  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (provider), TRUE);
-  panel_return_val_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider), TRUE);
-  panel_return_val_if_fail (value == NULL || G_IS_VALUE (value), FALSE);
-
-  if (G_UNLIKELY (handle_counter > G_MAXUINT - 2))
-    handle_counter = 0;
-  *handle = ++handle_counter;
-
-  if (value == NULL)
-    {
-      /* we send a dummy value over dbus */
-      g_value_init (&dummy_value, G_TYPE_UCHAR);
-      g_value_set_uchar (&dummy_value, '\0');
-      real_value = &dummy_value;
-    }
-
-  g_signal_emit (G_OBJECT (provider), external_signals[REMOTE_EVENT], 0,
-                 name, real_value, *handle);
-
-  if (real_value != value)
-    g_value_unset (&dummy_value);
-
-  return TRUE;
+  return (*PANEL_PLUGIN_EXTERNAL_GET_CLASS (provider)->remote_event) (PANEL_PLUGIN_EXTERNAL (provider),
+                                                                      name, value, handle);
 }
 
 
@@ -931,7 +912,7 @@ panel_plugin_external_set_locked (XfcePanelPluginProvider *provider,
   g_value_set_boolean (&value, locked);
 
   panel_plugin_external_queue_add (PANEL_PLUGIN_EXTERNAL (provider),
-                                   FALSE, SIGNAL_SET_LOCKED, &value);
+                                   PROVIDER_PROP_TYPE_SET_LOCKED, &value);
 
   g_value_unset (&value);
 }
@@ -948,8 +929,7 @@ panel_plugin_external_set_sensitive (PanelPluginExternal *external)
   g_value_init (&value, G_TYPE_BOOLEAN);
   g_value_set_boolean (&value, GTK_WIDGET_IS_SENSITIVE (external));
 
-  panel_plugin_external_queue_add (external, FALSE,
-                                   SIGNAL_WRAPPER_SET_SENSITIVE,
+  panel_plugin_external_queue_add (external, PROVIDER_PROP_TYPE_SET_SENSITIVE,
                                    &value);
 
   g_value_unset (&value);
@@ -957,69 +937,25 @@ panel_plugin_external_set_sensitive (PanelPluginExternal *external)
 
 
 
-static void
-panel_plugin_external_child_watch (GPid     pid,
-                                   gint     status,
-                                   gpointer user_data)
+void
+panel_plugin_external_restart (PanelPluginExternal *external)
 {
-  PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (user_data);
-
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
-  panel_return_if_fail (external->pid == pid);
 
-  /* only handle our exit status if the plugin exited normally */
-  if (WIFEXITED (status))
+  if (external->priv->pid != 0)
     {
-      /* extract our return value from the status */
-      switch (WEXITSTATUS (status))
-        {
-        case PLUGIN_EXIT_SUCCESS:
-          break;
-
-        case PLUGIN_EXIT_FAILURE:
-        case PLUGIN_EXIT_PREINIT_FAILED:
-        case PLUGIN_EXIT_CHECK_FAILED:
-        case PLUGIN_EXIT_NO_PROVIDER:
-          panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL,
-                       "Plugin exited with status %d. Removing from "
-                       "configuration.", WEXITSTATUS (status));
-
-          /* cleanup the plugin configuration (in panel-application) */
-          xfce_panel_plugin_provider_emit_signal (XFCE_PANEL_PLUGIN_PROVIDER (external),
-                                                  PROVIDER_SIGNAL_REMOVE_PLUGIN);
+      panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL,
+                   "%s-%d: child asked to restart; pid=%d",
+                   panel_module_get_name (external->module),
+                   external->unique_id, external->priv->pid);
 
+      panel_plugin_external_queue_free (external);
 
-          /* wait until everything is settled */
-          exo_gtk_object_destroy_later (GTK_OBJECT (external));
-          break;
-        }
+      if (external->priv->embedded)
+        panel_plugin_external_queue_add_action (external, PROVIDER_PROP_TYPE_ACTION_QUIT_FOR_RESTART);
+      else
+        kill (external->priv->pid, SIGUSR1);
     }
-
-  g_spawn_close_pid (pid);
-}
-
-
-
-static void
-panel_plugin_external_child_watch_destroyed (gpointer user_data)
-{
-  PANEL_PLUGIN_EXTERNAL (user_data)->watch_id = 0;
-}
-
-
-
-GtkWidget *
-panel_plugin_external_new (PanelModule  *module,
-                           gint          unique_id,
-                           gchar       **arguments)
-{
-  panel_return_val_if_fail (PANEL_IS_MODULE (module), NULL);
-  panel_return_val_if_fail (unique_id != -1, NULL);
-
-  return g_object_new (PANEL_TYPE_PLUGIN_EXTERNAL,
-                       "module", module,
-                       "unique-id", unique_id,
-                       "arguments", arguments, NULL);
 }
 
 
@@ -1035,8 +971,7 @@ panel_plugin_external_set_background_alpha (PanelPluginExternal *external,
   g_value_init (&value, G_TYPE_DOUBLE);
   g_value_set_double (&value, alpha);
 
-  panel_plugin_external_queue_add (external, FALSE,
-                                   SIGNAL_WRAPPER_BACKGROUND_ALPHA,
+  panel_plugin_external_queue_add (external, PROVIDER_PROP_TYPE_SET_BACKGROUND_ALPHA,
                                    &value);
 
   g_value_unset (&value);
@@ -1048,28 +983,26 @@ void
 panel_plugin_external_set_background_color (PanelPluginExternal *external,
                                             const GdkColor      *color)
 {
-  GValue       value = { 0, };
-  const gchar *prop;
+  GValue value = { 0, };
 
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
 
   if (G_LIKELY (color != NULL))
     {
-      prop = SIGNAL_WRAPPER_BACKGROUND_COLOR;
-
       g_value_init (&value, G_TYPE_STRING);
       g_value_take_string (&value, gdk_color_to_string (color));
+
+      panel_plugin_external_queue_add (external,
+                                       PROVIDER_PROP_TYPE_SET_BACKGROUND_COLOR,
+                                       &value);
+
+      g_value_unset (&value);
     }
   else
     {
-      prop = SIGNAL_WRAPPER_BACKGROUND_UNSET;
-
-      g_value_init (&value, G_TYPE_BOOLEAN);
+      panel_plugin_external_queue_add_action (external,
+                                              PROVIDER_PROP_TYPE_ACTION_BACKGROUND_UNSET);
     }
-
-  panel_plugin_external_queue_add (external, FALSE, prop, &value);
-
-  g_value_unset (&value);
 }
 
 
@@ -1082,20 +1015,36 @@ panel_plugin_external_set_background_image (PanelPluginExternal *external,
 
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
 
-  if (G_UNLIKELY (image != NULL))
+  if (!external->priv->embedded
+      && PANEL_IS_PLUGIN_EXTERNAL_46 (external))
+    {
+      /* hack to set the background of 4.6 plugins before the child is
+       * embedded, so it is directly send with the startup arguments */
+      panel_plugin_external_46_set_background_image (PANEL_PLUGIN_EXTERNAL_46 (external), image);
+    }
+  else if (G_UNLIKELY (image != NULL))
     {
       g_value_init (&value, G_TYPE_STRING);
       g_value_set_string (&value, image);
 
-      panel_plugin_external_queue_add (external, FALSE,
-                                       SIGNAL_WRAPPER_BACKGROUND_IMAGE,
+      panel_plugin_external_queue_add (external,
+                                       PROVIDER_PROP_TYPE_SET_BACKGROUND_IMAGE,
                                        &value);
 
       g_value_unset (&value);
     }
   else
     {
-      /* unset the bg */
-      panel_plugin_external_set_background_color (external, NULL);
+      panel_plugin_external_queue_add_action (external,
+                                              PROVIDER_PROP_TYPE_ACTION_BACKGROUND_UNSET);
     }
 }
+
+
+
+GPid
+panel_plugin_external_get_pid (PanelPluginExternal *external)
+{
+  panel_return_val_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external), 0);
+  return external->priv->pid;
+}
diff --git a/panel/panel-plugin-external.h b/panel/panel-plugin-external.h
index 7864ad7..5163447 100644
--- a/panel/panel-plugin-external.h
+++ b/panel/panel-plugin-external.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2009 Nick Schermer <nick at xfce.org>
+ * Copyright (C) 2008-2010 Nick Schermer <nick at xfce.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -26,8 +26,9 @@
 
 G_BEGIN_DECLS
 
-typedef struct _PanelPluginExternalClass PanelPluginExternalClass;
-typedef struct _PanelPluginExternal      PanelPluginExternal;
+typedef struct _PanelPluginExternalClass   PanelPluginExternalClass;
+typedef struct _PanelPluginExternal        PanelPluginExternal;
+typedef struct _PanelPluginExternalPrivate PanelPluginExternalPrivate;
 
 #define PANEL_TYPE_PLUGIN_EXTERNAL            (panel_plugin_external_get_type ())
 #define PANEL_PLUGIN_EXTERNAL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_PLUGIN_EXTERNAL, PanelPluginExternal))
@@ -36,20 +37,64 @@ typedef struct _PanelPluginExternal      PanelPluginExternal;
 #define PANEL_IS_PLUGIN_EXTERNAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_PLUGIN_EXTERNAL))
 #define PANEL_PLUGIN_EXTERNAL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PANEL_TYPE_PLUGIN_EXTERNAL, PanelPluginExternalClass))
 
-GType      panel_plugin_external_get_type             (void) G_GNUC_CONST;
+struct _PanelPluginExternalClass
+{
+  GtkSocketClass __parent__;
 
-GtkWidget *panel_plugin_external_new                  (PanelModule          *module,
-                                                       gint                  unique_id,
-                                                       gchar               **arguments) G_GNUC_MALLOC;
+  /* send panel values to the plugin or wrapper */
+  void       (*set_properties) (PanelPluginExternal *external,
+                                GSList              *properties);
 
-void       panel_plugin_external_set_background_alpha (PanelPluginExternal  *external,
-                                                       gdouble               alpha);
+  /* complete startup array for the plugin */
+  gchar    **(*get_argv)       (PanelPluginExternal  *external,
+                                gchar               **arguments);
 
-void       panel_plugin_external_set_background_color (PanelPluginExternal  *external,
-                                                       const GdkColor       *color);
+  /* handling of remote events */
+  gboolean   (*remote_event)   (PanelPluginExternal  *external,
+                                const gchar          *name,
+                                const GValue         *value,
+                                guint                *handle);
+};
 
-void       panel_plugin_external_set_background_image (PanelPluginExternal  *external,
-                                                       const gchar          *image);
+struct _PanelPluginExternal
+{
+  GtkSocket __parent__;
+
+  PanelPluginExternalPrivate *priv;
+
+  PanelModule                *module;
+
+  gint                        unique_id;
+
+  /* some info received on plugin startup by the
+   * implementations of the abstract object */
+  guint                       show_configure : 1;
+  guint                       show_about : 1;
+};
+
+typedef struct
+{
+  XfcePanelPluginProviderPropType type;
+  GValue                          value;
+}
+PluginProperty;
+
+
+
+GType        panel_plugin_external_get_type             (void) G_GNUC_CONST;
+
+void         panel_plugin_external_restart              (PanelPluginExternal  *external);
+
+void         panel_plugin_external_set_background_alpha (PanelPluginExternal  *external,
+                                                         gdouble               alpha);
+
+void         panel_plugin_external_set_background_color (PanelPluginExternal  *external,
+                                                         const GdkColor       *color);
+
+void         panel_plugin_external_set_background_image (PanelPluginExternal  *external,
+                                                         const gchar          *image);
+
+GPid         panel_plugin_external_get_pid              (PanelPluginExternal  *external);
 
 G_END_DECLS
 
diff --git a/panel/panel-preferences-dialog.c b/panel/panel-preferences-dialog.c
index 3f956b1..68a0235 100644
--- a/panel/panel-preferences-dialog.c
+++ b/panel/panel-preferences-dialog.c
@@ -38,39 +38,50 @@
 #include <panel/panel-item-dialog.h>
 #include <panel/panel-preferences-dialog.h>
 #include <panel/panel-preferences-dialog-ui.h>
+#include <panel/panel-plugin-external.h>
 
 #define PREFERENCES_HELP_URL "http://www.xfce.org"
 
 
 
-static void panel_preferences_dialog_finalize (GObject *object);
-static void panel_preferences_dialog_response (GtkWidget *window, gint response_id, PanelPreferencesDialog *dialog);
-
-
-static void panel_preferences_dialog_bindings_unbind (PanelPreferencesDialog *dialog);
-static void panel_preferences_dialog_bindings_add (PanelPreferencesDialog *dialog, const gchar *property1, const gchar *property2);
-static void panel_preferences_dialog_bindings_update (PanelPreferencesDialog *dialog);
-
-static void panel_preferences_dialog_output_changed (GtkComboBox *combobox, PanelPreferencesDialog *dialog);
-
-static void panel_preferences_dialog_bg_style_changed (PanelPreferencesDialog *dialog);
-static void panel_preferences_dialog_bg_image_file_set (GtkFileChooserButton *button, PanelPreferencesDialog *dialog);
-static void panel_preferences_dialog_bg_image_notified (PanelPreferencesDialog *dialog);
-
-static void panel_preferences_dialog_panel_combobox_changed (GtkComboBox *combobox, PanelPreferencesDialog *dialog);
-static void panel_preferences_dialog_panel_combobox_rebuild (PanelPreferencesDialog *dialog);
-static void panel_preferences_dialog_panel_add (GtkWidget *widget, PanelPreferencesDialog *dialog);
-static void panel_preferences_dialog_panel_remove (GtkWidget *widget, PanelPreferencesDialog *dialog);
-
-
-static XfcePanelPluginProvider *panel_preferences_dialog_item_get_selected (PanelPreferencesDialog *dialog, GtkTreeIter *return_iter);
-static void panel_preferences_dialog_item_store_rebuild (GtkWidget *itembar, PanelPreferencesDialog *dialog);
-static void panel_preferences_dialog_item_move (GtkWidget *button, PanelPreferencesDialog *dialog);
-static void panel_preferences_dialog_item_remove (GtkWidget *button, PanelPreferencesDialog *dialog);
-static void panel_preferences_dialog_item_add (GtkWidget *button, PanelPreferencesDialog *dialog);
-static void panel_preferences_dialog_item_properties (GtkWidget *button, PanelPreferencesDialog *dialog);
-static void panel_preferences_dialog_item_about (GtkWidget *button, PanelPreferencesDialog *dialog);
-static void panel_preferences_dialog_item_selection_changed (GtkTreeSelection *selection, PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_finalize               (GObject                *object);
+static void                     panel_preferences_dialog_response               (GtkWidget              *window, 
+                                                                                 gint                    response_id, 
+                                                                                 PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_bindings_unbind        (PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_bindings_add           (PanelPreferencesDialog *dialog, 
+                                                                                 const gchar            *property1, 
+                                                                                 const gchar            *property2);
+static void                     panel_preferences_dialog_bindings_update        (PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_output_changed         (GtkComboBox            *combobox, 
+                                                                                 PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_bg_style_changed       (PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_bg_image_file_set      (GtkFileChooserButton   *button, 
+                                                                                 PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_bg_image_notified      (PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_panel_combobox_changed (GtkComboBox            *combobox, 
+                                                                                 PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_panel_combobox_rebuild (PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_panel_add              (GtkWidget              *widget, 
+                                                                                 PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_panel_remove           (GtkWidget              *widget, 
+                                                                                 PanelPreferencesDialog *dialog);
+static XfcePanelPluginProvider *panel_preferences_dialog_item_get_selected      (PanelPreferencesDialog *dialog, 
+                                                                                 GtkTreeIter            *return_iter);
+static void                     panel_preferences_dialog_item_store_rebuild     (GtkWidget              *itembar, 
+                                                                                 PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_item_move              (GtkWidget              *button, 
+                                                                                 PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_item_remove            (GtkWidget              *button, 
+                                                                                 PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_item_add               (GtkWidget              *button, 
+                                                                                 PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_item_properties        (GtkWidget              *button, 
+                                                                                 PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_item_about             (GtkWidget              *button, 
+                                                                                 PanelPreferencesDialog *dialog);
+static void                     panel_preferences_dialog_item_selection_changed (GtkTreeSelection       *selection, 
+                                                                                 PanelPreferencesDialog *dialog);
 
 
 
@@ -228,7 +239,7 @@ panel_preferences_dialog_init (PanelPreferencesDialog *dialog)
   renderer = gtk_cell_renderer_text_new ();
   column = gtk_tree_view_column_new ();
   gtk_tree_view_column_pack_start (column, renderer, TRUE);
-  gtk_tree_view_column_set_attributes (column, renderer, "text",
+  gtk_tree_view_column_set_attributes (column, renderer, "markup",
                                        ITEM_COLUMN_DISPLAY_NAME, NULL);
   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
 
@@ -863,7 +874,7 @@ panel_preferences_dialog_item_store_rebuild (GtkWidget              *itembar,
   GList       *items, *li;
   guint        i;
   PanelModule *module;
-  gchar       *tooltip;
+  gchar       *tooltip, *display_name;
 
   panel_return_if_fail (PANEL_IS_PREFERENCES_DIALOG (dialog));
   panel_return_if_fail (GTK_IS_LIST_STORE (dialog->store));
@@ -875,24 +886,46 @@ panel_preferences_dialog_item_store_rebuild (GtkWidget              *itembar,
   items = gtk_container_get_children (GTK_CONTAINER (itembar));
   for (li = items, i = 0; li != NULL; li = li->next, i++)
     {
-      /* I18N: tooltip in preferences dialog when hovering an item in the list */
-      tooltip = g_strdup_printf (_("Internal name: %s-%d"),
-                                 xfce_panel_plugin_provider_get_name (li->data),
-                                 xfce_panel_plugin_provider_get_unique_id (li->data));
-
       /* get the panel module from the plugin */
       module = panel_module_get_from_plugin_provider (li->data);
 
+      if (PANEL_IS_PLUGIN_EXTERNAL (li->data))
+        {
+          /* I18N: append (external) in the preferences dialog if the plugin
+           * runs external */
+          display_name = g_strdup_printf (_("%s <span color=\"grey\" size=\"small\">(external)</span>"),
+                                          panel_module_get_display_name (module));
+
+          /* I18N: tooltip in preferences dialog when hovering an item in the list
+           * for external plugins */
+          tooltip = g_strdup_printf (_("Internal name: %s-%d\n"
+                                       "PID: %d"),
+                                     xfce_panel_plugin_provider_get_name (li->data),
+                                     xfce_panel_plugin_provider_get_unique_id (li->data),
+                                     panel_plugin_external_get_pid (PANEL_PLUGIN_EXTERNAL (li->data)));
+        }
+      else
+        {
+          display_name = g_strdup (panel_module_get_display_name (module));
+
+          /* I18N: tooltip in preferences dialog when hovering an item in the list
+           * for internal plugins */
+          tooltip = g_strdup_printf (_("Internal name: %s-%d"),
+                                     xfce_panel_plugin_provider_get_name (li->data),
+                                     xfce_panel_plugin_provider_get_unique_id (li->data));
+        }
+
       gtk_list_store_insert_with_values (dialog->store, NULL, i,
                                          ITEM_COLUMN_ICON_NAME,
                                          panel_module_get_icon_name (module),
                                          ITEM_COLUMN_DISPLAY_NAME,
-                                         panel_module_get_display_name (module),
+                                         display_name,
                                          ITEM_COLUMN_TOOLTIP,
                                          tooltip,
                                          ITEM_COLUMN_PROVIDER, li->data, -1);
 
       g_free (tooltip);
+      g_free (display_name);
     }
 
   g_list_free (items);
diff --git a/panel/panel-window.c b/panel/panel-window.c
index f62323c..35c53bc 100644
--- a/panel/panel-window.c
+++ b/panel/panel-window.c
@@ -2344,9 +2344,6 @@ panel_window_set_povider_info (PanelWindow *window,
       if (PANEL_IS_PLUGIN_EXTERNAL (provider))
         panel_plugin_external_set_background_alpha (PANEL_PLUGIN_EXTERNAL (provider),
             base_window->background_alpha);
-      else if (PANEL_IS_PLUGIN_EXTERNAL_46 (provider))
-        panel_plugin_external_46_set_background_alpha (PANEL_PLUGIN_EXTERNAL_46 (provider),
-            base_window->background_alpha);
     }
 
   if (base_window->background_style == PANEL_BG_STYLE_COLOR)
@@ -2354,18 +2351,12 @@ panel_window_set_povider_info (PanelWindow *window,
       if (PANEL_IS_PLUGIN_EXTERNAL (provider))
         panel_plugin_external_set_background_color (PANEL_PLUGIN_EXTERNAL (provider),
             base_window->background_color);
-      else if (PANEL_IS_PLUGIN_EXTERNAL_46 (provider))
-        panel_plugin_external_46_set_background_color (PANEL_PLUGIN_EXTERNAL_46 (provider),
-            base_window->background_color);
     }
   else if (base_window->background_style == PANEL_BG_STYLE_IMAGE)
     {
       if (PANEL_IS_PLUGIN_EXTERNAL (provider))
         panel_plugin_external_set_background_image (PANEL_PLUGIN_EXTERNAL (provider),
             base_window->background_image);
-      else if (PANEL_IS_PLUGIN_EXTERNAL_46 (provider))
-        panel_plugin_external_46_set_background_image (PANEL_PLUGIN_EXTERNAL_46 (provider),
-            base_window->background_image);
     }
 
   panel_window_set_plugin_orientation (provider, window);
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 10029ee..c112ba6 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -22,6 +22,7 @@ panel/panel-module-factory.c
 panel/panel-module.c
 panel/panel-plugin-external.c
 panel/panel-plugin-external-46.c
+panel/panel-plugin-external-wrapper.c
 panel/panel-preferences-dialog.c
 panel/panel-preferences-dialog.glade
 panel/panel-tic-tac-toe.c
diff --git a/wrapper/Makefile.am b/wrapper/Makefile.am
index b90b97e..7263dcd 100644
--- a/wrapper/Makefile.am
+++ b/wrapper/Makefile.am
@@ -44,7 +44,7 @@ wrapper_DEPENDENCIES = \
 
 if MAINTAINER_MODE
 
-wrapper-dbus-client-infos.h: $(top_builddir)/panel/panel-plugin-external-infos.xml Makefile
+wrapper-dbus-client-infos.h: $(top_builddir)/panel/panel-plugin-external-wrapper-infos.xml Makefile
 	$(AM_V_GEN) dbus-binding-tool --mode=glib-client $< > $@
 
 #wrapper-marshal.h: $(top_builddir)/panel/panel-marshal.list Makefile
diff --git a/wrapper/main.c b/wrapper/main.c
index 36a9ea8..11a04cf 100644
--- a/wrapper/main.c
+++ b/wrapper/main.c
@@ -52,6 +52,7 @@
 
 static GQuark   plug_quark = 0;
 static gboolean gproxy_destroyed = FALSE;
+static gint     retval = PLUGIN_EXIT_FAILURE;
 
 
 
@@ -60,21 +61,21 @@ wrapper_gproxy_set (DBusGProxy              *dbus_gproxy,
                     const GPtrArray         *array,
                     XfcePanelPluginProvider *provider)
 {
-  WrapperPlug *plug;
-  guint        i;
-  GValue      *value;
-  gchar       *property;
-  GValue       msg = { 0, };
+  WrapperPlug                    *plug;
+  guint                           i;
+  GValue                         *value;
+  XfcePanelPluginProviderPropType type;
+  GValue                          msg = { 0, };
 
   panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
 
-  g_value_init (&msg, PANEL_TYPE_DBUS_SET_MESSAGE);
+  g_value_init (&msg, PANEL_TYPE_DBUS_SET_PROPERTY);
 
   for (i = 0; i < array->len; i++)
     {
       g_value_set_static_boxed (&msg, g_ptr_array_index (array, i));
       if (!dbus_g_type_struct_get (&msg,
-                                   DBUS_SET_PROPERTY, &property,
+                                   DBUS_SET_TYPE, &type,
                                    DBUS_SET_VALUE, &value,
                                    G_MAXUINT))
         {
@@ -82,43 +83,71 @@ wrapper_gproxy_set (DBusGProxy              *dbus_gproxy,
           continue;
         }
 
-      if (strcmp (property, SIGNAL_SET_SIZE) == 0)
-        xfce_panel_plugin_provider_set_size (provider, g_value_get_int (value));
-      else if (strcmp (property, SIGNAL_SET_ORIENTATION) == 0)
-        xfce_panel_plugin_provider_set_orientation (provider, g_value_get_uint (value));
-      else if (strcmp (property, SIGNAL_SET_SCREEN_POSITION) == 0)
-        xfce_panel_plugin_provider_set_screen_position (provider, g_value_get_uint (value));
-      else if (strcmp (property, SIGNAL_SET_LOCKED) == 0)
-        xfce_panel_plugin_provider_set_locked (provider, g_value_get_boolean (value));
-      else if (strcmp (property, SIGNAL_SAVE) == 0)
-        xfce_panel_plugin_provider_save (provider);
-      else if (strcmp (property, SIGNAL_SHOW_CONFIGURE) == 0)
-        xfce_panel_plugin_provider_show_configure (provider);
-      else if (strcmp (property, SIGNAL_SHOW_ABOUT) == 0)
-        xfce_panel_plugin_provider_show_about (provider);
-      else if (strcmp (property, SIGNAL_REMOVED) == 0)
-        xfce_panel_plugin_provider_removed (provider);
-      else if (strcmp (property, SIGNAL_WRAPPER_SET_SENSITIVE) == 0)
-        gtk_widget_set_sensitive (GTK_WIDGET (provider), g_value_get_boolean (value));
-      else if (strcmp (property, SIGNAL_WRAPPER_QUIT) == 0)
-        gtk_main_quit ();
-      else
+      switch (type)
         {
+        case PROVIDER_PROP_TYPE_SET_SIZE:
+          xfce_panel_plugin_provider_set_size (provider, g_value_get_int (value));
+          break;
+
+        case PROVIDER_PROP_TYPE_SET_ORIENTATION:
+          xfce_panel_plugin_provider_set_orientation (provider, g_value_get_int (value));
+          break;
+
+        case PROVIDER_PROP_TYPE_SET_SCREEN_POSITION:
+          xfce_panel_plugin_provider_set_screen_position (provider, g_value_get_int (value));
+          break;
+
+        case PROVIDER_PROP_TYPE_SET_LOCKED:
+          xfce_panel_plugin_provider_set_locked (provider, g_value_get_boolean (value));
+          break;
+
+        case PROVIDER_PROP_TYPE_SET_SENSITIVE:
+          gtk_widget_set_sensitive (GTK_WIDGET (provider), g_value_get_boolean (value));
+          break;
+
+        case PROVIDER_PROP_TYPE_SET_BACKGROUND_ALPHA:
+        case PROVIDER_PROP_TYPE_SET_BACKGROUND_COLOR:
+        case PROVIDER_PROP_TYPE_SET_BACKGROUND_IMAGE:
+        case PROVIDER_PROP_TYPE_ACTION_BACKGROUND_UNSET:
           plug = g_object_get_qdata (G_OBJECT (provider), plug_quark);
 
-          if (strcmp (property, SIGNAL_WRAPPER_BACKGROUND_ALPHA) == 0)
+          if (type == PROVIDER_PROP_TYPE_SET_BACKGROUND_ALPHA)
             wrapper_plug_set_background_alpha (plug, g_value_get_double (value));
-          else if (strcmp (property, SIGNAL_WRAPPER_BACKGROUND_COLOR) == 0)
+          else if (type == PROVIDER_PROP_TYPE_SET_BACKGROUND_COLOR)
             wrapper_plug_set_background_color (plug, g_value_get_string (value));
-          else if (strcmp (property, SIGNAL_WRAPPER_BACKGROUND_IMAGE) == 0)
+          else if (type == PROVIDER_PROP_TYPE_SET_BACKGROUND_IMAGE)
             wrapper_plug_set_background_image (plug, g_value_get_string (value));
-          else if (strcmp (property, SIGNAL_WRAPPER_BACKGROUND_UNSET) == 0)
+          else /* PROVIDER_PROP_TYPE_ACTION_BACKGROUND_UNSET */
             wrapper_plug_set_background_color (plug, NULL);
-          else
-            panel_assert_not_reached ();
+          break;
+
+        case PROVIDER_PROP_TYPE_ACTION_REMOVED:
+          xfce_panel_plugin_provider_removed (provider);
+          break;
+
+        case PROVIDER_PROP_TYPE_ACTION_SAVE:
+          xfce_panel_plugin_provider_save (provider);
+          break;
+
+        case PROVIDER_PROP_TYPE_ACTION_QUIT_FOR_RESTART:
+          retval = PLUGIN_EXIT_SUCCESS_AND_RESTART;
+        case PROVIDER_PROP_TYPE_ACTION_QUIT:
+          gtk_main_quit ();
+          break;
+
+        case PROVIDER_PROP_TYPE_ACTION_SHOW_CONFIGURE:
+          xfce_panel_plugin_provider_show_configure (provider);
+          break;
+
+        case PROVIDER_PROP_TYPE_ACTION_SHOW_ABOUT:
+          xfce_panel_plugin_provider_show_about (provider);
+          break;
+
+        default:
+          panel_assert_not_reached ();
+          break;
         }
 
-      g_free (property);
       g_value_unset (value);
       g_free (value);
     }
@@ -168,7 +197,7 @@ wrapper_marshal_VOID__STRING_BOXED_UINT (GClosure     *closure,
   register GCClosure *cc = (GCClosure*) closure;
   register gpointer data1, data2;
 
-  g_return_if_fail (n_param_values == 4);
+  panel_return_if_fail (n_param_values == 4);
 
   if (G_CCLOSURE_SWAP_DATA (closure))
     {
@@ -180,6 +209,7 @@ wrapper_marshal_VOID__STRING_BOXED_UINT (GClosure     *closure,
       data1 = g_value_peek_pointer (param_values + 0);
       data2 = closure->data;
     }
+
   callback = (GMarshalFunc_VOID__STRING_BOXED_UINT) (marshal_data ? marshal_data : cc->callback);
 
   callback (data1,
@@ -222,7 +252,6 @@ main (gint argc, gchar **argv)
   gchar                    process_name[16];
 #endif
   GModule                 *library = NULL;
-  gint                     retval = PLUGIN_EXIT_FAILURE;
   XfcePanelPluginPreInit   preinit_func;
   DBusGConnection         *dbus_gconnection;
   DBusGProxy              *dbus_gproxy = NULL;
@@ -252,7 +281,7 @@ main (gint argc, gchar **argv)
   if (G_UNLIKELY (argc < PLUGIN_ARGV_ARGUMENTS))
     {
       g_critical ("Not enough arguments are passed to the wrapper");
-      return PLUGIN_EXIT_FAILURE;
+      return PLUGIN_EXIT_ARGUMENTS_FAILED;
     }
 
   /* put all arguments in understandable strings */
@@ -355,7 +384,6 @@ main (gint argc, gchar **argv)
       /* show the plugin */
       gtk_widget_show (GTK_WIDGET (provider));
 
-      /* enter the main loop */
       gtk_main ();
 
       /* disconnect signals */
@@ -371,8 +399,8 @@ main (gint argc, gchar **argv)
       if (plug != NULL)
         gtk_widget_destroy (GTK_WIDGET (plug));
 
-      /* everything when fine */
-      retval = PLUGIN_EXIT_SUCCESS;
+      if (retval != PLUGIN_EXIT_SUCCESS_AND_RESTART)
+        retval = PLUGIN_EXIT_SUCCESS;
     }
   else
     {
@@ -380,7 +408,6 @@ main (gint argc, gchar **argv)
     }
 
 leave:
-  /* release the proxy */
   if (G_LIKELY (dbus_gproxy != NULL))
     {
       if (G_LIKELY (gproxy_destroy_id != 0 && !gproxy_destroyed))
@@ -389,21 +416,16 @@ leave:
       g_object_unref (G_OBJECT (dbus_gproxy));
     }
 
-  /* close the type module */
   if (G_LIKELY (module != NULL))
     g_object_unref (G_OBJECT (module));
 
-  /* close plugin module */
   if (G_LIKELY (library != NULL))
     g_module_close (library);
 
   if (G_UNLIKELY (error != NULL))
     {
-      /* print the critical error */
       g_critical ("Wrapper %s-%d: %s.", name,
                   unique_id, error->message);
-
-      /* cleanup */
       g_error_free (error);
     }
 



More information about the Xfce4-commits mailing list