[gnome-panel/bonobo-less: 91/93] [panel] Use a gio extension point to handle applets



commit bd8305fde4c52f6766d13fdac4842f95ecd78cc1
Author: Vincent Untz <vuntz gnome org>
Date:   Wed May 26 05:29:33 2010 +0200

    [panel] Use a gio extension point to handle applets
    
    This way, we can have an external module to load bonobo applets.

 configure.in                                       |    4 +
 gnome-panel/Makefile.am                            |   24 +-
 gnome-panel/libpanel-applet-private/Makefile.am    |   37 +
 .../panel-applet-container.c                       |    0
 .../panel-applet-container.h                       |    0
 .../panel-applet-frame-dbus.c                      |  468 ++++++++
 .../panel-applet-frame-dbus.h                      |   61 +
 .../libpanel-applet-private/panel-applet-mini.c    |    5 +
 .../panel-applets-manager-dbus.c                   |  610 ++++++++++
 .../panel-applets-manager-dbus.h                   |   56 +
 gnome-panel/main.c                                 |    2 -
 gnome-panel/panel-applet-frame.c                   | 1188 +++++++++-----------
 gnome-panel/panel-applet-frame.h                   |   80 ++-
 gnome-panel/panel-applet-info.c                    |  111 ++
 gnome-panel/panel-applet-info.h                    |   47 +
 gnome-panel/panel-applets-manager.c                |  580 ++--------
 gnome-panel/panel-applets-manager.h                |   71 +-
 gnome-panel/panel-modules.c                        |   78 ++
 gnome-panel/panel-modules.h                        |   30 +
 gnome-panel/panel-test-applets.c                   |   40 +-
 20 files changed, 2264 insertions(+), 1228 deletions(-)
---
diff --git a/configure.in b/configure.in
index 70ace27..fe04238 100644
--- a/configure.in
+++ b/configure.in
@@ -269,6 +269,9 @@ else
 	have_randr=no
 fi
 
+dnl Modules dir
+AC_SUBST([modulesdir],"\$(libdir)/gnome-panel/modules")
+
 dnl Applets dir
 AC_SUBST([appletsdir],"\$(datadir)/gnome-panel/applets")
 
@@ -325,6 +328,7 @@ icons/48x48/Makefile
 icons/scalable/Makefile
 gnome-panel/Makefile
 gnome-panel/libegg/Makefile
+gnome-panel/libpanel-applet-private/Makefile
 gnome-panel/libpanel-util/Makefile
 gnome-panel/gnome-panel.desktop.in
 libpanel-applet/libpanelapplet-2.0.pc
diff --git a/gnome-panel/Makefile.am b/gnome-panel/Makefile.am
index be9e130..0993dfe 100644
--- a/gnome-panel/Makefile.am
+++ b/gnome-panel/Makefile.am
@@ -1,6 +1,6 @@
 ## We require new-style dependency handling.
 AUTOMAKE_OPTIONS = 1.3
-SUBDIRS = libegg libpanel-util
+SUBDIRS = libegg libpanel-applet-private libpanel-util
 
 NULL =
 
@@ -14,6 +14,7 @@ INCLUDES =							\
 	-DBUILDERDIR=\""$(uidir)"\"				\
 	-DICONDIR=\""$(datadir)/gnome-panel/pixmaps"\"		\
 	-DDATADIR=\""$(datadir)"\"				\
+	-DPANEL_MODULES_DIR=\"$(modulesdir)\"			\
 	-DPANEL_APPLETS_DIR=\"$(appletsdir)\"			\
 	-DGMENU_I_KNOW_THIS_IS_UNSTABLE				\
 	$(DISABLE_DEPRECATED_CFLAGS)				\
@@ -63,7 +64,6 @@ panel_sources =			\
 	panel-context-menu.c 	\
 	launcher.c		\
 	panel-applet-frame.c	\
-	panel-applet-container.c \
 	panel-applets-manager.c	\
 	panel-shell.c		\
 	panel-background.c	\
@@ -88,6 +88,8 @@ panel_sources =			\
 	panel-lockdown.c	\
 	panel-addto.c		\
 	panel-ditem-editor.c	\
+	panel-modules.c		\
+	panel-applet-info.c	\
 	$(NULL)
 
 panel_headers =			\
@@ -110,7 +112,6 @@ panel_headers =			\
 	panel-context-menu.h 	\
 	launcher.h		\
 	panel-applet-frame.h	\
-	panel-applet-container.h \
 	panel-applets-manager.h	\
 	panel-shell.h		\
 	panel-background.h	\
@@ -137,6 +138,8 @@ panel_headers =			\
 	panel-addto.h		\
 	panel-ditem-editor.h	\
 	panel-icon-names.h	\
+	panel-modules.h		\
+	panel-applet-info.h	\
 	$(NULL)
 
 gnome_panel_SOURCES =			\
@@ -145,9 +148,10 @@ gnome_panel_SOURCES =			\
 	$(NULL)
 
 gnome_panel_LDADD =		\
-	$(top_builddir)/gnome-panel/libegg/libegg.la \
-	$(top_builddir)/gnome-panel/libpanel-util/libpanel-util.la \
-	$(PANEL_LIBS)		\
+	$(top_builddir)/gnome-panel/libegg/libegg.la					\
+	$(top_builddir)/gnome-panel/libpanel-applet-private/libpanel-applet-private.la	\
+	$(top_builddir)/gnome-panel/libpanel-util/libpanel-util.la			\
+	$(PANEL_LIBS)									\
 	$(X_LIBS)
 
 gnome_panel_LDFLAGS = -export-dynamic
@@ -182,13 +186,17 @@ gnome-panel-add: gnome-panel-add.in Makefile
 	$(AM_V_at)chmod a+x $@
 
 panel_test_applets_SOURCES =		\
-	panel-applet-container.c	\
+	panel-modules.c			\
+	panel-applet-info.c		\
 	panel-applets-manager.c		\
 	panel-marshal.c			\
 	panel-test-applets.c
 
 panel_test_applets_LDFLAGS = -export-dynamic
-panel_test_applets_LDADD = $(PANEL_LIBS)
+panel_test_applets_LDADD = 		\
+	$(top_builddir)/gnome-panel/libpanel-applet-private/libpanel-applet-private-mini.la	\
+	$(top_builddir)/gnome-panel/libpanel-util/libpanel-util.la				\
+	$(PANEL_LIBS)
 
 EXTRA_DIST =					\
 	$(ui_DATA)				\
diff --git a/gnome-panel/libpanel-applet-private/Makefile.am b/gnome-panel/libpanel-applet-private/Makefile.am
new file mode 100644
index 0000000..0782d3e
--- /dev/null
+++ b/gnome-panel/libpanel-applet-private/Makefile.am
@@ -0,0 +1,37 @@
+NULL =
+
+INCLUDES =							\
+	-I.							\
+	-I$(srcdir)						\
+	-I$(top_builddir)/gnome-panel				\
+	-I$(top_builddir)/gnome-panel/libpanel-applets-private	\
+	-I$(top_builddir)/gnome-panel/libpanel-util		\
+	-DDATADIR=\""$(datadir)"\"				\
+	-DPANEL_APPLETS_DIR=\"$(appletsdir)\"			\
+	$(DISABLE_DEPRECATED_CFLAGS)				\
+	$(PANEL_CFLAGS)						\
+	$(WARN_CFLAGS)						\
+	$(NULL)
+
+noinst_LTLIBRARIES=		\
+	libpanel-applet-private.la	\
+	libpanel-applet-private-mini.la
+
+libpanel_applet_private_la_SOURCES=	\
+	panel-applets-manager-dbus.c	\
+	panel-applets-manager-dbus.h	\
+	panel-applet-container.c	\
+	panel-applet-container.h	\
+	panel-applet-frame-dbus.c	\
+	panel-applet-frame-dbus.h	\
+	$(NULL)
+
+libpanel_applet_private_mini_la_SOURCES=	\
+	panel-applet-mini.c		\
+	panel-applets-manager-dbus.c	\
+	panel-applets-manager-dbus.h	\
+	panel-applet-container.c	\
+	panel-applet-container.h	\
+	$(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/gnome-panel/panel-applet-container.c b/gnome-panel/libpanel-applet-private/panel-applet-container.c
similarity index 100%
rename from gnome-panel/panel-applet-container.c
rename to gnome-panel/libpanel-applet-private/panel-applet-container.c
diff --git a/gnome-panel/panel-applet-container.h b/gnome-panel/libpanel-applet-private/panel-applet-container.h
similarity index 100%
rename from gnome-panel/panel-applet-container.h
rename to gnome-panel/libpanel-applet-private/panel-applet-container.h
diff --git a/gnome-panel/libpanel-applet-private/panel-applet-frame-dbus.c b/gnome-panel/libpanel-applet-private/panel-applet-frame-dbus.c
new file mode 100644
index 0000000..dd1d1e6
--- /dev/null
+++ b/gnome-panel/libpanel-applet-private/panel-applet-frame-dbus.c
@@ -0,0 +1,468 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * panel-applet-frame-dbus.c: panel side container for applets
+ *
+ * Copyright (C) 2001 - 2003 Sun Microsystems, Inc.
+ * Copyright (C) 2010 Carlos Garcia Campos <carlosgc gnome org>
+ * Copyright (C) 2010 Vincent Untz <vuntz gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Authors:
+ *	Mark McLoughlin <mark skynet ie>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <panel-applet-frame.h>
+#include <panel-applets-manager.h>
+
+#include "panel-applet-container.h"
+
+#include "panel-applet-frame-dbus.h"
+
+G_DEFINE_TYPE (PanelAppletFrameDBus,
+	       panel_applet_frame_dbus,
+	       PANEL_TYPE_APPLET_FRAME)
+
+struct _PanelAppletFrameDBusPrivate
+{
+	PanelAppletContainer *container;
+	GCancellable         *bg_cancellable;
+};
+
+/* Keep in sync with panel-applet.h. Uggh. */	
+typedef enum {
+	APPLET_FLAGS_NONE   = 0,
+	APPLET_EXPAND_MAJOR = 1 << 0,
+	APPLET_EXPAND_MINOR = 1 << 1,
+	APPLET_HAS_HANDLE   = 1 << 2
+} PanelAppletFlags;
+
+
+static guint
+get_panel_applet_orient (PanelOrientation orientation)
+{
+	/* For some reason libpanel-applet and panel use a different logic for
+	 * orientation, so we need to convert it. We should fix this. */
+	switch (orientation) {
+	case PANEL_ORIENTATION_TOP:
+		return 1;
+	case PANEL_ORIENTATION_BOTTOM:
+		return 0;
+	case PANEL_ORIENTATION_LEFT:
+		return 3;
+	case PANEL_ORIENTATION_RIGHT:
+		return 2;
+	default:
+		g_assert_not_reached ();
+		break;
+	}
+}
+
+static void
+panel_applet_frame_dbus_update_flags (PanelAppletFrame *frame,
+				      GVariant         *value)
+{
+	guint32  flags;
+	gboolean major;
+	gboolean minor;
+	gboolean has_handle;
+
+	flags = g_variant_get_uint32 (value);
+
+	major = (flags & APPLET_EXPAND_MAJOR) != 0;
+	minor = (flags & APPLET_EXPAND_MINOR) != 0;
+	has_handle = (flags & APPLET_HAS_HANDLE) != 0;
+
+	_panel_applet_frame_update_flags (frame, major, minor, has_handle);
+}
+
+
+static void
+panel_applet_frame_dbus_get_flags_cb (PanelAppletContainer *container,
+				      GAsyncResult         *res,
+				      PanelAppletFrame     *frame)
+{
+	GVariant *value;
+	GError   *error = NULL;
+
+	value = panel_applet_container_child_get_finish (container, res, &error);
+	if (!value) {
+		g_warning ("%s\n", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	panel_applet_frame_dbus_update_flags (frame, value);
+	g_variant_unref (value);
+}
+
+static void
+panel_applet_frame_dbus_get_size_hints_cb (PanelAppletContainer *container,
+					   GAsyncResult         *res,
+					   PanelAppletFrame     *frame)
+{
+	GVariant   *value;
+	const gint *sz;
+	gint       *size_hints = NULL;
+	gsize       n_elements;
+	GError     *error = NULL;
+
+	value = panel_applet_container_child_get_finish (container, res, &error);
+	if (!value) {
+		g_warning ("%s\n", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	sz = g_variant_get_fixed_array (value, &n_elements, sizeof (gint32));
+	if (n_elements > 0) {
+		size_hints = g_new (gint32, n_elements);
+		memcpy (size_hints, sz, n_elements * sizeof (gint32));
+	}
+
+	_panel_applet_frame_update_size_hints (frame, size_hints, n_elements);
+	g_variant_unref (value);
+}
+
+static void
+panel_applet_frame_dbus_init_properties (PanelAppletFrame *frame)
+{
+	PanelAppletFrameDBus *dbus_frame = PANEL_APPLET_FRAME_DBUS (frame);
+
+	panel_applet_container_child_get (dbus_frame->priv->container, "flags", NULL,
+					  (GAsyncReadyCallback) panel_applet_frame_dbus_get_flags_cb,
+					  frame);
+	panel_applet_container_child_get (dbus_frame->priv->container, "size-hints", NULL,
+					  (GAsyncReadyCallback) panel_applet_frame_dbus_get_size_hints_cb,
+					  frame);
+}
+
+static void
+panel_applet_frame_dbus_sync_menu_state (PanelAppletFrame *frame,
+					 gboolean          movable,
+					 gboolean          removable,
+					 gboolean          lockable,
+					 gboolean          locked,
+					 gboolean          locked_down)
+{
+	PanelAppletFrameDBus *dbus_frame = PANEL_APPLET_FRAME_DBUS (frame);
+
+	panel_applet_container_child_set (dbus_frame->priv->container,
+					  "locked", g_variant_new_boolean (lockable && locked),
+					  NULL, NULL, NULL);
+	panel_applet_container_child_set (dbus_frame->priv->container,
+					  "locked-down", g_variant_new_boolean (locked_down),
+					  NULL, NULL, NULL);
+}
+
+static void
+panel_applet_frame_dbus_popup_menu (PanelAppletFrame *frame,
+				    guint             button,
+				    guint32           timestamp)
+{
+	PanelAppletFrameDBus *dbus_frame = PANEL_APPLET_FRAME_DBUS (frame);
+
+	panel_applet_container_child_popup_menu (dbus_frame->priv->container,
+						 button, timestamp,
+						 NULL, NULL, NULL);
+}
+
+static void
+change_orientation_cb (PanelAppletContainer *container,
+		       GAsyncResult         *res,
+		       PanelAppletFrame     *frame)
+{
+	GError *error = NULL;
+
+	if (!panel_applet_container_child_set_finish (container, res, &error)) {
+		g_warning ("%s\n", error->message);
+		g_error_free (error);
+
+		return;
+	}
+
+	gtk_widget_queue_resize (GTK_WIDGET (frame));
+}
+
+static void
+panel_applet_frame_dbus_change_orientation (PanelAppletFrame *frame,
+					    PanelOrientation  orientation)
+{
+	PanelAppletFrameDBus *dbus_frame = PANEL_APPLET_FRAME_DBUS (frame);
+
+	panel_applet_container_child_set (dbus_frame->priv->container,
+					  "orient",
+					  g_variant_new_uint32 (get_panel_applet_orient (orientation)),
+					  NULL,
+					  (GAsyncReadyCallback)change_orientation_cb,
+					  frame);
+}
+
+static void
+panel_applet_frame_dbus_change_size (PanelAppletFrame *frame,
+				     guint             size)
+{
+	PanelAppletFrameDBus *dbus_frame = PANEL_APPLET_FRAME_DBUS (frame);
+
+	panel_applet_container_child_set (dbus_frame->priv->container,
+					  "size", g_variant_new_uint32 (size),
+					  NULL, NULL, NULL);
+}
+
+static void
+container_child_background_set (GObject      *source_object,
+				GAsyncResult *res,
+				gpointer      user_data)
+{
+	PanelAppletContainer *container = PANEL_APPLET_CONTAINER (source_object);
+	PanelAppletFrameDBus *frame = PANEL_APPLET_FRAME_DBUS (user_data);
+
+	panel_applet_container_child_set_finish (container, res, NULL);
+
+	if (frame->priv->bg_cancellable)
+		g_object_unref (frame->priv->bg_cancellable);
+	frame->priv->bg_cancellable = NULL;
+}
+
+static void
+panel_applet_frame_dbus_change_background (PanelAppletFrame    *frame,
+					   PanelBackgroundType  type)
+{
+	PanelAppletFrameDBus *dbus_frame = PANEL_APPLET_FRAME_DBUS (frame);
+	char *bg_str;
+
+	bg_str = _panel_applet_frame_get_background_string (
+			frame, PANEL_WIDGET (GTK_WIDGET (frame)->parent), type);
+
+	if (bg_str != NULL) {
+		if (dbus_frame->priv->bg_cancellable)
+			g_cancellable_cancel (dbus_frame->priv->bg_cancellable);
+		dbus_frame->priv->bg_cancellable = g_cancellable_new ();
+
+		panel_applet_container_child_set (dbus_frame->priv->container,
+						  "background",
+						  g_variant_new_string (bg_str),
+						  dbus_frame->priv->bg_cancellable,
+						  container_child_background_set,
+						  dbus_frame);
+		g_free (bg_str);
+	}
+}
+
+static void
+panel_applet_frame_dbus_flags_changed (PanelAppletContainer *container,
+				       const gchar          *prop_name,
+				       GVariant             *value,
+				       PanelAppletFrame     *frame)
+{
+	panel_applet_frame_dbus_update_flags (frame, value);
+}
+
+static void
+panel_applet_frame_dbus_size_hints_changed (PanelAppletContainer *container,
+					    const gchar          *prop_name,
+					    GVariant             *value,
+					    PanelAppletFrame     *frame)
+{
+	const gint *sz;
+	gint       *size_hints = NULL;
+	gsize       n_elements;
+
+	sz = g_variant_get_fixed_array (value, &n_elements, sizeof (gint32));
+	if (n_elements > 0) {
+		size_hints = g_new (gint32, n_elements);
+		memcpy (size_hints, sz, n_elements * sizeof (gint32));
+	}
+
+	_panel_applet_frame_update_size_hints (frame, size_hints, n_elements);
+}
+
+static void
+panel_applet_frame_dbus_applet_broken (PanelAppletContainer *container,
+				       PanelAppletFrame     *frame)
+{
+	_panel_applet_frame_applet_broken (frame);
+}
+
+static void
+panel_applet_frame_dbus_applet_remove (PanelAppletContainer *container,
+				       PanelAppletFrame     *frame)
+{
+	_panel_applet_frame_applet_remove (frame);
+}
+
+static void
+panel_applet_frame_dbus_applet_move (PanelAppletContainer *container,
+				     PanelAppletFrame     *frame)
+{
+	_panel_applet_frame_applet_move (frame);
+}
+
+static void
+panel_applet_frame_dbus_applet_lock (PanelAppletContainer *container,
+				     gboolean              locked,
+				     PanelAppletFrame     *frame)
+{
+	_panel_applet_frame_applet_lock (frame, locked);
+}
+
+static void
+panel_applet_frame_dbus_finalize (GObject *object)
+{
+	PanelAppletFrameDBus *frame = PANEL_APPLET_FRAME_DBUS (object);
+
+	if (frame->priv->bg_cancellable)
+		g_object_unref (frame->priv->bg_cancellable);
+	frame->priv->bg_cancellable = NULL;
+
+	G_OBJECT_CLASS (panel_applet_frame_dbus_parent_class)->finalize (object);
+}
+
+static void
+panel_applet_frame_dbus_init (PanelAppletFrameDBus *frame)
+{
+	GtkWidget *container;
+
+	frame->priv = G_TYPE_INSTANCE_GET_PRIVATE (frame,
+						   PANEL_TYPE_APPLET_FRAME_DBUS,
+						   PanelAppletFrameDBusPrivate);
+
+	container = panel_applet_container_new ();
+	gtk_widget_show (container);
+	gtk_container_add (GTK_CONTAINER (frame), container);
+	frame->priv->container = PANEL_APPLET_CONTAINER (container);
+
+	g_signal_connect (container, "child-property-changed::flags",
+			  G_CALLBACK (panel_applet_frame_dbus_flags_changed),
+			  frame);
+	g_signal_connect (container, "child-property-changed::size-hints",
+			  G_CALLBACK (panel_applet_frame_dbus_size_hints_changed),
+			  frame);
+	g_signal_connect (container, "applet-broken",
+			  G_CALLBACK (panel_applet_frame_dbus_applet_broken),
+			  frame);
+	g_signal_connect (container, "applet-remove",
+			  G_CALLBACK (panel_applet_frame_dbus_applet_remove),
+			  frame);
+	g_signal_connect (container, "applet-move",
+			  G_CALLBACK (panel_applet_frame_dbus_applet_move),
+			  frame);
+	g_signal_connect (container, "applet-lock",
+			  G_CALLBACK (panel_applet_frame_dbus_applet_lock),
+			  frame);
+}
+
+static void
+panel_applet_frame_dbus_class_init (PanelAppletFrameDBusClass *class)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+	PanelAppletFrameClass *frame_class = PANEL_APPLET_FRAME_CLASS (class);
+
+	gobject_class->finalize = panel_applet_frame_dbus_finalize;
+
+	frame_class->init_properties = panel_applet_frame_dbus_init_properties;
+	frame_class->sync_menu_state = panel_applet_frame_dbus_sync_menu_state;
+	frame_class->popup_menu = panel_applet_frame_dbus_popup_menu;
+	frame_class->change_orientation = panel_applet_frame_dbus_change_orientation;
+	frame_class->change_size = panel_applet_frame_dbus_change_size;
+	frame_class->change_background = panel_applet_frame_dbus_change_background;
+
+	g_type_class_add_private (class, sizeof (PanelAppletFrameDBusPrivate));
+}
+
+static void
+panel_applet_frame_dbus_activated (PanelAppletContainer *container,
+				   GAsyncResult         *res,
+				   PanelAppletFrame     *frame)
+{
+	PanelAppletFrameActivating *frame_act;
+	GError *error = NULL;
+
+	if (!panel_applet_container_add_finish (container, res, &error))
+		g_assert (error != NULL);
+
+	frame_act = g_object_get_data (G_OBJECT (frame), "panel-applet-frame-activating");
+	g_object_set_data (G_OBJECT (frame), "panel-applet-frame-activating", NULL);
+
+	_panel_applet_frame_activated (frame, frame_act, error);
+}
+
+gboolean
+panel_applet_frame_dbus_load (const gchar                 *iid,
+			      PanelAppletFrameActivating  *frame_act)
+{
+	PanelAppletFrameDBus *dbus_frame;
+	PanelAppletFrame     *frame;
+	GVariantBuilder       builder;
+	gchar                *conf_path;
+	gchar                *background;
+	guint                 orient;
+
+	g_return_val_if_fail (iid != NULL, FALSE);
+	g_return_val_if_fail (frame_act != NULL, FALSE);
+
+	if (!panel_applets_manager_factory_activate (iid))
+		return FALSE;
+
+	dbus_frame = g_object_new (PANEL_TYPE_APPLET_FRAME_DBUS, NULL);
+	frame = PANEL_APPLET_FRAME (dbus_frame);
+	_panel_applet_frame_set_iid (frame, iid);
+
+	orient = get_panel_applet_orient (panel_applet_frame_activating_get_orientation (frame_act));
+	conf_path = panel_applet_frame_activating_get_conf_path (frame_act);
+	/* we can't really get a background string at this point since we don't
+	 * know the position of the applet */
+	background = NULL;
+
+	g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+	g_variant_builder_add (&builder, "{sv}",
+			       "prefs-key",
+			       g_variant_new_string (conf_path));
+	g_variant_builder_add (&builder, "{sv}",
+			       "orient",
+			       g_variant_new_uint32 (orient));
+	g_variant_builder_add (&builder, "{sv}",
+			       "size",
+			       g_variant_new_uint32 (panel_applet_frame_activating_get_size (frame_act)));
+	g_variant_builder_add (&builder, "{sv}",
+			       "locked",
+			       g_variant_new_boolean (panel_applet_frame_activating_get_locked (frame_act)));
+	g_variant_builder_add (&builder, "{sv}",
+			       "locked-down",
+			       g_variant_new_boolean (panel_applet_frame_activating_get_locked_down (frame_act)));
+	if (background) {
+		g_variant_builder_add (&builder, "{sv}",
+				       "background",
+				       g_variant_new_string (background));
+	}
+
+	g_object_set_data (G_OBJECT (frame), "panel-applet-frame-activating", frame_act);
+
+	panel_applet_container_add (dbus_frame->priv->container,
+				    iid, NULL,
+				    (GAsyncReadyCallback) panel_applet_frame_dbus_activated,
+				    frame,
+				    g_variant_builder_end (&builder));
+
+	g_free (conf_path);
+	g_free (background);
+
+	return TRUE;
+}
diff --git a/gnome-panel/libpanel-applet-private/panel-applet-frame-dbus.h b/gnome-panel/libpanel-applet-private/panel-applet-frame-dbus.h
new file mode 100644
index 0000000..cb133b0
--- /dev/null
+++ b/gnome-panel/libpanel-applet-private/panel-applet-frame-dbus.h
@@ -0,0 +1,61 @@
+/*
+ * panel-applet-frame-dbus.h: panel side container for applets
+ *
+ * Copyright (C) 2001 - 2003 Sun Microsystems, Inc.
+ * Copyright (C) 2010 Vincent Untz <vuntz gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Authors:
+ *	Mark McLoughlin <mark skynet ie>
+ */
+
+#ifndef __PANEL_APPLET_FRAME_DBUS_H__
+#define __PANEL_APPLET_FRAME_DBUS_H__
+
+#include <panel-applet-frame.h>
+
+G_BEGIN_DECLS
+
+#define PANEL_TYPE_APPLET_FRAME_DBUS         (panel_applet_frame_dbus_get_type ())
+#define PANEL_APPLET_FRAME_DBUS(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), PANEL_TYPE_APPLET_FRAME_DBUS, PanelAppletFrameDBus))
+#define PANEL_APPLET_FRAME_DBUS_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), PANEL_TYPE_APPLET_FRAME_DBUS, PanelAppletFrameDBusClass))
+#define PANEL_IS_APPLET_FRAME_DBUS(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), PANEL_TYPE_APPLET_FRAME_DBUS))
+#define PANEL_IS_APPLET_FRAME_DBUS_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), PANEL_TYPE_APPLET_FRAME_DBUS))
+#define PANEL_APPLET_FRAME_DBUS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PANEL_TYPE_APPLET_FRAME_DBUS, PanelAppletFrameDBusClass))
+
+typedef struct _PanelAppletFrameDBus        PanelAppletFrameDBus;
+typedef struct _PanelAppletFrameDBusClass   PanelAppletFrameDBusClass;
+typedef struct _PanelAppletFrameDBusPrivate PanelAppletFrameDBusPrivate;
+
+struct _PanelAppletFrameDBusClass {
+        PanelAppletFrameClass parent_class;
+};
+
+struct _PanelAppletFrameDBus{
+	PanelAppletFrame parent;
+
+        PanelAppletFrameDBusPrivate  *priv;
+};
+
+GType     panel_applet_frame_dbus_get_type           (void) G_GNUC_CONST;
+
+gboolean  panel_applet_frame_dbus_load               (const gchar                 *iid,
+						      PanelAppletFrameActivating  *frame_act);
+
+G_END_DECLS
+
+#endif /* __PANEL_APPLET_FRAME_DBUS_H__ */
diff --git a/gnome-panel/libpanel-applet-private/panel-applet-mini.c b/gnome-panel/libpanel-applet-private/panel-applet-mini.c
new file mode 100644
index 0000000..e9c498e
--- /dev/null
+++ b/gnome-panel/libpanel-applet-private/panel-applet-mini.c
@@ -0,0 +1,5 @@
+/* Symbols needed for libpanel-applet-private-mini, which is used by the test
+ * program */
+#include <glib.h>
+gboolean panel_applet_frame_dbus_load (const gchar *iid, gpointer frame_act);
+gboolean panel_applet_frame_dbus_load (const gchar *iid, gpointer frame_act) { return FALSE; }
diff --git a/gnome-panel/libpanel-applet-private/panel-applets-manager-dbus.c b/gnome-panel/libpanel-applet-private/panel-applets-manager-dbus.c
new file mode 100644
index 0000000..67eed60
--- /dev/null
+++ b/gnome-panel/libpanel-applet-private/panel-applets-manager-dbus.c
@@ -0,0 +1,610 @@
+/*
+ * panel-applets-manager-dbus.c
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <carlosgc gnome org>
+ * Copyright (C) 2010 Vincent Untz <vuntz gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <gio/gio.h>
+#include <gmodule.h>
+#include <string.h>
+
+#include <panel-applets-manager.h>
+
+#include "panel-applet-frame-dbus.h"
+
+#include "panel-applets-manager-dbus.h"
+
+G_DEFINE_TYPE_WITH_CODE (PanelAppletsManagerDBus,
+			 panel_applets_manager_dbus,
+			 PANEL_TYPE_APPLETS_MANAGER,
+			 g_io_extension_point_implement (PANEL_APPLETS_MANAGER_EXTENSION_POINT_NAME,
+							 g_define_type_id,
+							 "dbus",
+							 5))
+
+struct _PanelAppletsManagerDBusPrivate
+{
+	GHashTable *applet_factories;
+	GList      *monitors;
+};
+
+typedef gint (* ActivateAppletFunc) (void);
+
+typedef struct _PanelAppletFactoryInfo {
+	gchar              *id;
+	gchar              *location;
+	gboolean            in_process;
+	GModule            *module;
+	ActivateAppletFunc  activate_applet;
+	guint               n_applets;
+
+	gchar              *srcdir;
+
+	GList              *applet_list;
+	gboolean            has_old_ids;
+} PanelAppletFactoryInfo;
+
+#define PANEL_APPLET_FACTORY_GROUP "Applet Factory"
+#define PANEL_APPLETS_EXTENSION    ".panel-applet"
+
+static void
+panel_applet_factory_info_free (PanelAppletFactoryInfo *info)
+{
+	if (!info)
+		return;
+
+	g_free (info->id);
+	g_free (info->location);
+	g_list_foreach (info->applet_list,
+			(GFunc)panel_applet_info_free,
+			NULL);
+	g_list_free (info->applet_list);
+	info->applet_list = NULL;
+	g_free (info->srcdir);
+
+	g_slice_free (PanelAppletFactoryInfo, info);
+}
+
+static PanelAppletInfo *
+_panel_applets_manager_get_applet_info (GKeyFile    *applet_file,
+					const gchar *group,
+					const gchar *factory_id)
+{
+	PanelAppletInfo  *info;
+	char             *iid;
+	char             *name;
+	char             *comment;
+	char             *icon;
+	char            **old_ids;
+
+	iid = g_strdup_printf ("%s::%s", factory_id, group);
+	name = g_key_file_get_locale_string (applet_file, group,
+					     "Name", NULL, NULL);
+	comment = g_key_file_get_locale_string (applet_file, group,
+						"Description", NULL, NULL);
+	icon = g_key_file_get_string (applet_file, group, "Icon", NULL);
+	/* Bonobo compatibility */
+	old_ids = g_key_file_get_string_list (applet_file, group,
+					      "BonoboId", NULL, NULL);
+
+	info = panel_applet_info_new (iid, name, comment, icon, (const char **) old_ids);
+
+	g_free (iid);
+	g_free (name);
+	g_free (comment);
+	g_free (icon);
+	g_strfreev (old_ids);
+
+	return info;
+}
+
+static PanelAppletFactoryInfo *
+panel_applets_manager_get_applet_factory_info_from_file (const gchar *filename)
+{
+	PanelAppletFactoryInfo *info;
+	GKeyFile               *applet_file;
+	gchar                 **groups;
+	gsize                   n_groups;
+	gint                    i;
+	GError                 *error = NULL;
+
+	applet_file = g_key_file_new ();
+	if (!g_key_file_load_from_file (applet_file, filename, G_KEY_FILE_NONE, &error)) {
+		g_warning ("Error opening panel applet file %s: %s",
+			   filename, error->message);
+		g_error_free (error);
+		g_key_file_free (applet_file);
+
+		return NULL;
+	}
+
+	info = g_slice_new0 (PanelAppletFactoryInfo);
+	info->id = g_key_file_get_string (applet_file, PANEL_APPLET_FACTORY_GROUP, "Id", NULL);
+	if (!info->id) {
+		g_warning ("Bad panel applet file %s: Could not find 'Id' in group '%s'",
+			   filename, PANEL_APPLET_FACTORY_GROUP);
+		panel_applet_factory_info_free (info);
+		g_key_file_free (applet_file);
+
+		return NULL;
+	}
+
+	info->in_process = g_key_file_get_boolean (applet_file, PANEL_APPLET_FACTORY_GROUP,
+						   "InProcess", NULL);
+	if (info->in_process) {
+		info->location = g_key_file_get_string (applet_file, PANEL_APPLET_FACTORY_GROUP,
+							"Location", NULL);
+		if (!info->location) {
+			g_warning ("Bad panel applet file %s: In-process applet without 'Location'",
+				   filename);
+			panel_applet_factory_info_free (info);
+			g_key_file_free (applet_file);
+
+			return NULL;
+		}
+	}
+
+	info->has_old_ids = FALSE;
+
+	groups = g_key_file_get_groups (applet_file, &n_groups);
+	for (i = 0; i < n_groups; i++) {
+		PanelAppletInfo *ainfo;
+
+		if (g_strcmp0 (groups[i], PANEL_APPLET_FACTORY_GROUP) == 0)
+			continue;
+
+		ainfo = _panel_applets_manager_get_applet_info (applet_file,
+								groups[i], info->id);
+		if (panel_applet_info_get_old_ids (ainfo) != NULL)
+			info->has_old_ids = TRUE;
+
+		info->applet_list = g_list_prepend (info->applet_list, ainfo);
+	}
+	g_strfreev (groups);
+
+	g_key_file_free (applet_file);
+
+	if (!info->applet_list) {
+		panel_applet_factory_info_free (info);
+		return NULL;
+	}
+
+	info->srcdir = g_path_get_dirname (filename);
+
+	return info;
+}
+
+static GSList *
+panel_applets_manager_get_applets_dirs (void)
+{
+	const gchar *dir = NULL;
+	gchar      **paths;
+	guint        i;
+	GSList      *retval = NULL;
+
+	dir = g_getenv ("GNOME_PANEL_APPLETS_DIR");
+	if (!dir || g_strcmp0 (dir, "") == 0) {
+		return g_slist_prepend (NULL, g_strdup (PANEL_APPLETS_DIR));
+	}
+
+	paths = g_strsplit (dir, ":", 0);
+	for (i = 0; paths[i]; i++) {
+		if (g_slist_find_custom (retval, paths[i], (GCompareFunc)g_strcmp0))
+			continue;
+		retval = g_slist_prepend (retval, g_strdup (paths[i]));
+	}
+	g_strfreev (paths);
+
+	return g_slist_reverse (retval);
+}
+
+static void
+applets_directory_changed (GFileMonitor     *monitor,
+			   GFile            *file,
+			   GFile            *other_file,
+			   GFileMonitorEvent event_type,
+			   gpointer          user_data)
+{
+	PanelAppletsManagerDBus *manager = PANEL_APPLETS_MANAGER_DBUS (user_data);
+
+	switch (event_type) {
+	case G_FILE_MONITOR_EVENT_CHANGED:
+	case G_FILE_MONITOR_EVENT_CREATED: {
+		PanelAppletFactoryInfo *info;
+		PanelAppletFactoryInfo *old_info;
+		gchar                  *filename;
+		GSList                 *dirs, *d;
+
+		filename = g_file_get_path (file);
+		if (!g_str_has_suffix (filename, PANEL_APPLETS_EXTENSION)) {
+			g_free (filename);
+			return;
+		}
+
+		info = panel_applets_manager_get_applet_factory_info_from_file (filename);
+		g_free (filename);
+
+		if (!info)
+			return;
+
+		old_info = g_hash_table_lookup (manager->priv->applet_factories, info->id);
+		if (!old_info) {
+			/* New applet, just insert it */
+			g_hash_table_insert (manager->priv->applet_factories, g_strdup (info->id), info);
+			return;
+		}
+
+		/* Make sure we don't update an applet
+		 * that has changed in another source dir
+		 * unless it takes precedence over the
+		 * current one
+		 */
+		if (g_strcmp0 (info->srcdir, old_info->srcdir) == 0) {
+			g_hash_table_insert (manager->priv->applet_factories, g_strdup (info->id), info);
+			return;
+		}
+
+		dirs = panel_applets_manager_get_applets_dirs ();
+
+		for (d = dirs; d; d = g_slist_next (d)) {
+			gchar *path = (gchar *)d->data;
+
+			if (g_strcmp0 (path, old_info->srcdir) == 0) {
+				panel_applet_factory_info_free (info);
+				break;
+			} else if (g_strcmp0 (path, info->srcdir) == 0) {
+				g_hash_table_insert (manager->priv->applet_factories, g_strdup (info->id), info);
+				break;
+			}
+		}
+
+		g_slist_foreach (dirs, (GFunc)g_free, NULL);
+		g_slist_free (dirs);
+	}
+		break;
+	default:
+		/* Ignore any other change */
+		break;
+	}
+}
+
+static gboolean
+panel_applets_manager_load_applet_infos (PanelAppletsManagerDBus *manager)
+{
+	GSList      *dirs, *d;
+	GDir        *dir;
+	const gchar *dirent;
+	GError      *error = NULL;
+	gboolean     retval = FALSE;
+
+	dirs = panel_applets_manager_get_applets_dirs ();
+	for (d = dirs; d; d = g_slist_next (d)) {
+		GFileMonitor *monitor;
+		GFile        *dir_file;
+		gchar        *path = (gchar *)d->data;
+
+		dir = g_dir_open (path, 0, &error);
+		if (!dir) {
+			g_warning ("%s", error->message);
+			g_error_free (error);
+			g_free (path);
+
+			continue;
+		}
+
+		/* Monitor dir */
+		dir_file = g_file_new_for_path (path);
+		monitor = g_file_monitor_directory (dir_file,
+						    G_FILE_MONITOR_NONE,
+						    NULL, NULL);
+		if (monitor) {
+			g_signal_connect (monitor, "changed",
+					  G_CALLBACK (applets_directory_changed),
+					  manager);
+			manager->priv->monitors = g_list_prepend (manager->priv->monitors, monitor);
+		}
+		g_object_unref (dir_file);
+
+		while ((dirent = g_dir_read_name (dir))) {
+			PanelAppletFactoryInfo *info;
+			gchar                  *file;
+
+			if (!g_str_has_suffix (dirent, PANEL_APPLETS_EXTENSION))
+				continue;
+
+			file = g_build_filename (path, dirent, NULL);
+			info = panel_applets_manager_get_applet_factory_info_from_file (file);
+			g_free (file);
+
+			if (!info)
+				continue;
+
+			if (g_hash_table_lookup (manager->priv->applet_factories, info->id)) {
+				panel_applet_factory_info_free (info);
+				continue;
+			}
+
+			g_hash_table_insert (manager->priv->applet_factories, g_strdup (info->id), info);
+			retval = TRUE;
+		}
+
+		g_dir_close (dir);
+		g_free (path);
+	}
+
+	g_slist_free (dirs);
+
+	return retval;
+}
+
+static GList *
+panel_applets_manager_dbus_get_applets (PanelAppletsManager *manager)
+{
+	PanelAppletsManagerDBus *dbus_manager = PANEL_APPLETS_MANAGER_DBUS (manager);
+
+	GHashTableIter iter;
+	gpointer       key, value;
+	GList         *retval = NULL;
+
+	g_hash_table_iter_init (&iter, dbus_manager->priv->applet_factories);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		PanelAppletFactoryInfo *info;
+
+		info = (PanelAppletFactoryInfo *)value;
+		retval = g_list_concat (retval, g_list_copy (info->applet_list));
+	}
+
+	return retval;
+}
+
+static PanelAppletFactoryInfo *
+get_applet_factory_info (PanelAppletsManager *manager,
+			 const gchar         *iid)
+{
+	PanelAppletsManagerDBus *dbus_manager = PANEL_APPLETS_MANAGER_DBUS (manager);
+
+	PanelAppletFactoryInfo *info;
+	const gchar            *sp;
+	gchar                  *factory_id;
+
+	sp = g_strrstr (iid, "::");
+	if (!sp)
+		return NULL;
+
+	factory_id = g_strndup (iid, strlen (iid) - strlen (sp));
+	info = g_hash_table_lookup (dbus_manager->priv->applet_factories, factory_id);
+	g_free (factory_id);
+
+	return info;
+}
+
+static gboolean
+panel_applets_manager_dbus_factory_activate (PanelAppletsManager *manager,
+					     const gchar         *iid)
+{
+	PanelAppletFactoryInfo *info;
+	ActivateAppletFunc      activate_applet;
+
+	info = get_applet_factory_info (manager, iid);
+	if (!info)
+		return FALSE;
+
+	/* Out-of-process applets are activated by the session bus */
+	if (!info->in_process)
+		return TRUE;
+
+	if (info->module) {
+		if (info->n_applets == 0) {
+			if (info->activate_applet () != 0) {
+				g_warning ("Failed to reactivate factory %s\n", iid);
+				return FALSE;
+			}
+		}
+		info->n_applets++;
+
+		return TRUE;
+	}
+
+	info->module = g_module_open (info->location, G_MODULE_BIND_LAZY);
+	if (!info->module) {
+		/* FIXME: use a GError? */
+		g_warning ("Failed to load applet %s: %s\n",
+			   iid, g_module_error ());
+		return FALSE;
+	}
+
+	if (!g_module_symbol (info->module, "_panel_applet_shlib_factory", (gpointer *)&activate_applet)) {
+		/* FIXME: use a GError? */
+		g_warning ("Failed to load applet %s: %s\n",
+			   iid, g_module_error ());
+		g_module_close (info->module);
+		info->module = NULL;
+
+		return FALSE;
+	}
+
+	/* Activate the applet */
+	if (activate_applet () != 0) {
+		/* FIXME: use a GError? */
+		g_warning ("Failed to load applet %s\n", iid);
+		g_module_close (info->module);
+		info->module = NULL;
+
+		return FALSE;
+	}
+	info->activate_applet = activate_applet;
+
+	info->n_applets = 1;
+
+	return TRUE;
+}
+
+static gboolean
+panel_applets_manager_dbus_factory_deactivate (PanelAppletsManager *manager,
+					       const gchar         *iid)
+{
+	PanelAppletFactoryInfo *info;
+
+	info = get_applet_factory_info (manager, iid);
+	if (!info)
+		return FALSE;
+
+	/* Out-of-process applets are deactivated by the session bus */
+	if (!info->in_process)
+		return TRUE;
+
+	if (!info->module)
+		return TRUE;
+
+	if (--info->n_applets == 0) {
+		/* FIXME: we should close the module here,
+		 * however applet types are registered static
+		 */
+#if 0
+		g_module_close (info->module);
+		info->module = NULL;
+#endif
+	}
+
+	return TRUE;
+}
+
+static PanelAppletInfo *
+panel_applets_manager_dbus_get_applet_info (PanelAppletsManager *manager,
+					    const gchar         *iid)
+{
+	PanelAppletFactoryInfo *info;
+	GList                  *l;
+
+	info = get_applet_factory_info (manager, iid);
+	if (!info)
+		return NULL;
+
+	for (l = info->applet_list; l; l = g_list_next (l)) {
+		PanelAppletInfo *ainfo = (PanelAppletInfo *)l->data;
+
+		if (g_strcmp0 (panel_applet_info_get_iid (ainfo), iid) == 0)
+			return ainfo;
+	}
+
+	return NULL;
+}
+
+static PanelAppletInfo *
+panel_applets_manager_dbus_get_applet_info_from_old_id (PanelAppletsManager *manager,
+							const gchar         *iid)
+{
+	PanelAppletsManagerDBus *dbus_manager = PANEL_APPLETS_MANAGER_DBUS (manager);
+
+	GHashTableIter iter;
+	gpointer       key, value;
+
+	g_hash_table_iter_init (&iter, dbus_manager->priv->applet_factories);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		PanelAppletFactoryInfo *info;
+		GList                  *l;
+
+		info = (PanelAppletFactoryInfo *)value;
+		if (!info->has_old_ids)
+			continue;
+
+		for (l = info->applet_list; l; l = g_list_next (l)) {
+			PanelAppletInfo *ainfo;
+			gint             i = 0;
+			const gchar * const *old_ids;
+
+			ainfo = (PanelAppletInfo *)l->data;
+
+			old_ids = panel_applet_info_get_old_ids (ainfo);
+
+			if (old_ids == NULL)
+				continue;
+
+			while (old_ids[i]) {
+				if (g_strcmp0 (old_ids[i], iid) == 0)
+					return ainfo;
+				i++;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+static gboolean
+panel_applets_manager_dbus_load_applet (PanelAppletsManager         *manager,
+					const gchar                 *iid,
+					PanelAppletFrameActivating  *frame_act)
+{
+	return panel_applet_frame_dbus_load (iid, frame_act);
+}
+
+static void
+panel_applets_manager_dbus_finalize (GObject *object)
+{
+	PanelAppletsManagerDBus *manager = PANEL_APPLETS_MANAGER_DBUS (object);
+
+	if (manager->priv->monitors) {
+		g_list_foreach (manager->priv->monitors, (GFunc)g_object_unref, NULL);
+		g_list_free (manager->priv->monitors);
+		manager->priv->monitors = NULL;
+	}
+
+	if (manager->priv->applet_factories) {
+		g_hash_table_destroy (manager->priv->applet_factories);
+		manager->priv->applet_factories = NULL;
+	}
+
+	G_OBJECT_CLASS (panel_applets_manager_dbus_parent_class)->finalize (object);
+}
+
+static void
+panel_applets_manager_dbus_init (PanelAppletsManagerDBus *manager)
+{
+	manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
+						     PANEL_TYPE_APPLETS_MANAGER_DBUS,
+						     PanelAppletsManagerDBusPrivate);
+
+	manager->priv->applet_factories = g_hash_table_new_full (g_str_hash,
+								 g_str_equal,
+								 (GDestroyNotify) g_free,
+								 (GDestroyNotify) panel_applet_factory_info_free);
+
+	panel_applets_manager_load_applet_infos (manager);
+}
+
+static void
+panel_applets_manager_dbus_class_init (PanelAppletsManagerDBusClass *class)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+	PanelAppletsManagerClass *manager_class = PANEL_APPLETS_MANAGER_CLASS (class);
+
+	gobject_class->finalize = panel_applets_manager_dbus_finalize;
+
+	manager_class->get_applets = panel_applets_manager_dbus_get_applets;
+	manager_class->factory_activate = panel_applets_manager_dbus_factory_activate;
+	manager_class->factory_deactivate = panel_applets_manager_dbus_factory_deactivate;
+	manager_class->get_applet_info = panel_applets_manager_dbus_get_applet_info;
+	manager_class->get_applet_info_from_old_id = panel_applets_manager_dbus_get_applet_info_from_old_id;
+	manager_class->load_applet = panel_applets_manager_dbus_load_applet;
+
+	g_type_class_add_private (class, sizeof (PanelAppletsManagerDBusPrivate));
+}
diff --git a/gnome-panel/libpanel-applet-private/panel-applets-manager-dbus.h b/gnome-panel/libpanel-applet-private/panel-applets-manager-dbus.h
new file mode 100644
index 0000000..9d2705e
--- /dev/null
+++ b/gnome-panel/libpanel-applet-private/panel-applets-manager-dbus.h
@@ -0,0 +1,56 @@
+/*
+ * panel-applets-manager-dbus.h
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <carlosgc gnome org>
+ * Copyright (C) 2010 Vincent Untz <vuntz gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __PANEL_APPLETS_MANAGER_DBUS_H__
+#define __PANEL_APPLETS_MANAGER_DBUS_H__
+
+#include <panel-applets-manager.h>
+
+G_BEGIN_DECLS
+
+#define PANEL_TYPE_APPLETS_MANAGER_DBUS			(panel_applets_manager_dbus_get_type ())
+#define PANEL_APPLETS_MANAGER_DBUS(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_APPLETS_MANAGER_DBUS, PanelAppletsManagerDBus))
+#define PANEL_APPLETS_MANAGER_DBUS_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST ((klass), PANEL_TYPE_APPLETS_MANAGER_DBUS, PanelAppletsManagerDBusClass))
+#define PANEL_IS_APPLETS_MANAGER_DBUS(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), PANEL_TYPE_APPLETS_MANAGER_DBUS))
+#define PANEL_IS_APPLETS_MANAGER_DBUS_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_APPLETS_MANAGER_DBUS))
+#define PANEL_APPLETS_MANAGER_DBUS_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), PANEL_TYPE_APPLETS_MANAGER_DBUS, PanelAppletsManagerDBusClass))
+
+typedef struct _PanelAppletsManagerDBus		PanelAppletsManagerDBus;
+typedef struct _PanelAppletsManagerDBusClass	PanelAppletsManagerDBusClass;
+typedef struct _PanelAppletsManagerDBusPrivate	PanelAppletsManagerDBusPrivate;
+
+struct _PanelAppletsManagerDBusClass {
+	PanelAppletsManagerClass parent_class;
+};
+
+struct _PanelAppletsManagerDBus {
+	PanelAppletsManager parent;
+
+	/*< private > */
+	PanelAppletsManagerDBusPrivate *priv;
+};
+
+GType panel_applets_manager_dbus_get_type (void);
+
+G_END_DECLS
+
+#endif /* __PANEL_APPLETS_MANAGER_DBUS_H__ */
diff --git a/gnome-panel/main.c b/gnome-panel/main.c
index e314e1d..0f09ee3 100644
--- a/gnome-panel/main.c
+++ b/gnome-panel/main.c
@@ -100,7 +100,6 @@ main (int argc, char **argv)
 		return -1;
 	}
 
-	panel_applets_manager_init ();
 	panel_action_protocol_init ();
 	panel_multiscreen_init ();
 	panel_init_stock_icons_and_items ();
@@ -132,7 +131,6 @@ main (int argc, char **argv)
 	gtk_main ();
 
 	panel_lockdown_finalize ();
-	panel_applets_manager_shutdown ();
 
 	gconf_client_remove_dir (panel_gconf_get_client (),
 				 "/desktop/gnome/interface",
diff --git a/gnome-panel/panel-applet-frame.c b/gnome-panel/panel-applet-frame.c
index 3d6c418..36db459 100644
--- a/gnome-panel/panel-applet-frame.c
+++ b/gnome-panel/panel-applet-frame.c
@@ -33,10 +33,8 @@
 #include <gdk/gdk.h>
 #include <gdk/gdkx.h>
 
-#include "panel-applet-frame.h"
 #include "panel-applets-manager.h"
 #include "panel-profile.h"
-#include "panel-util.h"
 #include "panel.h"
 #include "applet.h"
 #include "panel-marshal.h"
@@ -46,7 +44,32 @@
 #include "xstuff.h"
 #include "panel-compatibility.h"
 
-G_DEFINE_TYPE (PanelAppletFrame, panel_applet_frame, PANEL_TYPE_APPLET_CONTAINER)
+#include "panel-applet-frame.h"
+
+static void panel_applet_frame_activating_free (PanelAppletFrameActivating *frame_act);
+
+static void panel_applet_frame_loading_failed  (const char  *iid,
+					        PanelWidget *panel,
+					        const char  *id);
+
+static void panel_applet_frame_load            (const gchar *iid,
+						PanelWidget *panel,
+						gboolean     locked,
+						int          position,
+						gboolean     exactpos,
+						const char  *id);
+
+struct _PanelAppletFrameActivating {
+	gboolean     locked;
+	PanelWidget *panel;
+	int          position;
+	gboolean     exactpos;
+	char        *id;
+};
+
+/* PanelAppletFrame implementation */
+
+G_DEFINE_TYPE (PanelAppletFrame, panel_applet_frame, GTK_TYPE_BIN)
 
 #define PANEL_APPLET_FRAME_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_APPLET_FRAME, PanelAppletFramePrivate))
 
@@ -65,625 +88,9 @@ struct _PanelAppletFramePrivate {
 	GdkRectangle     handle_rect;
 
 	guint            has_handle : 1;
-
-	GCancellable    *bg_cancellable;
-};
-
-typedef struct {
-	gboolean  locked;
-	int       position;
-	gboolean  exactpos;
-	char     *id;
-} PanelAppletFrameActivating;
-
-/* Keep in sync with panel-applet.h. Uggh.
- */	
-typedef enum {
-	APPLET_FLAGS_NONE   = 0,
-	APPLET_EXPAND_MAJOR = 1 << 0,
-	APPLET_EXPAND_MINOR = 1 << 1,
-	APPLET_HAS_HANDLE   = 1 << 2
-} PanelAppletFlags;
-
-static GSList *no_reload_applets = NULL;
-
-static char *panel_applet_frame_get_background_string (PanelAppletFrame    *frame,
-						       PanelWidget         *panel,
-						       PanelBackgroundType  type);
-
-static void
-panel_applet_frame_update_flags (PanelAppletFrame *frame,
-				 guint             flags)
-{
-	gboolean major;
-	gboolean minor;
-	gboolean old_has_handle;
-
-	major = flags & APPLET_EXPAND_MAJOR;
-	minor = flags & APPLET_EXPAND_MINOR;
-
-	panel_widget_set_applet_expandable (
-		frame->priv->panel, GTK_WIDGET (frame), major, minor);
-
-	old_has_handle = frame->priv->has_handle;
-	frame->priv->has_handle = (flags & APPLET_HAS_HANDLE) != 0;
-
-	if (!old_has_handle && frame->priv->has_handle) {
-		/* we've added an handle, so we need to get the background for
-		 * it */
-		PanelBackground *background;
-
-		background = &frame->priv->panel->background;
-		panel_applet_frame_change_background (frame, background->type);
-	}
-}
-
-static void
-panel_applet_frame_update_size_hints (PanelAppletFrame *frame,
-				      gint             *size_hints,
-				      guint             n_elements)
-{
-	if (frame->priv->has_handle) {
-		gint extra_size = HANDLE_SIZE + 1;
-		gint i;
-
-		for (i = 0; i < n_elements; i++)
-			size_hints[i] += extra_size;
-	}
-
-	/* It takes the ownership of size-hints array */
-	panel_widget_set_applet_size_hints (frame->priv->panel,
-					    GTK_WIDGET (frame),
-					    size_hints,
-					    n_elements);
-}
-
-static void
-panel_applet_frame_get_flags_cb (PanelAppletContainer *container,
-				 GAsyncResult         *res,
-				 PanelAppletFrame     *frame)
-{
-	GVariant *value;
-	GError   *error = NULL;
-
-	value = panel_applet_container_child_get_finish (container, res, &error);
-	if (!value) {
-		g_warning ("%s\n", error->message);
-		g_error_free (error);
-		return;
-	}
-
-	panel_applet_frame_update_flags (frame, g_variant_get_uint32 (value));
-	g_variant_unref (value);
-}
-
-static void
-panel_applet_frame_get_size_hints_cb (PanelAppletContainer *container,
-				      GAsyncResult         *res,
-				      PanelAppletFrame     *frame)
-{
-	GVariant   *value;
-	const gint *sz;
-	gint       *size_hints = NULL;
-	gsize       n_elements;
-	GError     *error = NULL;
-
-	value = panel_applet_container_child_get_finish (container, res, &error);
-	if (!value) {
-		g_warning ("%s\n", error->message);
-		g_error_free (error);
-		return;
-	}
-
-	sz = g_variant_get_fixed_array (value, &n_elements, sizeof (gint32));
-	if (n_elements > 0) {
-		size_hints = g_new (gint32, n_elements);
-		memcpy (size_hints, sz, n_elements * sizeof (gint32));
-	}
-	panel_applet_frame_update_size_hints (frame, size_hints, n_elements);
-	g_variant_unref (value);
-}
-
-static void
-panel_applet_frame_flags_changed (PanelAppletContainer *container,
-				  const gchar          *prop_name,
-				  GVariant             *value,
-				  PanelAppletFrame     *frame)
-{
-	panel_applet_frame_update_flags (frame, g_variant_get_uint32 (value));
-}
-
-static void
-panel_applet_frame_size_hints_changed (PanelAppletContainer *container,
-				       const gchar          *prop_name,
-				       GVariant             *value,
-				       PanelAppletFrame     *frame)
-{
-	const gint *sz;
-	gint       *size_hints = NULL;
-	gsize       n_elements;
-
-	sz = g_variant_get_fixed_array (value, &n_elements, sizeof (gint32));
-	if (n_elements > 0) {
-		size_hints = g_new (gint32, n_elements);
-		memcpy (size_hints, sz, n_elements * sizeof (gint32));
-	}
-	panel_applet_frame_update_size_hints (frame, size_hints, n_elements);
-}
-
-static void
-panel_applet_frame_init_properties (PanelAppletFrame *frame)
-{
-	PanelAppletContainer *container = PANEL_APPLET_CONTAINER (frame);
-
-	panel_applet_container_child_get (container, "flags", NULL,
-					  (GAsyncReadyCallback)panel_applet_frame_get_flags_cb,
-					  frame);
-	panel_applet_container_child_get (container, "size-hints", NULL,
-					  (GAsyncReadyCallback)panel_applet_frame_get_size_hints_cb,
-					  frame);
-	g_signal_connect (container, "child-property-changed::flags",
-			  G_CALLBACK (panel_applet_frame_flags_changed),
-			  frame);
-	g_signal_connect (container, "child-property-changed::size-hints",
-			  G_CALLBACK (panel_applet_frame_size_hints_changed),
-			  frame);
-}
-
-void
-panel_applet_frame_sync_menu_state (PanelAppletFrame *frame)
-{
-	PanelWidget *panel_widget;
-	gboolean     locked_down;
-	gboolean     locked;
-	gboolean     lockable;
-	gboolean     movable;
-	gboolean     removable;
-
-	panel_widget = PANEL_WIDGET (GTK_WIDGET (frame)->parent);
-
-	lockable = panel_applet_lockable (frame->priv->applet_info);
-	movable = panel_applet_can_freely_move (frame->priv->applet_info);
-	removable = panel_profile_id_lists_are_writable ();
-
-	locked = panel_widget_get_applet_locked (panel_widget, GTK_WIDGET (frame));
-	locked_down = panel_lockdown_get_locked_down ();
-
-	panel_applet_container_child_set (PANEL_APPLET_CONTAINER (frame),
-					  "locked", g_variant_new_boolean (lockable && locked),
-					  NULL, NULL, NULL);
-	panel_applet_container_child_set (PANEL_APPLET_CONTAINER (frame),
-					  "locked-down", g_variant_new_boolean (locked_down),
-					  NULL, NULL, NULL);
-}
-
-enum {
-	LOADING_FAILED_RESPONSE_DONT_DELETE,
-	LOADING_FAILED_RESPONSE_DELETE
 };
 
 static void
-panel_applet_frame_loading_failed_response (GtkWidget *dialog,
-					    guint      response,
-					    char      *id)
-{
-	gtk_widget_destroy (dialog);
-
-	if (response == LOADING_FAILED_RESPONSE_DELETE &&
-	    !panel_lockdown_get_locked_down () &&
-	    panel_profile_id_lists_are_writable ()) {
-		GSList *item;
-
-		item = g_slist_find_custom (no_reload_applets, id,
-					    (GCompareFunc) strcmp);
-		if (item) {
-			g_free (item->data);
-			no_reload_applets = g_slist_delete_link (no_reload_applets,
-								 item);
-		}
-
-		panel_profile_remove_from_list (PANEL_GCONF_APPLETS, id);
-	}
-
-	g_free (id);
-}
-
-static void
-panel_applet_frame_loading_failed (PanelAppletFrame  *frame,
-				   const char        *id)
-{
-	GtkWidget *dialog;
-	char      *problem_txt;
-	gboolean   locked_down;
-
-	no_reload_applets = g_slist_prepend (no_reload_applets,
-					     g_strdup (id));
-
-	locked_down = panel_lockdown_get_locked_down ();
-
-	problem_txt = g_strdup_printf (_("The panel encountered a problem "
-					 "while loading \"%s\"."),
-				       frame->priv->iid);
-
-	dialog = gtk_message_dialog_new (NULL, 0,
-					 locked_down ? GTK_MESSAGE_INFO : GTK_MESSAGE_WARNING,
-					 GTK_BUTTONS_NONE,
-					 "%s", problem_txt);
-	g_free (problem_txt);
-
-	if (locked_down) {
-		gtk_dialog_add_buttons (GTK_DIALOG (dialog),
-					GTK_STOCK_OK, LOADING_FAILED_RESPONSE_DONT_DELETE,
-					NULL);
-	} else {
-		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-					_("Do you want to delete the applet "
-					  "from your configuration?"));
-		gtk_dialog_add_buttons (GTK_DIALOG (dialog),
-					PANEL_STOCK_DONT_DELETE, LOADING_FAILED_RESPONSE_DONT_DELETE,
-					GTK_STOCK_DELETE, LOADING_FAILED_RESPONSE_DELETE,
-					NULL);
-	}
-
-	gtk_dialog_set_default_response (GTK_DIALOG (dialog),
-					 LOADING_FAILED_RESPONSE_DONT_DELETE);
-
-	gtk_window_set_screen (GTK_WINDOW (dialog),
-			       gtk_window_get_screen (GTK_WINDOW (frame->priv->panel->toplevel)));
-
-	g_signal_connect (dialog, "response",
-			  G_CALLBACK (panel_applet_frame_loading_failed_response),
-			  g_strdup (id));
-
-	panel_widget_register_open_dialog (frame->priv->panel, dialog);
-	gtk_window_set_urgency_hint (GTK_WINDOW (dialog), TRUE);
-	/* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=165132 */
-	gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
-
-	gtk_widget_show_all (dialog);
-
-	g_free (frame->priv->iid);
-	frame->priv->iid = NULL;
-
-	gtk_widget_destroy (GTK_WIDGET (frame));
-}
-
-static guint
-get_panel_applet_orient (PanelOrientation orientation)
-{
-	/* For some reason libpanel-applet and panel use
-	 * a different logic for orientation, so we need
-	 * to convert it. We should fix this.
-	 */
-	switch (orientation) {
-	case PANEL_ORIENTATION_TOP:
-		return 1;
-	case PANEL_ORIENTATION_BOTTOM:
-		return 0;
-	case PANEL_ORIENTATION_LEFT:
-		return 3;
-	case PANEL_ORIENTATION_RIGHT:
-		return 2;
-	default:
-		g_assert_not_reached ();
-		break;
-	}
-}
-
-static void
-panel_applet_frame_activated (PanelAppletContainer       *container,
-			      GAsyncResult               *res,
-			      PanelAppletFrameActivating *frame_act)
-{
-	PanelAppletFrame   *frame = PANEL_APPLET_FRAME (container);
-	GtkWidget          *widget = NULL;
-	AppletInfo         *info;
-	GError             *error = NULL;
-
-	if (!panel_applet_container_add_finish (container, res, &error)) {
-		g_warning (G_STRLOC ": failed to load applet %s:\n%s",
-			   frame->priv->iid, error->message);
-		g_error_free (error);
-		goto error_out;
-	}
-
-	gtk_widget_show_all (GTK_WIDGET (frame));
-
-	info = panel_applet_register (GTK_WIDGET (frame), GTK_WIDGET (frame),
-				      NULL, frame->priv->panel,
-				      frame_act->locked, frame_act->position,
-				      frame_act->exactpos, PANEL_OBJECT_APPLET,
-				      frame_act->id);
-	frame->priv->applet_info = info;
-
-	panel_widget_set_applet_size_constrained (frame->priv->panel,
-						  GTK_WIDGET (frame), TRUE);
-
-	panel_applet_frame_sync_menu_state (frame);
-	panel_applet_frame_init_properties (frame);
-
-	panel_lockdown_notify_add (G_CALLBACK (panel_applet_frame_sync_menu_state),
-				   frame);
-
-	panel_applet_stop_loading (frame_act->id);
-	g_free (frame_act->id);
-	g_free (frame_act);
-
-	return;
-
-error_out:
-	panel_applet_frame_loading_failed (frame, frame_act->id);
-	if (widget)
-		g_object_unref (widget);
-	panel_applet_stop_loading (frame_act->id);
-	g_free (frame_act->id);
-	g_free (frame_act);
-}
-
-static void
-panel_applet_frame_load (const gchar *iid,
-			 PanelWidget *panel,
-			 gboolean     locked,
-			 int          position,
-			 gboolean     exactpos,
-			 const char  *id)
-{
-	PanelAppletFrame           *frame;
-	PanelAppletFrameActivating *frame_act;
-	GVariantBuilder             builder;
-	gchar                      *prefs_key;
-	gchar                      *background;
-	guint                       orient;
-
-	g_return_if_fail (iid != NULL);
-	g_return_if_fail (panel != NULL);
-	g_return_if_fail (id != NULL);
-
-	if (g_slist_find_custom (no_reload_applets, id,
-				 (GCompareFunc) strcmp))
-		return;
-
-	if (panel_lockdown_is_applet_disabled (iid))
-		return;
-
-	frame = g_object_new (PANEL_TYPE_APPLET_FRAME, NULL);
-	frame->priv->panel = panel;
-	frame->priv->iid   = g_strdup (iid);
-
-	if (!panel_applets_manager_factory_activate (iid)) {
-		panel_applet_frame_loading_failed (frame, id);
-		panel_applet_stop_loading (id);
-
-		return;
-	}
-
-	frame_act = g_new (PanelAppletFrameActivating, 1);
-	frame_act->locked   = locked;
-	frame_act->position = position;
-	frame_act->exactpos = exactpos;
-	frame_act->id       = g_strdup (id);
-
-	prefs_key = g_strdup_printf (PANEL_APPLET_PREFS_KEY, frame_act->id);
-	background = panel_applet_frame_get_background_string (frame,
-							       frame->priv->panel,
-							       frame->priv->panel->background.type);
-	orient = get_panel_applet_orient (panel_widget_get_applet_orientation (frame->priv->panel));
-
-	g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
-	g_variant_builder_add (&builder, "{sv}",
-			       "prefs-key",
-			       g_variant_new_string (prefs_key));
-	g_variant_builder_add (&builder, "{sv}",
-			       "orient",
-			       g_variant_new_uint32 (orient));
-	g_variant_builder_add (&builder, "{sv}",
-			       "size",
-			       g_variant_new_uint32 (frame->priv->panel->sz));
-	g_variant_builder_add (&builder, "{sv}",
-			       "locked",
-			       g_variant_new_boolean (locked));
-	g_variant_builder_add (&builder, "{sv}",
-			       "locked-down",
-			       g_variant_new_boolean (panel_lockdown_get_locked_down ()));
-	if (background) {
-		g_variant_builder_add (&builder, "{sv}",
-				       "background",
-				       g_variant_new_string (background));
-	}
-
-	panel_applet_container_add (PANEL_APPLET_CONTAINER (frame),
-				    frame->priv->iid, NULL,
-				    (GAsyncReadyCallback)panel_applet_frame_activated,
-				    frame_act,
-				    g_variant_builder_end (&builder));
-	g_free (prefs_key);
-	g_free (background);
-}
-
-void
-panel_applet_frame_load_from_gconf (PanelWidget *panel_widget,
-				    gboolean     locked,
-				    int          position,
-				    const char  *id)
-{
-	gchar *applet_iid;
-
-	g_return_if_fail (panel_widget != NULL);
-	g_return_if_fail (id != NULL);
-
-	applet_iid = panel_compatiblity_get_applet_iid (id);
-	if (!applet_iid)
-		return;
-
-	panel_applet_frame_load (applet_iid, panel_widget,
-				 locked, position, TRUE, id);
-
-	g_free (applet_iid);
-}
-
-void
-panel_applet_frame_create (PanelToplevel *toplevel,
-			   int            position,
-			   const char    *iid)
-{
-	GConfClient *client;
-	const char  *key;
-	char        *id;
-
-	g_return_if_fail (iid != NULL);
-
-	client =  panel_gconf_get_client ();
-
-	id = panel_profile_prepare_object (PANEL_OBJECT_APPLET, toplevel, position, FALSE);
-
-	key = panel_gconf_full_key (PANEL_GCONF_APPLETS, id, "applet_iid");
-	gconf_client_set_string (client, key, iid, NULL);
-
-	panel_profile_add_to_list (PANEL_GCONF_APPLETS, id);
-
-	g_free (id);
-}
-
-static void
-change_orientation_cb (PanelAppletContainer *container,
-		       GAsyncResult         *res)
-{
-	GError   *error = NULL;
-
-	if (!panel_applet_container_child_set_finish (container, res, &error)) {
-		g_warning ("%s\n", error->message);
-		g_error_free (error);
-
-		return;
-	}
-
-	gtk_widget_queue_resize (GTK_WIDGET (container));
-}
-
-void
-panel_applet_frame_change_orientation (PanelAppletFrame *frame,
-				       PanelOrientation  orientation)
-{
-	if (orientation == frame->priv->orientation)
-		return;
-
-	frame->priv->orientation = orientation;
-	panel_applet_container_child_set (PANEL_APPLET_CONTAINER (frame),
-					  "orient",
-					  g_variant_new_uint32 (get_panel_applet_orient (orientation)),
-					  NULL,
-					  (GAsyncReadyCallback)change_orientation_cb,
-					  NULL);
-}
-
-void
-panel_applet_frame_change_size (PanelAppletFrame *frame,
-				guint             size)
-{
-	panel_applet_container_child_set (PANEL_APPLET_CONTAINER (frame),
-					  "size", g_variant_new_uint32 (size),
-					  NULL, NULL, NULL);
-}
-
-static char *
-panel_applet_frame_get_background_string (PanelAppletFrame    *frame,
-					  PanelWidget         *panel,
-					  PanelBackgroundType  type)
-{
-	int x;
-	int y;
-
-	x = GTK_WIDGET (frame)->allocation.x;
-	y = GTK_WIDGET (frame)->allocation.y;
-
-	if (frame->priv->has_handle) {
-		switch (frame->priv->orientation) {
-		case PANEL_ORIENTATION_TOP:
-		case PANEL_ORIENTATION_BOTTOM:
-			if (gtk_widget_get_direction (GTK_WIDGET (frame)) !=
-			    GTK_TEXT_DIR_RTL)
-				x += frame->priv->handle_rect.width;
-			break;
-		case PANEL_ORIENTATION_LEFT:
-		case PANEL_ORIENTATION_RIGHT:
-			y += frame->priv->handle_rect.height;
-			break;
-		default:
-			g_assert_not_reached ();
-			break;
-		}
-	}
-
-	return panel_background_make_string (&panel->background, x, y);
-}
-
-static void
-container_child_background_set (GObject      *source_object,
-				GAsyncResult *res,
-				gpointer      user_data)
-{
-	PanelAppletContainer *container = PANEL_APPLET_CONTAINER (source_object);
-	PanelAppletFrame     *frame = PANEL_APPLET_FRAME (source_object);
-
-	panel_applet_container_child_set_finish (container, res, NULL);
-
-	if (frame->priv->bg_cancellable)
-		g_object_unref (frame->priv->bg_cancellable);
-	frame->priv->bg_cancellable = NULL;
-}
-
-void
-panel_applet_frame_change_background (PanelAppletFrame    *frame,
-				      PanelBackgroundType  type)
-{
-	char *bg_str;
-
-	g_return_if_fail (PANEL_IS_APPLET_FRAME (frame));
-	g_return_if_fail (PANEL_IS_WIDGET (GTK_WIDGET (frame)->parent));
-
-	if (frame->priv->has_handle) {
-		PanelBackground *background;
-
-		background = &PANEL_WIDGET (GTK_WIDGET (frame)->parent)->background;
-		panel_background_change_background_on_widget (background,
-							      GTK_WIDGET (frame));
-	}
-
-	bg_str = panel_applet_frame_get_background_string (
-			frame, PANEL_WIDGET (GTK_WIDGET (frame)->parent), type);
-
-	if (bg_str != NULL) {
-		if (frame->priv->bg_cancellable)
-			g_cancellable_cancel (frame->priv->bg_cancellable);
-		frame->priv->bg_cancellable = g_cancellable_new ();
-
-		panel_applet_container_child_set (PANEL_APPLET_CONTAINER (frame),
-						  "background",
-						  g_variant_new_string (bg_str),
-						  frame->priv->bg_cancellable,
-						  container_child_background_set,
-						  NULL);
-		g_free (bg_str);
-	}
-}
-
-static void
-panel_applet_frame_finalize (GObject *object)
-{
-	PanelAppletFrame *frame = PANEL_APPLET_FRAME (object);
-
-	panel_applets_manager_factory_deactivate (frame->priv->iid);
-
-	panel_lockdown_notify_remove (G_CALLBACK (panel_applet_frame_sync_menu_state),
-				      frame);
-
-	g_free (frame->priv->iid);
-	frame->priv->iid = NULL;
-
-        G_OBJECT_CLASS (panel_applet_frame_parent_class)->finalize (object);
-}
-
-static void
 panel_applet_frame_paint (GtkWidget    *widget,
 			  GdkRectangle *area)
 {
@@ -732,7 +139,6 @@ panel_applet_frame_expose (GtkWidget      *widget,
 		GTK_WIDGET_CLASS (panel_applet_frame_parent_class)->expose_event (widget, event);
 
 		panel_applet_frame_paint (widget, &event->area);
-
 	}
 
 	return FALSE;
@@ -771,10 +177,9 @@ panel_applet_frame_size_request (GtkWidget      *widget,
 	frame = PANEL_APPLET_FRAME (widget);
 	bin = GTK_BIN (widget);
 
-	if (!frame->priv->has_handle) {
-		GTK_WIDGET_CLASS (panel_applet_frame_parent_class)->size_request (widget, requisition);
-		return;
-	}
+	/* This is a GtkBin subclass, so we have to implement size request
+	 * ourselves in all cases, without relying on the parent class
+	 * implementation */
   
 	requisition->width = 0;
 	requisition->height = 0;
@@ -786,6 +191,9 @@ panel_applet_frame_size_request (GtkWidget      *widget,
 		requisition->height = child_requisition.height;
 	}
 
+	if (!frame->priv->has_handle)
+		return;
+
 	requisition->width += GTK_CONTAINER (widget)->border_width;
 	requisition->height += GTK_CONTAINER (widget)->border_width;
 
@@ -821,9 +229,14 @@ panel_applet_frame_size_allocate (GtkWidget     *widget,
 	frame = PANEL_APPLET_FRAME (widget);
 	bin = GTK_BIN (widget);
 
+	/* This is a GtkBin subclass, so we have to implement size allocation
+	 * ourselves in all cases, without relying on the parent class
+	 * implementation */
+
 	if (!frame->priv->has_handle) {
-		GTK_WIDGET_CLASS (panel_applet_frame_parent_class)->size_allocate (widget,
-								allocation);
+		if (bin->child && gtk_widget_get_visible (bin->child))
+			gtk_widget_size_allocate (bin->child, allocation);
+
 		panel_applet_frame_update_background_size (frame,
 							   &old_allocation,
 							   allocation);
@@ -947,14 +360,12 @@ panel_applet_frame_button_changed (GtkWidget      *widget,
 	case 3:
 		if (event->type == GDK_BUTTON_PRESS ||
 		    event->type == GDK_2BUTTON_PRESS) {
-			PanelAppletContainer *container;
-
-			container = PANEL_APPLET_CONTAINER (frame);
 			gdk_pointer_ungrab (GDK_CURRENT_TIME);
-			panel_applet_container_child_popup_menu (container,
-								 event->button,
-								 event->time,
-								 NULL, NULL, NULL);
+
+			PANEL_APPLET_FRAME_GET_CLASS (frame)->popup_menu (frame,
+									  event->button,
+									  event->time);
+
 			handled = TRUE;
 		} else if (event->type == GDK_BUTTON_RELEASE)
 			handled = TRUE;
@@ -967,6 +378,255 @@ panel_applet_frame_button_changed (GtkWidget      *widget,
 }
 
 static void
+panel_applet_frame_finalize (GObject *object)
+{
+	PanelAppletFrame *frame = PANEL_APPLET_FRAME (object);
+
+	panel_applets_manager_factory_deactivate (frame->priv->iid);
+
+	panel_lockdown_notify_remove (G_CALLBACK (panel_applet_frame_sync_menu_state),
+				      frame);
+
+	g_free (frame->priv->iid);
+	frame->priv->iid = NULL;
+
+        G_OBJECT_CLASS (panel_applet_frame_parent_class)->finalize (object);
+}
+
+static void
+panel_applet_frame_class_init (PanelAppletFrameClass *klass)
+{
+	GObjectClass   *gobject_class = (GObjectClass *) klass;
+	GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
+
+	gobject_class->finalize = panel_applet_frame_finalize;
+
+	widget_class->expose_event         = panel_applet_frame_expose;
+	widget_class->size_request         = panel_applet_frame_size_request;
+	widget_class->size_allocate        = panel_applet_frame_size_allocate;
+	widget_class->button_press_event   = panel_applet_frame_button_changed;
+	widget_class->button_release_event = panel_applet_frame_button_changed;
+
+	g_type_class_add_private (klass, sizeof (PanelAppletFramePrivate));
+}
+
+static void
+panel_applet_frame_init (PanelAppletFrame *frame)
+{
+	frame->priv = PANEL_APPLET_FRAME_GET_PRIVATE (frame);
+
+	frame->priv->panel       = NULL;
+	frame->priv->orientation = PANEL_ORIENTATION_TOP;
+	frame->priv->applet_info = NULL;
+	frame->priv->has_handle  = FALSE;
+}
+
+static void
+panel_applet_frame_init_properties (PanelAppletFrame *frame)
+{
+	PANEL_APPLET_FRAME_GET_CLASS (frame)->init_properties (frame);
+}
+
+void
+panel_applet_frame_sync_menu_state (PanelAppletFrame *frame)
+{
+	PanelWidget *panel_widget;
+	gboolean     locked_down;
+	gboolean     locked;
+	gboolean     lockable;
+	gboolean     movable;
+	gboolean     removable;
+
+	panel_widget = PANEL_WIDGET (GTK_WIDGET (frame)->parent);
+
+	movable = panel_applet_can_freely_move (frame->priv->applet_info);
+	removable = panel_profile_id_lists_are_writable ();
+	lockable = panel_applet_lockable (frame->priv->applet_info);
+
+	locked = panel_widget_get_applet_locked (panel_widget, GTK_WIDGET (frame));
+	locked_down = panel_lockdown_get_locked_down ();
+
+	PANEL_APPLET_FRAME_GET_CLASS (frame)->sync_menu_state (frame, movable, removable, lockable, locked, locked_down);
+}
+
+void
+panel_applet_frame_change_orientation (PanelAppletFrame *frame,
+				       PanelOrientation  orientation)
+{
+	if (orientation == frame->priv->orientation)
+		return;
+
+	frame->priv->orientation = orientation;
+	PANEL_APPLET_FRAME_GET_CLASS (frame)->change_orientation (frame, orientation);
+}
+
+void
+panel_applet_frame_change_size (PanelAppletFrame *frame,
+				guint             size)
+{
+	PANEL_APPLET_FRAME_GET_CLASS (frame)->change_size (frame, size);
+}
+
+void
+panel_applet_frame_change_background (PanelAppletFrame    *frame,
+				      PanelBackgroundType  type)
+{
+	g_return_if_fail (PANEL_IS_APPLET_FRAME (frame));
+	g_return_if_fail (PANEL_IS_WIDGET (GTK_WIDGET (frame)->parent));
+
+	if (frame->priv->has_handle) {
+		PanelBackground *background;
+
+		background = &PANEL_WIDGET (GTK_WIDGET (frame)->parent)->background;
+		panel_background_change_background_on_widget (background,
+							      GTK_WIDGET (frame));
+	}
+
+	PANEL_APPLET_FRAME_GET_CLASS (frame)->change_background (frame, type);
+}
+
+void
+panel_applet_frame_set_panel (PanelAppletFrame *frame,
+			      PanelWidget      *panel)
+{
+	g_return_if_fail (PANEL_IS_APPLET_FRAME (frame));
+	g_return_if_fail (PANEL_IS_WIDGET (panel));
+
+	frame->priv->panel = panel;
+}
+
+void
+_panel_applet_frame_set_iid (PanelAppletFrame *frame,
+			     const gchar      *iid)
+{
+	if (frame->priv->iid)
+		g_free (frame->priv->iid);
+	frame->priv->iid = g_strdup (iid);
+}
+
+void
+_panel_applet_frame_activated (PanelAppletFrame           *frame,
+			       PanelAppletFrameActivating *frame_act,
+			       GError                     *error)
+{
+	AppletInfo *info;
+
+	g_assert (frame->priv->iid != NULL);
+
+	if (error != NULL) {
+		g_warning ("Failed to load applet %s:\n%s",
+			   frame->priv->iid, error->message);
+		g_error_free (error);
+
+		panel_applet_frame_loading_failed (frame->priv->iid,
+						   frame_act->panel,
+						   frame_act->id);
+		panel_applet_frame_activating_free (frame_act);
+		gtk_widget_destroy (GTK_WIDGET (frame));
+
+		return;
+	}
+
+	frame->priv->panel = frame_act->panel;
+	gtk_widget_show_all (GTK_WIDGET (frame));
+
+	info = panel_applet_register (GTK_WIDGET (frame), GTK_WIDGET (frame),
+				      NULL, frame->priv->panel,
+				      frame_act->locked, frame_act->position,
+				      frame_act->exactpos, PANEL_OBJECT_APPLET,
+				      frame_act->id);
+	frame->priv->applet_info = info;
+
+	panel_widget_set_applet_size_constrained (frame->priv->panel,
+						  GTK_WIDGET (frame), TRUE);
+
+	panel_applet_frame_sync_menu_state (frame);
+	panel_applet_frame_init_properties (frame);
+
+	panel_lockdown_notify_add (G_CALLBACK (panel_applet_frame_sync_menu_state),
+				   frame);
+
+	panel_applet_stop_loading (frame_act->id);
+	panel_applet_frame_activating_free (frame_act);
+}
+
+void
+_panel_applet_frame_update_flags (PanelAppletFrame *frame,
+				  gboolean          major,
+				  gboolean          minor,
+				  gboolean          has_handle)
+{
+	gboolean old_has_handle;
+
+	panel_widget_set_applet_expandable (
+		frame->priv->panel, GTK_WIDGET (frame), major, minor);
+
+	old_has_handle = frame->priv->has_handle;
+	frame->priv->has_handle = has_handle;
+
+	if (!old_has_handle && frame->priv->has_handle) {
+		/* we've added an handle, so we need to get the background for
+		 * it */
+		PanelBackground *background;
+
+		background = &frame->priv->panel->background;
+		panel_applet_frame_change_background (frame, background->type);
+	}
+}
+
+void
+_panel_applet_frame_update_size_hints (PanelAppletFrame *frame,
+				       gint             *size_hints,
+				       guint             n_elements)
+{
+	if (frame->priv->has_handle) {
+		gint extra_size = HANDLE_SIZE + 1;
+		gint i;
+
+		for (i = 0; i < n_elements; i++)
+			size_hints[i] += extra_size;
+	}
+
+	/* It takes the ownership of size-hints array */
+	panel_widget_set_applet_size_hints (frame->priv->panel,
+					    GTK_WIDGET (frame),
+					    size_hints,
+					    n_elements);
+}
+
+char *
+_panel_applet_frame_get_background_string (PanelAppletFrame    *frame,
+					   PanelWidget         *panel,
+					   PanelBackgroundType  type)
+{
+	int x;
+	int y;
+
+	x = GTK_WIDGET (frame)->allocation.x;
+	y = GTK_WIDGET (frame)->allocation.y;
+
+	if (frame->priv->has_handle) {
+		switch (frame->priv->orientation) {
+		case PANEL_ORIENTATION_TOP:
+		case PANEL_ORIENTATION_BOTTOM:
+			if (gtk_widget_get_direction (GTK_WIDGET (frame)) !=
+			    GTK_TEXT_DIR_RTL)
+				x += frame->priv->handle_rect.width;
+			break;
+		case PANEL_ORIENTATION_LEFT:
+		case PANEL_ORIENTATION_RIGHT:
+			y += frame->priv->handle_rect.height;
+			break;
+		default:
+			g_assert_not_reached ();
+			break;
+		}
+	}
+
+	return panel_background_make_string (&panel->background, x, y);
+}
+
+static void
 panel_applet_frame_reload_response (GtkWidget        *dialog,
 				    int               response,
 				    PanelAppletFrame *frame)
@@ -1018,14 +678,13 @@ panel_applet_frame_reload_response (GtkWidget        *dialog,
 	gtk_widget_destroy (dialog);
 }
 
-static void
-panel_applet_frame_applet_broken (PanelAppletContainer *container)
+void
+_panel_applet_frame_applet_broken (PanelAppletFrame *frame)
 {
-	PanelAppletFrame *frame = PANEL_APPLET_FRAME (container);
-	GtkWidget        *dialog;
-	GdkScreen        *screen;
-	const char       *applet_name = NULL;
-	char             *dialog_txt;
+	GtkWidget  *dialog;
+	GdkScreen  *screen;
+	const char *applet_name = NULL;
+	char       *dialog_txt;
 
 	screen = gtk_widget_get_screen (GTK_WIDGET (frame));
 
@@ -1077,10 +736,24 @@ panel_applet_frame_applet_broken (PanelAppletContainer *container)
 	g_free (dialog_txt);
 }
 
-static void
-panel_applet_frame_applet_move (PanelAppletContainer *container)
+void
+_panel_applet_frame_applet_remove (PanelAppletFrame *frame)
 {
-	GtkWidget *widget = GTK_WIDGET (container);
+	AppletInfo *info;
+
+	if (!frame->priv->applet_info)
+		return;
+
+	info = frame->priv->applet_info;
+	frame->priv->applet_info = NULL;
+
+	panel_profile_delete_object (info);
+}
+
+void
+_panel_applet_frame_applet_move (PanelAppletFrame *frame)
+{
+	GtkWidget *widget = GTK_WIDGET (frame);
 
 	if (!PANEL_IS_WIDGET (widget->parent))
 		return;
@@ -1091,74 +764,221 @@ panel_applet_frame_applet_move (PanelAppletContainer *container)
 					GDK_CURRENT_TIME);
 }
 
-static void
-panel_applet_frame_applet_remove (PanelAppletContainer *container)
+void
+_panel_applet_frame_applet_lock (PanelAppletFrame *frame,
+				 gboolean          locked)
 {
-	PanelAppletFrame *frame = PANEL_APPLET_FRAME (container);
-	AppletInfo       *info;
+	PanelWidget *panel_widget = PANEL_WIDGET (GTK_WIDGET (frame)->parent);
 
-	if (!frame->priv->applet_info)
+	if (panel_widget_get_applet_locked (panel_widget, GTK_WIDGET (frame)) == locked)
 		return;
 
-	info = frame->priv->applet_info;
-	frame->priv->applet_info = NULL;
+	panel_applet_toggle_locked (frame->priv->applet_info);
+}
 
-	panel_profile_delete_object (info);
+/* Generic methods */
+
+static GSList *no_reload_applets = NULL;
+
+enum {
+	LOADING_FAILED_RESPONSE_DONT_DELETE,
+	LOADING_FAILED_RESPONSE_DELETE
+};
+
+static void
+panel_applet_frame_activating_free (PanelAppletFrameActivating *frame_act)
+{
+	g_free (frame_act->id);
+	g_slice_free (PanelAppletFrameActivating, frame_act);
+}
+
+PanelOrientation
+panel_applet_frame_activating_get_orientation (PanelAppletFrameActivating *frame_act)
+{
+	return panel_widget_get_applet_orientation (frame_act->panel);
+}
+
+guint32
+panel_applet_frame_activating_get_size (PanelAppletFrameActivating *frame_act)
+{
+	return frame_act->panel->sz;
+}
+
+gboolean
+panel_applet_frame_activating_get_locked (PanelAppletFrameActivating *frame_act)
+{
+	return frame_act->locked;
+}
+
+gboolean
+panel_applet_frame_activating_get_locked_down (PanelAppletFrameActivating *frame_act)
+{
+	return panel_lockdown_get_locked_down ();
+}
+
+gchar *
+panel_applet_frame_activating_get_conf_path (PanelAppletFrameActivating *frame_act)
+{
+	return g_strdup_printf (PANEL_APPLET_PREFS_KEY, frame_act->id);
 }
 
 static void
-panel_applet_frame_applet_lock (PanelAppletContainer *container,
-				gboolean              locked)
+panel_applet_frame_loading_failed_response (GtkWidget *dialog,
+					    guint      response,
+					    char      *id)
 {
-	PanelAppletFrame *frame = PANEL_APPLET_FRAME (container);
-	PanelWidget      *panel_widget = PANEL_WIDGET (GTK_WIDGET (frame)->parent);
+	gtk_widget_destroy (dialog);
 
-	if (panel_widget_get_applet_locked (panel_widget, GTK_WIDGET (frame)) == locked)
-		return;
+	if (response == LOADING_FAILED_RESPONSE_DELETE &&
+	    !panel_lockdown_get_locked_down () &&
+	    panel_profile_id_lists_are_writable ()) {
+		GSList *item;
 
-	panel_applet_toggle_locked (frame->priv->applet_info);
+		item = g_slist_find_custom (no_reload_applets, id,
+					    (GCompareFunc) strcmp);
+		if (item) {
+			g_free (item->data);
+			no_reload_applets = g_slist_delete_link (no_reload_applets,
+								 item);
+		}
+
+		panel_profile_remove_from_list (PANEL_GCONF_APPLETS, id);
+	}
+
+	g_free (id);
 }
 
 static void
-panel_applet_frame_class_init (PanelAppletFrameClass *klass)
+panel_applet_frame_loading_failed (const char  *iid,
+				   PanelWidget *panel,
+				   const char  *id)
 {
-	GObjectClass   *gobject_class = (GObjectClass *) klass;
-	GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
-	PanelAppletContainerClass *container_class = (PanelAppletContainerClass *) klass;
+	GtkWidget *dialog;
+	char      *problem_txt;
+	gboolean   locked_down;
 
-	gobject_class->finalize = panel_applet_frame_finalize;
+	panel_applet_stop_loading (id);
+	no_reload_applets = g_slist_prepend (no_reload_applets,
+					     g_strdup (id));
 
-	widget_class->expose_event         = panel_applet_frame_expose;
-	widget_class->size_request         = panel_applet_frame_size_request;
-	widget_class->size_allocate        = panel_applet_frame_size_allocate;
-	widget_class->button_press_event   = panel_applet_frame_button_changed;
-	widget_class->button_release_event = panel_applet_frame_button_changed;
+	locked_down = panel_lockdown_get_locked_down ();
 
-	container_class->applet_broken = panel_applet_frame_applet_broken;
-	container_class->applet_move = panel_applet_frame_applet_move;
-	container_class->applet_remove = panel_applet_frame_applet_remove;
-	container_class->applet_lock = panel_applet_frame_applet_lock;
+	problem_txt = g_strdup_printf (_("The panel encountered a problem "
+					 "while loading \"%s\"."),
+				       iid);
 
-	g_type_class_add_private (klass, sizeof (PanelAppletFramePrivate));
+	dialog = gtk_message_dialog_new (NULL, 0,
+					 locked_down ? GTK_MESSAGE_INFO : GTK_MESSAGE_WARNING,
+					 GTK_BUTTONS_NONE,
+					 "%s", problem_txt);
+	g_free (problem_txt);
+
+	if (locked_down) {
+		gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+					GTK_STOCK_OK, LOADING_FAILED_RESPONSE_DONT_DELETE,
+					NULL);
+	} else {
+		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+					_("Do you want to delete the applet "
+					  "from your configuration?"));
+		gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+					PANEL_STOCK_DONT_DELETE, LOADING_FAILED_RESPONSE_DONT_DELETE,
+					GTK_STOCK_DELETE, LOADING_FAILED_RESPONSE_DELETE,
+					NULL);
+	}
+
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+					 LOADING_FAILED_RESPONSE_DONT_DELETE);
+
+	gtk_window_set_screen (GTK_WINDOW (dialog),
+			       gtk_window_get_screen (GTK_WINDOW (panel->toplevel)));
+
+	g_signal_connect (dialog, "response",
+			  G_CALLBACK (panel_applet_frame_loading_failed_response),
+			  g_strdup (id));
+
+	panel_widget_register_open_dialog (panel, dialog);
+	gtk_window_set_urgency_hint (GTK_WINDOW (dialog), TRUE);
+	/* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=165132 */
+	gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
+
+	gtk_widget_show_all (dialog);
 }
 
 static void
-panel_applet_frame_init (PanelAppletFrame *frame)
+panel_applet_frame_load (const gchar *iid,
+			 PanelWidget *panel,
+			 gboolean     locked,
+			 int          position,
+			 gboolean     exactpos,
+			 const char  *id)
 {
-	frame->priv = PANEL_APPLET_FRAME_GET_PRIVATE (frame);
+	PanelAppletFrameActivating *frame_act;
 
-	frame->priv->panel       = NULL;
-	frame->priv->orientation = PANEL_ORIENTATION_TOP;
-	frame->priv->applet_info = NULL;
-	frame->priv->has_handle  = FALSE;
+	g_return_if_fail (iid != NULL);
+	g_return_if_fail (panel != NULL);
+	g_return_if_fail (id != NULL);
+
+	if (g_slist_find_custom (no_reload_applets, id,
+				 (GCompareFunc) strcmp))
+		return;
+
+	if (panel_lockdown_is_applet_disabled (iid))
+		return;
+
+	frame_act = g_slice_new0 (PanelAppletFrameActivating);
+	frame_act->locked   = locked;
+	frame_act->panel    = panel;
+	frame_act->position = position;
+	frame_act->exactpos = exactpos;
+	frame_act->id       = g_strdup (id);
+
+	if (!panel_applets_manager_load_applet (iid, frame_act)) {
+		panel_applet_frame_loading_failed (iid, panel, id);
+		panel_applet_frame_activating_free (frame_act);
+	}
 }
 
 void
-panel_applet_frame_set_panel (PanelAppletFrame *frame,
-			      PanelWidget      *panel)
+panel_applet_frame_load_from_gconf (PanelWidget *panel_widget,
+				    gboolean     locked,
+				    int          position,
+				    const char  *id)
 {
-	g_return_if_fail (PANEL_IS_APPLET_FRAME (frame));
-	g_return_if_fail (PANEL_IS_WIDGET (panel));
+	gchar *applet_iid;
 
-	frame->priv->panel = panel;
+	g_return_if_fail (panel_widget != NULL);
+	g_return_if_fail (id != NULL);
+
+	applet_iid = panel_compatiblity_get_applet_iid (id);
+	if (!applet_iid)
+		return;
+
+	panel_applet_frame_load (applet_iid, panel_widget,
+				 locked, position, TRUE, id);
+
+	g_free (applet_iid);
+}
+
+void
+panel_applet_frame_create (PanelToplevel *toplevel,
+			   int            position,
+			   const char    *iid)
+{
+	GConfClient *client;
+	const char  *key;
+	char        *id;
+
+	g_return_if_fail (iid != NULL);
+
+	client =  panel_gconf_get_client ();
+
+	id = panel_profile_prepare_object (PANEL_OBJECT_APPLET, toplevel, position, FALSE);
+
+	key = panel_gconf_full_key (PANEL_GCONF_APPLETS, id, "applet_iid");
+	gconf_client_set_string (client, key, iid, NULL);
+
+	panel_profile_add_to_list (PANEL_GCONF_APPLETS, id);
+
+	g_free (id);
 }
diff --git a/gnome-panel/panel-applet-frame.h b/gnome-panel/panel-applet-frame.h
index 7dc635c..fbb780d 100644
--- a/gnome-panel/panel-applet-frame.h
+++ b/gnome-panel/panel-applet-frame.h
@@ -27,7 +27,6 @@
 
 #include <gtk/gtk.h>
 
-#include "panel-applet-container.h"
 #include "panel-widget.h"
 #include "applet.h"
 
@@ -44,14 +43,36 @@ typedef struct _PanelAppletFrame        PanelAppletFrame;
 typedef struct _PanelAppletFrameClass   PanelAppletFrameClass;
 typedef struct _PanelAppletFramePrivate PanelAppletFramePrivate;
 
-struct _PanelAppletFrame{
-	PanelAppletContainer container;
+struct _PanelAppletFrameClass {
+        GtkBinClass parent_class;
 
-        PanelAppletFramePrivate  *priv;
+	void     (*init_properties)       (PanelAppletFrame    *frame);
+
+	void     (*sync_menu_state)       (PanelAppletFrame    *frame,
+					   gboolean             movable,
+					   gboolean             removable,
+					   gboolean             lockable,
+					   gboolean             locked,
+					   gboolean             locked_down);
+
+	void     (*popup_menu)            (PanelAppletFrame    *frame,
+					   guint                button,
+					   guint32              timestamp);
+
+	void     (*change_orientation)    (PanelAppletFrame    *frame,
+					   PanelOrientation     orientation);
+
+	void     (*change_size)           (PanelAppletFrame    *frame,
+					   guint                size);
+
+	void     (*change_background)     (PanelAppletFrame    *frame,
+					   PanelBackgroundType  type);
 };
 
-struct _PanelAppletFrameClass {
-        PanelAppletContainerClass container_class;
+struct _PanelAppletFrame {
+	GtkBin parent;
+
+        PanelAppletFramePrivate  *priv;
 };
 
 GType panel_applet_frame_get_type           (void) G_GNUC_CONST;
@@ -60,6 +81,11 @@ void  panel_applet_frame_create             (PanelToplevel       *toplevel,
 					     int                  position,
 					     const char          *iid);
 
+void  panel_applet_frame_load_from_gconf    (PanelWidget         *panel_widget,
+					     gboolean             locked,
+					     int                  position,
+					     const char          *id);
+
 void  panel_applet_frame_sync_menu_state    (PanelAppletFrame    *frame);
 
 void  panel_applet_frame_change_orientation (PanelAppletFrame    *frame,
@@ -71,14 +97,46 @@ void  panel_applet_frame_change_size        (PanelAppletFrame    *frame,
 void  panel_applet_frame_change_background  (PanelAppletFrame    *frame,
 					     PanelBackgroundType  type);
 
-void  panel_applet_frame_load_from_gconf    (PanelWidget         *panel_widget,
-					     gboolean             locked,
-					     int                  position,
-					     const char          *id);
-
 void  panel_applet_frame_set_panel          (PanelAppletFrame    *frame,
 					     PanelWidget         *panel);
 
+
+/* For module implementations only */
+
+typedef struct _PanelAppletFrameActivating        PanelAppletFrameActivating;
+
+PanelOrientation  panel_applet_frame_activating_get_orientation (PanelAppletFrameActivating *frame_act);
+guint32           panel_applet_frame_activating_get_size        (PanelAppletFrameActivating *frame_act);
+gboolean          panel_applet_frame_activating_get_locked      (PanelAppletFrameActivating *frame_act);
+gboolean          panel_applet_frame_activating_get_locked_down (PanelAppletFrameActivating *frame_act);
+gchar            *panel_applet_frame_activating_get_conf_path   (PanelAppletFrameActivating *frame_act);
+
+void  _panel_applet_frame_set_iid               (PanelAppletFrame           *frame,
+						 const gchar                *iid);
+
+void  _panel_applet_frame_activated             (PanelAppletFrame           *frame,
+						 PanelAppletFrameActivating *frame_act,
+						 GError                     *error);
+
+void  _panel_applet_frame_update_flags          (PanelAppletFrame *frame,
+						 gboolean          major,
+						 gboolean          minor,
+						 gboolean          has_handle);
+
+void  _panel_applet_frame_update_size_hints     (PanelAppletFrame *frame,
+						 gint             *size_hints,
+						 guint             n_elements);
+
+char *_panel_applet_frame_get_background_string (PanelAppletFrame    *frame,
+						 PanelWidget         *panel,
+						 PanelBackgroundType  type);
+
+void  _panel_applet_frame_applet_broken         (PanelAppletFrame *frame);
+
+void  _panel_applet_frame_applet_remove         (PanelAppletFrame *frame);
+void  _panel_applet_frame_applet_move           (PanelAppletFrame *frame);
+void  _panel_applet_frame_applet_lock           (PanelAppletFrame *frame,
+						 gboolean          locked);
 G_END_DECLS
 
 #endif /* __PANEL_APPLET_FRAME_H__ */
diff --git a/gnome-panel/panel-applet-info.c b/gnome-panel/panel-applet-info.c
new file mode 100644
index 0000000..4c376d9
--- /dev/null
+++ b/gnome-panel/panel-applet-info.c
@@ -0,0 +1,111 @@
+/*
+ * panel-applet-info.c
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <carlosgc gnome org>
+ * Copyright (C) 2010 Vincent Untz <vuntz gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "panel-applet-info.h"
+
+struct _PanelAppletInfo {
+	gchar  *iid;
+
+	gchar  *name;
+	gchar  *comment;
+	gchar  *icon;
+
+	gchar **old_ids;
+};
+
+PanelAppletInfo *
+panel_applet_info_new (const gchar  *iid,
+		       const gchar  *name,
+		       const gchar  *comment,
+		       const gchar  *icon,
+		       const gchar **old_ids)
+{
+	PanelAppletInfo *info;
+	int len;
+
+	info = g_slice_new0 (PanelAppletInfo);
+
+	info->iid = g_strdup (iid);
+	info->name = g_strdup (name);
+	info->comment = g_strdup (comment);
+	info->icon = g_strdup (icon);
+
+	/* Bonobo compatibility */
+	len = g_strv_length ((gchar **) old_ids);
+	if (len > 0) {
+		int i;
+
+		info->old_ids = g_new0 (gchar *, len + 1);
+
+		for (i = 0; i < len; i++)
+			info->old_ids[i] = g_strdup (old_ids[i]);
+	}
+
+	return info;
+}
+
+void
+panel_applet_info_free (PanelAppletInfo *info)
+{
+	if (!info)
+		return;
+
+	g_free (info->iid);
+	g_free (info->name);
+	g_free (info->comment);
+	g_free (info->icon);
+	g_strfreev (info->old_ids);
+
+	g_slice_free (PanelAppletInfo, info);
+}
+
+const gchar *
+panel_applet_info_get_iid (PanelAppletInfo *info)
+{
+	return info->iid;
+}
+
+const gchar *
+panel_applet_info_get_name (PanelAppletInfo *info)
+{
+	return info->name;
+}
+
+const gchar *
+panel_applet_info_get_description (PanelAppletInfo *info)
+{
+	return info->comment;
+}
+
+const gchar *
+panel_applet_info_get_icon (PanelAppletInfo *info)
+{
+	return info->icon;
+}
+
+const gchar * const *
+panel_applet_info_get_old_ids (PanelAppletInfo *info)
+{
+	return (const gchar * const *) info->old_ids;
+}
diff --git a/gnome-panel/panel-applet-info.h b/gnome-panel/panel-applet-info.h
new file mode 100644
index 0000000..6e1a7a7
--- /dev/null
+++ b/gnome-panel/panel-applet-info.h
@@ -0,0 +1,47 @@
+/*
+ * panel-applet-info.h
+ *
+ * Copyright (C) 2010 Carlos Garcia Campos <carlosgc gnome org>
+ * Copyright (C) 2010 Vincent Untz <vuntz gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __PANEL_APPLET_INFO_H__
+#define __PANEL_APPLET_INFO_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PanelAppletInfo PanelAppletInfo;
+
+PanelAppletInfo *panel_applet_info_new                             (const gchar  *iid,
+								    const gchar  *name,
+								    const gchar  *comment,
+								    const gchar  *icon,
+								    const gchar **old_ids);
+void             panel_applet_info_free                            (PanelAppletInfo *info);
+
+const gchar     *panel_applet_info_get_iid                         (PanelAppletInfo *info);
+const gchar     *panel_applet_info_get_name                        (PanelAppletInfo *info);
+const gchar     *panel_applet_info_get_description                 (PanelAppletInfo *info);
+const gchar     *panel_applet_info_get_icon                        (PanelAppletInfo *info);
+const gchar * const *panel_applet_info_get_old_ids                 (PanelAppletInfo *info);
+
+G_END_DECLS
+
+#endif /* __PANEL_APPLET_INFO_H__ */
diff --git a/gnome-panel/panel-applets-manager.c b/gnome-panel/panel-applets-manager.c
index 9a0dfd8..b4760ed 100644
--- a/gnome-panel/panel-applets-manager.c
+++ b/gnome-panel/panel-applets-manager.c
@@ -1,7 +1,8 @@
 /*
- * panel-applets-manmanger.c
+ * panel-applets-manager.c
  *
  * Copyright (C) 2010 Carlos Garcia Campos <carlosgc gnome org>
+ * Copyright (C) 2010 Vincent Untz <vuntz gnome org>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -22,522 +23,138 @@
 #include <config.h>
 
 #include <gio/gio.h>
-#include <gmodule.h>
-#include <string.h>
 
-#include "panel-applets-manager.h"
-
-static GHashTable *applet_factories;
-static GList      *monitors = NULL;
-
-typedef gint (* ActivateAppletFunc) (void);
-
-typedef struct _PanelAppletFactoryInfo {
-	gchar             *id;
-	gchar             *location;
-	gboolean           in_process;
-	GModule           *module;
-	ActivateAppletFunc activate_applet;
-	guint              n_applets;
-
-	gchar             *srcdir;
-
-	GList             *applet_list;
-	gboolean           has_old_ids;
-} PanelAppletFactoryInfo;
-
-struct _PanelAppletInfo {
-	gchar  *iid;
+#include <libpanel-util/panel-cleanup.h>
 
-	gchar  *name;
-	gchar  *comment;
-	gchar  *icon;
+#include "panel-modules.h"
 
-	gchar **old_ids;
-};
+#include "panel-applets-manager.h"
 
-#define PANEL_APPLET_FACTORY_GROUP "Applet Factory"
-#define PANEL_APPLETS_EXTENSION    ".panel-applet"
+G_DEFINE_ABSTRACT_TYPE (PanelAppletsManager, panel_applets_manager, G_TYPE_OBJECT)
 
 static void
-panel_applet_info_free (PanelAppletInfo *info)
+panel_applets_manager_init (PanelAppletsManager *manager)
 {
-	if (!info)
-		return;
-
-	g_free (info->iid);
-	g_free (info->name);
-	g_free (info->comment);
-	g_free (info->icon);
-	g_strfreev (info->old_ids);
-
-	g_slice_free (PanelAppletInfo, info);
 }
 
 static void
-panel_applet_factory_info_free (PanelAppletFactoryInfo *info)
-{
-	if (!info)
-		return;
-
-	g_free (info->id);
-	g_free (info->location);
-	g_list_foreach (info->applet_list,
-			(GFunc)panel_applet_info_free,
-			NULL);
-	g_list_free (info->applet_list);
-	info->applet_list = NULL;
-	g_free (info->srcdir);
-
-	g_slice_free (PanelAppletFactoryInfo, info);
-}
-
-static PanelAppletInfo *
-_panel_applets_manager_get_applet_info (GKeyFile    *applet_file,
-					const gchar *group,
-					const gchar *factory_id)
+panel_applets_manager_class_init (PanelAppletsManagerClass *class)
 {
-	PanelAppletInfo *info;
-
-	info = g_slice_new0 (PanelAppletInfo);
-
-	info->iid = g_strdup_printf ("%s::%s", factory_id, group);
-	info->name = g_key_file_get_locale_string (applet_file, group,
-						   "Name", NULL, NULL);
-	info->comment = g_key_file_get_locale_string (applet_file, group,
-						      "Description", NULL, NULL);
-	info->icon = g_key_file_get_string (applet_file, group, "Icon", NULL);
-
-	/* Bonobo compatibility */
-	info->old_ids = g_key_file_get_string_list (applet_file, group,
-						    "BonoboId", NULL, NULL);
-
-	return info;
 }
 
-static PanelAppletFactoryInfo *
-panel_applets_manager_get_applet_factory_info_from_file (const gchar *filename)
-{
-	PanelAppletFactoryInfo *info;
-	GKeyFile               *applet_file;
-	gchar                 **groups;
-	gsize                   n_groups;
-	gint                    i;
-	GError                 *error = NULL;
-
-	applet_file = g_key_file_new ();
-	if (!g_key_file_load_from_file (applet_file, filename, G_KEY_FILE_NONE, &error)) {
-		g_warning ("Error opening panel applet file %s: %s",
-			   filename, error->message);
-		g_error_free (error);
-		g_key_file_free (applet_file);
-
-		return NULL;
-	}
-
-	info = g_slice_new0 (PanelAppletFactoryInfo);
-	info->id = g_key_file_get_string (applet_file, PANEL_APPLET_FACTORY_GROUP, "Id", NULL);
-	if (!info->id) {
-		g_warning ("Bad panel applet file %s: Could not find 'Id' in group '%s'",
-			   filename, PANEL_APPLET_FACTORY_GROUP);
-		panel_applet_factory_info_free (info);
-		g_key_file_free (applet_file);
-
-		return NULL;
-	}
-
-	info->in_process = g_key_file_get_boolean (applet_file, PANEL_APPLET_FACTORY_GROUP,
-						   "InProcess", NULL);
-	if (info->in_process) {
-		info->location = g_key_file_get_string (applet_file, PANEL_APPLET_FACTORY_GROUP,
-							"Location", NULL);
-		if (!info->location) {
-			g_warning ("Bad panel applet file %s: In-process applet without 'Location'",
-				   filename);
-			panel_applet_factory_info_free (info);
-			g_key_file_free (applet_file);
-
-			return NULL;
-		}
-	}
-
-	info->has_old_ids = FALSE;
-
-	groups = g_key_file_get_groups (applet_file, &n_groups);
-	for (i = 0; i < n_groups; i++) {
-		PanelAppletInfo *ainfo;
-
-		if (strcmp (groups[i], PANEL_APPLET_FACTORY_GROUP) == 0)
-			continue;
-
-		ainfo = _panel_applets_manager_get_applet_info (applet_file,
-								groups[i], info->id);
-		if (ainfo->old_ids)
-			info->has_old_ids = TRUE;
-
-		info->applet_list = g_list_prepend (info->applet_list, ainfo);
-	}
-	g_strfreev (groups);
-
-	g_key_file_free (applet_file);
-
-	if (!info->applet_list) {
-		panel_applet_factory_info_free (info);
-		return NULL;
-	}
+/* Generic methods */
 
-	info->srcdir = g_path_get_dirname (filename);
+static GSList *panel_applets_managers = NULL;
 
-	return info;
-}
-
-static GSList *
-panel_applets_manager_get_applets_dirs (void)
+static void
+_panel_applets_manager_cleanup (gpointer data)
 {
-	const gchar *dir = NULL;
-	gchar      **paths;
-	guint        i;
-	GSList      *retval = NULL;
-
-	dir = g_getenv ("PANEL_APPLETS_DIR");
-	if (!dir || strcmp (dir, "") == 0) {
-		return g_slist_prepend (NULL, g_strdup (PANEL_APPLETS_DIR));
-	}
-
-	paths = g_strsplit (dir, ":", 0);
-	for (i = 0; paths[i]; i++) {
-		if (g_slist_find_custom (retval, paths[i], (GCompareFunc)strcmp))
-			continue;
-		retval = g_slist_prepend (retval, g_strdup (paths[i]));
-	}
-	g_strfreev (paths);
-
-	return g_slist_reverse (retval);
+	g_slist_foreach (panel_applets_managers, (GFunc) g_object_unref, NULL);
+	g_slist_free (panel_applets_managers);
+	panel_applets_managers = NULL;
 }
 
 static void
-applets_directory_changed (GFileMonitor     *monitor,
-			   GFile            *file,
-			   GFile            *other_file,
-			   GFileMonitorEvent event_type,
-			   gpointer          user_data)
+_panel_applets_managers_ensure_loaded (void)
 {
-	switch (event_type) {
-	case G_FILE_MONITOR_EVENT_CHANGED:
-	case G_FILE_MONITOR_EVENT_CREATED: {
-		PanelAppletFactoryInfo *info;
-		PanelAppletFactoryInfo *old_info;
-		gchar                  *filename;
-		GSList                 *dirs, *d;
-
-		filename = g_file_get_path (file);
-		if (!g_str_has_suffix (filename, PANEL_APPLETS_EXTENSION)) {
-			g_free (filename);
-			return;
-		}
-
-		info = panel_applets_manager_get_applet_factory_info_from_file (filename);
-		g_free (filename);
-
-		if (!info)
-			return;
-
-		old_info = g_hash_table_lookup (applet_factories, info->id);
-		if (!old_info) {
-			/* New applet, just insert it */
-			g_hash_table_insert (applet_factories, g_strdup (info->id), info);
-			return;
-		}
-
-		/* Make sure we don't update an applet
-		 * that has changed in another source dir
-		 * unless it takes precedence over the
-		 * current one
-		 */
-		if (strcmp (info->srcdir, old_info->srcdir) == 0) {
-			g_hash_table_insert (applet_factories, g_strdup (info->id), info);
-			return;
-		}
-
-		dirs = panel_applets_manager_get_applets_dirs ();
-
-		for (d = dirs; d; d = g_slist_next (d)) {
-			gchar *path = (gchar *)d->data;
-
-			if (strcmp (path, old_info->srcdir) == 0) {
-				panel_applet_factory_info_free (info);
-				break;
-			} else if (strcmp (path, info->srcdir) == 0) {
-				g_hash_table_insert (applet_factories, g_strdup (info->id), info);
-				break;
-			}
-		}
+	GIOExtensionPoint *point;
+	GList             *extensions, *l;
 
-		g_slist_foreach (dirs, (GFunc)g_free, NULL);
-		g_slist_free (dirs);
-	}
-		break;
-	default:
-		/* Ignore any other change */
-		break;
-	}
-}
-
-static gboolean
-_panel_applets_manager_init (void)
-{
-	GSList      *dirs, *d;
-	GDir        *dir;
-	const gchar *dirent;
-	GError      *error = NULL;
-	gboolean     retval = FALSE;
-
-	dirs = panel_applets_manager_get_applets_dirs ();
-	for (d = dirs; d; d = g_slist_next (d)) {
-		GFileMonitor *monitor;
-		GFile        *dir_file;
-		gchar        *path = (gchar *)d->data;
-
-		dir = g_dir_open (path, 0, &error);
-		if (!dir) {
-			g_warning ("%s", error->message);
-			g_error_free (error);
-			g_free (path);
+	if (panel_applets_managers != NULL)
+		return;
 
-			continue;
-		}
-
-		/* Monitor dir */
-		dir_file = g_file_new_for_path (path);
-		monitor = g_file_monitor_directory (dir_file,
-						    G_FILE_MONITOR_NONE,
-						    NULL, NULL);
-		if (monitor) {
-			g_signal_connect (monitor, "changed",
-					  G_CALLBACK (applets_directory_changed),
-					  NULL);
-			monitors = g_list_prepend (monitors, monitor);
-		}
-		g_object_unref (dir_file);
-
-		while ((dirent = g_dir_read_name (dir))) {
-			PanelAppletFactoryInfo *info;
-			gchar                  *file;
-
-			if (!g_str_has_suffix (dirent, PANEL_APPLETS_EXTENSION))
-				continue;
-
-			file = g_build_filename (path, dirent, NULL);
-			info = panel_applets_manager_get_applet_factory_info_from_file (file);
-			g_free (file);
-
-			if (!info)
-				continue;
-
-			if (g_hash_table_lookup (applet_factories, info->id)) {
-				panel_applet_factory_info_free (info);
-				continue;
-			}
-
-			g_hash_table_insert (applet_factories, g_strdup (info->id), info);
-			retval = TRUE;
-		}
-
-		g_dir_close (dir);
-		g_free (path);
-	}
+	panel_cleanup_register (PANEL_CLEAN_FUNC (_panel_applets_manager_cleanup), NULL);
 
-	g_slist_free (dirs);
+	panel_modules_ensure_loaded ();
 
-	return retval;
-}
+	point = g_io_extension_point_lookup (PANEL_APPLETS_MANAGER_EXTENSION_POINT_NAME);
 
-gboolean
-panel_applets_manager_init (void)
-{
-	if (applet_factories)
-		return TRUE;
+	extensions = g_io_extension_point_get_extensions (point);
 
-	applet_factories = g_hash_table_new_full (g_str_hash,
-						  g_str_equal,
-						  (GDestroyNotify)g_free,
-						  (GDestroyNotify)panel_applet_factory_info_free);
+	if (extensions == NULL)
+		g_error ("No PanelAppletsManager implementations exist.");
 
-	return _panel_applets_manager_init ();
-}
+	for (l = extensions; l != NULL; l = l->next) {
+		GIOExtension *extension;
+		GType         type;
+		GObject      *object;
 
-void
-panel_applets_manager_shutdown (void)
-{
-	if (monitors) {
-		g_list_foreach (monitors, (GFunc)g_object_unref, NULL);
-		g_list_free (monitors);
-		monitors = NULL;
+		extension = l->data;
+		type = g_io_extension_get_type (extension);
+		object = g_object_new (type, NULL);
+		panel_applets_managers = g_slist_prepend (panel_applets_managers, object);
 	}
 
-	if (applet_factories) {
-		g_hash_table_destroy (applet_factories);
-		applet_factories = NULL;
-	}
+	panel_applets_managers = g_slist_reverse (panel_applets_managers);
 }
 
 GList *
 panel_applets_manager_get_applets (void)
 {
-	GHashTableIter iter;
-	gpointer       key, value;
-	GList         *retval = NULL;
+	GSList *l;
+	GList  *retval = NULL;
 
-	g_hash_table_iter_init (&iter, applet_factories);
-	while (g_hash_table_iter_next (&iter, &key, &value)) {
-		PanelAppletFactoryInfo *info;
+	_panel_applets_managers_ensure_loaded ();
 
-		info = (PanelAppletFactoryInfo *)value;
-		retval = g_list_concat (retval, g_list_copy (info->applet_list));
+	for (l = panel_applets_managers; l != NULL; l = l->next) {
+		GList *applets;
+		PanelAppletsManager *manager = PANEL_APPLETS_MANAGER (l->data);
+
+		applets = PANEL_APPLETS_MANAGER_GET_CLASS (manager)->get_applets (manager);
+		if (applets)
+			retval = g_list_concat (retval, applets);
 	}
 
 	return retval;
 }
 
-static PanelAppletFactoryInfo *
-get_applet_factory_info (const gchar *iid)
-{
-	PanelAppletFactoryInfo *info;
-	const gchar            *sp;
-	gchar                  *factory_id;
-
-	if (!applet_factories)
-		return NULL;
-
-	sp = g_strrstr (iid, "::");
-	if (!sp)
-		return NULL;
-
-	factory_id = g_strndup (iid, strlen (iid) - strlen (sp));
-	info = g_hash_table_lookup (applet_factories, factory_id);
-	g_free (factory_id);
-
-	return info;
-}
-
 gboolean
 panel_applets_manager_factory_activate (const gchar *iid)
 {
-	PanelAppletFactoryInfo *info;
-	ActivateAppletFunc      activate_applet;
-
-	info = get_applet_factory_info (iid);
-	if (!info)
-		return FALSE;
-
-	/* Out process applets are activated
-	 * by the session bus
-	 */
-	if (!info->in_process)
-		return TRUE;
-
-	if (info->module) {
-		if (info->n_applets == 0) {
-			if (info->activate_applet () != 0) {
-				g_warning ("Failed to reactivate factory %s\n", iid);
-				return FALSE;
-			}
-		}
-		info->n_applets++;
-
-		return TRUE;
-	}
-
-	info->module = g_module_open (info->location, G_MODULE_BIND_LAZY);
-	if (!info->module) {
-		/* FIXME: use a GError? */
-		g_warning ("Failed to load applet %s: %s\n",
-			   iid, g_module_error ());
-		return FALSE;
-	}
-
-	if (!g_module_symbol (info->module, "_panel_applet_shlib_factory", (gpointer *)&activate_applet)) {
-		/* FIXME: use a GError? */
-		g_warning ("Failed to load applet %s: %s\n",
-			   iid, g_module_error ());
-		g_module_close (info->module);
-		info->module = NULL;
+	GSList *l;
 
-		return FALSE;
-	}
+	_panel_applets_managers_ensure_loaded ();
 
-	/* Activate the applet */
-	if (activate_applet () != 0) {
-		/* FIXME: use a GError? */
-		g_warning ("Failed to load applet %s\n", iid);
-		g_module_close (info->module);
-		info->module = NULL;
+	for (l = panel_applets_managers; l != NULL; l = l->next) {
+		PanelAppletsManager *manager = PANEL_APPLETS_MANAGER (l->data);
 
-		return FALSE;
+		if (PANEL_APPLETS_MANAGER_GET_CLASS (manager)->factory_activate (manager, iid))
+			return TRUE;
 	}
-	info->activate_applet = activate_applet;
-
-	info->n_applets = 1;
 
-	return TRUE;
+	return FALSE;
 }
 
 void
 panel_applets_manager_factory_deactivate (const gchar *iid)
 {
-	PanelAppletFactoryInfo *info;
+	GSList *l;
 
-	info = get_applet_factory_info (iid);
-	if (!info)
-		return;
+	_panel_applets_managers_ensure_loaded ();
 
-	/* Out process applets are deactivated
-	 * by the session bus
-	 */
-	if (!info->in_process)
-		return;
+	for (l = panel_applets_managers; l != NULL; l = l->next) {
+		PanelAppletsManager *manager = PANEL_APPLETS_MANAGER (l->data);
 
-	if (!info->module)
-		return;
-
-	if (--info->n_applets == 0) {
-		/* FIXME: we should close the module here,
-		 * however applet types are registered static
-		 */
-#if 0
-		g_module_close (info->module);
-		info->module = NULL;
-#endif
+		if (PANEL_APPLETS_MANAGER_GET_CLASS (manager)->factory_deactivate (manager, iid))
+			return;
 	}
 }
 
-gboolean
-panel_applets_manager_is_factory_in_process (const gchar *iid)
-{
-	PanelAppletFactoryInfo *info;
-
-	info = get_applet_factory_info (iid);
-	if (!info)
-		return FALSE;
-
-	return info->in_process;
-}
-
 PanelAppletInfo *
 panel_applets_manager_get_applet_info (const gchar *iid)
 {
-	PanelAppletFactoryInfo *info;
-	GList                  *l;
+	GSList *l;
+	PanelAppletInfo *retval = NULL;
+
+	_panel_applets_managers_ensure_loaded ();
 
-	info = get_applet_factory_info (iid);
-	if (!info)
-		return NULL;
+	for (l = panel_applets_managers; l != NULL; l = l->next) {
+		PanelAppletsManager *manager = PANEL_APPLETS_MANAGER (l->data);
 
-	for (l = info->applet_list; l; l = g_list_next (l)) {
-		PanelAppletInfo *ainfo = (PanelAppletInfo *)l->data;
+		retval = PANEL_APPLETS_MANAGER_GET_CLASS (manager)->get_applet_info (manager, iid);
 
-		if (strcmp (ainfo->iid, iid) == 0)
-			return ainfo;
+		if (retval != NULL)
+			return retval;
 	}
 
 	return NULL;
@@ -546,60 +163,39 @@ panel_applets_manager_get_applet_info (const gchar *iid)
 PanelAppletInfo *
 panel_applets_manager_get_applet_info_from_old_id (const gchar *iid)
 {
-	GHashTableIter iter;
-	gpointer       key, value;
+	GSList *l;
+	PanelAppletInfo *retval = NULL;
 
-	g_hash_table_iter_init (&iter, applet_factories);
-	while (g_hash_table_iter_next (&iter, &key, &value)) {
-		PanelAppletFactoryInfo *info;
-		GList                  *l;
+	_panel_applets_managers_ensure_loaded ();
 
-		info = (PanelAppletFactoryInfo *)value;
-		if (!info->has_old_ids)
-			continue;
-
-		for (l = info->applet_list; l; l = g_list_next (l)) {
-			PanelAppletInfo *ainfo;
-			gint             i = 0;
+	for (l = panel_applets_managers; l != NULL; l = l->next) {
+		PanelAppletsManager *manager = PANEL_APPLETS_MANAGER (l->data);
 
-			ainfo = (PanelAppletInfo *)l->data;
+		retval = PANEL_APPLETS_MANAGER_GET_CLASS (manager)->get_applet_info_from_old_id (manager, iid);
 
-			if (!ainfo->old_ids)
-				continue;
-
-			while (ainfo->old_ids[i]) {
-				if (strcmp (ainfo->old_ids[i], iid) == 0)
-					return ainfo;
-				i++;
-			}
-		}
+		if (retval != NULL)
+			return retval;
 	}
 
 	return NULL;
 }
 
-const gchar *
-panel_applet_info_get_iid (PanelAppletInfo *info)
+gboolean
+panel_applets_manager_load_applet (const gchar                *iid,
+				   PanelAppletFrameActivating *frame_act)
 {
-	return info->iid;
-}
+	GSList *l;
 
-const gchar *
-panel_applet_info_get_name (PanelAppletInfo *info)
-{
-	return info->name;
-}
+	_panel_applets_managers_ensure_loaded ();
 
-const gchar *
-panel_applet_info_get_description (PanelAppletInfo *info)
-{
-	return info->comment;
-}
+	for (l = panel_applets_managers; l != NULL; l = l->next) {
+		PanelAppletsManager *manager = PANEL_APPLETS_MANAGER (l->data);
 
-const gchar *
-panel_applet_info_get_icon (PanelAppletInfo *info)
-{
-	return info->icon;
-}
+		if (!PANEL_APPLETS_MANAGER_GET_CLASS (manager)->get_applet_info (manager, iid))
+			continue;
 
+		return PANEL_APPLETS_MANAGER_GET_CLASS (manager)->load_applet (manager, iid, frame_act);
+	}
 
+	return FALSE;
+}
diff --git a/gnome-panel/panel-applets-manager.h b/gnome-panel/panel-applets-manager.h
index 235a18c..f36c1c3 100644
--- a/gnome-panel/panel-applets-manager.h
+++ b/gnome-panel/panel-applets-manager.h
@@ -1,7 +1,8 @@
 /*
- * panel-applets-manmanger.h
+ * panel-applets-manager.h
  *
  * Copyright (C) 2010 Carlos Garcia Campos <carlosgc gnome org>
+ * Copyright (C) 2010 Vincent Untz <vuntz gnome org>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -22,27 +23,67 @@
 #ifndef __PANEL_APPLETS_MANAGER_H__
 #define __PANEL_APPLETS_MANAGER_H__
 
-#include <glib.h>
+#include <glib-object.h>
+
+#include "panel-applet-frame.h"
+#include "panel-applet-info.h"
 
 G_BEGIN_DECLS
 
-typedef struct _PanelAppletInfo PanelAppletInfo;
+#define PANEL_TYPE_APPLETS_MANAGER		(panel_applets_manager_get_type ())
+#define PANEL_APPLETS_MANAGER(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_APPLETS_MANAGER, PanelAppletsManager))
+#define PANEL_APPLETS_MANAGER_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass), PANEL_TYPE_APPLETS_MANAGER, PanelAppletsManagerClass))
+#define PANEL_IS_APPLETS_MANAGER(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), PANEL_TYPE_APPLETS_MANAGER))
+#define PANEL_IS_APPLETS_MANAGER_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_APPLETS_MANAGER))
+#define PANEL_APPLETS_MANAGER_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), PANEL_TYPE_APPLETS_MANAGER, PanelAppletsManagerClass))
+
+/**
+ * PANEL_APPLETS_MANAGER_EXTENSION_POINT_NAME:
+ *
+ * Extension point for #PanelAppletsManager functionality.
+ **/
+#define PANEL_APPLETS_MANAGER_EXTENSION_POINT_NAME "panel-applets-manager"
+
+typedef struct _PanelAppletsManager		PanelAppletsManager;
+typedef struct _PanelAppletsManagerClass	PanelAppletsManagerClass;
+
+struct _PanelAppletsManagerClass {
+	GObjectClass parent_class;
+
+	GList *            (*get_applets)           (PanelAppletsManager  *manager);
+
+	gboolean           (*factory_activate)      (PanelAppletsManager  *manager,
+						     const gchar          *iid);
+	gboolean           (*factory_deactivate)    (PanelAppletsManager  *manager,
+						     const gchar          *iid);
+
+	PanelAppletInfo  * (*get_applet_info)       (PanelAppletsManager  *manager,
+						     const gchar          *iid);
+
+	PanelAppletInfo  * (*get_applet_info_from_old_id) (PanelAppletsManager  *manager,
+							   const gchar          *iid);
+
+	gboolean           (*load_applet)           (PanelAppletsManager         *manager,
+						     const gchar                 *iid,
+						     PanelAppletFrameActivating  *frame_act);
+};
+
+struct _PanelAppletsManager {
+	GObject parent;
+};
+
+GType             panel_applets_manager_get_type                    (void);
 
-gboolean         panel_applets_manager_init                        (void);
-void             panel_applets_manager_shutdown                    (void);
-GList           *panel_applets_manager_get_applets                 (void);
+GList            *panel_applets_manager_get_applets                 (void);
 
-gboolean         panel_applets_manager_factory_activate            (const gchar     *iid);
-void             panel_applets_manager_factory_deactivate          (const gchar     *iid);
+gboolean          panel_applets_manager_factory_activate            (const gchar     *iid);
+void              panel_applets_manager_factory_deactivate          (const gchar     *iid);
 
-gboolean         panel_applets_manager_is_factory_in_process       (const gchar     *iid);
-PanelAppletInfo *panel_applets_manager_get_applet_info             (const gchar     *iid);
-PanelAppletInfo *panel_applets_manager_get_applet_info_from_old_id (const gchar     *iid);
+PanelAppletInfo  *panel_applets_manager_get_applet_info             (const gchar     *iid);
+PanelAppletInfo  *panel_applets_manager_get_applet_info_from_old_id (const gchar     *iid);
 
-const gchar     *panel_applet_info_get_iid                         (PanelAppletInfo *info);
-const gchar     *panel_applet_info_get_name                        (PanelAppletInfo *info);
-const gchar     *panel_applet_info_get_description                 (PanelAppletInfo *info);
-const gchar     *panel_applet_info_get_icon                        (PanelAppletInfo *info);
+gboolean          panel_applets_manager_load_applet                 (const gchar                *iid,
+								     PanelAppletFrameActivating *frame_act);
 
 G_END_DECLS
 
diff --git a/gnome-panel/panel-modules.c b/gnome-panel/panel-modules.c
new file mode 100644
index 0000000..7719385
--- /dev/null
+++ b/gnome-panel/panel-modules.c
@@ -0,0 +1,78 @@
+/*
+ * panel-modules.c
+ *
+ * Copyright (C) 2010 Vincent Untz <vuntz gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Authors:
+ *      Vincent Untz <vuntz gnome org>
+ */
+
+#include <config.h>
+
+#include <gio/gio.h>
+
+#include <libpanel-applet-private/panel-applets-manager-dbus.h>
+
+#include "panel-applets-manager.h"
+
+#include "panel-modules.h"
+
+static void
+panel_modules_ensure_extension_points_registered (void)
+{
+	static gboolean registered_extensions = FALSE;
+	GIOExtensionPoint *ep;
+
+	if (!registered_extensions) {
+		registered_extensions = TRUE;
+
+		ep = g_io_extension_point_register (PANEL_APPLETS_MANAGER_EXTENSION_POINT_NAME);
+		g_io_extension_point_set_required_type (ep, PANEL_TYPE_APPLETS_MANAGER);
+	}
+ }
+
+void
+panel_modules_ensure_loaded (void)
+{
+	static gboolean loaded_dirs = FALSE;
+	const char *module_path;
+
+	panel_modules_ensure_extension_points_registered ();
+
+	if (!loaded_dirs) {
+		loaded_dirs = TRUE;
+
+		g_io_modules_scan_all_in_directory (PANEL_MODULES_DIR);
+
+		module_path = g_getenv ("GNOME_PANEL_EXTRA_MODULES");
+
+		if (module_path) {
+			gchar **paths;
+			int i;
+
+			paths = g_strsplit (module_path, ":", 0);
+
+			for (i = 0; paths[i] != NULL; i++)
+				g_io_modules_scan_all_in_directory (paths[i]);
+
+			g_strfreev (paths);
+		}
+
+		panel_applets_manager_dbus_get_type ();
+	}
+}
diff --git a/gnome-panel/panel-modules.h b/gnome-panel/panel-modules.h
new file mode 100644
index 0000000..02ddd04
--- /dev/null
+++ b/gnome-panel/panel-modules.h
@@ -0,0 +1,30 @@
+/*
+ * panel-modules.h
+ *
+ * Copyright (C) 2010 Vincent Untz <vuntz gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Authors:
+ *      Vincent Untz <vuntz gnome org>
+ */
+
+#ifndef __PANEL_MODULES_H__
+#define __PANEL_MODULES_H__
+
+void     panel_modules_ensure_loaded     (void);
+
+#endif /* __PANEL_MODULES_H__ */
diff --git a/gnome-panel/panel-test-applets.c b/gnome-panel/panel-test-applets.c
index 283e7dd..58b1a3a 100644
--- a/gnome-panel/panel-test-applets.c
+++ b/gnome-panel/panel-test-applets.c
@@ -12,8 +12,12 @@
 #include <gtk/gtk.h>
 #include <gconf/gconf.h>
 
-#include <gnome-panel/panel-applet-container.h>
-#include <gnome-panel/panel-applets-manager.h>
+#include <libpanel-util/panel-cleanup.h>
+
+#include <libpanel-applet-private/panel-applet-container.h>
+#include <libpanel-applet-private/panel-applets-manager-dbus.h>
+
+#include "panel-modules.h"
 
 G_GNUC_UNUSED void on_execute_button_clicked (GtkButton *button, gpointer dummy);
 
@@ -253,13 +257,14 @@ setup_combo (GtkWidget  *combo_box,
 static void
 setup_options (void)
 {
-	GList           *applet_list, *l;
-	int              i;
-	char            *prefs_dir;
-	char            *unique_key;
-	GtkListStore    *model;
-	GtkTreeIter      iter;
-	GtkCellRenderer *renderer;
+	PanelAppletsManager *manager;
+	GList               *applet_list, *l;
+	int                  i;
+	char                *prefs_dir;
+	char                *unique_key;
+	GtkListStore        *model;
+	GtkTreeIter          iter;
+	GtkCellRenderer     *renderer;
 
 	model = gtk_list_store_new (NUMBER_COLUMNS,
 				    G_TYPE_STRING,
@@ -268,7 +273,8 @@ setup_options (void)
 	gtk_combo_box_set_model (GTK_COMBO_BOX (applet_combo),
 				 GTK_TREE_MODEL (model));
 
-	applet_list = panel_applets_manager_get_applets ();
+	manager = g_object_new (PANEL_TYPE_APPLETS_MANAGER_DBUS, NULL);
+	applet_list = PANEL_APPLETS_MANAGER_GET_CLASS (manager)->get_applets (manager);
 	for (l = applet_list, i = 1; l; l = g_list_next (l), i++) {
 		PanelAppletInfo *info = (PanelAppletInfo *)l->data;
 
@@ -279,6 +285,7 @@ setup_options (void)
 				    -1);
 	}
 	g_list_free (applet_list);
+	g_object_unref (manager);
 
 	renderer = gtk_cell_renderer_text_new ();
 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (applet_combo),
@@ -325,18 +332,19 @@ main (int argc, char **argv)
 		return 1;
 	}
 
+	panel_modules_ensure_loaded ();
+
 	if (g_file_test ("../libpanel-applet", G_FILE_TEST_IS_DIR)) {
 		applets_dir = g_strdup_printf ("%s:../libpanel-applet", PANEL_APPLETS_DIR);
-		g_setenv ("PANEL_APPLETS_DIR", applets_dir, FALSE);
+		g_setenv ("GNOME_PANEL_APPLETS_DIR", applets_dir, FALSE);
 		g_free (applets_dir);
 	}
 
-	panel_applets_manager_init ();
-
 	if (cli_iid) {
 		load_applet_from_command_line ();
 		gtk_main ();
-		panel_applets_manager_shutdown ();
+		panel_cleanup_do ();
+
 		return 0;
 	}
 
@@ -349,7 +357,7 @@ main (int argc, char **argv)
 	if (error) {
 		g_warning ("Error loading \"%s\": %s", uifile, error->message);
 		g_error_free (error);
-		panel_applets_manager_shutdown ();
+		panel_cleanup_do ();
 
 		return 1;
 	}
@@ -374,7 +382,7 @@ main (int argc, char **argv)
 
 	gtk_main ();
 
-	panel_applets_manager_shutdown ();
+	panel_cleanup_do ();
 
 	return 0;
 }



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