diff --git a/libgnomekbd/Makefile.am b/libgnomekbd/Makefile.am
index 45f2376..8189f20 100644
--- a/libgnomekbd/Makefile.am
+++ b/libgnomekbd/Makefile.am
@@ -42,6 +42,7 @@ libgnomekbd_la_SOURCES = \
                          gkbd-util.c
 
 libgnomekbdui_la_SOURCES = \
+                         gkbd-configuration.c \
                          gkbd-indicator-config.c \
                          gkbd-indicator.c \
                          gkbd-status.c \
@@ -59,6 +60,7 @@ CLEANFILES = $(BUILT_SOURCES) $(schema_DATA)
 
 gnomekbdincdir = $(includedir)/libgnomekbd
 gnomekbdinc_HEADERS = \
+                      gkbd-configuration.h \
                       gkbd-desktop-config.h \
                       gkbd-keyboard-config.h \
                       gkbd-indicator.h \
diff --git a/libgnomekbd/gkbd-configuration.c b/libgnomekbd/gkbd-configuration.c
new file mode 100644
index 0000000..0171e2f
--- /dev/null
+++ b/libgnomekbd/gkbd-configuration.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2010 Canonical Ltd.
+ * 
+ * Authors: Jan Arne Petersen <jpetersen@openismus.com>
+ * 
+ * Based on gkbd-status.c by Sergey V. Udaltsov <svu@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <memory.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdkx.h>
+#include <glib/gi18n.h>
+
+#include <gkbd-configuration.h>
+
+#include <gkbd-desktop-config.h>
+#include <gkbd-indicator-config.h>
+
+struct _GkbdConfigurationPrivate {
+	XklEngine *engine;
+	XklConfigRegistry *registry;
+
+	GkbdDesktopConfig cfg;
+	GkbdIndicatorConfig ind_cfg;
+	GkbdKeyboardConfig kbd_cfg;
+
+	gchar **full_group_names;
+	gchar **short_group_names;
+
+	gulong state_changed_handler;
+	gulong config_changed_handler;
+};
+
+enum {
+	SIGNAL_CHANGED,
+	SIGNAL_GROUP_CHANGED,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+#define GKBD_CONFIGURATION_GET_PRIVATE(o) \
+	(G_TYPE_INSTANCE_GET_PRIVATE ((o), GKBD_TYPE_CONFIGURATION, GkbdConfigurationPrivate))
+
+G_DEFINE_TYPE (GkbdConfiguration, gkbd_configuration, G_TYPE_OBJECT)
+
+/* Should be called once for all widgets */
+static void
+gkbd_configuration_cfg_changed (GConfClient * client,
+				guint cnxn_id, GConfEntry * entry,
+				GkbdConfiguration * configuration)
+{
+	GkbdConfigurationPrivate *priv = configuration->priv;
+
+	xkl_debug (100,
+		   "General configuration changed in GConf - reiniting...\n");
+	gkbd_desktop_config_load_from_gconf (&priv->cfg);
+	gkbd_desktop_config_activate (&priv->cfg);
+
+	g_signal_emit (configuration,
+		       signals[SIGNAL_CHANGED], 0);
+}
+
+/* Should be called once for all widgets */
+static void
+gkbd_configuration_ind_cfg_changed (GConfClient * client,
+				    guint cnxn_id, GConfEntry * entry,
+				    GkbdConfiguration * configuration)
+{
+	GkbdConfigurationPrivate *priv = configuration->priv;
+	xkl_debug (100,
+		   "Applet configuration changed in GConf - reiniting...\n");
+	gkbd_indicator_config_load_from_gconf (&priv->ind_cfg);
+
+	gkbd_indicator_config_free_image_filenames (&priv->ind_cfg);
+	gkbd_indicator_config_load_image_filenames (&priv->ind_cfg,
+						    &priv->kbd_cfg);
+
+	gkbd_indicator_config_activate (&priv->ind_cfg);
+
+	g_signal_emit (configuration,
+		       signals[SIGNAL_CHANGED], 0);
+}
+
+static void
+gkbd_configuration_load_group_names (GkbdConfiguration * configuration,
+				     XklConfigRec * xklrec)
+{
+	GkbdConfigurationPrivate *priv = configuration->priv;
+
+	if (!gkbd_desktop_config_load_group_descriptions (&priv->cfg,
+							  priv->registry,
+							  (const char **) xklrec->layouts,
+							  (const char **) xklrec->variants,
+	     						  &priv->short_group_names,
+							  &priv->full_group_names)) {
+		/* We just populate no short names (remain NULL) - 
+		 * full names are going to be used anyway */
+		gint i, total_groups =
+		    xkl_engine_get_num_groups (priv->engine);
+		xkl_debug (150, "group descriptions loaded: %d!\n",
+			   total_groups);
+		priv->full_group_names =
+		    g_new0 (char *, total_groups + 1);
+
+		if (xkl_engine_get_features (priv->engine) &
+		    XKLF_MULTIPLE_LAYOUTS_SUPPORTED) {
+			GSList *lst = priv->kbd_cfg.layouts_variants;
+			for (i = 0; lst; lst = lst->next, i++) {
+				priv->full_group_names[i] =
+				    g_strdup ((char *) lst->data);
+			}
+		} else {
+			for (i = total_groups; --i >= 0;) {
+				priv->full_group_names[i] =
+				    g_strdup_printf ("Group %d", i);
+			}
+		}
+	}
+}
+
+/* Should be called once for all widgets */
+static void
+gkbd_configuration_kbd_cfg_callback (XklEngine *engine,
+				     GkbdConfiguration *configuration)
+{
+	GkbdConfigurationPrivate *priv = configuration->priv;
+	XklConfigRec *xklrec = xkl_config_rec_new ();
+	xkl_debug (100,
+		   "XKB configuration changed on X Server - reiniting...\n");
+
+	gkbd_keyboard_config_load_from_x_current (&priv->kbd_cfg,
+						  xklrec);
+
+	gkbd_indicator_config_free_image_filenames (&priv->ind_cfg);
+	gkbd_indicator_config_load_image_filenames (&priv->ind_cfg,
+						    &priv->kbd_cfg);
+
+	g_strfreev (priv->full_group_names);
+	priv->full_group_names = NULL;
+
+	g_strfreev (priv->short_group_names);
+	priv->short_group_names = NULL;
+
+	gkbd_configuration_load_group_names (configuration,
+				 	     xklrec);
+
+	g_signal_emit (configuration,
+		       signals[SIGNAL_CHANGED],
+		       0);
+
+	g_object_unref (G_OBJECT (xklrec));
+}
+
+/* Should be called once for all applets */
+static void
+gkbd_configuration_state_callback (XklEngine * engine,
+				   XklEngineStateChange changeType,
+			    	   gint group, gboolean restore,
+				   GkbdConfiguration * configuration)
+{
+	xkl_debug (150, "group is now %d, restore: %d\n", group, restore);
+
+	if (changeType == GROUP_CHANGED) {
+		g_signal_emit (configuration,
+			       signals[SIGNAL_GROUP_CHANGED], 0,
+			       group);
+	}
+}
+
+static void
+gkbd_configuration_init (GkbdConfiguration *configuration)
+{
+	GkbdConfigurationPrivate *priv;
+	GConfClient *gconf_client;
+	XklConfigRec *xklrec = xkl_config_rec_new ();
+
+	priv = GKBD_CONFIGURATION_GET_PRIVATE (configuration);
+	configuration->priv = priv;
+
+	priv->engine = xkl_engine_get_instance (GDK_DISPLAY ());
+	if (priv->engine == NULL) {
+		xkl_debug (0, "Libxklavier initialization error");
+		return;
+	}
+
+	gconf_client = gconf_client_get_default ();
+
+	priv->state_changed_handler =
+	    g_signal_connect (priv->engine, "X-state-changed",
+			      G_CALLBACK (gkbd_configuration_state_callback),
+			      configuration);
+	priv->config_changed_handler =
+	    g_signal_connect (priv->engine, "X-config-changed",
+			      G_CALLBACK (gkbd_configuration_kbd_cfg_callback),
+			      configuration);
+
+	gkbd_desktop_config_init (&priv->cfg, gconf_client,
+				  priv->engine);
+	gkbd_keyboard_config_init (&priv->kbd_cfg, gconf_client,
+				   priv->engine);
+	gkbd_indicator_config_init (&priv->ind_cfg, gconf_client,
+				    priv->engine);
+
+	g_object_unref (gconf_client);
+
+	gkbd_desktop_config_load_from_gconf (&priv->cfg);
+	gkbd_desktop_config_activate (&priv->cfg);
+
+	priv->registry = xkl_config_registry_get_instance (priv->engine);
+	xkl_config_registry_load (priv->registry,
+				  priv->cfg.load_extra_items);
+
+	gkbd_keyboard_config_load_from_x_current (&priv->kbd_cfg,
+						  xklrec);
+
+	gkbd_indicator_config_load_from_gconf (&priv->ind_cfg);
+
+	gkbd_indicator_config_load_image_filenames (&priv->ind_cfg,
+						    &priv->kbd_cfg);
+
+	gkbd_indicator_config_activate (&priv->ind_cfg);
+
+	gkbd_configuration_load_group_names (configuration,
+					     xklrec);
+	g_object_unref (G_OBJECT (xklrec));
+
+	gkbd_desktop_config_start_listen (&priv->cfg,
+					  (GConfClientNotifyFunc) gkbd_configuration_cfg_changed,
+					  configuration);
+	gkbd_indicator_config_start_listen (&priv->ind_cfg,
+					    (GConfClientNotifyFunc) gkbd_configuration_ind_cfg_changed,
+					    configuration);
+	xkl_engine_start_listen (priv->engine,
+				 XKLL_TRACK_KEYBOARD_STATE);
+
+	xkl_debug (100, "Initiating the widget startup process for %p\n",
+		   configuration);
+}
+
+static void
+gkbd_configuration_finalize (GObject * obj)
+{
+	GkbdConfiguration *configuration = GKBD_CONFIGURATION (obj);
+	GkbdConfigurationPrivate *priv = configuration->priv;
+
+	xkl_debug (100,
+		   "Starting the gnome-kbd-configuration widget shutdown process for %p\n",
+		   configuration);
+
+	xkl_engine_stop_listen (priv->engine,
+				XKLL_TRACK_KEYBOARD_STATE);
+
+	gkbd_desktop_config_stop_listen (&priv->cfg);
+	gkbd_indicator_config_stop_listen (&priv->ind_cfg);
+
+	gkbd_indicator_config_term (&priv->ind_cfg);
+	gkbd_keyboard_config_term (&priv->kbd_cfg);
+	gkbd_desktop_config_term (&priv->cfg);
+
+	if (g_signal_handler_is_connected (priv->engine,
+					   priv->state_changed_handler)) {
+		g_signal_handler_disconnect (priv->engine,
+					     priv->state_changed_handler);
+		priv->state_changed_handler = 0;
+	}
+	if (g_signal_handler_is_connected (priv->engine,
+					   priv->config_changed_handler)) {
+		g_signal_handler_disconnect (priv->engine,
+					     priv->config_changed_handler);
+		priv->config_changed_handler = 0;
+	}
+
+	g_object_unref (priv->registry);
+	priv->registry = NULL;
+	g_object_unref (priv->engine);
+	priv->engine = NULL;
+
+	G_OBJECT_CLASS (gkbd_configuration_parent_class)->finalize (obj);
+}
+
+static void
+gkbd_configuration_class_init (GkbdConfigurationClass * klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	/* Initing vtable */
+	object_class->finalize = gkbd_configuration_finalize;
+
+	/* Signals */
+	signals[SIGNAL_CHANGED] = g_signal_new ("changed",
+						GKBD_TYPE_CONFIGURATION,
+						G_SIGNAL_RUN_LAST,
+						0,
+						NULL, NULL,
+						g_cclosure_marshal_VOID__VOID,
+						G_TYPE_NONE,
+						0);
+	signals[SIGNAL_GROUP_CHANGED] = g_signal_new ("group-changed",
+						      GKBD_TYPE_CONFIGURATION,
+						      G_SIGNAL_RUN_LAST,
+						      0,
+						      NULL, NULL,
+						      g_cclosure_marshal_VOID__INT,
+						      G_TYPE_NONE,
+						      1,
+						      G_TYPE_INT);
+
+	g_type_class_add_private (klass, sizeof (GkbdConfigurationPrivate));
+}
+
+GkbdConfiguration *
+gkbd_configuration_get (void)
+{
+	static gpointer instance = NULL;
+
+	if (!instance) {
+		instance = g_object_new (GKBD_TYPE_CONFIGURATION, NULL);
+		g_object_add_weak_pointer (instance, &instance);
+	} else {
+		g_object_ref (instance);
+	}
+
+	return instance;
+}
+
+XklEngine *
+gkbd_configuration_get_xkl_engine (GkbdConfiguration *configuration)
+{
+	return configuration->priv->engine;
+}
+
+const char * const *
+gkbd_configuration_get_group_names (GkbdConfiguration *configuration)
+{
+	return configuration->priv->full_group_names;
+}
+
+const char * const *
+gkbd_configuration_get_short_group_names (GkbdConfiguration *configuration)
+{
+	return configuration->priv->short_group_names;
+}
diff --git a/libgnomekbd/gkbd-configuration.h b/libgnomekbd/gkbd-configuration.h
new file mode 100644
index 0000000..c3fc54e
--- /dev/null
+++ b/libgnomekbd/gkbd-configuration.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 Canonical Ltd.
+ * 
+ * Authors: Jan Arne Petersen <jpetersen@openismus.com>
+ * 
+ * Based on gkbd-status.h by Sergey V. Udaltsov <svu@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GKBD_CONFIGURATION_H__
+#define __GKBD_CONFIGURATION_H__
+
+#include <glib-object.h>
+
+#include <libxklavier/xklavier.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GkbdConfiguration GkbdConfiguration;
+typedef struct _GkbdConfigurationPrivate GkbdConfigurationPrivate;
+typedef struct _GkbdConfigurationClass GkbdConfigurationClass;
+
+#define GKBD_TYPE_CONFIGURATION           (gkbd_configuration_get_type ())
+#define GKBD_CONFIGURATION(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GKBD_TYPE_CONFIGURATION, GkbdConfiguration))
+#define GKBD_INDCATOR_CLASS(obj)          (G_TYPE_CHECK_CLASS_CAST ((obj), GKBD_TYPE_CONFIGURATION,  GkbdConfigurationClass))
+#define GKBD_IS_CONFIGURATION(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GKBD_TYPE_CONFIGURATION))
+#define GKBD_IS_CONFIGURATION_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE ((obj), GKBD_TYPE_CONFIGURATION))
+#define GKBD_CONFIGURATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GKBD_TYPE_CONFIGURATION, GkbdConfigurationClass))
+
+struct _GkbdConfiguration {
+	GObject parent;
+
+	GkbdConfigurationPrivate *priv;
+};
+
+struct _GkbdConfigurationClass {
+	GObjectClass parent_class;
+};
+
+extern GType gkbd_configuration_get_type (void);
+
+extern GkbdConfiguration *gkbd_configuration_get (void);
+
+extern XklEngine *gkbd_configuration_get_xkl_engine (GkbdConfiguration *configuration);
+
+extern const char * const *gkbd_configuration_get_group_names (GkbdConfiguration *configuration);
+extern const char * const *gkbd_configuration_get_short_group_names (GkbdConfiguration *configuration);
+
+G_END_DECLS
+
+#endif
