diff --git a/configure.ac b/configure.ac
index dfe82d2..f763772 100644
--- a/configure.ac
+++ b/configure.ac
@@ -120,7 +120,7 @@ COMMON_MODULES="gtk+-3.0 >= $GTK_REQUIRED_VERSION
  gsettings-desktop-schemas >= $SCHEMAS_REQUIRED_VERSION
  libnotify >= $LIBNOTIFY_REQUIRED_VERSION"
 
-LIBGD_INIT([_view-common static])
+LIBGD_INIT([_view-common notification static])
 
 PKG_CHECK_MODULES(LIBLANGUAGE, $COMMON_MODULES gnome-desktop-3.0 fontconfig)
 PKG_CHECK_MODULES(LIBSHORTCUTS, $COMMON_MODULES x11)
@@ -158,6 +158,7 @@ PKG_CHECK_MODULES(PRIVACY_PANEL, $COMMON_MODULES)
 PKG_CHECK_MODULES(REGION_PANEL, $COMMON_MODULES
                   polkit-gobject-1 >= $POLKIT_REQUIRED_VERSION
                   gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION
+                  accountsservice >= $ACCOUNTSSERVICE_REQUIRED_VERSION
                   $IBUS_MODULE)
 PKG_CHECK_MODULES(SCREEN_PANEL, $COMMON_MODULES)
 PKG_CHECK_MODULES(SEARCH_PANEL, $COMMON_MODULES)
diff --git a/egg-list-box b/egg-list-box
--- a/egg-list-box
+++ b/egg-list-box
@@ -1 +1 @@
-Subproject commit 491db4b5eb181f1e13b909644dfd0ad971231099
+Subproject commit 491db4b5eb181f1e13b909644dfd0ad971231099-dirty
diff --git a/panels/common/Makefile.am b/panels/common/Makefile.am
index e262d3b..6655972 100644
--- a/panels/common/Makefile.am
+++ b/panels/common/Makefile.am
@@ -13,6 +13,8 @@ BUILT_SOURCES =			\
 
 liblanguage_la_SOURCES =		\
 	$(BUILT_SOURCES)		\
+	cc-util.c			\
+	cc-util.h			\
 	cc-common-language.c		\
 	cc-common-language.h		\
 	cc-language-chooser.c		\
diff --git a/panels/common/cc-common-language.c b/panels/common/cc-common-language.c
index 4c496da..3e0d272 100644
--- a/panels/common/cc-common-language.c
+++ b/panels/common/cc-common-language.c
@@ -113,13 +113,13 @@ iter_for_language (GtkTreeModel *model,
                 g_free (l);
         } while (gtk_tree_model_iter_next (model, iter));
 
-        name = gnome_normalize_language_name (lang);
+        name = gnome_normalize_locale (lang);
         if (name != NULL) {
                 if (region) {
-                        language = gnome_get_region_from_name (name, NULL);
+                        language = gnome_get_country_from_locale (name, NULL);
                 }
                 else {
-                        language = gnome_get_language_from_name (name, NULL);
+                        language = gnome_get_language_from_locale (name, NULL);
                 }
 
                 gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
@@ -167,7 +167,7 @@ cc_common_language_has_font (const gchar *locale)
         object_set = NULL;
         font_set = NULL;
 
-        if (!gnome_parse_language_name (locale, &language_code, NULL, NULL, NULL))
+        if (!gnome_parse_locale (locale, &language_code, NULL, NULL, NULL))
                 return FALSE;
 
         charset = FcLangGetCharSet ((FcChar8 *) language_code);
@@ -242,7 +242,7 @@ add_one_language (gpointer d)
     return FALSE;
   }
 
-  name = gnome_normalize_language_name (data->languages[data->position]);
+  name = gnome_normalize_locale (data->languages[data->position]);
   if (g_hash_table_lookup (data->user_langs, name) != NULL) {
     g_free (name);
     goto next;
@@ -254,10 +254,10 @@ add_one_language (gpointer d)
   }
 
   if (data->regions) {
-    language = gnome_get_region_from_name (name, NULL);
+    language = gnome_get_country_from_locale (name, NULL);
   }
   else {
-    language = gnome_get_language_from_name (name, NULL);
+    language = gnome_get_language_from_locale (name, NULL);
   }
   if (!language) {
     g_debug ("Ignoring '%s' as a locale, because we couldn't figure the language name", name);
@@ -292,7 +292,7 @@ cc_common_language_add_available_languages (GtkListStore *store,
 
   data->store = g_object_ref (store);
   data->user_langs = g_hash_table_ref (user_langs);
-  data->languages = gnome_get_all_language_names ();
+  data->languages = gnome_get_all_locales ();
   data->regions = regions;
   data->position = 0;
 
@@ -314,7 +314,7 @@ cc_common_language_get_current_language (void)
 
         locale = (const gchar *) setlocale (LC_MESSAGES, NULL);
         if (locale)
-                language = gnome_normalize_language_name (locale);
+                language = gnome_normalize_locale (locale);
         else
                 language = NULL;
 
@@ -467,10 +467,10 @@ user_language_has_translations (const char *locale)
         char *name, *language_code, *territory_code;
         gboolean ret;
 
-        gnome_parse_language_name (locale,
-                                   &language_code,
-                                   &territory_code,
-                                   NULL, NULL);
+        gnome_parse_locale (locale,
+                            &language_code,
+                            &territory_code,
+                            NULL, NULL);
         name = g_strdup_printf ("%s%s%s",
                                 language_code,
                                 territory_code != NULL? "_" : "",
@@ -557,9 +557,9 @@ add_other_users_language (GHashTable *ht)
                 if (lang != NULL && *lang != '\0' &&
                     cc_common_language_has_font (lang) &&
                     user_language_has_translations (lang)) {
-                        name = gnome_normalize_language_name (lang);
+                        name = gnome_normalize_locale (lang);
                         if (!g_hash_table_lookup (ht, name)) {
-                                language = gnome_get_language_from_name (name, NULL);
+                                language = gnome_get_language_from_locale (name, NULL);
                                 g_hash_table_insert (ht, name, language);
                         }
                         else {
@@ -574,55 +574,48 @@ add_other_users_language (GHashTable *ht)
         g_object_unref (proxy);
 }
 
-#define TRANSLATED_LANG(x) g_strdup(dgettext("iso_639", x))
-
 static void
 insert_language (GHashTable *ht,
-		 const char *short_lang,
-		 const char *long_lang,
-		 gboolean    in_iso_639,
-		 const char *lang_label)
+                 const char *lang)
 {
-	const char *lang;
-	char *old_lang;
-	char *label;
-	char *key;
-
-	if (gnome_language_has_translations (long_lang))
-		lang = long_lang;
-	else if (short_lang != NULL && gnome_language_has_translations (short_lang))
-		lang = short_lang;
-	else {
-		g_warning ("%s lacks translations, why is it default?", long_lang);
-		return;
-	}
+        gboolean has_translations;
+        char *label_own_lang;
+        char *label_current_lang;
+        char *label_untranslated;
+        char *key;
+
+        has_translations = gnome_language_has_translations (lang);
+        if (!has_translations) {
+                char *lang_code = g_strndup (lang, 2);
+                has_translations = gnome_language_has_translations (lang_code);
+                g_free (lang_code);
+
+                if (!has_translations)
+                        return;
+        }
 
-	g_debug ("We have translations for %s", lang);
-
-	key = g_strdup_printf ("%s.utf8", long_lang);
-
-	old_lang = g_strdup (setlocale (LC_MESSAGES, NULL));
-	setlocale (LC_MESSAGES, key);
-	g_debug ("Set new lang '%s' (old lang: %s)", key, old_lang);
-	if (in_iso_639)
-		label = dgettext ("iso_639", lang_label);
-	else
-		label = gettext (lang_label);
-	/* We don't have a translation for lang_label in
-	 * its own language? */
-	if (g_strcmp0 (label, lang_label) == 0 &&
-	    g_str_has_prefix (long_lang, "en_") == FALSE) {
-		g_warning ("No translation for %s in %s, trying in current language", lang_label, key);
-		setlocale (LC_MESSAGES, old_lang);
-		g_debug ("Resetting to old lang '%s'", old_lang);
-		label = _(lang_label);
-		g_hash_table_insert (ht, key, g_strdup (label));
-	} else {
-		g_hash_table_insert (ht, key, g_strdup (label));
-		setlocale (LC_MESSAGES, old_lang);
-		g_debug ("Resetting to old lang '%s'", old_lang);
-	}
-	g_free (old_lang);
+        g_debug ("We have translations for %s", lang);
+
+        key = g_strdup_printf ("%s.utf8", lang);
+
+        label_own_lang = gnome_get_language_from_locale (key, key);
+        label_current_lang = gnome_get_language_from_locale (key, NULL);
+        label_untranslated = gnome_get_language_from_locale (key, "C");
+
+        /* We don't have a translation for the label in
+         * its own language? */
+        if (g_strcmp0 (label_own_lang, label_untranslated) == 0) {
+                if (g_strcmp0 (label_current_lang, label_untranslated) == 0)
+                        g_hash_table_insert (ht, key, g_strdup (label_untranslated));
+                else
+                        g_hash_table_insert (ht, key, g_strdup (label_current_lang));
+        } else {
+                g_hash_table_insert (ht, key, g_strdup (label_own_lang));
+        }
+
+        g_free (label_own_lang);
+        g_free (label_current_lang);
+        g_free (label_untranslated);
 }
 
 GHashTable *
@@ -632,18 +625,15 @@ cc_common_language_get_initial_languages (void)
 
         ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 
-        /* Add some common languages first,
-         * only the languages not listed in ISO-639 are
-         * marked for translation */
-        insert_language (ht, "en", "en_US", TRUE, "English");
-        insert_language (ht, NULL, "en_GB", FALSE, N_("British English"));
-        insert_language (ht, "de", "de_DE", TRUE, "German");
-        insert_language (ht, "fr", "fr_FR", TRUE, "French");
-        insert_language (ht, "es", "es_ES", FALSE, N_("Spanish"));
-        insert_language (ht, NULL, "zh_CN", FALSE, N_("Chinese (simplified)"));
-        insert_language (ht, "ja", "ja_JP", TRUE, "Japanese");
-        insert_language (ht, "ru", "ru_RU", FALSE, "Russian");
-        insert_language (ht, "ar", "ar_EG", TRUE, "Arabic");
+        insert_language (ht, "en_US");
+        insert_language (ht, "en_GB");
+        insert_language (ht, "de_DE");
+        insert_language (ht, "fr_FR");
+        insert_language (ht, "es_ES");
+        insert_language (ht, "zh_CN");
+        insert_language (ht, "ja_JP");
+        insert_language (ht, "ru_RU");
+        insert_language (ht, "ar_EG");
 
         return ht;
 }
@@ -663,7 +653,7 @@ cc_common_language_get_user_languages (void)
         /* Add current locale */
         name = cc_common_language_get_current_language ();
         if (g_hash_table_lookup (ht, name) == NULL) {
-                language = gnome_get_language_from_name (name, NULL);
+                language = gnome_get_language_from_locale (name, NULL);
                 g_hash_table_insert (ht, name, language);
         } else {
                 g_free (name);
@@ -691,14 +681,14 @@ cc_common_language_get_initial_regions (const gchar *lang)
         g_hash_table_insert (ht, g_strdup ("zh_CN.utf8"), g_strdup (_("China")));
 #endif
 
-        gnome_parse_language_name (lang, &language, NULL, NULL, NULL);
-        langs = gnome_get_all_language_names ();
+        gnome_parse_locale (lang, &language, NULL, NULL, NULL);
+        langs = gnome_get_all_locales ();
         for (i = 0; langs[i]; i++) {
                 gchar *l, *s;
-                gnome_parse_language_name (langs[i], &l, NULL, NULL, NULL);
+                gnome_parse_locale (langs[i], &l, NULL, NULL, NULL);
                 if (g_strcmp0 (language, l) == 0) {
                         if (!g_hash_table_lookup (ht, langs[i])) {
-                                s = gnome_get_region_from_name (langs[i], NULL);
+                                s = gnome_get_country_from_locale (langs[i], NULL);
                                 g_hash_table_insert (ht, g_strdup (langs[i]), s);
                         }
                 }
@@ -709,3 +699,53 @@ cc_common_language_get_initial_regions (const gchar *lang)
 
         return ht;
 }
+
+static void
+foreach_user_lang_cb (gpointer key,
+                      gpointer value,
+                      gpointer user_data)
+{
+        GtkListStore *store = (GtkListStore *) user_data;
+        const char *locale = (const char *) key;
+        const char *display_locale = (const char *) value;
+        GtkTreeIter iter;
+
+        gtk_list_store_append (store, &iter);
+        gtk_list_store_set (store, &iter,
+                            LOCALE_COL, locale,
+                            DISPLAY_LOCALE_COL, display_locale,
+                            -1);
+}
+
+void
+cc_common_language_add_user_languages (GtkTreeModel *model)
+{
+        char *name;
+        GtkTreeIter iter;
+        GtkListStore *store = GTK_LIST_STORE (model);
+        GHashTable *user_langs;
+        const char *display;
+
+        gtk_list_store_clear (store);
+
+        user_langs = cc_common_language_get_initial_languages ();
+
+        /* Add the current locale first */
+        name = cc_common_language_get_current_language ();
+        display = g_hash_table_lookup (user_langs, name);
+
+        gtk_list_store_append (store, &iter);
+        gtk_list_store_set (store, &iter, LOCALE_COL, name, DISPLAY_LOCALE_COL, display, -1);
+        g_hash_table_remove (user_langs, name);
+        g_free (name);
+
+        /* The rest of the languages */
+        g_hash_table_foreach (user_langs, (GHFunc) foreach_user_lang_cb, store);
+
+        /* And now the "Other…" selection */
+        gtk_list_store_append (store, &iter);
+        gtk_list_store_set (store, &iter, LOCALE_COL, NULL, DISPLAY_LOCALE_COL, _("Other…"), -1);
+
+        g_hash_table_destroy (user_langs);
+}
+
diff --git a/panels/common/cc-common-language.h b/panels/common/cc-common-language.h
index f08d142..ae50035 100644
--- a/panels/common/cc-common-language.h
+++ b/panels/common/cc-common-language.h
@@ -55,6 +55,8 @@ void     cc_common_language_setup_list              (GtkWidget    *treeview,
 						     GHashTable   *initial);
 void     cc_common_language_select_current_language (GtkTreeView  *treeview);
 
+void     cc_common_language_add_user_languages (GtkTreeModel *model);
+
 G_END_DECLS
 
 #endif
diff --git a/panels/common/cc-language-chooser.c b/panels/common/cc-language-chooser.c
index 63161c4..59efd0b 100644
--- a/panels/common/cc-language-chooser.c
+++ b/panels/common/cc-language-chooser.c
@@ -1,338 +1,480 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
  *
- * Copyright 2009-2010  Red Hat, Inc,
+ * 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 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.
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
  *
- * Written by: Matthias Clasen <mclasen@redhat.com>
+ * Written by:
+ *     Matthias Clasen
  */
 
-#include "config.h"
+#define _GNU_SOURCE
+#include <config.h>
+#include "cc-language-chooser.h"
+#include "cc-common-resources.h"
 
-#include <stdlib.h>
 #include <locale.h>
-
-#include <glib.h>
+#include <string.h>
 #include <glib/gi18n.h>
 #include <gio/gio.h>
 #include <gtk/gtk.h>
 
-#include <fontconfig/fontconfig.h>
+#include "egg-list-box/egg-list-box.h"
 
-#include "cc-language-chooser.h"
 #include "cc-common-language.h"
-#include "cc-common-resources.h"
+#include "cc-util.h"
 
-gchar *
-cc_language_chooser_get_language (GtkWidget *chooser)
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-languages.h>
+
+typedef struct {
+        GtkWidget *no_results;
+        GtkWidget *more_item;
+        GtkWidget *filter_entry;
+        GtkWidget *language_list;
+        GtkWidget *scrolledwindow;
+        gboolean adding_languages;
+        gboolean showing_extra;
+        gchar *language;
+        gchar **filter_words;
+} CcLanguageChooserPrivate;
+
+#define GET_PRIVATE(chooser) ((CcLanguageChooserPrivate *) g_object_get_data (G_OBJECT (chooser), "private"))
+
+static void
+set_locale_id (GtkDialog *chooser,
+               const gchar       *locale_id)
+{
+        CcLanguageChooserPrivate *priv = GET_PRIVATE (chooser);
+        GList *children, *l;
+
+        children = gtk_container_get_children (GTK_CONTAINER (priv->language_list));
+        for (l = children; l; l = l->next) {
+                GtkWidget *row = l->data;
+                GtkWidget *check = g_object_get_data (G_OBJECT (row), "check");
+                const gchar *language = g_object_get_data (G_OBJECT (row), "locale-id");
+                if (check == NULL || language == NULL)
+                        continue;
+
+                if (g_strcmp0 (locale_id, language) == 0) {
+                        gboolean is_extra;
+                        gtk_image_set_from_icon_name (GTK_IMAGE (check), "object-select-symbolic", GTK_ICON_SIZE_MENU);
+
+                        /* make sure the selected language is shown */
+                        is_extra = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (row), "is-extra"));
+                        if (!priv->showing_extra && is_extra) {
+                                g_object_set_data (G_OBJECT (row), "is-extra", GINT_TO_POINTER (FALSE));
+                                egg_list_box_refilter (EGG_LIST_BOX (priv->language_list));
+                        }
+                } else {
+                        gtk_image_clear (GTK_IMAGE (check));
+                        g_object_set (check, "icon-size", GTK_ICON_SIZE_MENU, NULL);
+                }
+        }
+        g_list_free (children);
+
+        g_free (priv->language);
+        priv->language = g_strdup (locale_id);
+}
+
+static gint
+sort_languages (gconstpointer a,
+            gconstpointer b,
+            gpointer      data)
 {
-        GtkTreeView *tv;
-        GtkTreeSelection *selection;
-        GtkTreeModel *model;
-        GtkTreeIter iter;
-        gchar *lang;
+        const gchar *la;
+        const gchar *lb;
 
-        tv = (GtkTreeView *) g_object_get_data (G_OBJECT (chooser), "list");
-        selection = gtk_tree_view_get_selection (tv);
+        if (g_object_get_data (G_OBJECT (a), "locale-id") == NULL)
+                return 1;
+        if (g_object_get_data (G_OBJECT (b), "locale-id") == NULL)
+                return -1;
 
-        if (gtk_tree_selection_get_selected (selection, &model, &iter))
-                gtk_tree_model_get (model, &iter, LOCALE_COL, &lang, -1);
-        else
-                lang = NULL;
+        la = g_object_get_data (G_OBJECT (a), "locale-name");
+        lb = g_object_get_data (G_OBJECT (b), "locale-name");
 
-        return lang;
+        return g_strcmp0 (la, lb);
 }
 
-void
-cc_language_chooser_clear_filter (GtkWidget *chooser)
+static GtkWidget *
+padded_label_new (char *text, gboolean narrow)
 {
-	GtkEntry *entry;
+        GtkWidget *widget;
 
-	entry = (GtkEntry *) g_object_get_data (G_OBJECT (chooser), "filter-entry");
-	gtk_entry_set_text (entry, "");
+        widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
+        gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
+        gtk_widget_set_margin_top (widget, 10);
+        gtk_widget_set_margin_bottom (widget, 10);
+        gtk_widget_set_margin_left (widget, narrow ? 10 : 80);
+        gtk_widget_set_margin_right (widget, narrow ? 10 : 80);
+        gtk_box_pack_start (GTK_BOX (widget), gtk_label_new (text), FALSE, FALSE, 0);
+
+        return widget;
 }
 
-static void
-row_activated (GtkTreeView       *tree_view,
-               GtkTreePath       *path,
-               GtkTreeViewColumn *column,
-               GtkWidget         *chooser)
+static GtkWidget *
+language_widget_new (const gchar *locale_id,
+                     const gchar *current_locale_id,
+                     gboolean     is_extra)
 {
-        gtk_dialog_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
+        gchar *locale_name;
+        gchar *locale_current_name;
+        gchar *locale_untranslated_name;
+        GtkWidget *widget;
+        GtkWidget *check;
+
+        locale_name = gnome_get_language_from_locale (locale_id, locale_id);
+        locale_current_name = gnome_get_language_from_locale (locale_id, NULL);
+        locale_untranslated_name = gnome_get_language_from_locale (locale_id, "C");
+
+        widget = padded_label_new (locale_name, is_extra);
+
+        check = gtk_image_new ();
+        g_object_set (check, "icon-size", GTK_ICON_SIZE_MENU, NULL);
+        gtk_box_pack_start (GTK_BOX (widget), check, FALSE, FALSE, 0);
+        if (g_strcmp0 (locale_id, current_locale_id) == 0)
+                gtk_image_set_from_icon_name (GTK_IMAGE (check), "object-select-symbolic", GTK_ICON_SIZE_MENU);
+
+        g_object_set_data (G_OBJECT (widget), "check", check);
+        g_object_set_data_full (G_OBJECT (widget), "locale-id", g_strdup (locale_id), g_free);
+        g_object_set_data_full (G_OBJECT (widget), "locale-name", locale_name, g_free);
+        g_object_set_data_full (G_OBJECT (widget), "locale-current-name", locale_current_name, g_free);
+        g_object_set_data_full (G_OBJECT (widget), "locale-untranslated-name", locale_untranslated_name, g_free);
+        g_object_set_data (G_OBJECT (widget), "is-extra", GUINT_TO_POINTER (is_extra));
+
+        return widget;
 }
 
-static void
-languages_foreach_cb (gpointer key,
-		      gpointer value,
-		      gpointer user_data)
+static GtkWidget *
+more_widget_new (void)
 {
-	GtkListStore *store = (GtkListStore *) user_data;
-	const char *locale = (const char *) key;
-	const char *display_locale = (const char *) value;
-	GtkTreeIter iter;
-
-	gtk_list_store_append (store, &iter);
-	gtk_list_store_set (store, &iter,
-			    LOCALE_COL, locale,
-			    DISPLAY_LOCALE_COL, display_locale,
-			    -1);
+        GtkWidget *widget;
+
+        widget = padded_label_new ("…", FALSE);
+        gtk_widget_set_tooltip_text (widget, _("More…"));
+        return widget;
 }
 
-void
-cc_add_user_languages (GtkTreeModel *model)
+static GtkWidget *
+no_results_widget_new (void)
+{
+        GtkWidget *widget;
+
+        widget = padded_label_new (_("No languages found"), TRUE);
+        gtk_widget_set_sensitive (widget, FALSE);
+        return widget;
+}
+
+static void
+add_languages (GtkDialog   *chooser,
+               gchar      **locale_ids,
+               GHashTable  *initial)
 {
-        char *name;
-        GtkTreeIter iter;
-        GtkListStore *store = GTK_LIST_STORE (model);
-        GHashTable *user_langs;
-        const char *display;
+        CcLanguageChooserPrivate *priv = GET_PRIVATE (chooser);
 
-        gtk_list_store_clear (store);
+        priv->adding_languages = TRUE;
 
-	user_langs = cc_common_language_get_initial_languages ();
+        while (*locale_ids) {
+                gchar *locale_id;
+                gboolean is_initial;
+                GtkWidget *widget;
 
-	/* Add the current locale first */
-	name = cc_common_language_get_current_language ();
-	display = g_hash_table_lookup (user_langs, name);
+                locale_id = *locale_ids;
+                locale_ids ++;
 
-        gtk_list_store_append (store, &iter);
-        gtk_list_store_set (store, &iter, LOCALE_COL, name, DISPLAY_LOCALE_COL, display, -1);
-        g_hash_table_remove (user_langs, name);
-        g_free (name);
+                if (!cc_common_language_has_font (locale_id))
+                        continue;
+
+                is_initial = (g_hash_table_lookup (initial, locale_id) != NULL);
+                widget = language_widget_new (locale_id, priv->language, !is_initial);
+                gtk_container_add (GTK_CONTAINER (priv->language_list), widget);
+        }
 
-        /* The rest of the languages */
-	g_hash_table_foreach (user_langs, (GHFunc) languages_foreach_cb, store);
+        gtk_container_add (GTK_CONTAINER (priv->language_list), priv->more_item);
+        gtk_container_add (GTK_CONTAINER (priv->language_list), priv->no_results);
 
-	/* And now the "Other…" selection */
-        gtk_list_store_append (store, &iter);
-        gtk_list_store_set (store, &iter, LOCALE_COL, NULL, DISPLAY_LOCALE_COL, _("Other…"), -1);
+        gtk_widget_show_all (priv->language_list);
 
-        g_hash_table_destroy (user_langs);
+        priv->adding_languages = FALSE;
 }
 
 static void
-remove_timeout (gpointer data,
-		GObject *where_the_object_was)
+add_all_languages (GtkDialog *chooser)
 {
-	guint timeout = GPOINTER_TO_UINT (data);
-	g_source_remove (timeout);
+        gchar **locale_ids;
+        GHashTable *initial;
+
+        locale_ids = gnome_get_all_locales ();
+        initial = cc_common_language_get_initial_languages ();
+        add_languages (chooser, locale_ids, initial);
+        g_hash_table_destroy (initial);
+        g_strfreev (locale_ids);
 }
 
-static void
-remove_async (gpointer data)
+static gboolean
+match_all (gchar       **words,
+           const gchar  *str)
 {
-  guint async_id = GPOINTER_TO_UINT (data);
+        gchar **w;
 
-  g_source_remove (async_id);
-}
+        for (w = words; *w; ++w)
+                if (!strstr (str, *w))
+                        return FALSE;
 
-static void
-selection_changed (GtkTreeSelection *selection,
-                   GtkWidget        *chooser)
-{
-	gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser),
-					   GTK_RESPONSE_OK,
-				           gtk_tree_selection_get_selected (selection, NULL, NULL));
+        return TRUE;
 }
 
 static gboolean
-finish_language_chooser (gpointer user_data)
+language_visible (GtkWidget *child,
+                  gpointer   user_data)
 {
-	GtkWidget *chooser = (GtkWidget *) user_data;
-	GtkWidget *list;
-	GtkTreeModel *model;
-	GtkWindow *parent;
-	GHashTable *user_langs;
-	guint timeout;
-        guint async_id;
-	GtkTreeSelection *selection;
-        gboolean regions;
-
-	/* Did we get called after the widget was destroyed? */
-	if (chooser == NULL)
-		return FALSE;
-
-        regions = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (chooser), "regions"));
-
-	list = g_object_get_data (G_OBJECT (chooser), "list");
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (list));
-	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-	user_langs = g_object_get_data (G_OBJECT (chooser), "user-langs");
-
-	async_id = cc_common_language_add_available_languages (GTK_LIST_STORE (model), regions, user_langs);
-        g_object_set_data_full (G_OBJECT (chooser), "language-async", GUINT_TO_POINTER (async_id), remove_async);
-
-	parent = gtk_window_get_transient_for (GTK_WINDOW (chooser));
-	gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (parent)), NULL);
-
-	g_object_set_data (G_OBJECT (chooser), "user-langs", NULL);
-	timeout = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (chooser), "timeout"));
-	g_object_weak_unref (G_OBJECT (chooser), (GWeakNotify) remove_timeout, GUINT_TO_POINTER (timeout));
-
-	/* And now listen for changes */
-        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
-        g_signal_connect (G_OBJECT (selection), "changed",
-                          G_CALLBACK (selection_changed), chooser);
-
-	return FALSE;
+        GtkDialog *chooser = user_data;
+        CcLanguageChooserPrivate *priv = GET_PRIVATE (chooser);
+        gchar *locale_name = NULL;
+        gchar *locale_current_name = NULL;
+        gchar *locale_untranslated_name = NULL;
+        gboolean is_extra;
+        gboolean visible;
+
+        if (child == priv->more_item)
+                return !priv->showing_extra;
+
+        /* We hide this in the after-refilter handler below. */
+        if (child == priv->no_results)
+                return TRUE;
+
+        is_extra = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (child), "is-extra"));
+
+        if (!priv->showing_extra && is_extra)
+                return FALSE;
+
+        if (!priv->filter_words)
+                return TRUE;
+
+        visible = FALSE;
+
+        locale_name =
+                cc_util_normalize_casefold_and_unaccent (g_object_get_data (G_OBJECT (child), "locale-name"));
+        visible = match_all (priv->filter_words, locale_name);
+        if (visible)
+                goto out;
+
+        locale_current_name =
+                cc_util_normalize_casefold_and_unaccent (g_object_get_data (G_OBJECT (child), "locale-current-name"));
+        visible = match_all (priv->filter_words, locale_current_name);
+        if (visible)
+                goto out;
+
+        locale_untranslated_name =
+                cc_util_normalize_casefold_and_unaccent (g_object_get_data (G_OBJECT (child), "locale-untranslated-name"));
+        visible = match_all (priv->filter_words, locale_untranslated_name);
+
+out:
+        g_free (locale_untranslated_name);
+        g_free (locale_current_name);
+        g_free (locale_name);
+        return visible;
 }
 
 static void
-filter_clear (GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEvent *event, gpointer user_data)
+filter_changed (GtkDialog *chooser)
 {
-	gtk_entry_set_text (entry, "");
+        CcLanguageChooserPrivate *priv = GET_PRIVATE (chooser);
+        gchar *filter_contents = NULL;
+
+        g_clear_pointer (&priv->filter_words, g_strfreev);
+
+        filter_contents =
+                cc_util_normalize_casefold_and_unaccent (gtk_entry_get_text (GTK_ENTRY (priv->filter_entry)));
+        if (!filter_contents) {
+                egg_list_box_refilter (EGG_LIST_BOX (priv->language_list));
+                return;
+        }
+        priv->filter_words = g_strsplit_set (g_strstrip (filter_contents), " ", 0);
+        g_free (filter_contents);
+        egg_list_box_refilter (EGG_LIST_BOX (priv->language_list));
 }
 
 static void
-filter_changed (GtkWidget *entry, GParamSpec *pspec, GtkWidget *list)
+show_more (GtkDialog *chooser)
 {
-	const gchar *pattern;
-	GtkTreeModel *filter_model;
-	GtkTreeModel *model;
-
-	pattern = gtk_entry_get_text (GTK_ENTRY (entry));
-
-	filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (list));
-	model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model));
-
-	if (g_strcmp0 (pattern, "") == 0) {
-                g_object_set (G_OBJECT (entry),
-                              "secondary-icon-name", "edit-find-symbolic",
-                              "secondary-icon-activatable", FALSE,
-                              "secondary-icon-sensitive", FALSE,
-                              NULL);
-
-		g_object_set_data_full (G_OBJECT (model), "filter-string",
-					g_strdup (""), g_free);
-
-        } else {
-                g_object_set (G_OBJECT (entry),
-                              "secondary-icon-name", "edit-clear-symbolic",
-                              "secondary-icon-activatable", TRUE,
-                              "secondary-icon-sensitive", TRUE,
-                              NULL);
-
-		g_object_set_data_full (G_OBJECT (model), "filter-string",
-					g_utf8_casefold (pattern, -1), g_free);
-        }
+        CcLanguageChooserPrivate *priv = GET_PRIVATE (chooser);
+        GtkWidget *widget;
+        gint width, height;
+
+        gtk_window_get_size (GTK_WINDOW (chooser), &width, &height);
+        gtk_widget_set_size_request (GTK_WIDGET (chooser), width, height);
+        gtk_window_set_resizable (GTK_WINDOW (chooser), TRUE);
 
-	gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter_model));
+        widget = priv->scrolledwindow;
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+
+        gtk_widget_show (priv->filter_entry);
+        gtk_widget_grab_focus (priv->filter_entry);
+
+        priv->showing_extra = TRUE;
+
+        egg_list_box_refilter (EGG_LIST_BOX (priv->language_list));
 }
 
-static gboolean
-filter_languages (GtkTreeModel *model,
-		  GtkTreeIter  *iter,
-		  gpointer      data)
+static void
+child_activated (EggListBox        *box,
+                 GtkWidget         *child,
+                 GtkDialog *chooser)
 {
-	const gchar *filter_string;
-	gchar *locale, *l;
-	gboolean visible;
+        CcLanguageChooserPrivate *priv = GET_PRIVATE (chooser);
+        gchar *new_locale_id;
+
+        if (priv->adding_languages)
+                return;
+
+        if (child == NULL)
+                return;
+
+        if (child == priv->no_results)
+                return;
+
+        if (child == priv->more_item) {
+                show_more (chooser);
+                return;
+        }
+        new_locale_id = g_object_get_data (G_OBJECT (child), "locale-id");
+        set_locale_id (chooser, new_locale_id);
+}
+
+typedef struct {
+        gint count;
+        GtkWidget *ignore;
+} CountChildrenData;
 
-	filter_string = g_object_get_data (G_OBJECT (model), "filter-string");
+static void
+count_visible_children (GtkWidget *widget,
+                        gpointer   user_data)
+{
+        CountChildrenData *data = user_data;
+        if (widget != data->ignore &&
+            gtk_widget_get_child_visible (widget) &&
+            gtk_widget_get_visible (widget))
+                data->count++;
+}
 
-	if (filter_string == NULL)
-		return TRUE;
+static void
+end_refilter (EggListBox *list_box,
+              gpointer    user_data)
+{
+        GtkDialog *chooser = user_data;
+        CcLanguageChooserPrivate *priv = GET_PRIVATE (chooser);
+        CountChildrenData data = { 0 };
 
-	gtk_tree_model_get (model, iter, DISPLAY_LOCALE_COL, &locale, -1);
-	if (locale == NULL)
-		return FALSE;
+        data.ignore = priv->no_results;
 
-	l = g_utf8_casefold (locale, -1);
+        gtk_container_foreach (GTK_CONTAINER (list_box),
+                               count_visible_children, &data);
 
-	visible = strstr (l, filter_string) != NULL;
+        gtk_widget_set_visible (priv->no_results, (data.count == 0));
+}
 
-	g_free (locale);
-	g_free (l);
+static void
+cc_language_chooser_private_free (gpointer data)
+{
+        CcLanguageChooserPrivate *priv = data;
 
-	return visible;
+        g_strfreev (priv->filter_words);
+        g_free (priv->language);
+        g_free (priv);
 }
 
+#define WID(name) ((GtkWidget *) gtk_builder_get_object (builder, name))
+
 GtkWidget *
-cc_language_chooser_new (GtkWidget *parent, gboolean regions)
+cc_language_chooser_new (GtkWidget *parent)
 {
         GtkBuilder *builder;
-        GError *error = NULL;
         GtkWidget *chooser;
-        GtkWidget *list;
-        GtkWidget *button;
-	GtkWidget *entry;
-        GHashTable *user_langs;
-        GdkCursor *cursor;
-        guint timeout;
-	GtkTreeModel *model;
-	GtkTreeModel *filter_model;
+        CcLanguageChooserPrivate *priv;
+        GError *error = NULL;
 
         g_resources_register (cc_common_get_resource ());
 
         builder = gtk_builder_new ();
-        if (!gtk_builder_add_from_resource (builder,
-                                            "/org/gnome/control-center/common/language-chooser.ui",
-                                            &error)) {
+        if (gtk_builder_add_from_resource (builder, "/org/gnome/control-center/common/language-chooser.ui", &error) == 0) {
+                g_object_unref (builder);
                 g_warning ("failed to load language chooser: %s", error->message);
                 g_error_free (error);
                 return NULL;
         }
 
-        chooser = (GtkWidget *) gtk_builder_get_object (builder, "dialog");
-        gtk_window_set_default_size (GTK_WINDOW (chooser), 250, 400);
+        chooser = WID ("language-dialog");
+        priv = g_new0 (CcLanguageChooserPrivate, 1);
+        g_object_set_data_full (G_OBJECT (chooser), "private", priv, cc_language_chooser_private_free);
+        g_object_set_data_full (G_OBJECT (chooser), "builder", builder, g_object_unref);
 
-        if (regions) {
-                gtk_window_set_title (GTK_WINDOW (chooser), _("Select a region"));
-                /* communicate the preference to finish_language_chooser() */
-                g_object_set_data (G_OBJECT (chooser), "regions", GINT_TO_POINTER (TRUE));
-        }
+        priv->filter_entry = WID ("language-filter-entry");
+        priv->language_list = WID ("language-list");
+        priv->scrolledwindow = WID ("language-scrolledwindow");
+        priv->more_item = more_widget_new ();
+        priv->no_results = no_results_widget_new ();
 
-        list = (GtkWidget *) gtk_builder_get_object (builder, "language-list");
-        g_object_set_data (G_OBJECT (chooser), "list", list);
-        g_signal_connect (list, "row-activated",
-                          G_CALLBACK (row_activated), chooser);
+        egg_list_box_set_adjustment (EGG_LIST_BOX (priv->language_list),
+                                     gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow)));
 
-        button = (GtkWidget *) gtk_builder_get_object (builder, "ok-button");
-        gtk_widget_grab_default (button);
+        egg_list_box_set_sort_func (EGG_LIST_BOX (priv->language_list),
+                                    sort_languages, chooser, NULL);
+        egg_list_box_set_filter_func (EGG_LIST_BOX (priv->language_list),
+                                      language_visible, chooser, NULL);
+        egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->language_list),
+                                         GTK_SELECTION_NONE);
+        add_all_languages (GTK_DIALOG (chooser));
 
-	entry = (GtkWidget *) gtk_builder_get_object (builder, "filter-entry");
-        g_object_set_data (G_OBJECT (chooser), "filter-entry", entry);
-	g_signal_connect (entry, "notify::text",
-			  G_CALLBACK (filter_changed), list);
-	g_signal_connect (entry, "icon-release",
-			  G_CALLBACK (filter_clear), NULL);
-        gtk_widget_grab_focus (entry);
+        g_signal_connect_swapped (priv->filter_entry, "changed",
+                                  G_CALLBACK (filter_changed), chooser);
 
-	user_langs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-	cc_common_language_setup_list (list, user_langs, NULL);
+        g_signal_connect (priv->language_list, "child-activated",
+                          G_CALLBACK (child_activated), chooser);
 
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (list));
-	filter_model = gtk_tree_model_filter_new (model, NULL);
-	gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter_model), filter_languages,
-						NULL, NULL);
-	gtk_tree_view_set_model (GTK_TREE_VIEW (list), filter_model);
+        g_signal_connect_after (priv->language_list, "refilter",
+                                G_CALLBACK (end_refilter), chooser);
 
-	/* Setup so that the list is added after the dialogue is shown */
-        cursor = gdk_cursor_new (GDK_WATCH);
-        gdk_window_set_cursor (gtk_widget_get_window (parent), cursor);
-        g_object_unref (cursor);
+        egg_list_box_refilter (EGG_LIST_BOX (priv->language_list));
 
         gtk_window_set_transient_for (GTK_WINDOW (chooser), GTK_WINDOW (parent));
 
-	g_object_set_data_full (G_OBJECT (chooser), "user-langs",
-				user_langs, (GDestroyNotify) g_hash_table_destroy);
-        timeout = g_idle_add ((GSourceFunc) finish_language_chooser, chooser);
-        g_object_set_data (G_OBJECT (chooser), "timeout", GUINT_TO_POINTER (timeout));
-        g_object_weak_ref (G_OBJECT (chooser), (GWeakNotify) remove_timeout, GUINT_TO_POINTER (timeout));
+        return chooser;
+}
 
-        g_object_unref (builder);
+void
+cc_language_chooser_clear_filter (GtkWidget *chooser)
+{
+        CcLanguageChooserPrivate *priv = GET_PRIVATE (chooser);
 
-        return chooser;
+        gtk_entry_set_text (GTK_ENTRY (priv->filter_entry), "");
+}
+
+const gchar *
+cc_language_chooser_get_language (GtkWidget *chooser)
+{
+        CcLanguageChooserPrivate *priv = GET_PRIVATE (chooser);
+
+        return priv->language;
+}
+
+void
+cc_language_chooser_set_language (GtkWidget   *chooser,
+                                  const gchar *language)
+{
+        set_locale_id (GTK_DIALOG (chooser), language);
 }
diff --git a/panels/common/cc-language-chooser.h b/panels/common/cc-language-chooser.h
index da557dc..fb288c2 100644
--- a/panels/common/cc-language-chooser.h
+++ b/panels/common/cc-language-chooser.h
@@ -1,38 +1,39 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+/*
+ * Copyright (C) 2013 Red Hat, Inc
  *
- * Copyright 2009-2010  Red Hat, Inc,
+ * 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 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.
+ * 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.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
  *
- * Written by: Matthias Clasen <mclasen@redhat.com>
+ * Written by:
+ *     Matthias Clasen
  */
 
 #ifndef __CC_LANGUAGE_CHOOSER_H__
 #define __CC_LANGUAGE_CHOOSER_H__
 
 #include <gtk/gtk.h>
+#include <glib-object.h>
 
 G_BEGIN_DECLS
 
-void              cc_add_user_languages            (GtkTreeModel *model);
-
-GtkWidget        *cc_language_chooser_new          (GtkWidget *parent,
-                                                    gboolean   regions);
-void              cc_language_chooser_clear_filter (GtkWidget *chooser);
-gchar            *cc_language_chooser_get_language (GtkWidget *chooser);
+GtkWidget   *cc_language_chooser_new          (GtkWidget   *parent);
+void         cc_language_chooser_clear_filter (GtkWidget   *chooser);
+const gchar *cc_language_chooser_get_language (GtkWidget   *chooser);
+void         cc_language_chooser_set_language (GtkWidget   *chooser,
+                                               const gchar *language);
 
 G_END_DECLS
 
-#endif
+#endif /* __CC_LANGUAGE_CHOOSER_H__ */
diff --git a/panels/common/cc-util.c b/panels/common/cc-util.c
new file mode 100644
index 0000000..e51a9d2
--- /dev/null
+++ b/panels/common/cc-util.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
+ *
+ * The Control Center 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.
+ *
+ * The Control Center 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 the Control Center; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+
+#include "cc-util.h"
+
+/* Combining diacritical mark?
+ *  Basic range: [0x0300,0x036F]
+ *  Supplement:  [0x1DC0,0x1DFF]
+ *  For Symbols: [0x20D0,0x20FF]
+ *  Half marks:  [0xFE20,0xFE2F]
+ */
+#define IS_CDM_UCS4(c) (((c) >= 0x0300 && (c) <= 0x036F)  || \
+                        ((c) >= 0x1DC0 && (c) <= 0x1DFF)  || \
+                        ((c) >= 0x20D0 && (c) <= 0x20FF)  || \
+                        ((c) >= 0xFE20 && (c) <= 0xFE2F))
+
+/* Copied from tracker/src/libtracker-fts/tracker-parser-glib.c under the GPL
+ * And then from gnome-shell/src/shell-util.c
+ *
+ * Originally written by Aleksander Morgado <aleksander@gnu.org>
+ */
+char *
+cc_util_normalize_casefold_and_unaccent (const char *str)
+{
+  char *normalized, *tmp;
+  int i = 0, j = 0, ilen;
+
+  if (str == NULL)
+    return NULL;
+
+  normalized = g_utf8_normalize (str, -1, G_NORMALIZE_NFKD);
+  tmp = g_utf8_casefold (normalized, -1);
+  g_free (normalized);
+
+  ilen = strlen (tmp);
+
+  while (i < ilen)
+    {
+      gunichar unichar;
+      gchar *next_utf8;
+      gint utf8_len;
+
+      /* Get next character of the word as UCS4 */
+      unichar = g_utf8_get_char_validated (&tmp[i], -1);
+
+      /* Invalid UTF-8 character or end of original string. */
+      if (unichar == (gunichar) -1 ||
+          unichar == (gunichar) -2)
+        {
+          break;
+        }
+
+      /* Find next UTF-8 character */
+      next_utf8 = g_utf8_next_char (&tmp[i]);
+      utf8_len = next_utf8 - &tmp[i];
+
+      if (IS_CDM_UCS4 ((guint32) unichar))
+        {
+          /* If the given unichar is a combining diacritical mark,
+           * just update the original index, not the output one */
+          i += utf8_len;
+          continue;
+        }
+
+      /* If already found a previous combining
+       * diacritical mark, indexes are different so
+       * need to copy characters. As output and input
+       * buffers may overlap, need to use memmove
+       * instead of memcpy */
+      if (i != j)
+        {
+          memmove (&tmp[j], &tmp[i], utf8_len);
+        }
+
+      /* Update both indexes */
+      i += utf8_len;
+      j += utf8_len;
+    }
+
+  /* Force proper string end */
+  tmp[j] = '\0';
+
+  return tmp;
+}
diff --git a/panels/common/cc-util.h b/panels/common/cc-util.h
new file mode 100644
index 0000000..42b09ff
--- /dev/null
+++ b/panels/common/cc-util.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
+ *
+ * The Control Center 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.
+ *
+ * The Control Center 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 the Control Center; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+
+#ifndef _CC_UTIL_H
+#define _CC_UTIL_H
+
+#include <glib.h>
+
+char *cc_util_normalize_casefold_and_unaccent (const char *str);
+
+#endif
diff --git a/panels/common/language-chooser.ui b/panels/common/language-chooser.ui
index 5665938..c2ea28b 100644
--- a/panels/common/language-chooser.ui
+++ b/panels/common/language-chooser.ui
@@ -1,108 +1,68 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
-  <object class="GtkDialog" id="dialog">
-    <property name="height_request">400</property>
-    <property name="border_width">5</property>
+  <object class="GtkDialog" id="language-dialog">
+    <property name="title" translatable="yes">Language</property>
     <property name="modal">True</property>
-    <property name="window_position">center-on-parent</property>
-    <property name="type_hint">dialog</property>
-    <property name="title" translatable="yes">Select a language</property>
-    <property name="icon_name">system-users</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="resizable">False</property>
     <child internal-child="vbox">
-      <object class="GtkBox" id="content-area">
+      <object class="GtkBox" id="language-vbox">
         <property name="visible">True</property>
         <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
+        <property name="spacing">0</property>
         <child>
-          <object class="GtkBox" id="content-box">
+          <object class="GtkScrolledWindow" id="language-scrolledwindow">
             <property name="visible">True</property>
-            <property name="orientation">vertical</property>
-            <property name="border_width">5</property>
-            <property name="spacing">6</property>
+            <property name="hscrollbar-policy">never</property>
+            <property name="vscrollbar-policy">never</property>
+            <property name="shadow-type">in</property>
+            <property name="margin-left">6</property>
+            <property name="margin-right">6</property>
+            <property name="margin-top">6</property>
+            <property name="margin-bottom">6</property>
             <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow1">
+              <object class="GtkViewport" id="language-viewport">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="hscrollbar_policy">never</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <property name="shadow_type">in</property>
                 <child>
-                  <object class="GtkTreeView" id="language-list">
+                  <object class="EggListBox" id="language-list">
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="headers_visible">False</property>
-                    <property name="headers_clickable">False</property>
-                    <property name="enable_search">False</property>
+                    <property name="can-focus">True</property>
+                    <property name="vexpand">True</property>
+                    <property name="halign">fill</property>
+                    <property name="valign">fill</property>
                   </object>
                 </child>
               </object>
-              <packing>
-                <property name="position">0</property>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkEntry" id="filter-entry">
-                <property name="visible">True</property>
-	        <property name="can_focus">True</property>
-	        <property name="secondary_icon_name">edit-find-symbolic</property>
-	        <property name="secondary_icon_activatable">False</property>
-	        <property name="secondary_icon_sensitive">False</property>
-              </object>
-              <packing>
-                <property name="position">1</property>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-              </packing>
             </child>
           </object>
         </child>
+        <child>
+          <object class="GtkSearchEntry" id="language-filter-entry">
+            <property name="visible">False</property>
+            <property name="hexpand">True</property>
+            <property name="margin-left">6</property>
+            <property name="margin-right">6</property>
+            <property name="margin-top">6</property>
+            <property name="margin-bottom">6</property>
+          </object>
+        </child>
         <child internal-child="action_area">
-          <object class="GtkButtonBox" id="action-area">
+          <object class="GtkButtonBox" id="language-action-area">
             <property name="visible">True</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="cancel-button">
-                <property name="label" translatable="yes">_Cancel</property>
-                <property name="use_underline">True</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
+            <property name="orientation">horizontal</property>
             <child>
               <object class="GtkButton" id="ok-button">
-                <property name="label" translatable="yes">_Select</property>
-                <property name="use_underline">True</property>
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="receives_default">True</property>
+                <property name="label" translatable="yes">_Done</property>
+                <property name="use_underline" >True</property>
               </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
             </child>
           </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
         </child>
       </object>
     </child>
     <action-widgets>
-      <action-widget response="-6">cancel-button</action-widget>
       <action-widget response="-5">ok-button</action-widget>
     </action-widgets>
   </object>
diff --git a/panels/keyboard/gnome-keyboard-panel.ui b/panels/keyboard/gnome-keyboard-panel.ui
index cce05ee..dcd3b36 100644
--- a/panels/keyboard/gnome-keyboard-panel.ui
+++ b/panels/keyboard/gnome-keyboard-panel.ui
@@ -630,7 +630,7 @@
                     <property name="can_focus">False</property>
                     <child>
                       <object class="GtkLinkButton" id="linkbutton">
-                        <property name="label" translatable="yes">Layout Settings</property>
+                        <property name="label" translatable="yes">Input Sources</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">True</property>
diff --git a/panels/keyboard/keyboard-general.c b/panels/keyboard/keyboard-general.c
index 7b4af75..26c1db0 100644
--- a/panels/keyboard/keyboard-general.c
+++ b/panels/keyboard/keyboard-general.c
@@ -61,10 +61,9 @@ layout_link_clicked (GtkLinkButton *button,
 {
   CcShell *shell;
   GError *error = NULL;
-  const char *argv[] = { "layouts", NULL };
 
   shell = cc_panel_get_shell (panel);
-  if (cc_shell_set_active_panel_from_id (shell, "region", argv, &error) == FALSE)
+  if (cc_shell_set_active_panel_from_id (shell, "region", NULL, &error) == FALSE)
     {
       g_warning ("Failed to activate Region panel: %s", error->message);
       g_error_free (error);
diff --git a/panels/region/Makefile.am b/panels/region/Makefile.am
index 8f6a6cb..e334259 100644
--- a/panels/region/Makefile.am
+++ b/panels/region/Makefile.am
@@ -4,8 +4,8 @@ cappletname = region
 INCLUDES =						\
 	$(PANEL_CFLAGS)					\
 	$(REGION_PANEL_CFLAGS)				\
-	-DGNOMELOCALEDIR="\"$(datadir)/locale\""	\
 	-I$(srcdir)/../common/				\
+	-I$(top_srcdir)/libgd/				\
 	$(NULL)
 
 noinst_LTLIBRARIES = libregion.la
@@ -18,17 +18,21 @@ libregion_la_SOURCES =	\
 	$(BUILT_SOURCES) \
 	cc-region-panel.c \
 	cc-region-panel.h \
-	gnome-region-panel-formats.c \
-	gnome-region-panel-formats.h \
-	gnome-region-panel-lang.c \
-	gnome-region-panel-lang.h \
-	gnome-region-panel-system.c \
-	gnome-region-panel-system.h \
-	gnome-region-panel-input.c \
-	gnome-region-panel-input.h \
+	cc-format-chooser.c \
+	cc-format-chooser.h \
+	cc-input-options.c \
+	cc-input-options.h \
+	cc-input-chooser.c \
+	cc-input-chooser.h \
+	cc-ibus-utils.c	\
+	cc-ibus-utils.h \
 	$(NULL)
 
-libregion_la_LIBADD = $(PANEL_LIBS) $(REGION_PANEL_LIBS) $(builddir)/../common/liblanguage.la
+libregion_la_LIBADD = \
+	$(PANEL_LIBS) \
+	$(REGION_PANEL_LIBS) \
+	$(top_builddir)/libgd/libgd.la \
+	$(builddir)/../common/liblanguage.la
 
 resource_files = $(shell glib-compile-resources --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/region.gresource.xml)
 cc-region-resources.c: region.gresource.xml $(resource_files)
diff --git a/panels/region/cc-format-chooser.c b/panels/region/cc-format-chooser.c
new file mode 100644
index 0000000..a52bf0f
--- /dev/null
+++ b/panels/region/cc-format-chooser.c
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Written by:
+ *     Matthias Clasen
+ */
+
+#define _GNU_SOURCE
+#include <config.h>
+#include "cc-format-chooser.h"
+
+#include <locale.h>
+#include <langinfo.h>
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include "egg-list-box/egg-list-box.h"
+
+#include "cc-common-language.h"
+#include "cc-util.h"
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-languages.h>
+
+
+typedef struct {
+        GtkWidget *no_results;
+        GtkWidget *more_item;
+        GtkWidget *filter_entry;
+        GtkWidget *list;
+        GtkWidget *scrolledwindow;
+        GtkWidget *full_date;
+        GtkWidget *medium_date;
+        GtkWidget *short_date;
+        GtkWidget *time;
+        GtkWidget *number;
+        GtkWidget *measurement;
+        GtkWidget *paper;
+        gboolean adding;
+        gboolean showing_extra;
+        gchar *region;
+        gchar **filter_words;
+} CcFormatChooserPrivate;
+
+#define GET_PRIVATE(chooser) ((CcFormatChooserPrivate *) g_object_get_data (G_OBJECT (chooser), "private"))
+
+static void
+display_date (GtkWidget *label, GDateTime *dt, const gchar *format)
+{
+        gchar *s;
+        s = g_date_time_format (dt, format);
+        s = g_strstrip (s);
+        gtk_label_set_text (GTK_LABEL (label), s);
+        g_free (s);
+}
+
+static void
+update_format_examples (GtkDialog *chooser)
+{
+        CcFormatChooserPrivate *priv = GET_PRIVATE (chooser);
+        gchar *locale;
+        GDateTime *dt;
+        gchar *s;
+        const gchar *fmt;
+        GtkPaperSize *paper;
+
+        locale = g_strdup (setlocale (LC_TIME, NULL));
+        setlocale (LC_TIME, priv->region);
+
+        dt = g_date_time_new_now_local ();
+        display_date (priv->full_date, dt, "%A %e %B %Y");
+        display_date (priv->medium_date, dt, "%e %b %Y");
+        display_date (priv->short_date, dt, "%x");
+        display_date (priv->time, dt, "%X");
+
+        setlocale (LC_TIME, locale);
+        g_free (locale);
+
+        locale = g_strdup (setlocale (LC_NUMERIC, NULL));
+        setlocale (LC_NUMERIC, priv->region);
+
+        s = g_strdup_printf ("%'.2f", 123456789.00);
+        gtk_label_set_text (GTK_LABEL (priv->number), s);
+        g_free (s);
+
+        setlocale (LC_NUMERIC, locale);
+        g_free (locale);
+
+#if 0
+        locale = g_strdup (setlocale (LC_MONETARY, NULL));
+        setlocale (LC_MONETARY, priv->region);
+
+        num_info = localeconv ();
+        if (num_info != NULL)
+                gtk_label_set_text (GTK_LABEL (priv->currency), num_info->currency_symbol);
+
+        setlocale (LC_MONETARY, locale);
+        g_free (locale);
+#endif
+
+#ifdef LC_MEASUREMENT
+        locale = g_strdup (setlocale (LC_MEASUREMENT, NULL));
+        setlocale (LC_MEASUREMENT, priv->region);
+
+        fmt = nl_langinfo (_NL_MEASUREMENT_MEASUREMENT);
+        if (fmt && *fmt == 2)
+                gtk_label_set_text (GTK_LABEL (priv->measurement), C_("measurement format", "Imperial"));
+        else
+                gtk_label_set_text (GTK_LABEL (priv->measurement), C_("measurement format", "Metric"));
+
+        setlocale (LC_MEASUREMENT, locale);
+        g_free (locale);
+#endif
+
+#ifdef LC_PAPER
+        locale = g_strdup (setlocale (LC_PAPER, NULL));
+        setlocale (LC_PAPER, priv->region);
+
+        paper = gtk_paper_size_new (gtk_paper_size_get_default ());
+        gtk_label_set_text (GTK_LABEL (priv->paper), gtk_paper_size_get_display_name (paper));
+        gtk_paper_size_free (paper);
+
+        setlocale (LC_PAPER, locale);
+        g_free (locale);
+#endif
+}
+
+static void
+set_locale_id (GtkDialog   *chooser,
+               const gchar *locale_id)
+{
+        CcFormatChooserPrivate *priv = GET_PRIVATE (chooser);
+        GList *children, *l;
+
+        children = gtk_container_get_children (GTK_CONTAINER (priv->list));
+        for (l = children; l; l = l->next) {
+                GtkWidget *row = l->data;
+                GtkWidget *check = g_object_get_data (G_OBJECT (row), "check");
+                const gchar *region = g_object_get_data (G_OBJECT (row), "locale-id");
+                if (check == NULL || region == NULL)
+                        continue;
+
+                if (g_strcmp0 (locale_id, region) == 0) {
+                        gboolean is_extra;
+
+                        /* mark as selected */
+                        gtk_image_set_from_icon_name (GTK_IMAGE (check), "object-select-symbolic", GTK_ICON_SIZE_MENU);
+
+                        /* make sure this row is shown */
+                        is_extra = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (row), "is-extra"));
+                        if (!priv->showing_extra && is_extra) {
+                                g_object_set_data (G_OBJECT (row), "is-extra", GINT_TO_POINTER (FALSE));
+                                egg_list_box_refilter (EGG_LIST_BOX (priv->list));
+                        }
+
+                } else {
+                        /* mark as unselected */
+                        gtk_image_clear (GTK_IMAGE (check));
+                        g_object_set (check, "icon-size", GTK_ICON_SIZE_MENU, NULL);
+                }
+        }
+        g_list_free (children);
+
+        g_free (priv->region);
+        priv->region = g_strdup (locale_id);
+
+        update_format_examples (chooser);
+}
+
+static gint
+sort_regions (gconstpointer a,
+              gconstpointer b,
+              gpointer      data)
+{
+        const gchar *la;
+        const gchar *lb;
+
+        if (g_object_get_data (G_OBJECT (a), "locale-id") == NULL)
+                return 1;
+        if (g_object_get_data (G_OBJECT (b), "locale-id") == NULL)
+                return -1;
+
+        la = g_object_get_data (G_OBJECT (a), "locale-name");
+        lb = g_object_get_data (G_OBJECT (b), "locale-name");
+
+        return g_strcmp0 (la, lb);
+}
+
+static GtkWidget *
+padded_label_new (char *text, gboolean narrow)
+{
+        GtkWidget *widget;
+
+        widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
+        gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
+        gtk_widget_set_margin_top (widget, 10);
+        gtk_widget_set_margin_bottom (widget, 10);
+        gtk_widget_set_margin_left (widget, narrow ? 10 : 80);
+        gtk_widget_set_margin_right (widget, narrow ? 10 : 80);
+        gtk_box_pack_start (GTK_BOX (widget), gtk_label_new (text), FALSE, FALSE, 0);
+
+        return widget;
+}
+
+static GtkWidget *
+region_widget_new (const gchar *locale_id,
+                   gboolean     is_extra)
+{
+        gchar *locale_name;
+        gchar *locale_current_name;
+        gchar *locale_untranslated_name;
+        GtkWidget *widget;
+        GtkWidget *check;
+
+        locale_name = gnome_get_country_from_locale (locale_id, locale_id);
+        locale_current_name = gnome_get_country_from_locale (locale_id, NULL);
+        locale_untranslated_name = gnome_get_country_from_locale (locale_id, "C");
+
+        widget = padded_label_new (locale_name, is_extra);
+
+        check = gtk_image_new ();
+        g_object_set (check, "icon-size", GTK_ICON_SIZE_MENU, NULL);
+        gtk_box_pack_start (GTK_BOX (widget), check, FALSE, FALSE, 0);
+
+        g_object_set_data (G_OBJECT (widget), "check", check);
+        g_object_set_data_full (G_OBJECT (widget), "locale-id", g_strdup (locale_id), g_free);
+        g_object_set_data_full (G_OBJECT (widget), "locale-name", locale_name, g_free);
+        g_object_set_data_full (G_OBJECT (widget), "locale-current-name", locale_current_name, g_free);
+        g_object_set_data_full (G_OBJECT (widget), "locale-untranslated-name", locale_untranslated_name, g_free);
+        g_object_set_data (G_OBJECT (widget), "is-extra", GUINT_TO_POINTER (is_extra));
+
+        return widget;
+}
+
+static GtkWidget *
+more_widget_new (void)
+{
+        GtkWidget *widget;
+
+        widget = padded_label_new ("…", FALSE);
+        gtk_widget_set_tooltip_text (widget, _("More…"));
+        return widget;
+}
+
+static GtkWidget *
+no_results_widget_new (void)
+{
+        GtkWidget *widget;
+
+        widget = padded_label_new (_("No regions found"), TRUE);
+        gtk_widget_set_sensitive (widget, FALSE);
+        return widget;
+}
+
+static void
+add_regions (GtkDialog   *chooser,
+             gchar      **locale_ids,
+             GHashTable  *initial)
+{
+        CcFormatChooserPrivate *priv = GET_PRIVATE (chooser);
+
+        priv->adding = TRUE;
+
+        while (*locale_ids) {
+                gchar *locale_id;
+                gboolean is_initial;
+                GtkWidget *widget;
+
+                locale_id = *locale_ids;
+                locale_ids ++;
+
+                if (!cc_common_language_has_font (locale_id))
+                        continue;
+
+                is_initial = (g_hash_table_lookup (initial, locale_id) != NULL);
+                widget = region_widget_new (locale_id, !is_initial);
+                gtk_container_add (GTK_CONTAINER (priv->list), widget);
+        }
+
+        gtk_container_add (GTK_CONTAINER (priv->list), priv->more_item);
+        gtk_container_add (GTK_CONTAINER (priv->list), priv->no_results);
+
+        gtk_widget_show_all (priv->list);
+
+        priv->adding = FALSE;
+}
+
+static void
+add_all_regions (GtkDialog *chooser)
+{
+        gchar **locale_ids;
+        GHashTable *initial;
+
+        locale_ids = gnome_get_all_locales ();
+        initial = cc_common_language_get_initial_languages ();
+        add_regions (chooser, locale_ids, initial);
+        g_hash_table_destroy (initial);
+        g_strfreev (locale_ids);
+}
+
+static gboolean
+match_all (gchar       **words,
+           const gchar  *str)
+{
+        gchar **w;
+
+        for (w = words; *w; ++w)
+                if (!strstr (str, *w))
+                        return FALSE;
+
+        return TRUE;
+}
+
+static gboolean
+region_visible (GtkWidget *child,
+                gpointer   user_data)
+{
+        GtkDialog *chooser = user_data;
+        CcFormatChooserPrivate *priv = GET_PRIVATE (chooser);
+        gchar *locale_name = NULL;
+        gchar *locale_current_name = NULL;
+        gchar *locale_untranslated_name = NULL;
+        gboolean is_extra;
+        gboolean visible;
+
+        if (child == priv->more_item)
+                return !priv->showing_extra;
+
+        /* We hide this in the after-refilter handler below. */
+        if (child == priv->no_results)
+                return TRUE;
+
+        is_extra = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (child), "is-extra"));
+
+        if (!priv->showing_extra && is_extra)
+                return FALSE;
+
+        if (!priv->filter_words)
+                return TRUE;
+
+        visible = FALSE;
+
+        locale_name =
+                cc_util_normalize_casefold_and_unaccent (g_object_get_data (G_OBJECT (child), "locale-name"));
+        visible = match_all (priv->filter_words, locale_name);
+        if (visible)
+                 goto out;
+
+        locale_current_name =
+                cc_util_normalize_casefold_and_unaccent (g_object_get_data (G_OBJECT (child), "locale-current-name"));
+        visible = match_all (priv->filter_words, locale_current_name);
+        if (visible)
+                 goto out;
+
+        locale_untranslated_name =
+                cc_util_normalize_casefold_and_unaccent (g_object_get_data (G_OBJECT (child), "locale-untranslated-name"));
+        visible = match_all (priv->filter_words, locale_untranslated_name);
+
+out:
+        g_free (locale_untranslated_name);
+        g_free (locale_current_name);
+        g_free (locale_name);
+        return visible;
+}
+
+static void
+filter_changed (GtkDialog *chooser)
+{
+        CcFormatChooserPrivate *priv = GET_PRIVATE (chooser);
+        gchar *filter_contents = NULL;
+
+        g_clear_pointer (&priv->filter_words, g_strfreev);
+
+        filter_contents =
+                cc_util_normalize_casefold_and_unaccent (gtk_entry_get_text (GTK_ENTRY (priv->filter_entry)));
+        if (!filter_contents) {
+                egg_list_box_refilter (EGG_LIST_BOX (priv->list));
+                return;
+        }
+        priv->filter_words = g_strsplit_set (g_strstrip (filter_contents), " ", 0);
+        g_free (filter_contents);
+        egg_list_box_refilter (EGG_LIST_BOX (priv->list));
+}
+
+static void
+show_more (GtkDialog *chooser)
+{
+        CcFormatChooserPrivate *priv = GET_PRIVATE (chooser);
+        GtkWidget *widget;
+        gint width, height;
+
+        gtk_window_get_size (GTK_WINDOW (chooser), &width, &height);
+        gtk_widget_set_size_request (GTK_WIDGET (chooser), width, height);
+        gtk_window_set_resizable (GTK_WINDOW (chooser), TRUE);
+
+        widget = priv->scrolledwindow;
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget),
+                                        GTK_POLICY_NEVER,
+                                        GTK_POLICY_AUTOMATIC);
+
+        gtk_widget_show (priv->filter_entry);
+        gtk_widget_grab_focus (priv->filter_entry);
+
+        priv->showing_extra = TRUE;
+
+        egg_list_box_refilter (EGG_LIST_BOX (priv->list));
+}
+
+static void
+child_activated (EggListBox  *box,
+                 GtkWidget   *child,
+                 GtkDialog   *chooser)
+{
+        CcFormatChooserPrivate *priv = GET_PRIVATE (chooser);
+        gchar *new_locale_id;
+
+        if (priv->adding)
+                return;
+
+        if (child == NULL)
+                return;
+
+        if (child == priv->no_results)
+                return;
+
+        if (child == priv->more_item) {
+                show_more (chooser);
+                return;
+        }
+        new_locale_id = g_object_get_data (G_OBJECT (child), "locale-id");
+        set_locale_id (chooser, new_locale_id);
+}
+
+typedef struct {
+        gint count;
+        GtkWidget *ignore;
+} CountChildrenData;
+
+static void
+count_visible_children (GtkWidget *widget,
+                        gpointer   user_data)
+{
+        CountChildrenData *data = user_data;
+        if (widget!= data->ignore &&
+            gtk_widget_get_child_visible (widget) &&
+            gtk_widget_get_visible (widget))
+                data->count++;
+}
+
+static void
+end_refilter (EggListBox *list_box,
+              gpointer    user_data)
+{
+        GtkDialog *chooser = user_data;
+        CcFormatChooserPrivate *priv = GET_PRIVATE (chooser);
+        CountChildrenData data = { 0 };
+
+        data.ignore = priv->no_results;
+        gtk_container_foreach (GTK_CONTAINER (list_box),
+                               count_visible_children, &data);
+
+        gtk_widget_set_visible (priv->no_results, (data.count == 0));
+}
+
+static void
+cc_format_chooser_private_free (gpointer data)
+{
+        CcFormatChooserPrivate *priv = data;
+
+        g_strfreev (priv->filter_words);
+        g_free (priv->region);
+        g_free (priv);
+}
+
+#define WID(name) ((GtkWidget *) gtk_builder_get_object (builder, name))
+
+GtkWidget *
+cc_format_chooser_new (GtkWidget *parent)
+{
+        GtkBuilder *builder;
+        GtkWidget *chooser;
+        CcFormatChooserPrivate *priv;
+        GError *error = NULL;
+
+        builder = gtk_builder_new ();
+        if (gtk_builder_add_from_resource (builder, "/org/gnome/control-center/region/format-chooser.ui", &error) == 0) {
+                g_object_unref (builder);
+                g_warning ("failed to load format chooser: %s", error->message);
+                g_error_free (error);
+                return NULL;
+        }
+
+        chooser = WID ("dialog");
+        priv = g_new0 (CcFormatChooserPrivate, 1);
+        g_object_set_data_full (G_OBJECT (chooser), "private", priv, cc_format_chooser_private_free);
+        g_object_set_data_full (G_OBJECT (chooser), "builder", builder, g_object_unref);
+
+        priv->filter_entry = WID ("region-filter-entry");
+        priv->list = WID ("region-list");
+        priv->scrolledwindow = WID ("region-scrolledwindow");
+        priv->more_item = more_widget_new ();
+        priv->no_results = no_results_widget_new ();
+
+        priv->full_date = WID ("full-date-format");
+        priv->medium_date = WID ("medium-date-format");
+        priv->short_date = WID ("short-date-format");
+        priv->time = WID ("time-format");
+        priv->number = WID ("number-format");
+        priv->measurement = WID ("measurement-format");
+        priv->paper = WID ("paper-format");
+
+        egg_list_box_set_adjustment (EGG_LIST_BOX (priv->list),
+                                     gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow)));
+
+        egg_list_box_set_sort_func (EGG_LIST_BOX (priv->list),
+                                    sort_regions, chooser, NULL);
+        egg_list_box_set_filter_func (EGG_LIST_BOX (priv->list),
+                                      region_visible, chooser, NULL);
+        egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->list),
+                                         GTK_SELECTION_NONE);
+
+        add_all_regions (GTK_DIALOG (chooser));
+
+        g_signal_connect_swapped (priv->filter_entry, "changed",
+                                  G_CALLBACK (filter_changed), chooser);
+
+        g_signal_connect (priv->list, "child-activated",
+                          G_CALLBACK (child_activated), chooser);
+
+        g_signal_connect_after (priv->list, "refilter",
+                                G_CALLBACK (end_refilter), chooser);
+
+        egg_list_box_refilter (EGG_LIST_BOX (priv->list));
+
+        gtk_window_set_transient_for (GTK_WINDOW (chooser), GTK_WINDOW (parent));
+
+        return chooser;
+}
+
+void
+cc_format_chooser_clear_filter (GtkWidget *chooser)
+{
+        CcFormatChooserPrivate *priv = GET_PRIVATE (chooser);
+
+        gtk_entry_set_text (GTK_ENTRY (priv->filter_entry), "");
+}
+
+const gchar *
+cc_format_chooser_get_region (GtkWidget *chooser)
+{
+        CcFormatChooserPrivate *priv = GET_PRIVATE (chooser);
+
+        return priv->region;
+}
+
+void
+cc_format_chooser_set_region (GtkWidget   *chooser,
+                              const gchar *region)
+{
+        set_locale_id (GTK_DIALOG (chooser), region);
+}
diff --git a/panels/region/cc-format-chooser.h b/panels/region/cc-format-chooser.h
new file mode 100644
index 0000000..77152a7
--- /dev/null
+++ b/panels/region/cc-format-chooser.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc
+ *
+ * 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.
+ *
+ * Written by:
+ *     Matthias Clasen
+ */
+
+#ifndef __CC_FORMAT_CHOOSER_H__
+#define __CC_FORMAT_CHOOSER_H__
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+GtkWidget   *cc_format_chooser_new          (GtkWidget   *parent);
+void         cc_format_chooser_clear_filter (GtkWidget   *chooser);
+const gchar *cc_format_chooser_get_region   (GtkWidget   *chooser);
+void         cc_format_chooser_set_region   (GtkWidget   *chooser,
+                                             const gchar *region);
+
+G_END_DECLS
+
+#endif /* __CC_FORMAT_CHOOSER_H__ */
diff --git a/panels/region/cc-ibus-utils.c b/panels/region/cc-ibus-utils.c
new file mode 100644
index 0000000..54f9fb7
--- /dev/null
+++ b/panels/region/cc-ibus-utils.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc
+ *
+ * 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>
+
+#ifdef HAVE_IBUS
+#include "cc-ibus-utils.h"
+
+gchar *
+engine_get_display_name (IBusEngineDesc *engine_desc)
+{
+        const gchar *name;
+        const gchar *language_code;
+        const gchar *language;
+        gchar *display_name;
+
+        name = ibus_engine_desc_get_longname (engine_desc);
+        language_code = ibus_engine_desc_get_language (engine_desc);
+        language = ibus_get_language_name (language_code);
+        display_name = g_strdup_printf ("%s (%s)", language, name);
+
+        return display_name;
+}
+
+#endif /* HAVE_IBUS */
diff --git a/panels/region/cc-ibus-utils.h b/panels/region/cc-ibus-utils.h
new file mode 100644
index 0000000..12f2545
--- /dev/null
+++ b/panels/region/cc-ibus-utils.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc
+ *
+ * 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 __CC_IBUS_UTILS_H__
+#define __CC_IBUS_UTILS_H__
+
+#include <ibus.h>
+
+G_BEGIN_DECLS
+
+gchar *engine_get_display_name (IBusEngineDesc *engine_desc);
+
+G_END_DECLS
+
+#endif /* __CC_IBUS_UTILS_H__ */
diff --git a/panels/region/cc-input-chooser.c b/panels/region/cc-input-chooser.c
new file mode 100644
index 0000000..70af7a4
--- /dev/null
+++ b/panels/region/cc-input-chooser.c
@@ -0,0 +1,1138 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * 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 <locale.h>
+#include <glib/gi18n.h>
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-languages.h>
+
+#include "egg-list-box/egg-list-box.h"
+
+#include "cc-common-language.h"
+#include "cc-util.h"
+#include "cc-input-chooser.h"
+
+#ifdef HAVE_IBUS
+#include <ibus.h>
+#include "cc-ibus-utils.h"
+#endif  /* HAVE_IBUS */
+
+#define INPUT_SOURCE_TYPE_XKB "xkb"
+#define INPUT_SOURCE_TYPE_IBUS "ibus"
+
+#define ARROW_NEXT "go-next-symbolic"
+#define ARROW_PREV "go-previous-symbolic"
+
+#define MAIN_WINDOW_WIDTH_RATIO 0.60
+
+typedef enum {
+  ROW_TRAVEL_DIRECTION_NONE,
+  ROW_TRAVEL_DIRECTION_FORWARD,
+  ROW_TRAVEL_DIRECTION_BACKWARD
+} RowTravelDirection;
+
+typedef enum {
+  ROW_LABEL_POSITION_START,
+  ROW_LABEL_POSITION_CENTER,
+  ROW_LABEL_POSITION_END
+} RowLabelPosition;
+
+typedef struct {
+  /* Not owned */
+  GtkWidget *add_button;
+  GtkWidget *filter_entry;
+  GtkWidget *list;
+  GtkWidget *scrolledwindow;
+  GtkAdjustment *adjustment;
+  GnomeXkbInfo *xkb_info;
+  GHashTable *ibus_engines;
+
+  /* Owned */
+  GtkWidget *more_item;
+  GtkWidget *no_results;
+  GHashTable *locales;
+  GHashTable *locales_by_language;
+  gboolean showing_extra;
+  gchar **filter_words;
+} CcInputChooserPrivate;
+
+#define GET_PRIVATE(chooser) ((CcInputChooserPrivate *) g_object_get_data (G_OBJECT (chooser), "private"))
+#define WID(name) ((GtkWidget *) gtk_builder_get_object (builder, name))
+
+typedef struct {
+  gchar *id;
+  gchar *name;
+  gchar *unaccented_name;
+  gchar *untranslated_name;
+  GtkWidget *default_input_source_widget;
+  GtkWidget *locale_widget;
+  GtkWidget *back_widget;
+  GHashTable *layout_widgets_by_id;
+  GHashTable *engine_widgets_by_id;
+} LocaleInfo;
+
+static void
+locale_info_free (gpointer data)
+{
+  LocaleInfo *info = data;
+
+  g_free (info->id);
+  g_free (info->name);
+  g_free (info->unaccented_name);
+  g_free (info->untranslated_name);
+  g_object_unref (info->default_input_source_widget);
+  g_object_unref (info->locale_widget);
+  g_object_unref (info->back_widget);
+  g_hash_table_destroy (info->layout_widgets_by_id);
+  g_hash_table_destroy (info->engine_widgets_by_id);
+  g_free (info);
+}
+
+static void
+set_row_widget_margins (GtkWidget *widget)
+{
+  gtk_widget_set_margin_left (widget, 20);
+  gtk_widget_set_margin_right (widget, 20);
+  gtk_widget_set_margin_top (widget, 6);
+  gtk_widget_set_margin_bottom (widget, 6);
+}
+
+static GtkWidget *
+padded_label_new (const gchar        *text,
+                  RowLabelPosition    position,
+                  RowTravelDirection  direction,
+                  gboolean            dim_label)
+{
+  GtkWidget *widget;
+  GtkWidget *label;
+  GtkWidget *arrow;
+  gdouble alignment;
+  gboolean rtl;
+
+  rtl = (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL);
+
+  if (position == ROW_LABEL_POSITION_START)
+    alignment = 0.0;
+  else if (position == ROW_LABEL_POSITION_CENTER)
+    alignment = 0.5;
+  else
+    alignment = 1.0;
+
+  widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+  if (direction == ROW_TRAVEL_DIRECTION_BACKWARD)
+    {
+      arrow = gtk_image_new_from_icon_name (rtl ? ARROW_NEXT : ARROW_PREV,
+                                            GTK_ICON_SIZE_MENU);
+      gtk_box_pack_start (GTK_BOX (widget), arrow, FALSE, TRUE, 0);
+    }
+
+  label = gtk_label_new (text);
+  gtk_misc_set_alignment (GTK_MISC (label), alignment, 0.5);
+  set_row_widget_margins (label);
+  gtk_box_pack_start (GTK_BOX (widget), label, TRUE, TRUE, 0);
+  if (dim_label)
+    gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");
+
+  if (direction == ROW_TRAVEL_DIRECTION_FORWARD)
+    {
+      arrow = gtk_image_new_from_icon_name (rtl ? ARROW_PREV : ARROW_NEXT,
+                                            GTK_ICON_SIZE_MENU);
+      gtk_box_pack_start (GTK_BOX (widget), arrow, FALSE, TRUE, 0);
+    }
+
+  return widget;
+}
+
+static GtkWidget *
+more_widget_new (void)
+{
+  GtkWidget *widget;
+
+  widget = padded_label_new ("…", ROW_LABEL_POSITION_CENTER, ROW_TRAVEL_DIRECTION_NONE, FALSE);
+  gtk_widget_set_tooltip_text (widget, _("More…"));
+
+  return widget;
+}
+
+static GtkWidget *
+no_results_widget_new (void)
+{
+  return padded_label_new (_("No input sources found"), ROW_LABEL_POSITION_CENTER, ROW_TRAVEL_DIRECTION_NONE, TRUE);
+}
+
+static GtkWidget *
+back_widget_new (const gchar *text)
+{
+  return padded_label_new (text, ROW_LABEL_POSITION_CENTER, ROW_TRAVEL_DIRECTION_BACKWARD, TRUE);
+}
+
+static GtkWidget *
+locale_widget_new (const gchar *text)
+{
+  return padded_label_new (text, ROW_LABEL_POSITION_START, ROW_TRAVEL_DIRECTION_FORWARD, FALSE);
+}
+
+static GtkWidget *
+locale_separator_widget_new (const gchar *text)
+{
+  return padded_label_new (text, ROW_LABEL_POSITION_CENTER, ROW_TRAVEL_DIRECTION_NONE, TRUE);
+}
+
+static GtkWidget *
+input_source_widget_new (GtkWidget   *chooser,
+                         const gchar *type,
+                         const gchar *id)
+{
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+  GtkWidget *widget;
+
+  if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
+    {
+      const gchar *display_name;
+
+      gnome_xkb_info_get_layout_info (priv->xkb_info, id, &display_name, NULL, NULL, NULL);
+
+      widget = padded_label_new (display_name,
+                                 ROW_LABEL_POSITION_START,
+                                 ROW_TRAVEL_DIRECTION_NONE,
+                                 FALSE);
+      g_object_set_data (G_OBJECT (widget), "name", (gpointer) display_name);
+      g_object_set_data_full (G_OBJECT (widget), "unaccented-name",
+                              cc_util_normalize_casefold_and_unaccent (display_name), g_free);
+    }
+  else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
+    {
+#ifdef HAVE_IBUS
+      gchar *display_name;
+      GtkWidget *image;
+
+      display_name = engine_get_display_name (g_hash_table_lookup (priv->ibus_engines, id));
+
+      widget = padded_label_new (display_name,
+                                 ROW_LABEL_POSITION_START,
+                                 ROW_TRAVEL_DIRECTION_NONE,
+                                 FALSE);
+      image = gtk_image_new_from_icon_name ("system-run-symbolic", GTK_ICON_SIZE_MENU);
+      set_row_widget_margins (image);
+      gtk_style_context_add_class (gtk_widget_get_style_context (image), "dim-label");
+      gtk_box_pack_start (GTK_BOX (widget), image, FALSE, TRUE, 0);
+
+      g_object_set_data_full (G_OBJECT (widget), "name", display_name, g_free);
+      g_object_set_data_full (G_OBJECT (widget), "unaccented-name",
+                              cc_util_normalize_casefold_and_unaccent (display_name), g_free);
+#else
+      widget = NULL;
+#endif  /* HAVE_IBUS */
+    }
+
+  if (widget)
+    {
+      g_object_set_data (G_OBJECT (widget), "type", (gpointer) type);
+      g_object_set_data (G_OBJECT (widget), "id", (gpointer) id);
+    }
+
+  return widget;
+}
+
+static void
+remove_all_children (GtkContainer *container)
+{
+  GList *list, *l;
+
+  list = gtk_container_get_children (container);
+  for (l = list; l; l = l->next)
+    gtk_container_remove (container, (GtkWidget *) l->data);
+  g_list_free (list);
+}
+
+static void
+set_fixed_size (GtkWidget *chooser)
+{
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+  GtkPolicyType policy;
+  gint width, height;
+
+  gtk_scrolled_window_get_policy (GTK_SCROLLED_WINDOW (priv->scrolledwindow), &policy, NULL);
+  if (policy == GTK_POLICY_AUTOMATIC)
+    return;
+
+  /* Don't let it automatically get wider than the main CC window nor
+     get taller than the initial height */
+  gtk_window_get_size (gtk_window_get_transient_for (GTK_WINDOW (chooser)),
+                       &width, NULL);
+  gtk_window_get_size (GTK_WINDOW (chooser), NULL, &height);
+  gtk_widget_set_size_request (chooser, width * MAIN_WINDOW_WIDTH_RATIO, height);
+
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolledwindow),
+                                  GTK_POLICY_AUTOMATIC,
+                                  GTK_POLICY_AUTOMATIC);
+}
+
+static void
+add_input_source_widgets_for_locale (GtkWidget  *chooser,
+                                     LocaleInfo *info)
+{
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+  GtkWidget *widget;
+  GHashTableIter iter;
+  const gchar *id;
+
+  if (info->default_input_source_widget)
+    gtk_container_add (GTK_CONTAINER (priv->list), info->default_input_source_widget);
+
+  g_hash_table_iter_init (&iter, info->layout_widgets_by_id);
+  while (g_hash_table_iter_next (&iter, (gpointer *) &id, (gpointer *) &widget))
+    gtk_container_add (GTK_CONTAINER (priv->list), widget);
+
+  g_hash_table_iter_init (&iter, info->engine_widgets_by_id);
+  while (g_hash_table_iter_next (&iter, (gpointer *) &id, (gpointer *) &widget))
+    gtk_container_add (GTK_CONTAINER (priv->list), widget);
+}
+
+static void
+show_input_sources_for_locale (GtkWidget   *chooser,
+                               LocaleInfo  *info)
+{
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+
+  set_fixed_size (chooser);
+
+  remove_all_children (GTK_CONTAINER (priv->list));
+
+  if (!info->back_widget)
+    {
+      info->back_widget = g_object_ref_sink (back_widget_new (info->name));
+      g_object_set_data (G_OBJECT (info->back_widget), "back", GINT_TO_POINTER (TRUE));
+      g_object_set_data (G_OBJECT (info->back_widget), "locale-info", info);
+    }
+  gtk_container_add (GTK_CONTAINER (priv->list), info->back_widget);
+
+  add_input_source_widgets_for_locale (chooser, info);
+
+  gtk_widget_show_all (priv->list);
+
+  gtk_adjustment_set_value (priv->adjustment,
+                            gtk_adjustment_get_lower (priv->adjustment));
+  egg_list_box_set_separator_funcs (EGG_LIST_BOX (priv->list), NULL, NULL, NULL);
+  egg_list_box_refilter (EGG_LIST_BOX (priv->list));
+  egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->list), GTK_SELECTION_SINGLE);
+
+  if (gtk_widget_is_visible (priv->filter_entry))
+    gtk_widget_grab_focus (priv->filter_entry);
+}
+
+static gboolean
+is_current_locale (const gchar *locale)
+{
+  return g_strcmp0 (setlocale (LC_CTYPE, NULL), locale) == 0;
+}
+
+static void
+show_locale_widgets (GtkWidget *chooser)
+{
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+  GHashTable *initial;
+  LocaleInfo *info;
+  GHashTableIter iter;
+
+  remove_all_children (GTK_CONTAINER (priv->list));
+
+  if (!priv->showing_extra)
+    initial = cc_common_language_get_initial_languages ();
+
+  g_hash_table_iter_init (&iter, priv->locales);
+  while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info))
+    {
+      if (!info->default_input_source_widget &&
+          !g_hash_table_size (info->layout_widgets_by_id) &&
+          !g_hash_table_size (info->engine_widgets_by_id))
+        continue;
+
+      if (!info->locale_widget)
+        {
+          info->locale_widget = g_object_ref_sink (locale_widget_new (info->name));
+          g_object_set_data (G_OBJECT (info->locale_widget), "locale-info", info);
+
+          if (!priv->showing_extra &&
+              !g_hash_table_contains (initial, info->id) &&
+              !is_current_locale (info->id))
+            g_object_set_data (G_OBJECT (info->locale_widget), "is-extra", GINT_TO_POINTER (TRUE));
+        }
+      gtk_container_add (GTK_CONTAINER (priv->list), info->locale_widget);
+    }
+
+  gtk_container_add (GTK_CONTAINER (priv->list), priv->more_item);
+
+  gtk_widget_show_all (priv->list);
+
+  gtk_adjustment_set_value (priv->adjustment,
+                            gtk_adjustment_get_lower (priv->adjustment));
+  egg_list_box_set_separator_funcs (EGG_LIST_BOX (priv->list), NULL, NULL, NULL);
+  egg_list_box_refilter (EGG_LIST_BOX (priv->list));
+  egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->list), GTK_SELECTION_NONE);
+
+  if (gtk_widget_is_visible (priv->filter_entry))
+    gtk_widget_grab_focus (priv->filter_entry);
+
+  if (!priv->showing_extra)
+    g_hash_table_destroy (initial);
+}
+
+static gint
+list_sort (gconstpointer a,
+           gconstpointer b,
+           gpointer      data)
+{
+  GtkWidget *chooser = data;
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+  LocaleInfo *ia;
+  LocaleInfo *ib;
+  const gchar *la;
+  const gchar *lb;
+  gint retval;
+
+  /* Always goes at the start */
+  if (a == priv->no_results)
+    return -1;
+  if (b == priv->no_results)
+    return 1;
+
+  /* Always goes at the end */
+  if (a == priv->more_item)
+    return 1;
+  if (b == priv->more_item)
+    return -1;
+
+  ia = g_object_get_data (G_OBJECT (a), "locale-info");
+  ib = g_object_get_data (G_OBJECT (b), "locale-info");
+
+  /* The "Other" locale always goes at the end */
+  if (!ia->id[0] && ib->id[0])
+    return 1;
+  else if (ia->id[0] && !ib->id[0])
+    return -1;
+
+  retval = g_strcmp0 (ia->name, ib->name);
+  if (retval)
+    return retval;
+
+  la = g_object_get_data (G_OBJECT (a), "name");
+  lb = g_object_get_data (G_OBJECT (b), "name");
+
+  /* Only input sources have a "name" property and they should always
+     go after their respective heading */
+  if (la && !lb)
+    return 1;
+  else if (!la && lb)
+    return -1;
+  else if (!la && !lb)
+    return 0; /* Shouldn't happen */
+
+  /* The default input source always goes first in its group */
+  if (g_object_get_data (G_OBJECT (a), "default"))
+    return -1;
+  if (g_object_get_data (G_OBJECT (b), "default"))
+    return 1;
+
+  return g_strcmp0 (la, lb);
+}
+
+static gboolean
+match_all (gchar       **words,
+           const gchar  *str)
+{
+  gchar **w;
+
+  for (w = words; *w; ++w)
+    if (!strstr (str, *w))
+      return FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+list_filter (GtkWidget *child,
+             gpointer   user_data)
+{
+  GtkDialog *chooser = user_data;
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+  LocaleInfo *info;
+  gboolean is_extra;
+  const gchar *source_name;
+
+  if (child == priv->more_item)
+    return !priv->showing_extra;
+
+  /* We hide this in the after-refilter handler below. */
+  if (child == priv->no_results)
+    return TRUE;
+
+  is_extra = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (child), "is-extra"));
+
+  if (!priv->showing_extra && is_extra)
+    return FALSE;
+
+  if (!priv->filter_words)
+    return TRUE;
+
+  info = g_object_get_data (G_OBJECT (child), "locale-info");
+
+  if (match_all (priv->filter_words, info->unaccented_name))
+    return TRUE;
+
+  if (match_all (priv->filter_words, info->untranslated_name))
+    return TRUE;
+
+  source_name = g_object_get_data (G_OBJECT (child), "unaccented-name");
+  if (source_name && match_all (priv->filter_words, source_name))
+    return TRUE;
+
+  return FALSE;
+}
+
+static void
+update_separator (GtkWidget **separator,
+                  GtkWidget  *child,
+                  GtkWidget  *before,
+                  gpointer    user_data)
+{
+  LocaleInfo *child_info = NULL;
+  LocaleInfo *before_info = NULL;
+
+  if (*separator)
+    return;
+
+  if (child)
+    child_info = g_object_get_data (G_OBJECT (child), "locale-info");
+
+  if (before)
+    before_info = g_object_get_data (G_OBJECT (before), "locale-info");
+
+  if (child_info == before_info || !child_info)
+    return;
+
+  *separator = locale_separator_widget_new (child_info->name);
+  g_object_ref_sink (*separator);
+  gtk_widget_show_all (*separator);
+}
+
+static void
+show_filter_widgets (GtkWidget *chooser)
+{
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+  LocaleInfo *info;
+  GHashTableIter iter;
+
+  remove_all_children (GTK_CONTAINER (priv->list));
+
+  gtk_container_add (GTK_CONTAINER (priv->list), priv->no_results);
+
+  g_hash_table_iter_init (&iter, priv->locales);
+  while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info))
+    add_input_source_widgets_for_locale (chooser, info);
+
+  gtk_widget_show_all (priv->list);
+
+  gtk_adjustment_set_value (priv->adjustment,
+                            gtk_adjustment_get_lower (priv->adjustment));
+  egg_list_box_set_separator_funcs (EGG_LIST_BOX (priv->list), update_separator,
+                                    chooser, NULL);
+  egg_list_box_refilter (EGG_LIST_BOX (priv->list));
+  egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->list), GTK_SELECTION_SINGLE);
+
+  if (gtk_widget_is_visible (priv->filter_entry))
+    gtk_widget_grab_focus (priv->filter_entry);
+}
+
+static gboolean
+strvs_differ (gchar **av,
+              gchar **bv)
+{
+  gchar **a, **b;
+
+  for (a = av, b = bv; *a && *b; ++a, ++b)
+    if (!g_str_equal (*a, *b))
+      return TRUE;
+
+  if (*a == NULL && *b == NULL)
+    return FALSE;
+
+  return TRUE;
+}
+
+static void
+filter_changed (GtkWidget *chooser)
+{
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+  gboolean was_filtering;
+  gchar **previous_words;
+  gchar *filter_contents = NULL;
+
+  previous_words = priv->filter_words;
+  was_filtering = previous_words != NULL;
+
+  filter_contents =
+    cc_util_normalize_casefold_and_unaccent (gtk_entry_get_text (GTK_ENTRY (priv->filter_entry)));
+
+  if (filter_contents)
+    {
+      priv->filter_words = g_strsplit_set (g_strstrip (filter_contents), " ", 0);
+      g_free (filter_contents);
+    }
+
+  if (!priv->filter_words || !priv->filter_words[0])
+    {
+      g_clear_pointer (&priv->filter_words, g_strfreev);
+      if (was_filtering)
+        show_locale_widgets (chooser);
+    }
+  else
+    {
+      if (!was_filtering)
+        show_filter_widgets (chooser);
+      else if (strvs_differ (priv->filter_words, previous_words))
+        egg_list_box_refilter (EGG_LIST_BOX (priv->list));
+    }
+
+  g_strfreev (previous_words);
+}
+
+typedef struct {
+  gint count;
+  GtkWidget *ignore;
+} CountChildrenData;
+
+static void
+count_visible_children (GtkWidget *widget,
+                        gpointer   user_data)
+{
+  CountChildrenData *data = user_data;
+  if (widget != data->ignore &&
+      gtk_widget_get_child_visible (widget) &&
+      gtk_widget_get_visible (widget))
+    data->count++;
+}
+
+static void
+end_refilter (EggListBox *list_box,
+              gpointer    user_data)
+{
+  GtkDialog *chooser = user_data;
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+  CountChildrenData data = { 0 };
+  gboolean visible;
+
+  data.ignore = priv->no_results;
+
+  gtk_container_foreach (GTK_CONTAINER (list_box),
+                         count_visible_children, &data);
+
+  visible = (data.count == 0);
+
+  gtk_widget_set_visible (priv->no_results, visible);
+  egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->list),
+                                   visible ? GTK_SELECTION_NONE : GTK_SELECTION_SINGLE);
+}
+
+static void
+show_more (GtkWidget *chooser)
+{
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+
+  set_fixed_size (chooser);
+
+  gtk_widget_show (priv->filter_entry);
+  gtk_widget_grab_focus (priv->filter_entry);
+
+  priv->showing_extra = TRUE;
+
+  egg_list_box_refilter (EGG_LIST_BOX (priv->list));
+}
+
+static void
+child_activated (EggListBox *box,
+                 GtkWidget  *child,
+                 GtkWidget  *chooser)
+{
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+  gpointer data;
+
+  if (!child)
+    return;
+
+  if (child == priv->more_item)
+    {
+      show_more (chooser);
+      return;
+    }
+
+  data = g_object_get_data (G_OBJECT (child), "back");
+  if (data)
+    {
+      show_locale_widgets (chooser);
+      return;
+    }
+
+  data = g_object_get_data (G_OBJECT (child), "name");
+  if (data)
+    {
+      /* It's an input source, we just want to select it */
+      return;
+    }
+
+  data = g_object_get_data (G_OBJECT (child), "locale-info");
+  if (data)
+    {
+      show_input_sources_for_locale (chooser, (LocaleInfo *) data);
+      return;
+    }
+}
+
+static void
+child_selected (EggListBox *box,
+                GtkWidget  *child,
+                GtkWidget  *chooser)
+{
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+
+  gtk_widget_set_sensitive (priv->add_button, child != NULL);
+}
+
+static void
+add_default_widget (GtkWidget   *chooser,
+                    LocaleInfo  *info,
+                    const gchar *type,
+                    const gchar *id)
+{
+  info->default_input_source_widget = input_source_widget_new (chooser, type, id);
+  if (info->default_input_source_widget)
+    {
+      g_object_ref_sink (info->default_input_source_widget);
+      g_object_set_data (G_OBJECT (info->default_input_source_widget), "default", GINT_TO_POINTER (TRUE));
+      g_object_set_data (G_OBJECT (info->default_input_source_widget), "locale-info", info);
+    }
+}
+
+static void
+add_widgets_to_table (GtkWidget   *chooser,
+                      LocaleInfo  *info,
+                      GList       *list,
+                      const gchar *type,
+                      const gchar *default_id)
+{
+  GHashTable *table;
+  GtkWidget *widget;
+  const gchar *id;
+
+  if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
+    table = info->layout_widgets_by_id;
+  else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
+    table = info->engine_widgets_by_id;
+  else
+    return;
+
+  while (list)
+    {
+      id = (const gchar *) list->data;
+
+      /* The widget for the default input source lives elsewhere */
+      if (g_strcmp0 (id, default_id))
+        {
+          widget = input_source_widget_new (chooser, type, id);
+          if (widget)
+            {
+              g_object_set_data (G_OBJECT (widget), "locale-info", info);
+              g_hash_table_replace (table, (gpointer) id, g_object_ref_sink (widget));
+            }
+        }
+      list = list->next;
+    }
+}
+
+#ifdef HAVE_IBUS
+static gboolean
+maybe_set_as_default (GtkWidget   *chooser,
+                      LocaleInfo  *info,
+                      const gchar *engine_id)
+{
+  const gchar *type, *id;
+
+  if (!gnome_get_input_source_from_locale (info->id, &type, &id))
+    return FALSE;
+
+  if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS) &&
+      g_str_equal (id, engine_id) &&
+      info->default_input_source_widget == NULL)
+    {
+      add_default_widget (chooser, info, type, id);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+get_ibus_locale_infos (GtkWidget *chooser)
+{
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+  GHashTableIter iter;
+  LocaleInfo *info;
+  const gchar *engine_id;
+  IBusEngineDesc *engine;
+
+  if (!priv->ibus_engines)
+    return;
+
+  g_hash_table_iter_init (&iter, priv->ibus_engines);
+  while (g_hash_table_iter_next (&iter, (gpointer *) &engine_id, (gpointer *) &engine))
+    {
+      gchar *lang_code = NULL;
+      gchar *country_code = NULL;
+      const gchar *ibus_locale = ibus_engine_desc_get_language (engine);
+
+      if (gnome_parse_locale (ibus_locale, &lang_code, &country_code, NULL, NULL) &&
+          lang_code != NULL &&
+          country_code != NULL)
+        {
+          gchar *locale = g_strdup_printf ("%s_%s.utf8", lang_code, country_code);
+
+          info = g_hash_table_lookup (priv->locales, locale);
+          if (info)
+            {
+              const gchar *type, *id;
+
+              if (gnome_get_input_source_from_locale (locale, &type, &id) &&
+                  g_str_equal (type, INPUT_SOURCE_TYPE_IBUS) &&
+                  g_str_equal (id, engine_id))
+                {
+                  add_default_widget (chooser, info, type, id);
+                }
+              else
+                {
+                  GList tmp = { 0 };
+                  tmp.data = (gpointer) engine_id;
+                  add_widgets_to_table (chooser, info, &tmp, INPUT_SOURCE_TYPE_IBUS, NULL);
+                }
+            }
+          else
+            {
+              g_warning ("IBus returned locale '%s' that we don't know about", locale);
+            }
+
+          g_free (locale);
+        }
+      else if (lang_code != NULL)
+        {
+          GHashTableIter iter;
+          GHashTable *locales_for_language;
+          gchar *language;
+
+          /* Most IBus engines only specify the language so we try to
+             add them to all locales for that language. */
+
+          language = gnome_get_language_from_code (lang_code, NULL);
+          if (language)
+            locales_for_language = g_hash_table_lookup (priv->locales_by_language, language);
+          else
+            locales_for_language = NULL;
+          g_free (language);
+
+          if (locales_for_language)
+            {
+              g_hash_table_iter_init (&iter, locales_for_language);
+              while (g_hash_table_iter_next (&iter, (gpointer *) &info, NULL))
+                {
+                  if (!maybe_set_as_default (chooser, info, engine_id))
+                    {
+                      GList tmp = { 0 };
+                      tmp.data = (gpointer) engine_id;
+                      add_widgets_to_table (chooser, info, &tmp, INPUT_SOURCE_TYPE_IBUS, NULL);
+                    }
+                }
+            }
+        }
+      else
+        {
+          /* Add it to the "Other" locale */
+          GList tmp = { 0 };
+          tmp.data = (gpointer) engine_id;
+          info = g_hash_table_lookup (priv->locales, "");
+          add_widgets_to_table (chooser, info, &tmp, INPUT_SOURCE_TYPE_IBUS, NULL);
+        }
+
+      g_free (country_code);
+      g_free (lang_code);
+    }
+}
+#endif  /* HAVE_IBUS */
+
+static void
+add_locale_to_table (GHashTable  *table,
+                     const gchar *lang_code,
+                     LocaleInfo  *info)
+{
+  GHashTable *set;
+  gchar *language;
+
+  language = gnome_get_language_from_code (lang_code, NULL);
+
+  set = g_hash_table_lookup (table, language);
+  if (!set)
+    {
+      set = g_hash_table_new (NULL, NULL);
+      g_hash_table_replace (table, g_strdup (language), set);
+    }
+  g_hash_table_add (set, info);
+
+  g_free (language);
+}
+
+static void
+add_ids_to_set (GHashTable *set,
+                GList      *list)
+{
+  while (list)
+    {
+      g_hash_table_add (set, list->data);
+      list = list->next;
+    }
+}
+
+static void
+get_locale_infos (GtkWidget *chooser)
+{
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+  GHashTable *layouts_with_locale;
+  LocaleInfo *info;
+  gchar **locale_ids;
+  gchar **locale;
+  GList *list, *l;
+
+  priv->locales = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                         NULL, locale_info_free);
+  priv->locales_by_language = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                     g_free, (GDestroyNotify) g_hash_table_destroy);
+
+  layouts_with_locale = g_hash_table_new (g_str_hash, g_str_equal);
+
+  locale_ids = gnome_get_all_locales ();
+  for (locale = locale_ids; *locale; ++locale)
+    {
+      gchar *lang_code, *country_code;
+      gchar *simple_locale;
+      const gchar *type = NULL;
+      const gchar *id = NULL;
+
+      if (!gnome_parse_locale (*locale, &lang_code, &country_code, NULL, NULL))
+        continue;
+
+      simple_locale = g_strdup_printf ("%s_%s.utf8", lang_code, country_code);
+      if (g_hash_table_contains (priv->locales, simple_locale))
+        {
+          g_free (simple_locale);
+          g_free (country_code);
+          g_free (lang_code);
+          continue;
+        }
+
+      info = g_new0 (LocaleInfo, 1);
+      info->id = simple_locale; /* Take ownership */
+      info->name = gnome_get_language_from_locale (simple_locale, NULL);
+      info->unaccented_name = cc_util_normalize_casefold_and_unaccent (info->name);
+      info->untranslated_name = gnome_get_language_from_locale (simple_locale, "C");
+
+      g_hash_table_replace (priv->locales, simple_locale, info);
+      add_locale_to_table (priv->locales_by_language, lang_code, info);
+
+      if (gnome_get_input_source_from_locale (simple_locale, &type, &id) &&
+          g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
+        {
+          add_default_widget (chooser, info, type, id);
+          g_hash_table_add (layouts_with_locale, (gpointer) id);
+        }
+
+      /* We don't own these ids */
+      info->layout_widgets_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                          NULL, g_object_unref);
+      info->engine_widgets_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                          NULL, g_object_unref);
+
+      list = gnome_xkb_info_get_layouts_for_language (priv->xkb_info, lang_code);
+      add_widgets_to_table (chooser, info, list, INPUT_SOURCE_TYPE_XKB, id);
+      add_ids_to_set (layouts_with_locale, list);
+      g_list_free (list);
+
+      list = gnome_xkb_info_get_layouts_for_country (priv->xkb_info, country_code);
+      add_widgets_to_table (chooser, info, list, INPUT_SOURCE_TYPE_XKB, id);
+      add_ids_to_set (layouts_with_locale, list);
+      g_list_free (list);
+
+      g_free (lang_code);
+      g_free (country_code);
+    }
+  g_strfreev (locale_ids);
+
+  /* Add a "Other" locale to hold the remaining input sources */
+  info = g_new0 (LocaleInfo, 1);
+  info->id = g_strdup ("");
+  info->name = g_strdup (_("Other"));
+  info->unaccented_name = g_strdup ("");
+  info->untranslated_name = g_strdup ("");
+  g_hash_table_replace (priv->locales, info->id, info);
+
+  info->layout_widgets_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                      NULL, g_object_unref);
+  info->engine_widgets_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                      NULL, g_object_unref);
+
+  list = gnome_xkb_info_get_all_layouts (priv->xkb_info);
+  for (l = list; l; l = l->next)
+    if (!g_hash_table_contains (layouts_with_locale, l->data))
+      {
+        GList tmp = { 0 };
+        tmp.data = l->data;
+        add_widgets_to_table (chooser, info, &tmp, INPUT_SOURCE_TYPE_XKB, NULL);
+      }
+
+  g_list_free (list);
+
+  g_hash_table_destroy (layouts_with_locale);
+}
+
+static void
+cc_input_chooser_private_free (gpointer data)
+{
+  CcInputChooserPrivate *priv = data;
+
+  g_object_unref (priv->more_item);
+  g_object_unref (priv->no_results);
+  g_hash_table_destroy (priv->locales);
+  g_hash_table_destroy (priv->locales_by_language);
+  g_strfreev (priv->filter_words);
+  g_free (priv);
+}
+
+GtkWidget *
+cc_input_chooser_new (GtkWindow    *main_window,
+                      GnomeXkbInfo *xkb_info,
+                      GHashTable   *ibus_engines)
+{
+  GtkBuilder *builder;
+  GtkWidget *chooser;
+  CcInputChooserPrivate *priv;
+  gint width;
+  GError *error = NULL;
+
+  builder = gtk_builder_new ();
+  if (gtk_builder_add_from_resource (builder, "/org/gnome/control-center/region/input-chooser.ui", &error) == 0)
+    {
+      g_object_unref (builder);
+      g_warning ("failed to load input chooser: %s", error->message);
+      g_error_free (error);
+      return NULL;
+    }
+  chooser = WID ("input-dialog");
+  priv = g_new0 (CcInputChooserPrivate, 1);
+  g_object_set_data_full (G_OBJECT (chooser), "private", priv, cc_input_chooser_private_free);
+  g_object_set_data_full (G_OBJECT (chooser), "builder", builder, g_object_unref);
+
+  priv->xkb_info = xkb_info;
+  priv->ibus_engines = ibus_engines;
+
+  priv->add_button = WID ("add-button");
+  priv->filter_entry = WID ("filter-entry");
+  priv->list = WID ("list");
+  priv->scrolledwindow = WID ("scrolledwindow");
+  priv->adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
+
+  priv->more_item = g_object_ref_sink (more_widget_new ());
+  priv->no_results = g_object_ref_sink (no_results_widget_new ());
+
+  egg_list_box_set_adjustment (EGG_LIST_BOX (priv->list), priv->adjustment);
+  egg_list_box_set_filter_func (EGG_LIST_BOX (priv->list), list_filter, chooser, NULL);
+  egg_list_box_set_sort_func (EGG_LIST_BOX (priv->list), list_sort, chooser, NULL);
+  g_signal_connect (priv->list, "child-activated", G_CALLBACK (child_activated), chooser);
+  g_signal_connect (priv->list, "child-selected", G_CALLBACK (child_selected), chooser);
+  g_signal_connect_after (priv->list, "refilter", G_CALLBACK (end_refilter), chooser);
+
+  g_signal_connect_swapped (priv->filter_entry, "changed", G_CALLBACK (filter_changed), chooser);
+
+  get_locale_infos (chooser);
+#ifdef HAVE_IBUS
+  get_ibus_locale_infos (chooser);
+#endif  /* HAVE_IBUS */
+  show_locale_widgets (chooser);
+
+  /* Try to come up with a sensible width */
+  gtk_window_get_size (main_window, &width, NULL);
+  gtk_widget_set_size_request (chooser, width * MAIN_WINDOW_WIDTH_RATIO, -1);
+  gtk_window_set_resizable (GTK_WINDOW (chooser), TRUE);
+
+  gtk_window_set_transient_for (GTK_WINDOW (chooser), main_window);
+
+  return chooser;
+}
+
+void
+cc_input_chooser_set_ibus_engines (GtkWidget  *chooser,
+                                   GHashTable *ibus_engines)
+{
+#ifdef HAVE_IBUS
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+
+  /* This should only be called once when IBus shows up in case it
+     wasn't up yet when the user opened the input chooser dialog. */
+  g_return_if_fail (priv->ibus_engines == NULL);
+
+  priv->ibus_engines = ibus_engines;
+  get_ibus_locale_infos (chooser);
+  show_locale_widgets (chooser);
+#endif  /* HAVE_IBUS */
+}
+
+gboolean
+cc_input_chooser_get_selected (GtkWidget  *chooser,
+                               gchar     **type,
+                               gchar     **id,
+                               gchar     **name)
+{
+  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+  GtkWidget *selected;
+  const gchar *t, *i, *n;
+
+  selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->list));
+  if (!selected)
+    return FALSE;
+
+  t = g_object_get_data (G_OBJECT (selected), "type");
+  i = g_object_get_data (G_OBJECT (selected), "id");
+  n = g_object_get_data (G_OBJECT (selected), "name");
+
+  if (!t || !i || !n)
+    return FALSE;
+
+  *type = g_strdup (t);
+  *id = g_strdup (i);
+  *name = g_strdup (n);
+
+  return TRUE;
+}
diff --git a/panels/region/cc-input-chooser.h b/panels/region/cc-input-chooser.h
new file mode 100644
index 0000000..72a8881
--- /dev/null
+++ b/panels/region/cc-input-chooser.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc
+ *
+ * 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 __CC_INPUT_CHOOSER_H__
+#define __CC_INPUT_CHOOSER_H__
+
+#include <gtk/gtk.h>
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-xkb-info.h>
+
+
+G_BEGIN_DECLS
+
+GtkWidget   *cc_input_chooser_new          (GtkWindow    *parent,
+                                            GnomeXkbInfo *xkb_info,
+                                            GHashTable   *ibus_engines);
+void         cc_input_chooser_set_ibus_engines (GtkWidget *chooser,
+                                                GHashTable *ibus_engines);
+gboolean     cc_input_chooser_get_selected (GtkWidget    *chooser,
+                                            gchar       **type,
+                                            gchar       **id,
+                                            gchar       **name);
+
+G_END_DECLS
+
+#endif /* __CC_INPUT_CHOOSER_H__ */
diff --git a/panels/region/cc-input-options.c b/panels/region/cc-input-options.c
new file mode 100644
index 0000000..52ed6f8
--- /dev/null
+++ b/panels/region/cc-input-options.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Written by:
+ *     Matthias Clasen
+ */
+
+#define _GNU_SOURCE
+#include <config.h>
+#include "cc-input-options.h"
+
+#include <glib/gi18n.h>
+
+
+typedef struct {
+        GtkWidget *dialog;
+        GtkWidget *same_source;
+        GtkWidget *per_window_source;
+        GtkWidget *previous_source;
+        GtkWidget *next_source;
+        GtkWidget *alt_next_source;
+        GSettings *settings;
+} CcInputOptionsPrivate;
+
+#define GET_PRIVATE(options) ((CcInputOptionsPrivate *) g_object_get_data (G_OBJECT (options), "private"))
+
+static void
+cc_input_options_private_free (gpointer data)
+{
+        CcInputOptionsPrivate *priv = data;
+
+        g_clear_object (&priv->settings);
+        g_free (priv);
+}
+
+static void
+update_shortcut_label (GtkWidget   *widget,
+                       const gchar *value)
+{
+        gchar *text;
+        guint accel_key, *keycode;
+        GdkModifierType mods;
+
+        if (value == NULL || *value == '\0') {
+                gtk_widget_hide (widget);
+                return;
+        }
+
+        gtk_accelerator_parse_with_keycode (value, &accel_key, &keycode, &mods);
+        if (accel_key == 0 && keycode == NULL && mods == 0) {
+                g_warning ("Failed to parse keyboard shortcut: '%s'", value);
+                gtk_widget_hide (widget);
+                return;
+        }
+
+        text = gtk_accelerator_get_label_with_keycode (gtk_widget_get_display (widget), accel_key, *keycode, mods);
+        g_free (keycode);
+        gtk_label_set_text (GTK_LABEL (widget), text);
+        g_free (text);
+}
+
+static struct
+{
+  const gchar *value;
+  const gchar *description;
+} input_switcher_options[] =
+{
+  { "off", N_("Disabled") },
+  { "shift-l", N_("Left Shift") },
+  { "alt-l", N_("Left Alt") },
+  { "ctrl-l", N_("Left Ctrl") },
+  { "shift-r", N_("Right Shift") },
+  { "alt-r", N_("Right Alt") },
+  { "ctrl-r", N_("Right Ctrl") },
+  { "alt-shift-l", N_("Left Alt+Shift") },
+  { "alt-shift-r", N_("Right Alt+Shift") },
+  { "ctrl-shift-l", N_("Left Ctrl+Shift") },
+  { "ctrl-shift-r", N_("Right Ctrl+Shift") },
+  { "shift-l-shift-r", N_("Left+Right Shift") },
+  { "alt-l-alt-r", N_("Left+Right Alt") },
+  { "ctrl-l-ctrl-r", N_("Left+Right Ctrl") },
+  { "alt-shift", N_("Alt+Shift") },
+  { "ctrl-shift", N_("Ctrl+Shift") },
+  { "alt-ctrl", N_("Alt+Ctrl") },
+  { "caps", N_("Caps") },
+  { "shift-caps", N_("Shift+Caps") },
+  { "alt-caps", N_("Alt+Caps") },
+  { "ctrl-caps", N_("Ctrl+Caps") },
+  { NULL, NULL }
+};
+
+static void
+update_shortcuts (GtkWidget *options)
+{
+        CcInputOptionsPrivate *priv = GET_PRIVATE (options);
+        gchar **previous;
+        gchar **next;
+        gchar *previous_shortcut;
+        GSettings *settings;
+        gchar *s;
+        gint i;
+
+        settings = g_settings_new ("org.gnome.desktop.wm.keybindings");
+
+        previous = g_settings_get_strv (settings, "switch-input-source-backward");
+        next = g_settings_get_strv (settings, "switch-input-source");
+
+        previous_shortcut = g_strdup (previous[0]);
+        if (!previous_shortcut && next[0])
+                previous_shortcut = g_strconcat ("<Shift>", next[0], NULL);
+
+        update_shortcut_label (priv->previous_source, previous_shortcut);
+        update_shortcut_label (priv->next_source, next[0]);
+
+        g_free (previous_shortcut);
+
+        g_strfreev (previous);
+        g_strfreev (next);
+
+        g_object_unref (settings);
+
+        settings = g_settings_new ("org.gnome.settings-daemon.peripherals.keyboard");
+        s = g_settings_get_string (settings, "input-sources-switcher");
+
+        if (strcmp (s, "off") == 0) {
+                gtk_widget_hide (priv->alt_next_source);
+        } else {
+                for (i = 0; input_switcher_options[i].value; i++) {
+                        if (strcmp (s, input_switcher_options[i].value) == 0) {
+                                gtk_label_set_text (GTK_LABEL (priv->alt_next_source), _(input_switcher_options[i].description));
+                                break;
+                        }
+                }
+        }
+        g_free (s);
+        g_object_unref (settings);
+}
+
+#define WID(name) ((GtkWidget *) gtk_builder_get_object (builder, name))
+
+GtkWidget *
+cc_input_options_new (GtkWidget *parent)
+{
+        GtkBuilder *builder;
+        GtkWidget *options;
+        CcInputOptionsPrivate *priv;
+        GError *error = NULL;
+
+        builder = gtk_builder_new ();
+        if (gtk_builder_add_from_resource (builder, "/org/gnome/control-center/region/input-options.ui", &error) == 0) {
+                g_object_unref (builder);
+                g_warning ("failed to load input options: %s", error->message);
+                g_error_free (error);
+                return NULL;
+        }
+
+        options = WID ("dialog");
+        priv = g_new0 (CcInputOptionsPrivate, 1);
+        g_object_set_data_full (G_OBJECT (options), "private", priv, cc_input_options_private_free);
+        g_object_set_data_full (G_OBJECT (options), "builder", builder, g_object_unref);
+
+        priv->same_source = WID ("same-source");
+        priv->per_window_source = WID ("per-window-source");
+        priv->previous_source = WID ("previous-source");
+        priv->next_source = WID ("next-source");
+        priv->alt_next_source = WID ("alt-next-source");
+
+        g_object_bind_property (priv->previous_source, "visible",
+                                WID ("previous-source-label"), "visible",
+                                G_BINDING_DEFAULT);
+        g_object_bind_property (priv->next_source, "visible",
+                                WID ("next-source-label"), "visible",
+                                G_BINDING_DEFAULT);
+        g_object_bind_property (priv->alt_next_source, "visible",
+                                WID ("alt-next-source-label"), "visible",
+                                G_BINDING_DEFAULT);
+
+        priv->settings = g_settings_new ("org.gnome.desktop.input-sources");
+        g_settings_bind (priv->settings, "per-window",
+                         priv->per_window_source, "active",
+                         G_SETTINGS_BIND_DEFAULT);
+        g_settings_bind (priv->settings, "per-window",
+                         priv->same_source, "active",
+                         G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_INVERT_BOOLEAN);
+
+        update_shortcuts (options);
+
+        gtk_window_set_transient_for (GTK_WINDOW (options), GTK_WINDOW (parent));
+
+        return options;
+}
diff --git a/panels/region/cc-input-options.h b/panels/region/cc-input-options.h
new file mode 100644
index 0000000..5d7c4f2
--- /dev/null
+++ b/panels/region/cc-input-options.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 Red Hat, Inc
+ *
+ * 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.
+ *
+ * Written by:
+ *     Matthias Clasen
+ */
+
+#ifndef __CC_INPUT_OPTIONS_H__
+#define __CC_INPUT_OPTIONS_H__
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+GtkWidget *cc_input_options_new (GtkWidget *parent);
+
+G_END_DECLS
+
+#endif /* __CC_FORMAT_CHOOSER_H__ */
diff --git a/panels/region/cc-region-panel.c b/panels/region/cc-region-panel.c
index 6e59e7f..dbcb45e 100644
--- a/panels/region/cc-region-panel.c
+++ b/panels/region/cc-region-panel.c
@@ -19,123 +19,1494 @@
  *
  */
 
+#include <config.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+#include <gtk/gtk.h>
+#include <polkit/polkit.h>
+
 #include "cc-region-panel.h"
 #include "cc-region-resources.h"
+#include "cc-language-chooser.h"
+#include "cc-format-chooser.h"
+#include "cc-input-chooser.h"
+#include "cc-input-options.h"
 
-#include <gtk/gtk.h>
+#include "cc-common-language.h"
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-languages.h>
+#include <libgnome-desktop/gnome-xkb-info.h>
+
+#ifdef HAVE_IBUS
+#include <ibus.h>
+#include "cc-ibus-utils.h"
+#endif
+
+#include <act/act.h>
+
+#include "egg-list-box/egg-list-box.h"
+#include <libgd/gd-notification.h>
 
-#include "gnome-region-panel-input.h"
-#include "gnome-region-panel-lang.h"
-#include "gnome-region-panel-formats.h"
-#include "gnome-region-panel-system.h"
+#define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources"
+#define KEY_CURRENT_INPUT_SOURCE "current"
+#define KEY_INPUT_SOURCES        "sources"
+
+#define GNOME_SYSTEM_LOCALE_DIR "org.gnome.system.locale"
+#define KEY_REGION "region"
+
+#define INPUT_SOURCE_TYPE_XKB "xkb"
+#define INPUT_SOURCE_TYPE_IBUS "ibus"
 
 CC_PANEL_REGISTER (CcRegionPanel, cc_region_panel)
 
+#define WID(s) GTK_WIDGET (gtk_builder_get_object (self->priv->builder, s))
+
 #define REGION_PANEL_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_REGION_PANEL, CcRegionPanelPrivate))
 
+typedef enum {
+        CHOOSE_LANGUAGE,
+        ADD_INPUT,
+        REMOVE_INPUT
+} SystemOp;
+
 struct _CcRegionPanelPrivate {
 	GtkBuilder *builder;
-};
 
-enum {
-	PROP_0,
-	PROP_ARGV
-};
+        GtkWidget   *login_button;
+        GtkWidget   *login_label;
+        gboolean     login;
+        GPermission *permission;
+        SystemOp     op;
+        GDBusProxy  *localed;
+
+        GtkWidget *overlay;
+        GtkWidget *notification;
 
-enum {
-	LANGUAGE_PAGE,
-	FORMATS_PAGE,
-	LAYOUTS_PAGE,
-	SYSTEM_PAGE
+        GtkWidget *language_section;
+        GtkWidget *language_row;
+        GtkWidget *language_label;
+        GtkWidget *formats_row;
+        GtkWidget *formats_label;
+
+        ActUserManager *user_manager;
+        ActUser        *user;
+        GSettings      *locale_settings;
+
+        gchar *language;
+        gchar *region;
+        gchar *system_language;
+        gchar *system_region;
+
+        GtkWidget *input_section;
+        GtkWidget *options_button;
+        GtkWidget *input_list;
+        GtkWidget *add_input;
+        GtkWidget *remove_input;
+        GtkWidget *show_config;
+        GtkWidget *show_layout;
+
+        GSettings *input_settings;
+        GnomeXkbInfo *xkb_info;
+#ifdef HAVE_IBUS
+        IBusBus *ibus;
+        GHashTable *ibus_engines;
+        GCancellable *ibus_cancellable;
+#endif
 };
 
 static void
-cc_region_panel_set_page (CcRegionPanel *panel,
-			  const char    *page)
+cc_region_panel_finalize (GObject *object)
+{
+	CcRegionPanel *self = CC_REGION_PANEL (object);
+	CcRegionPanelPrivate *priv = self->priv;
+
+        priv->user_manager = NULL;
+        priv->user = NULL;
+        g_clear_object (&priv->permission);
+        g_clear_object (&priv->localed);
+        g_clear_object (&priv->builder);
+        g_clear_object (&priv->locale_settings);
+        g_clear_object (&priv->input_settings);
+        g_clear_object (&priv->xkb_info);
+#ifdef HAVE_IBUS
+        g_clear_object (&priv->ibus);
+        if (priv->ibus_cancellable)
+                g_cancellable_cancel (priv->ibus_cancellable);
+        g_clear_object (&priv->ibus_cancellable);
+        g_clear_pointer (&priv->ibus_engines, g_hash_table_destroy);
+#endif
+        g_free (priv->language);
+        g_free (priv->region);
+        g_free (priv->system_language);
+        g_free (priv->system_region);
+
+	G_OBJECT_CLASS (cc_region_panel_parent_class)->finalize (object);
+}
+
+static void
+cc_region_panel_constructed (GObject *object)
+{
+        CcRegionPanel *self = CC_REGION_PANEL (object);
+	CcRegionPanelPrivate *priv = self->priv;
+
+        G_OBJECT_CLASS (cc_region_panel_parent_class)->constructed (object);
+
+        cc_shell_embed_widget_in_header (cc_panel_get_shell (CC_PANEL (object)),
+                                         priv->login_button);
+}
+
+static const char *
+cc_region_panel_get_help_uri (CcPanel *panel)
+{
+        return "help:gnome-help/prefs-language";
+}
+
+static void
+cc_region_panel_class_init (CcRegionPanelClass * klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	CcPanelClass * panel_class = CC_PANEL_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (CcRegionPanelPrivate));
+
+	panel_class->get_help_uri = cc_region_panel_get_help_uri;
+
+        object_class->constructed = cc_region_panel_constructed;
+	object_class->finalize = cc_region_panel_finalize;
+}
+
+static void
+restart_now (CcRegionPanel *self)
+{
+        GDBusConnection *bus;
+
+        gd_notification_dismiss (GD_NOTIFICATION (self->priv->notification));
+
+        bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+        g_dbus_connection_call (bus,
+                                "org.gnome.SessionManager",
+                                "/org/gnome/SessionManager",
+                                "org.gnome.SessionManager",
+                                "Logout",
+                                g_variant_new ("(u)", 0),
+                                NULL, 0, G_MAXINT,
+                                NULL, NULL, NULL);
+}
+
+static void
+show_restart_notification (CcRegionPanel *self)
 {
-	GtkWidget *notebook;
-	int page_num;
+	CcRegionPanelPrivate *priv = self->priv;
+        GtkWidget *box;
+        GtkWidget *label;
+        GtkWidget *button;
 
-	if (g_strcmp0 (page, "formats") == 0)
-		page_num = FORMATS_PAGE;
-	else if (g_strcmp0 (page, "layouts") == 0)
-		page_num = LAYOUTS_PAGE;
-	else if (g_strcmp0 (page, "system") == 0)
-		page_num = SYSTEM_PAGE;
-	else
-		page_num = LANGUAGE_PAGE;
+        if (priv->notification)
+                return;
 
-	notebook = GTK_WIDGET (gtk_builder_get_object (panel->priv->builder, "region_notebook"));
-	gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), page_num);
+        priv->notification = gd_notification_new ();
+        g_object_add_weak_pointer (G_OBJECT (priv->notification),
+                                   (gpointer *)&priv->notification);
+        box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 24);
+        gtk_widget_set_margin_left (box, 12);
+        gtk_widget_set_margin_right (box, 12);
+        gtk_widget_set_margin_top (box, 6);
+        gtk_widget_set_margin_bottom (box, 6);
+        label = gtk_label_new (_("Your session needs to be restarted for changes to take effect"));
+        button = gtk_button_new_with_label (_("Restart Now"));
+        g_signal_connect_swapped (button, "clicked",
+                                  G_CALLBACK (restart_now), self);
+        gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
+        gtk_widget_show_all (box);
+
+        gtk_container_add (GTK_CONTAINER (priv->notification), box);
+        gtk_overlay_add_overlay (GTK_OVERLAY (self->priv->overlay), priv->notification);
+        gtk_widget_show (priv->notification);
 }
 
 static void
-cc_region_panel_set_property (GObject * object,
-			      guint property_id,
-			      const GValue * value,
-			      GParamSpec * pspec)
+update_separator_func (GtkWidget **separator,
+                       GtkWidget  *child,
+                       GtkWidget  *before,
+                       gpointer    user_data)
+{
+        if (before == NULL)
+                return;
+
+        if (*separator == NULL) {
+                *separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+                g_object_ref_sink (*separator);
+                gtk_widget_show (*separator);
+        }
+}
+
+static void set_localed_locale (CcRegionPanel *self,
+                                const gchar   *language);
+
+static gboolean
+update_language (CcRegionPanel *self,
+                 const gchar   *language)
 {
-	CcRegionPanel *self;
+	CcRegionPanelPrivate *priv = self->priv;
 
-	self = CC_REGION_PANEL (object);
+        if (priv->login) {
+                if (g_strcmp0 (language, priv->system_language) == 0)
+                        return FALSE;
+                set_localed_locale (self, language);
+                return FALSE; /* don't show notification for login */
+        } else {
+                if (g_strcmp0 (language, priv->language) == 0)
+                        return FALSE;
+                act_user_set_language (priv->user, language);
+                return TRUE;
+        }
+}
+
+static void
+language_response (GtkDialog     *chooser,
+                   gint           response_id,
+                   CcRegionPanel *self)
+{
+        const gchar *language;
+        gboolean changed;
 
-	switch (property_id) {
-        case PROP_ARGV: {
-                gchar **args;
+        changed = FALSE;
+
+        if (response_id == GTK_RESPONSE_OK) {
+                language = cc_language_chooser_get_language (GTK_WIDGET (chooser));
+                changed = update_language (self, language);
+        }
+
+        gtk_widget_destroy (GTK_WIDGET (chooser));
+
+        if (changed)
+                show_restart_notification (self);
+}
+
+static gboolean
+update_region (CcRegionPanel *self,
+               const gchar   *region)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+
+        if (g_strcmp0 (region, priv->region) == 0)
+                return FALSE;
+
+        g_settings_set_string (priv->locale_settings, KEY_REGION, region);
+        return TRUE;
+}
+
+static void
+format_response (GtkDialog *chooser,
+                 gint       response_id,
+                 CcRegionPanel *self)
+{
+        const gchar *region;
+        gboolean changed;
 
-                args = g_value_get_boxed (value);
+        changed = FALSE;
 
-                if (args && args[0]) {
-                        cc_region_panel_set_page (self, args[0]);
+        if (response_id == GTK_RESPONSE_OK) {
+                region = cc_format_chooser_get_region (GTK_WIDGET (chooser));
+                changed = update_region (self, region);
+        }
+
+        gtk_widget_destroy (GTK_WIDGET (chooser));
+
+        if (changed)
+                show_restart_notification (self);
+}
+
+static void
+show_language_chooser (CcRegionPanel *self,
+                       const gchar   *language)
+{
+        GtkWidget *toplevel;
+        GtkWidget *chooser;
+
+        toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+        chooser = cc_language_chooser_new (toplevel);
+        cc_language_chooser_set_language (chooser, language);
+        g_signal_connect (chooser, "response",
+                          G_CALLBACK (language_response), self);
+        gtk_window_present (GTK_WINDOW (chooser));
+}
+
+static void show_input_chooser (CcRegionPanel *self);
+static void remove_selected_input (CcRegionPanel *self);
+
+static void
+permission_acquired (GObject      *source,
+                     GAsyncResult *res,
+                     gpointer      data)
+{
+        CcRegionPanel *self = data;
+	CcRegionPanelPrivate *priv = self->priv;
+        GError *error = NULL;
+        gboolean allowed;
+
+        allowed = g_permission_acquire_finish (priv->permission, res, &error);
+        if (error) {
+                if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+                        g_warning ("Failed to acquire permission: %s\n", error->message);
+                g_error_free (error);
+                return;
+        }
+
+        if (allowed) {
+                switch (priv->op) {
+                case CHOOSE_LANGUAGE:
+                        show_language_chooser (self, priv->system_language);
+                        break;
+                case ADD_INPUT:
+                        show_input_chooser (self);
+                        break;
+                case REMOVE_INPUT:
+                        remove_selected_input (self);
+                        break;
+                default:
+                        g_warning ("Unknown privileged operation: %d\n", priv->op);
+                        break;
                 }
-                break;
         }
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id,
-						   pspec);
-	}
 }
 
 static void
-cc_region_panel_finalize (GObject * object)
+show_format_chooser (CcRegionPanel *self)
 {
-	CcRegionPanel *panel;
+	CcRegionPanelPrivate *priv = self->priv;
+        GtkWidget *toplevel;
+        GtkWidget *chooser;
 
-	panel = CC_REGION_PANEL (object);
+        toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+        chooser = cc_format_chooser_new (toplevel);
+        cc_format_chooser_set_region (chooser, priv->region);
+        g_signal_connect (chooser, "response",
+                          G_CALLBACK (format_response), self);
+        gtk_window_present (GTK_WINDOW (chooser));
+}
 
-	if (panel->priv && panel->priv->builder)
-		g_object_unref (panel->priv->builder);
+static void
+activate_language_child (CcRegionPanel *self, GtkWidget *child)
+{
+	CcRegionPanelPrivate *priv = self->priv;
 
-	G_OBJECT_CLASS (cc_region_panel_parent_class)->finalize (object);
+        if (child == priv->language_row) {
+                if (!priv->login) {
+                        show_language_chooser (self, priv->language);
+                } else if (g_permission_get_allowed (priv->permission)) {
+                        show_language_chooser (self, priv->system_language);
+                } else if (g_permission_get_can_acquire (priv->permission)) {
+                        priv->op = CHOOSE_LANGUAGE;
+                        g_permission_acquire_async (priv->permission,
+                                                    NULL,
+                                                    permission_acquired,
+                                                    self);
+                }
+        } else if (child == priv->formats_row) {
+                show_format_chooser (self);
+        }
 }
 
-static const char *
-cc_region_panel_get_help_uri (CcPanel *panel)
+static void
+update_language_label (CcRegionPanel *self)
 {
-  return "help:gnome-help/prefs-language";
+	CcRegionPanelPrivate *priv = self->priv;
+        const gchar *language;
+        gchar *name;
+
+        if (priv->login)
+                language = priv->system_language;
+        else
+                language = priv->language;
+        if (language)
+                name = gnome_get_language_from_locale (language, language);
+        else
+                name = g_strdup (C_("Language", "None"));
+        gtk_label_set_label (GTK_LABEL (priv->language_label), name);
+        g_free (name);
 }
 
 static void
-cc_region_panel_class_init (CcRegionPanelClass * klass)
+update_language_from_user (CcRegionPanel *self)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	CcPanelClass * panel_class = CC_PANEL_CLASS (klass);
+	CcRegionPanelPrivate *priv = self->priv;
+        const gchar *language;
 
-	g_type_class_add_private (klass, sizeof (CcRegionPanelPrivate));
+        if (act_user_is_loaded (priv->user))
+                language = act_user_get_language (priv->user);
+        else
+                language = "en_US.utf-8";
 
-	panel_class->get_help_uri = cc_region_panel_get_help_uri;
+        g_free (priv->language);
+        priv->language = g_strdup (language);
+        update_language_label (self);
+}
 
-	object_class->set_property = cc_region_panel_set_property;
-	object_class->finalize = cc_region_panel_finalize;
+static void
+update_region_from_setting (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        gchar *name;
+
+        g_free (priv->region);
+        priv->region = g_settings_get_string (priv->locale_settings, KEY_REGION);
+        name = gnome_get_country_from_locale (priv->region, priv->region);
+        gtk_label_set_label (GTK_LABEL (priv->formats_label), name);
+        g_free (name);
+}
+
+static void
+setup_language_section (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GtkWidget *widget;
+
+        priv->user = act_user_manager_get_user_by_id (priv->user_manager, getuid ());
+        g_signal_connect_swapped (priv->user, "notify::language",
+                                  G_CALLBACK (update_language_from_user), self);
+        g_signal_connect_swapped (priv->user, "notify::is-loaded",
+                                  G_CALLBACK (update_language_from_user), self);
+
+        priv->locale_settings = g_settings_new (GNOME_SYSTEM_LOCALE_DIR);
+        g_signal_connect_swapped (priv->locale_settings, "changed::" KEY_REGION,
+                                  G_CALLBACK (update_region_from_setting), self);
+
+        priv->language_section = WID ("language_section");
+        priv->language_row = WID ("language_row");
+        priv->language_label = WID ("language_label");
+        priv->formats_row = WID ("formats_row");
+        priv->formats_label = WID ("formats_label");
+
+        widget = WID ("language_list");
+        egg_list_box_set_selection_mode (EGG_LIST_BOX (widget),
+                                         GTK_SELECTION_NONE);
+        egg_list_box_set_separator_funcs (EGG_LIST_BOX (widget),
+                                          update_separator_func,
+                                          NULL, NULL);
+        g_signal_connect_swapped (widget, "child-activated",
+                                  G_CALLBACK (activate_language_child), self);
+
+        update_region_from_setting (self);
+        update_language_from_user (self);
+}
+
+#ifdef HAVE_IBUS
+static void
+update_ibus_active_sources (CcRegionPanel *self)
+{
+        CcRegionPanelPrivate *priv = self->priv;
+        GList *rows, *l;
+        GtkWidget *row;
+        const gchar *type;
+        const gchar *id;
+        IBusEngineDesc *engine_desc;
+        gchar *display_name;
+        GtkWidget *label;
+
+        rows = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
+        for (l = rows; l; l = l->next) {
+                row = l->data;
+                type = g_object_get_data (G_OBJECT (row), "type");
+                id = g_object_get_data (G_OBJECT (row), "id");
+                if (g_strcmp0 (type, INPUT_SOURCE_TYPE_IBUS) != 0)
+                        continue;
+
+                engine_desc = g_hash_table_lookup (priv->ibus_engines, id);
+                if (engine_desc) {
+                        display_name = engine_get_display_name (engine_desc);
+                        label = GTK_WIDGET (g_object_get_data (G_OBJECT (row), "label"));
+                        gtk_label_set_text (GTK_LABEL (label), display_name);
+                        g_free (display_name);
+                }
+        }
+        g_list_free (rows);
+}
+
+static void
+update_input_chooser (CcRegionPanel *self)
+{
+        CcRegionPanelPrivate *priv = self->priv;
+        GtkWidget *chooser;
+
+        chooser = g_object_get_data (G_OBJECT (self), "input-chooser");
+        if (!chooser)
+                return;
+
+        cc_input_chooser_set_ibus_engines (chooser, priv->ibus_engines);
+}
+
+static void
+fetch_ibus_engines_result (GObject       *object,
+                           GAsyncResult  *result,
+                           CcRegionPanel *self)
+{
+        CcRegionPanelPrivate *priv = self->priv;
+        GList *list, *l;
+        GError *error;
+
+        error = NULL;
+        list = ibus_bus_list_engines_async_finish (priv->ibus, result, &error);
+        g_clear_object (&priv->ibus_cancellable);
+        if (!list && error) {
+                g_warning ("Couldn't finish IBus request: %s", error->message);
+                g_error_free (error);
+                return;
+        }
+
+        /* Maps engine ids to engine description objects */
+        priv->ibus_engines = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+
+        for (l = list; l; l = l->next) {
+                IBusEngineDesc *engine = l->data;
+                const gchar *engine_id = ibus_engine_desc_get_name (engine);
+
+                if (g_str_has_prefix (engine_id, "xkb:"))
+                        g_object_unref (engine);
+                else
+                        g_hash_table_replace (priv->ibus_engines, (gpointer)engine_id, engine);
+        }
+        g_list_free (list);
+
+        update_ibus_active_sources (self);
+        update_input_chooser (self);
+}
+
+static void
+fetch_ibus_engines (CcRegionPanel *self)
+{
+        CcRegionPanelPrivate *priv = self->priv;
+
+        priv->ibus_cancellable = g_cancellable_new ();
+
+        ibus_bus_list_engines_async (priv->ibus,
+                                     -1,
+                                     priv->ibus_cancellable,
+                                     (GAsyncReadyCallback)fetch_ibus_engines_result,
+                                     self);
+
+  /* We've got everything we needed, don't want to be called again. */
+  g_signal_handlers_disconnect_by_func (priv->ibus, fetch_ibus_engines, self);
+}
+
+static void
+maybe_start_ibus (void)
+{
+        /* IBus doesn't export API in the session bus. The only thing
+         * we have there is a well known name which we can use as a
+         * sure-fire way to activate it.
+         */
+        g_bus_unwatch_name (g_bus_watch_name (G_BUS_TYPE_SESSION,
+                                              IBUS_SERVICE_IBUS,
+                                              G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
+                                              NULL,
+                                              NULL,
+                                              NULL,
+                                              NULL));
+}
+
+static GDesktopAppInfo *
+setup_app_info_for_id (const gchar *id)
+{
+  GDesktopAppInfo *app_info;
+  gchar *desktop_file_name;
+  gchar **strv;
+
+  strv = g_strsplit (id, ":", 2);
+  desktop_file_name = g_strdup_printf ("ibus-setup-%s.desktop", strv[0]);
+  g_strfreev (strv);
+
+  app_info = g_desktop_app_info_new (desktop_file_name);
+  g_free (desktop_file_name);
+
+  return app_info;
+}
+#endif
+
+static GtkWidget *
+add_input_row (CcRegionPanel   *self,
+               const gchar     *type,
+               const gchar     *id,
+               const gchar     *name,
+               GDesktopAppInfo *app_info)
+{
+        GtkWidget *row;
+        GtkWidget *label;
+        GtkWidget *image;
+
+        row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+        label = gtk_label_new (name);
+        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+        gtk_widget_set_margin_left (label, 20);
+        gtk_widget_set_margin_right (label, 20);
+        gtk_widget_set_margin_top (label, 6);
+        gtk_widget_set_margin_bottom (label, 6);
+        gtk_box_pack_start (GTK_BOX (row), label, TRUE, TRUE, 0);
+
+        if (strcmp (type, INPUT_SOURCE_TYPE_IBUS) == 0) {
+                image = gtk_image_new_from_icon_name ("system-run-symbolic", GTK_ICON_SIZE_BUTTON);
+                gtk_widget_set_margin_left (image, 20);
+                gtk_widget_set_margin_right (image, 20);
+                gtk_widget_set_margin_top (image, 6);
+                gtk_widget_set_margin_bottom (image, 6);
+                gtk_style_context_add_class (gtk_widget_get_style_context (image), "dim-label");
+                gtk_box_pack_start (GTK_BOX (row), image, FALSE, TRUE, 0);
+        }
+
+        gtk_widget_show_all (row);
+        gtk_container_add (GTK_CONTAINER (self->priv->input_list), row);
+
+        g_object_set_data (G_OBJECT (row), "label", label);
+        g_object_set_data (G_OBJECT (row), "type", (gpointer)type);
+        g_object_set_data_full (G_OBJECT (row), "id", g_strdup (id), g_free);
+        if (app_info) {
+                g_object_set_data_full (G_OBJECT (row), "app-info", g_object_ref (app_info), g_object_unref);
+        }
+
+        return row;
+}
+
+static void
+add_input_sources (CcRegionPanel *self,
+                   GVariant      *sources)
+{
+        CcRegionPanelPrivate *priv = self->priv;
+        GVariantIter iter;
+        const gchar *type;
+        const gchar *id;
+        const gchar *name;
+        gchar *display_name;
+        GDesktopAppInfo *app_info;
+
+        g_variant_iter_init (&iter, sources);
+        while (g_variant_iter_next (&iter, "(&s&s)", &type, &id)) {
+                display_name = NULL;
+                app_info = NULL;
+
+                if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) {
+                        gnome_xkb_info_get_layout_info (priv->xkb_info, id, &name, NULL, NULL, NULL);
+                        if (!name) {
+                                g_warning ("Couldn't find XKB input source '%s'", id);
+                                continue;
+                        }
+                        display_name = g_strdup (name);
+                        type = INPUT_SOURCE_TYPE_XKB;
+#ifdef HAVE_IBUS
+                } else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) {
+                        IBusEngineDesc *engine_desc = NULL;
+
+                        if (priv->ibus_engines)
+                                engine_desc = g_hash_table_lookup (priv->ibus_engines, id);
+                        if (engine_desc)
+                                display_name = engine_get_display_name (engine_desc);
+
+                        app_info = setup_app_info_for_id (id);
+                        type = INPUT_SOURCE_TYPE_IBUS;
+#endif
+                } else {
+                        g_warning ("Unhandled input source type '%s'", type);
+                        continue;
+                }
+
+                add_input_row (self, type, id, display_name ? display_name : id, app_info);
+                g_free (display_name);
+                g_clear_object (&app_info);
+        }
+}
+
+static void
+add_input_sources_from_settings (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GVariant *sources;
+        sources = g_settings_get_value (priv->input_settings, "sources");
+        add_input_sources (self, sources);
+        g_variant_unref (sources);
+}
+
+static void
+clear_input_sources (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GList *list, *l;
+        list = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
+        for (l = list; l; l = l->next) {
+                gtk_container_remove (GTK_CONTAINER (priv->input_list), GTK_WIDGET (l->data));
+        }
+        g_list_free (list);
+}
+
+static void
+select_by_id (GtkWidget   *row,
+              gpointer     data)
+{
+        const gchar *id = data;
+        const gchar *row_id;
+
+        row_id = (const gchar *)g_object_get_data (G_OBJECT (row), "id");
+        if (g_strcmp0 (row_id, id) == 0)
+                egg_list_box_select_child (EGG_LIST_BOX (gtk_widget_get_parent (row)), row);
+}
+
+static void
+select_input (CcRegionPanel *self,
+              const gchar   *id)
+{
+        gtk_container_foreach (GTK_CONTAINER (self->priv->input_list),
+                               select_by_id, (gpointer)id);
+}
+
+static void
+input_sources_changed (GSettings     *settings,
+                       const gchar   *key,
+                       CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GtkWidget *selected;
+        gchar *id = NULL;
+
+        selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->input_list));
+        if (selected)
+                id = g_strdup (g_object_get_data (G_OBJECT (selected), "id"));
+        clear_input_sources (self);
+        add_input_sources_from_settings (self);
+        if (id) {
+                select_input (self, id);
+                g_free (id);
+        }
+}
+
+
+static void
+update_buttons (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GtkWidget *selected;
+        GList *children;
+        gboolean multiple_sources;
+
+        children = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
+        multiple_sources = g_list_next (children) != NULL;
+        g_list_free (children);
+
+        selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->input_list));
+        if (selected == NULL) {
+                gtk_widget_set_visible (priv->show_config, FALSE);
+                gtk_widget_set_sensitive (priv->remove_input, FALSE);
+                gtk_widget_set_sensitive (priv->show_layout, FALSE);
+        } else {
+                GDesktopAppInfo *app_info;
+
+                app_info = (GDesktopAppInfo *)g_object_get_data (G_OBJECT (selected), "app-info");
+
+                gtk_widget_set_visible (priv->show_config, app_info != NULL);
+                gtk_widget_set_sensitive (priv->show_layout, TRUE);
+                gtk_widget_set_sensitive (priv->remove_input, multiple_sources);
+        }
+
+        gtk_widget_set_visible (priv->options_button,
+                                multiple_sources && !priv->login);
+}
+
+static void
+set_input_settings (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        const gchar *type;
+        const gchar *id;
+        GVariantBuilder builder;
+        GVariant *old_sources;
+        const gchar *old_current_type;
+        const gchar *old_current_id;
+        guint old_current;
+        guint old_n_sources;
+        guint index;
+        GList *list, *l;
+
+        old_sources = g_settings_get_value (priv->input_settings, KEY_INPUT_SOURCES);
+        old_current = g_settings_get_uint (priv->input_settings, KEY_CURRENT_INPUT_SOURCE);
+        old_n_sources = g_variant_n_children (old_sources);
+
+        if (old_n_sources > 0 && old_current < old_n_sources) {
+                g_variant_get_child (old_sources, old_current,
+                                     "(&s&s)", &old_current_type, &old_current_id);
+        } else {
+                old_current_type = "";
+                old_current_id = "";
+        }
+
+        g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
+        index = 0;
+        list = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
+        for (l = list; l; l = l->next) {
+                type = (const gchar *)g_object_get_data (G_OBJECT (l->data), "type");
+                id = (const gchar *)g_object_get_data (G_OBJECT (l->data), "id");
+                if (index != old_current &&
+                    g_str_equal (type, old_current_type) &&
+                    g_str_equal (id, old_current_id)) {
+                        g_settings_set_uint (priv->input_settings, KEY_CURRENT_INPUT_SOURCE, index);
+                }
+                g_variant_builder_add (&builder, "(ss)", type, id);
+                index += 1;
+        }
+        g_list_free (list);
+
+        g_settings_set_value (priv->input_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
+        g_settings_apply (priv->input_settings);
+
+        g_variant_unref (old_sources);
+}
+
+static void set_localed_input (CcRegionPanel *self);
+
+static void
+update_input (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+
+        if (priv->login) {
+                set_localed_input (self);
+        } else {
+                set_input_settings (self);
+        }
+}
+
+static void
+apologize_for_no_ibus_login (CcRegionPanel *self)
+{
+        GtkWidget *dialog;
+        GtkWidget *toplevel;
+        GtkWidget *image;
+
+        toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+
+        dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel),
+                                         GTK_DIALOG_MODAL,
+                                         GTK_MESSAGE_OTHER,
+                                         GTK_BUTTONS_OK,
+                                         _("Sorry"));
+        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                                  "%s", _("Input methods can't be used on the login screen"));
+        image = gtk_image_new_from_icon_name ("face-sad-symbolic",
+                                              GTK_ICON_SIZE_DIALOG);
+        gtk_widget_show (image);
+        gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image);
+
+        gtk_dialog_run (GTK_DIALOG (dialog));
+        gtk_widget_destroy (dialog);
+}
+
+static gboolean
+input_source_already_added (CcRegionPanel *self,
+                            const gchar   *id)
+{
+        CcRegionPanelPrivate *priv = self->priv;
+        GList *list, *l;
+        gboolean retval = FALSE;
+
+        list = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
+        for (l = list; l; l = l->next)
+                if (g_str_equal (id, (const gchar *) g_object_get_data (G_OBJECT (l->data), "id"))) {
+                        retval = TRUE;
+                        break;
+                }
+        g_list_free (list);
+
+        return retval;
+}
+
+static void
+input_response (GtkWidget *chooser, gint response_id, gpointer data)
+{
+	CcRegionPanel *self = data;
+        CcRegionPanelPrivate *priv = self->priv;
+        gchar *type;
+        gchar *id;
+        gchar *name;
+        GDesktopAppInfo *app_info = NULL;
+
+        if (response_id == GTK_RESPONSE_OK) {
+                if (cc_input_chooser_get_selected (chooser, &type, &id, &name) &&
+                    !input_source_already_added (self, id)) {
+                        if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) {
+                                g_free (type);
+                                type = INPUT_SOURCE_TYPE_IBUS;
+#ifdef HAVE_IBUS
+                                app_info = setup_app_info_for_id (id);
+#endif
+                        } else {
+                                g_free (type);
+                                type = INPUT_SOURCE_TYPE_XKB;
+                        }
+
+                        if (priv->login && g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) {
+                                apologize_for_no_ibus_login (self);
+                        } else {
+                                add_input_row (self, type, id, name, app_info);
+                                update_buttons (self);
+                                update_input (self);
+                        }
+                        g_free (id);
+                        g_free (name);
+                        g_clear_object (&app_info);
+                }
+        }
+        gtk_widget_destroy (chooser);
+        g_object_set_data (G_OBJECT (self), "input-chooser", NULL);
+}
+
+static void
+show_input_chooser (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GtkWidget *chooser;
+        GtkWidget *toplevel;
+
+        toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+        chooser = cc_input_chooser_new (GTK_WINDOW (toplevel),
+                                        priv->xkb_info,
+#ifdef HAVE_IBUS
+                                        priv->ibus_engines
+#else
+                                        NULL
+#endif
+                );
+        g_signal_connect (chooser, "response",
+                          G_CALLBACK (input_response), self);
+        gtk_window_present (GTK_WINDOW (chooser));
+
+        g_object_set_data (G_OBJECT (self), "input-chooser", chooser);
+}
+
+static void
+add_input (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+
+        if (!priv->login) {
+                show_input_chooser (self);
+        } else if (g_permission_get_allowed (priv->permission)) {
+                show_input_chooser (self);
+        } else if (g_permission_get_can_acquire (priv->permission)) {
+                priv->op = ADD_INPUT;
+                g_permission_acquire_async (priv->permission,
+                                            NULL,
+                                            permission_acquired,
+                                            self);
+        }
+}
+
+static GtkWidget *
+find_sibling (GtkContainer *container, GtkWidget *child)
+{
+        GList *list, *c;
+        GList *l;
+        GtkWidget *sibling;
+
+        list = gtk_container_get_children (container);
+        c = g_list_find (list, child);
+
+        for (l = c->next; l; l = l->next) {
+                sibling = l->data;
+                if (gtk_widget_get_visible (sibling) && gtk_widget_get_child_visible (sibling))
+                        goto out;
+        }
+
+        for (l = c->prev; l; l = l->prev) {
+                sibling = l->data;
+                if (gtk_widget_get_visible (sibling) && gtk_widget_get_child_visible (sibling))
+                        goto out;
+        }
+
+        sibling = NULL;
+
+out:
+        g_list_free (list);
+
+        return sibling;
+}
+
+static void
+do_remove_selected_input (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GtkWidget *selected;
+        GtkWidget *sibling;
+
+        selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->input_list));
+        if (selected == NULL)
+                return;
+
+        sibling = find_sibling (GTK_CONTAINER (priv->input_list), selected);
+        gtk_container_remove (GTK_CONTAINER (priv->input_list), selected);
+        egg_list_box_select_child (EGG_LIST_BOX (priv->input_list), sibling);
+
+        update_buttons (self);
+        update_input (self);
+}
+
+static void
+remove_selected_input (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+
+        if (!priv->login) {
+                do_remove_selected_input (self);
+        } else if (g_permission_get_allowed (priv->permission)) {
+                do_remove_selected_input (self);
+        } else if (g_permission_get_can_acquire (priv->permission)) {
+                priv->op = REMOVE_INPUT;
+                g_permission_acquire_async (priv->permission,
+                                            NULL,
+                                            permission_acquired,
+                                            self);
+        }
+}
+
+static void
+show_selected_settings (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GtkWidget *selected;
+        GdkAppLaunchContext *ctx;
+        GDesktopAppInfo *app_info;
+        const gchar *id;
+        GError *error = NULL;
+
+        selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->input_list));
+        if (selected == NULL)
+                return;
+
+        app_info = (GDesktopAppInfo *)g_object_get_data (G_OBJECT (selected), "app-info");
+        if  (app_info == NULL)
+                return;
+
+        ctx = gdk_display_get_app_launch_context (gdk_display_get_default ());
+        gdk_app_launch_context_set_timestamp (ctx, gtk_get_current_event_time ());
+
+        id = (const gchar *)g_object_get_data (G_OBJECT (selected), "id");
+        g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (ctx),
+                                     "IBUS_ENGINE_NAME", id);
+
+        if (!g_app_info_launch (G_APP_INFO (app_info), NULL, G_APP_LAUNCH_CONTEXT (ctx), &error)) {
+                g_warning ("Failed to launch input source setup: %s", error->message);
+                g_error_free (error);
+        }
+
+        g_object_unref (ctx);
+}
+
+static void
+show_selected_layout (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GtkWidget *selected;
+        const gchar *type;
+        const gchar *id;
+        const gchar *layout;
+        const gchar *variant;
+        gchar *commandline;
+
+        selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->input_list));
+        if (selected == NULL)
+                return;
+
+        type = (const gchar *)g_object_get_data (G_OBJECT (selected), "type");
+        id = (const gchar *)g_object_get_data (G_OBJECT (selected), "id");
+
+        if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) {
+                gnome_xkb_info_get_layout_info (priv->xkb_info,
+                                                id, NULL, NULL,
+                                                &layout, &variant);
+
+                if (!layout || !layout[0]) {
+                        g_warning ("Couldn't find XKB input source '%s'", id);
+                        return;
+                }
+#ifdef HAVE_IBUS
+        } else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) {
+                IBusEngineDesc *engine_desc = NULL;
+
+                if (priv->ibus_engines)
+                        engine_desc = g_hash_table_lookup (priv->ibus_engines, id);
+
+                if (engine_desc) {
+                        layout = ibus_engine_desc_get_layout (engine_desc);
+                        variant = "";
+                } else {
+                        g_warning ("Couldn't find IBus input source '%s'", id);
+                        return;
+                }
+#endif
+        } else {
+                g_warning ("Unhandled input source type '%s'", type);
+                return;
+        }
+
+        if (variant[0])
+                commandline = g_strdup_printf ("gkbd-keyboard-display -l \"%s\t%s\"",
+                                               layout, variant);
+        else
+                commandline = g_strdup_printf ("gkbd-keyboard-display -l %s",
+                                               layout);
+
+        g_spawn_command_line_async (commandline, NULL);
+        g_free (commandline);
+}
+
+static void
+options_response (GtkDialog     *options,
+                  gint           response_id,
+                  CcRegionPanel *self)
+{
+        gtk_widget_destroy (GTK_WIDGET (options));
+}
+
+
+static void
+show_input_options (CcRegionPanel *self)
+{
+        GtkWidget *toplevel;
+        GtkWidget *options;
+
+        toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+        options = cc_input_options_new (toplevel);
+        g_signal_connect (options, "response",
+                          G_CALLBACK (options_response), self);
+        gtk_window_present (GTK_WINDOW (options));
+}
+
+static void
+setup_input_section (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+
+        priv->input_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
+        g_settings_delay (priv->input_settings);
+
+        priv->xkb_info = gnome_xkb_info_new ();
+
+#ifdef HAVE_IBUS
+        ibus_init ();
+        if (!priv->ibus) {
+                priv->ibus = ibus_bus_new_async ();
+                if (ibus_bus_is_connected (priv->ibus))
+                        fetch_ibus_engines (self);
+                else
+                        g_signal_connect_swapped (priv->ibus, "connected",
+                                                  G_CALLBACK (fetch_ibus_engines), self);
+        }
+        maybe_start_ibus ();
+#endif
+
+        priv->input_section = WID ("input_section");
+        priv->options_button = WID ("input_options");
+        priv->input_list = WID ("input_list");
+        priv->add_input = WID ("input_source_add");
+        priv->remove_input = WID ("input_source_remove");
+        priv->show_config = WID ("input_source_config");
+        priv->show_layout = WID ("input_source_layout");
+
+        g_signal_connect_swapped (priv->options_button, "clicked",
+                                  G_CALLBACK (show_input_options), self);
+        g_signal_connect_swapped (priv->add_input, "clicked",
+                                  G_CALLBACK (add_input), self);
+        g_signal_connect_swapped (priv->remove_input, "clicked",
+                                  G_CALLBACK (remove_selected_input), self);
+        g_signal_connect_swapped (priv->show_config, "clicked",
+                                  G_CALLBACK (show_selected_settings), self);
+        g_signal_connect_swapped (priv->show_layout, "clicked",
+                                  G_CALLBACK (show_selected_layout), self);
+
+        egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->input_list),
+                                         GTK_SELECTION_SINGLE);
+        egg_list_box_set_separator_funcs (EGG_LIST_BOX (priv->input_list),
+                                          update_separator_func,
+                                          NULL, NULL);
+        g_signal_connect_swapped (priv->input_list, "child-selected",
+                                  G_CALLBACK (update_buttons), self);
+
+        g_signal_connect (priv->input_settings, "changed::" KEY_INPUT_SOURCES,
+                          G_CALLBACK (input_sources_changed), self);
+
+        add_input_sources_from_settings (self);
+        update_buttons (self);
+}
+
+static void
+on_localed_properties_changed (GDBusProxy     *proxy,
+                               GVariant       *changed_properties,
+                               const gchar   **invalidated_properties,
+                               CcRegionPanel  *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GVariant *v;
+
+        v = g_dbus_proxy_get_cached_property (proxy, "Locale");
+        if (v) {
+                const gchar **strv;
+                gsize len;
+                gint i;
+                const gchar *lang, *messages, *time;
+
+                strv = g_variant_get_strv (v, &len);
+
+                lang = messages = time = NULL;
+                for (i = 0; strv[i]; i++) {
+                        if (g_str_has_prefix (strv[i], "LANG=")) {
+                                lang = strv[i] + strlen ("LANG=");
+                        } else if (g_str_has_prefix (strv[i], "LC_MESSAGES=")) {
+                                messages = strv[i] + strlen ("LC_MESSAGES=");
+                        } else if (g_str_has_prefix (strv[i], "LC_TIME=")) {
+                                time = strv[i] + strlen ("LC_TIME=");
+                        }
+                }
+                if (!lang) {
+                        lang = "";
+                }
+                if (!messages) {
+                        messages = lang;
+                }
+                if (!time) {
+                        time = lang;
+                }
+                g_free (priv->system_language);
+                priv->system_language = g_strdup (messages);
+                g_free (priv->system_region);
+                priv->system_region = g_strdup (time);
+                g_variant_unref (v);
+
+                update_language_label (self);
+        }
+}
+
+static void
+add_input_sources_from_localed (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GVariant *v;
+        const gchar *s;
+        gchar **layouts = NULL;
+        gchar **variants = NULL;
+        gint i, n;
+
+        if (!priv->localed)
+                return;
+
+        v = g_dbus_proxy_get_cached_property (priv->localed, "X11Layout");
+        if (v) {
+                s = g_variant_get_string (v, NULL);
+                layouts = g_strsplit (s, ",", -1);
+                g_variant_unref (v);
+        }
+
+        v = g_dbus_proxy_get_cached_property (priv->localed, "X11Variant");
+        if (v) {
+                s = g_variant_get_string (v, NULL);
+                if (s && *s)
+                        variants = g_strsplit (s, ",", -1);
+                g_variant_unref (v);
+        }
+
+        if (variants && variants[0])
+                n = MIN (g_strv_length (layouts), g_strv_length (variants));
+        else if (layouts && layouts[0])
+                n = g_strv_length (layouts);
+        else
+                n = 0;
+
+        for (i = 0; i < n && layouts[i][0]; i++) {
+                const gchar *name;
+                gchar *id;
+
+                if (variants && variants[i] && variants[i][0])
+                        id = g_strdup_printf ("%s+%s", layouts[i], variants[i]);
+                else
+                        id = g_strdup (layouts[i]);
+
+                gnome_xkb_info_get_layout_info (priv->xkb_info, id, &name, NULL, NULL, NULL);
+
+                add_input_row (self, INPUT_SOURCE_TYPE_XKB, id, name ? name : id, NULL);
+
+                g_free (id);
+        }
+        if (n == 0) {
+                add_input_row (self, "none", "none", C_("Input source", "None"), NULL);
+        }
+
+        g_strfreev (variants);
+        g_strfreev (layouts);
+}
+
+static void
+set_localed_locale (CcRegionPanel *self,
+                    const gchar   *language)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GVariantBuilder *b;
+        gchar *s;
+
+        b = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+        s = g_strconcat ("LANG=", language, NULL);
+        g_variant_builder_add (b, "s", s);
+        g_free (s);
+
+        if (g_strcmp0 (priv->system_language, priv->system_region) != 0) {
+                s = g_strconcat ("LC_TIME=", priv->system_region, NULL);
+                g_variant_builder_add (b, "s", s);
+                g_free (s);
+                s = g_strconcat ("LC_NUMERIC=", priv->system_region, NULL);
+                g_variant_builder_add (b, "s", s);
+                g_free (s);
+                s = g_strconcat ("LC_MONETARY=", priv->system_region, NULL);
+                g_variant_builder_add (b, "s", s);
+                g_free (s);
+                s = g_strconcat ("LC_MEASUREMENT=", priv->system_region, NULL);
+                g_variant_builder_add (b, "s", s);
+                g_free (s);
+                s = g_strconcat ("LC_PAPER=", priv->system_region, NULL);
+                g_variant_builder_add (b, "s", s);
+                g_free (s);
+        }
+        g_dbus_proxy_call (priv->localed,
+                           "SetLocale",
+                           g_variant_new ("(asb)", b, TRUE),
+                           G_DBUS_CALL_FLAGS_NONE,
+                           -1, NULL, NULL, NULL);
+        g_variant_builder_unref (b);
+}
+
+static void
+set_localed_input (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GString *layouts;
+        GString *variants;
+        const gchar *type, *id;
+        GList *list, *li;
+        const gchar *l, *v;
+
+        layouts = g_string_new ("");
+        variants = g_string_new ("");
+
+        list = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
+        for (li = list; li; li = li->next) {
+                type = (const gchar *)g_object_get_data (G_OBJECT (li->data), "type");
+                id = (const gchar *)g_object_get_data (G_OBJECT (li->data), "id");
+                if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
+                        continue;
+
+                if (gnome_xkb_info_get_layout_info (priv->xkb_info, id, NULL, NULL, &l, &v)) {
+                        if (layouts->str[0]) {
+                                g_string_append_c (layouts, ',');
+                                g_string_append_c (variants, ',');
+                        }
+                        g_string_append (layouts, l);
+                        g_string_append (variants, v);
+                }
+        }
+        g_list_free (list);
+
+        g_dbus_proxy_call (priv->localed,
+                           "SetX11Keyboard",
+                           g_variant_new ("(ssssbb)", layouts->str, "", variants->str, "", TRUE, TRUE),
+                           G_DBUS_CALL_FLAGS_NONE,
+                           -1, NULL, NULL, NULL);
+
+        g_string_free (layouts, TRUE);
+        g_string_free (variants, TRUE);
+}
+
+static void
+localed_proxy_ready (GObject      *source,
+                     GAsyncResult *res,
+                     gpointer      data)
+{
+        CcRegionPanel *self = data;
+	CcRegionPanelPrivate *priv = self->priv;
+        GError *error = NULL;
+
+        priv->localed = g_dbus_proxy_new_finish (res, &error);
+
+        if (!priv->localed) {
+                g_warning ("Failed to contact localed: %s\n", error->message);
+                g_error_free (error);
+                return;
+        }
+
+        gtk_widget_set_sensitive (priv->login_button, TRUE);
+
+        g_signal_connect (priv->localed, "g-properties-changed",
+                          G_CALLBACK (on_localed_properties_changed), self);
+        on_localed_properties_changed (priv->localed, NULL, NULL, self);
+}
+
+static void
+login_changed (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        gboolean can_acquire;
+
+        priv->login = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->login_button));
+        gtk_widget_set_visible (priv->formats_row, !priv->login);
+        gtk_widget_set_visible (priv->login_label, priv->login);
+
+        can_acquire = priv->permission &&
+                (g_permission_get_allowed (priv->permission) ||
+                 g_permission_get_can_acquire (priv->permission));
+        /* FIXME: insensitive doesn't look quite right for this */
+        gtk_widget_set_sensitive (priv->language_section, !priv->login || can_acquire);
+        gtk_widget_set_sensitive (priv->input_section, !priv->login || can_acquire);
+
+        clear_input_sources (self);
+        if (priv->login)
+                add_input_sources_from_localed (self);
+        else
+                add_input_sources_from_settings (self);
+
+        update_language_label (self);
+        update_buttons (self);
+}
+
+static void
+setup_login_button (CcRegionPanel *self)
+{
+	CcRegionPanelPrivate *priv = self->priv;
+        GDBusConnection *bus;
+
+        priv->permission = polkit_permission_new_sync ("org.freedesktop.locale1.set-locale", NULL, NULL, NULL);
+        bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
+        g_dbus_proxy_new (bus,
+                          G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+                          NULL,
+                          "org.freedesktop.locale1",
+                          "/org/freedesktop/locale1",
+                          "org.freedesktop.locale1",
+                          NULL,
+                          (GAsyncReadyCallback) localed_proxy_ready,
+                          self);
+        g_object_unref (bus);
+
+        priv->login_label = WID ("login-label");
+        priv->login_button = gtk_toggle_button_new_with_label (_("Login Screen"));
+
+        gtk_widget_set_sensitive (priv->login_button, FALSE);
+
+        g_object_bind_property (priv->user_manager, "has-multiple-users",
+                                priv->login_button, "visible",
+                                G_BINDING_SYNC_CREATE);
 
-	g_object_class_override_property (object_class, PROP_ARGV, "argv");
+        g_signal_connect_swapped (priv->login_button, "notify::active",
+                                  G_CALLBACK (login_changed), self);
 }
 
 static void
-cc_region_panel_init (CcRegionPanel * self)
+cc_region_panel_init (CcRegionPanel *self)
 {
 	CcRegionPanelPrivate *priv;
-	GtkWidget *prefs_widget;
 	GError *error = NULL;
 
 	priv = self->priv = REGION_PANEL_PRIVATE (self);
@@ -144,7 +1515,7 @@ cc_region_panel_init (CcRegionPanel * self)
 	priv->builder = gtk_builder_new ();
 
 	gtk_builder_add_from_resource (priv->builder,
-                                       "/org/gnome/control-center/region/gnome-region-panel.ui",
+                                       "/org/gnome/control-center/region/region.ui",
                                        &error);
 	if (error != NULL) {
 		g_warning ("Error loading UI file: %s", error->message);
@@ -152,14 +1523,12 @@ cc_region_panel_init (CcRegionPanel * self)
 		return;
 	}
 
-	prefs_widget = (GtkWidget *) gtk_builder_get_object (priv->builder,
-							     "region_notebook");
-	gtk_widget_set_size_request (GTK_WIDGET (prefs_widget), -1, 400);
+        priv->user_manager = act_user_manager_get_default ();
 
-	gtk_widget_reparent (prefs_widget, GTK_WIDGET (self));
+        setup_login_button (self);
+        setup_language_section (self);
+        setup_input_section (self);
 
-        setup_input_tabs (priv->builder, self);
-	setup_language (priv->builder);
-	setup_formats (priv->builder);
-	setup_system (priv->builder);
+        priv->overlay = GTK_WIDGET (gtk_builder_get_object (priv->builder, "overlay"));
+	gtk_widget_reparent (priv->overlay, GTK_WIDGET (self));
 }
diff --git a/panels/region/format-chooser.ui b/panels/region/format-chooser.ui
new file mode 100644
index 0000000..906b171
--- /dev/null
+++ b/panels/region/format-chooser.ui
@@ -0,0 +1,345 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkDialog" id="dialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Formats</property>
+    <property name="type_hint">dialog</property>
+    <property name="modal">True</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can_focus">False</property>
+            <property name="homogeneous">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="ok-button">
+                <property name="label" translatable="yes">_Done</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">6</property>
+            <property name="margin_right">6</property>
+            <property name="margin_top">6</property>
+            <property name="margin_bottom">6</property>
+            <property name="hexpand">True</property>
+            <property name="spacing">20</property>
+            <child>
+              <object class="GtkBox" id="box2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="vexpand">True</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">6</property>
+                <child>
+                  <object class="GtkScrolledWindow" id="region-scrolledwindow">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="vexpand">True</property>
+                    <property name="hscrollbar_policy">never</property>
+                    <property name="vscrollbar_policy">never</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <object class="GtkViewport" id="viewport1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="EggListBox" id="region-list">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="vexpand">True</property>
+                            <property name="halign">fill</property>
+                            <property name="valign">fill</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSearchEntry" id="region-filter-entry">
+                    <property name="visible">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="can_focus">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkGrid" id="grid1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="valign">start</property>
+                <property name="margin_right">20</property>
+                <property name="hexpand">True</property>
+                <property name="row_spacing">6</property>
+                <property name="column_spacing">6</property>
+                <child>
+                  <object class="GtkLabel" id="label2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="margin_bottom">6</property>
+                    <property name="hexpand">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Preview</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
+                    <property name="width">2</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">Dates</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">1</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="full-date-format">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label">Wednesday, January 23</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">1</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="medium-date-format">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label">23 January 2013</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">2</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="short-date-format">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label">23/1/13</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">3</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">Times</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">4</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="time-format">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label">11:31 AM</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">4</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label5">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">Numbers</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">5</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label6">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">Measurement</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">6</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label7">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="label" translatable="yes">Paper</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">7</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="number-format">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label">123,456,789.00</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">5</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="measurement-format">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label">Metric</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">6</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="paper-format">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label">A4</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">7</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-5">ok-button</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/panels/region/gnome-region-panel-formats.c b/panels/region/gnome-region-panel-formats.c
deleted file mode 100644
index 5a95cef..0000000
--- a/panels/region/gnome-region-panel-formats.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * Copyright (C) 2011 Rodrigo Moya
- *
- * Written by: Rodrigo Moya <rodrigo@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, 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <glib/gi18n-lib.h>
-#include <locale.h>
-#include <langinfo.h>
-#include <stdlib.h>
-#define GNOME_DESKTOP_USE_UNSTABLE_API
-#include <libgnome-desktop/gnome-languages.h>
-
-#include "cc-common-language.h"
-#include "cc-language-chooser.h"
-#include "gnome-region-panel-formats.h"
-
-static void
-display_date (GtkLabel *label, GDateTime *dt, const gchar *format)
-{
-	gchar *s;
-
-	s = g_date_time_format (dt, format);
-	s = g_strstrip (s);
-	gtk_label_set_text (label, s);
-	g_free (s);
-}
-
-static void
-select_region (GtkTreeView *treeview, const gchar *lang)
-{
-        GtkTreeModel *model;
-        GtkTreeSelection *selection;
-        GtkTreeIter iter;
-        GtkTreePath *path;
-        gboolean cont;
-
-        model = gtk_tree_view_get_model (treeview);
-        selection = gtk_tree_view_get_selection (treeview);
-        cont = gtk_tree_model_get_iter_first (model, &iter);
-        while (cont) {
-                gchar *locale;
-
-                gtk_tree_model_get (model, &iter, 0, &locale, -1);
-                if (g_strcmp0 (locale, lang) == 0) {
-                        gtk_tree_selection_select_iter (selection, &iter);
-                        path = gtk_tree_model_get_path (model, &iter);
-                        gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0.0, 0.0);
-                        gtk_tree_path_free (path);
-                        g_free (locale);
-                        break;
-                }
-                g_free (locale);
-
-                cont = gtk_tree_model_iter_next (model, &iter);
-        }
-}
-
-static void
-update_examples_cb (GtkTreeSelection *selection, gpointer user_data)
-{
-	GtkBuilder *builder = GTK_BUILDER (user_data);
-        GtkTreeModel *model;
-        GtkTreeIter iter;
-        gchar *active_id;
-	gchar *locale;
-	GDateTime *dt;
-	gchar *s;
-	struct lconv *num_info;
-	const char *fmt;
-
-        if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
-                return;
-        }
-        gtk_tree_model_get (model, &iter, 0, &active_id, -1);
-
-	locale = g_strdup (setlocale (LC_TIME, NULL));
-        setlocale (LC_TIME, active_id);
-
-	dt = g_date_time_new_now_local ();
-
-	/* Display dates */
-	display_date (GTK_LABEL (gtk_builder_get_object (builder, "full_date_format")), dt, "%A %e %B %Y");
-	display_date (GTK_LABEL (gtk_builder_get_object (builder, "full_day_format")), dt, "%e %B %Y");
-	display_date (GTK_LABEL (gtk_builder_get_object (builder, "short_day_format")), dt, "%e %b %Y");
-	display_date (GTK_LABEL (gtk_builder_get_object (builder, "shortest_day_format")), dt, "%x");
-
-	/* Display times */
-	display_date (GTK_LABEL (gtk_builder_get_object (builder, "full_time_format")), dt, "%r %Z");
-	display_date (GTK_LABEL (gtk_builder_get_object (builder, "short_time_format")), dt, "%X");
-
-	setlocale (LC_TIME, locale);
-	g_free (locale);
-
-	/* Display numbers */
-	locale = g_strdup (setlocale (LC_NUMERIC, NULL));
-	setlocale (LC_NUMERIC, active_id);
-
-	s = g_strdup_printf ("%'.2f", 123456789.00);
-	gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "numbers_format")), s);
-	g_free (s);
-
-	setlocale (LC_NUMERIC, locale);
-	g_free (locale);
-
-	/* Display currency */
-	locale = g_strdup (setlocale (LC_MONETARY, NULL));
-	setlocale (LC_MONETARY, active_id);
-
-	num_info = localeconv ();
-	if (num_info != NULL) {
-		gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "currency_format")), num_info->currency_symbol);
-	}
-
-	setlocale (LC_MONETARY, locale);
-	g_free (locale);
-
-	/* Display measurement */
-#ifdef LC_MEASUREMENT
-	locale = g_strdup (setlocale (LC_MEASUREMENT, NULL));
-	setlocale (LC_MEASUREMENT, active_id);
-
-	fmt = nl_langinfo (_NL_MEASUREMENT_MEASUREMENT);
-	if (fmt && *fmt == 2)
-		gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "measurement_format")), C_("measurement format", "Imperial"));
-	else
-		gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (builder, "measurement_format")), C_("measurement format", "Metric"));
-
-	setlocale (LC_MEASUREMENT, locale);
-	g_free (locale);
-#endif
-        g_free (active_id);
-}
-
-
-static void
-update_settings_cb (GtkTreeSelection *selection, gpointer user_data)
-{
-        GtkBuilder *builder = GTK_BUILDER (user_data);
-        GtkTreeModel *model;
-        GtkTreeIter iter;
-        gchar *active_id;
-        GtkWidget *treeview;
-        GSettings *locale_settings;
-        gchar *current_setting;
-
-        if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
-                return;
-        }
-        gtk_tree_model_get (model, &iter, 0, &active_id, -1);
-
-        treeview = GTK_WIDGET (gtk_builder_get_object (builder, "region_selector"));
-
-        locale_settings = g_object_get_data (G_OBJECT (treeview), "settings");
-        current_setting = g_settings_get_string (locale_settings, "region");
-
-        if (g_strcmp0 (active_id, current_setting) != 0) {
-                g_settings_set_string (locale_settings, "region", active_id);
-        }
-
-        g_free (current_setting);
-        g_free (active_id);
-}
-
-static void
-setting_changed_cb (GSettings *locale_settings, gchar *key, GtkTreeView *treeview)
-{
-        gchar *current_setting;
-
-        current_setting = g_settings_get_string (locale_settings, "region");
-        select_region (treeview, current_setting);
-        g_free (current_setting);
-}
-
-static gint
-sort_regions (GtkTreeModel *model,
-              GtkTreeIter  *a,
-              GtkTreeIter  *b,
-              gpointer      data)
-{
-        gchar *la, *lb;
-        gint result;
-
-        gtk_tree_model_get (model, a, 1, &la, -1);
-        gtk_tree_model_get (model, b, 1, &lb, -1);
-
-        result = strcmp (la, lb);
-
-        g_free (la);
-        g_free (lb);
-
-        return result;
-}
-
-static void
-populate_regions (GtkBuilder *builder, const gchar *current_lang)
-{
-        gchar *current_region;
-        GSettings *locale_settings;
-        GHashTable *ht;
-        GHashTableIter htiter;
-        GtkTreeModel *model;
-        gchar *name, *language;
-        GtkWidget *treeview;
-        GtkTreeIter iter;
-        GtkTreeSelection *selection;
-
-        treeview = GTK_WIDGET (gtk_builder_get_object (builder, "region_selector"));
-        /* don't update the setting just because the list is repopulated */
-        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
-        g_signal_handlers_block_by_func (selection, update_settings_cb, builder);
-
-        model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
-        locale_settings = g_object_get_data (G_OBJECT (treeview), "settings");
-
-        ht = cc_common_language_get_initial_regions (current_lang);
-
-        current_region = g_settings_get_string (locale_settings, "region");
-        if (!current_region || !current_region[0]) {
-                current_region = g_strdup (current_lang);
-        }
-        else if (!g_hash_table_lookup (ht, current_region)) {
-                name = gnome_get_region_from_name (current_region, NULL);
-                g_hash_table_insert (ht, g_strdup (current_region), name);
-        }
-
-        gtk_list_store_clear (GTK_LIST_STORE (model));
-
-        g_hash_table_iter_init (&htiter, ht);
-        while (g_hash_table_iter_next (&htiter, (gpointer *)&name, (gpointer *)&language)) {
-                gtk_list_store_append (GTK_LIST_STORE (model), &iter);
-                gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, name, 1, language, -1);
-        }
-        g_hash_table_unref (ht);
-
-        select_region (GTK_TREE_VIEW (treeview), current_region);
-
-        g_free (current_region);
-
-        g_signal_handlers_unblock_by_func (selection, update_settings_cb, builder);
-}
-
-static void
-region_response (GtkDialog *dialog,
-                 gint       response_id,
-                 GtkWidget *treeview)
-{
-        gchar *lang;
-        GtkTreeModel *model;
-        GtkTreeSelection *selection;
-        GtkTreeIter iter;
-
-        gtk_widget_hide (GTK_WIDGET (dialog));
-
-        if (response_id != GTK_RESPONSE_OK) {
-                return;
-        }
-
-        lang = cc_language_chooser_get_language (GTK_WIDGET (dialog));
-
-        if (lang == NULL) {
-                return;
-        }
-        model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
-        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
-
-        if (cc_common_language_get_iter_for_region (model, lang, &iter)) {
-                gtk_tree_selection_select_iter (selection, &iter);
-        }
-
-        gtk_widget_grab_focus (treeview);
-
-        g_free (lang);
-}
-
-static void
-add_region (GtkWidget *button, GtkWidget *treeview)
-{
-        GtkWidget *toplevel;
-        GtkWidget *chooser;
-
-        toplevel = gtk_widget_get_toplevel (button);
-        chooser = g_object_get_data (G_OBJECT (button), "chooser");
-        if (chooser == NULL) {
-                chooser = cc_language_chooser_new (toplevel, TRUE);
-
-                g_signal_connect (chooser, "response",
-                                  G_CALLBACK (region_response), treeview);
-                g_signal_connect (chooser, "delete-event",
-                                  G_CALLBACK (gtk_widget_hide_on_delete), NULL);
-
-                g_object_set_data_full (G_OBJECT (button), "chooser",
-                                        chooser, (GDestroyNotify)gtk_widget_destroy);
-        }
-        else {
-                cc_language_chooser_clear_filter (chooser);
-        }
-
-        gdk_window_set_cursor (gtk_widget_get_window (toplevel), NULL);
-        gtk_window_present (GTK_WINDOW (chooser));
-}
-
-void
-setup_formats (GtkBuilder *builder)
-{
-	GtkWidget *treeview;
-	gchar *current_lang;
-	GtkTreeModel *model;
-        GtkCellRenderer *cell;
-        GtkTreeViewColumn *column;
-        GtkWidget *widget;
-        GtkStyleContext *context;
-        GSettings *locale_settings;
-        GtkTreeSelection *selection;
-
-	locale_settings = g_settings_new ("org.gnome.system.locale");
-
-        /* Setup junction between toolbar and treeview */
-        widget = (GtkWidget *)gtk_builder_get_object (builder, "region-swindow");
-        context = gtk_widget_get_style_context (widget);
-        gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
-        widget = (GtkWidget *)gtk_builder_get_object (builder, "region-toolbar");
-        context = gtk_widget_get_style_context (widget);
-        gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
-
-	/* Setup formats selector */
-	treeview = GTK_WIDGET (gtk_builder_get_object (builder, "region_selector"));
-        cell = gtk_cell_renderer_text_new ();
-        g_object_set (cell,
-                      "width-chars", 40,
-                      "ellipsize", PANGO_ELLIPSIZE_END,
-                      NULL);
-        column = gtk_tree_view_column_new_with_attributes (NULL, cell, "text", 1, NULL);
-        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
-
-        model = (GtkTreeModel*)gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
-        gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model),
-                                                 sort_regions, NULL, NULL);
-        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-                                              GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
-                                              GTK_SORT_ASCENDING);
-        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), model);
-
-        g_object_set_data_full (G_OBJECT (treeview), "settings", locale_settings, g_object_unref);
-
-        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
-        g_signal_connect (selection, "changed",
-                          G_CALLBACK (update_settings_cb), builder);
-        g_signal_connect (selection, "changed",
-                          G_CALLBACK (update_examples_cb), builder);
-
-        /* Connect buttons */
-        widget = (GtkWidget *)gtk_builder_get_object (builder, "region_add");
-        g_signal_connect (widget, "clicked",
-                          G_CALLBACK (add_region), treeview);
-
-	current_lang = cc_common_language_get_current_language ();
-        populate_regions (builder, current_lang);
-	g_free (current_lang);
-
-        g_signal_connect (locale_settings, "changed::region",
-                          G_CALLBACK (setting_changed_cb), treeview);
-}
-
-void
-formats_update_language (GtkBuilder  *builder,
-                         const gchar *language)
-{
-        populate_regions (builder, language);
-}
-
diff --git a/panels/region/gnome-region-panel-formats.h b/panels/region/gnome-region-panel-formats.h
deleted file mode 100644
index 6ba1176..0000000
--- a/panels/region/gnome-region-panel-formats.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2011 Rodrigo Moya
- *
- * Written by: Rodrigo Moya <rodrigo@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, 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 __GNOME_REGION_PANEL_FORMATS_H
-#define __GNOME_REGION_PANEL_FORMATS_H
-
-#include <gtk/gtk.h>
-
-void setup_formats (GtkBuilder *builder);
-void formats_update_language (GtkBuilder  *builder,
-                              const gchar *language);
-
-#endif
diff --git a/panels/region/gnome-region-panel-input-chooser.ui b/panels/region/gnome-region-panel-input-chooser.ui
deleted file mode 100644
index 0a3f346..0000000
--- a/panels/region/gnome-region-panel-input-chooser.ui
+++ /dev/null
@@ -1,144 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface>
-  <requires lib="gtk+" version="2.16"/>
-  <object class="GtkListStore" id="input_source_model">
-    <columns>
-      <!-- display name -->
-      <column type="gchararray"/>
-      <!-- input source type -->
-      <column type="gchararray"/>
-      <!-- type specific identifier -->
-      <column type="gchararray"/>
-    </columns>
-  </object>
-  <object class="GtkTreeModelFilter" id="filtered_input_source_model">
-    <property name="child_model">input_source_model</property>
-  </object>
-  <object class="GtkDialog" id="input_source_chooser">
-    <property name="visible">False</property>
-    <property name="can_focus">False</property>
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">Select an input source</property>
-    <property name="modal">True</property>
-    <property name="window_position">center-on-parent</property>
-    <property name="type_hint">dialog</property>
-    <child internal-child="vbox">
-      <object class="GtkBox" id="dialog-vbox3">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox" id="hbtnBox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="cancel-button">
-                <property name="label">gtk-cancel</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="receives_default">False</property>
-                <property name="use_action_appearance">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="pack_type">end</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="ok-button">
-                <property name="label">gtk-add</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="receives_default">False</property>
-                <property name="use_action_appearance">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="pack_type">end</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </object>
-        </child>
-        <child>
-          <object class="GtkVBox" id="vbox40">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="border_width">5</property>
-            <property name="spacing">6</property>
-            <child>
-              <object class="GtkVBox" id="vbox1">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkScrolledWindow" id="scrolledwindow1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="hscrollbar_policy">never</property>
-                    <property name="shadow_type">etched-in</property>
-                    <property name="min_content_width">450</property>
-                    <property name="min_content_height">250</property>
-                    <child>
-                      <object class="GtkTreeView" id="filtered_input_source_list">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="model">filtered_input_source_model</property>
-                        <property name="headers_visible">False</property>
-                        <property name="search_column">0</property>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkEntry" id="input_source_filter">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="invisible_char">•</property>
-                <property name="secondary-icon-name">edit-find-symbolic</property>
-                <property name="secondary-icon-activatable">False</property>
-                <property name="secondary-icon-sensitive">False</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="pack_type">end</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <action-widgets>
-      <action-widget response="-5">ok-button</action-widget>
-      <action-widget response="-6">cancel-button</action-widget>
-    </action-widgets>
-  </object>
-</interface>
diff --git a/panels/region/gnome-region-panel-input.c b/panels/region/gnome-region-panel-input.c
deleted file mode 100644
index 679fe03..0000000
--- a/panels/region/gnome-region-panel-input.c
+++ /dev/null
@@ -1,1481 +0,0 @@
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * Written by: Matthias Clasen <mclasen@redhat.com>
- *
- * 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, 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 <string.h>
-
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <gio/gdesktopappinfo.h>
-
-#define GNOME_DESKTOP_USE_UNSTABLE_API
-#include <libgnome-desktop/gnome-xkb-info.h>
-
-#ifdef HAVE_IBUS
-#include <ibus.h>
-#endif
-
-#include "gnome-region-panel-input.h"
-
-#define WID(s) GTK_WIDGET(gtk_builder_get_object (builder, s))
-
-#define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources"
-
-#define KEY_CURRENT_INPUT_SOURCE "current"
-#define KEY_INPUT_SOURCES        "sources"
-
-#define INPUT_SOURCE_TYPE_XKB  "xkb"
-#define INPUT_SOURCE_TYPE_IBUS "ibus"
-
-enum {
-  NAME_COLUMN,
-  TYPE_COLUMN,
-  ID_COLUMN,
-  SETUP_COLUMN,
-  N_COLUMNS
-};
-
-static GSettings *input_sources_settings = NULL;
-static GnomeXkbInfo *xkb_info = NULL;
-static GtkWidget *input_chooser = NULL; /* weak pointer */
-
-#ifdef HAVE_IBUS
-static IBusBus *ibus = NULL;
-static GHashTable *ibus_engines = NULL;
-static GCancellable *ibus_cancellable = NULL;
-
-static const gchar *supported_ibus_engines[] = {
-  /* Simplified Chinese */
-  "pinyin",
-  "bopomofo",
-  "wubi",
-  "erbi",
-  /* Default in Fedora, where ibus-libpinyin replaces ibus-pinyin */
-  "libpinyin",
-  "libbopomofo",
-
-  /* Traditional Chinese */
-  /* https://bugzilla.gnome.org/show_bug.cgi?id=680840 */
-  "chewing",
-  "cangjie5",
-  "cangjie3",
-  "quick5",
-  "quick3",
-  "stroke5",
-
-  /* Japanese */
-  "anthy",
-  "mozc-jp",
-  "skk",
-
-  /* Korean */
-  "hangul",
-
-  /* Thai */
-  "m17n:th:kesmanee",
-  "m17n:th:pattachote",
-  "m17n:th:tis820",
-
-  /* Vietnamese */
-  "m17n:vi:tcvn",
-  "m17n:vi:telex",
-  "m17n:vi:viqr",
-  "m17n:vi:vni",
-  "Unikey",
-
-  /* Sinhala */
-  "m17n:si:wijesekera",
-  "m17n:si:phonetic-dynamic",
-  "m17n:si:trans",
-  "sayura",
-
-  /* Indic */
-  /* https://fedoraproject.org/wiki/I18N/Indic#Keyboard_Layouts */
-
-  /* Assamese */
-  "m17n:as:phonetic",
-  "m17n:as:inscript",
-  "m17n:as:itrans",
-
-  /* Bengali */
-  "m17n:bn:inscript",
-  "m17n:bn:itrans",
-  "m17n:bn:probhat",
-
-  /* Gujarati */
-  "m17n:gu:inscript",
-  "m17n:gu:itrans",
-  "m17n:gu:phonetic",
-
-  /* Hindi */
-  "m17n:hi:inscript",
-  "m17n:hi:itrans",
-  "m17n:hi:phonetic",
-  "m17n:hi:remington",
-  "m17n:hi:typewriter",
-  "m17n:hi:vedmata",
-
-  /* Kannada */
-  "m17n:kn:kgp",
-  "m17n:kn:inscript",
-  "m17n:kn:itrans",
-
-  /* Kashmiri */
-  "m17n:ks:inscript",
-
-  /* Maithili */
-  "m17n:mai:inscript",
-
-  /* Malayalam */
-  "m17n:ml:inscript",
-  "m17n:ml:itrans",
-  "m17n:ml:mozhi",
-  "m17n:ml:swanalekha",
-
-  /* Marathi */
-  "m17n:mr:inscript",
-  "m17n:mr:itrans",
-  "m17n:mr:phonetic",
-
-  /* Nepali */
-  "m17n:ne:rom",
-  "m17n:ne:trad",
-
-  /* Oriya */
-  "m17n:or:inscript",
-  "m17n:or:itrans",
-  "m17n:or:phonetic",
-
-  /* Punjabi */
-  "m17n:pa:inscript",
-  "m17n:pa:itrans",
-  "m17n:pa:phonetic",
-  "m17n:pa:jhelum",
-
-  /* Sanskrit */
-  "m17n:sa:harvard-kyoto",
-
-  /* Sindhi */
-  "m17n:sd:inscript",
-
-  /* Tamil */
-  "m17n:ta:tamil99",
-  "m17n:ta:inscript",
-  "m17n:ta:itrans",
-  "m17n:ta:phonetic",
-  "m17n:ta:lk-renganathan",
-  "m17n:ta:vutam",
-  "m17n:ta:typewriter",
-
-  /* Telugu */
-  "m17n:te:inscript",
-  "m17n:te:apple",
-  "m17n:te:pothana",
-  "m17n:te:rts",
-
-  /* Urdu */
-  "m17n:ur:phonetic",
-
-  /* Inscript2 - https://bugzilla.gnome.org/show_bug.cgi?id=684854 */
-  "m17n:as:inscript2",
-  "m17n:bn:inscript2",
-  "m17n:brx:inscript2-deva",
-  "m17n:doi:inscript2-deva",
-  "m17n:gu:inscript2",
-  "m17n:hi:inscript2",
-  "m17n:kn:inscript2",
-  "m17n:kok:inscript2-deva",
-  "m17n:mai:inscript2",
-  "m17n:ml:inscript2",
-  "m17n:mni:inscript2-beng",
-  "m17n:mni:inscript2-mtei",
-  "m17n:mr:inscript2",
-  "m17n:ne:inscript2-deva",
-  "m17n:or:inscript2",
-  "m17n:pa:inscript2-guru",
-  "m17n:sa:inscript2",
-  "m17n:sat:inscript2-deva",
-  "m17n:sat:inscript2-olck",
-  "m17n:sd:inscript2-deva",
-  "m17n:ta:inscript2",
-  "m17n:te:inscript2",
-
-  /* No corresponding XKB map available for the languages */
-
-  /* Chinese Yi */
-  "m17n:ii:phonetic",
-
-  /* Tai-Viet */
-  "m17n:tai:sonla",
-
-  /* Kazakh in Arabic script */
-  "m17n:kk:arabic",
-
-  /* Yiddish */
-  "m17n:yi:yivo",
-
-  /* Canadian Aboriginal languages */
-  "m17n:ath:phonetic",
-  "m17n:bla:phonetic",
-  "m17n:cr:western",
-  "m17n:iu:phonetic",
-  "m17n:nsk:phonetic",
-  "m17n:oj:phonetic",
-
-  /* Non-trivial engines, like transliteration-based instead of
-     keymap-based.  Confirmation needed that the engines below are
-     actually used by local language users. */
-
-  /* Tibetan */
-  "m17n:bo:ewts",
-  "m17n:bo:tcrc",
-  "m17n:bo:wylie",
-
-  /* Esperanto */
-  "m17n:eo:h-f",
-  "m17n:eo:h",
-  "m17n:eo:plena",
-  "m17n:eo:q",
-  "m17n:eo:vi",
-  "m17n:eo:x",
-
-  /* Amharic */
-  "m17n:am:sera",
-
-  /* Russian */
-  "m17n:ru:translit",
-
-  /* Classical Greek */
-  "m17n:grc:mizuochi",
-
-  /* Lao */
-  "m17n:lo:lrt",
-
-  /* Postfix modifier input methods */
-  "m17n:da:post",
-  "m17n:sv:post",
-  NULL
-};
-#endif  /* HAVE_IBUS */
-
-static void       populate_model             (GtkListStore  *store,
-                                              GtkListStore  *active_sources_store);
-static GtkWidget *input_chooser_new          (GtkWindow     *main_window,
-                                              GtkListStore  *active_sources);
-static gboolean   input_chooser_get_selected (GtkWidget     *chooser,
-                                              GtkTreeModel **model,
-                                              GtkTreeIter   *iter);
-
-static gboolean
-strv_contains (const gchar * const *strv,
-               const gchar         *str)
-{
-  const gchar * const *p = strv;
-  for (p = strv; *p; p++)
-    if (g_strcmp0 (*p, str) == 0)
-      return TRUE;
-
-  return FALSE;
-}
-
-#ifdef HAVE_IBUS
-static void
-clear_ibus (void)
-{
-  g_cancellable_cancel (ibus_cancellable);
-  g_clear_object (&ibus_cancellable);
-  g_clear_pointer (&ibus_engines, g_hash_table_destroy);
-  g_clear_object (&ibus);
-}
-
-static gchar *
-engine_get_display_name (IBusEngineDesc *engine_desc)
-{
-  const gchar *name;
-  const gchar *language_code;
-  const gchar *language;
-  gchar *display_name;
-
-  name = ibus_engine_desc_get_longname (engine_desc);
-  language_code = ibus_engine_desc_get_language (engine_desc);
-  language = ibus_get_language_name (language_code);
-
-  display_name = g_strdup_printf ("%s (%s)", language, name);
-
-  return display_name;
-}
-
-static GDesktopAppInfo *
-setup_app_info_for_id (const gchar *id)
-{
-  GDesktopAppInfo *app_info;
-  gchar *desktop_file_name;
-  gchar **strv;
-
-  strv = g_strsplit (id, ":", 2);
-  desktop_file_name = g_strdup_printf ("ibus-setup-%s.desktop", strv[0]);
-  g_strfreev (strv);
-
-  app_info = g_desktop_app_info_new (desktop_file_name);
-  g_free (desktop_file_name);
-
-  return app_info;
-}
-
-static void
-input_chooser_repopulate (GtkListStore *active_sources_store)
-{
-  GtkBuilder *builder;
-  GtkListStore *model;
-
-  if (!input_chooser)
-    return;
-
-  builder = g_object_get_data (G_OBJECT (input_chooser), "builder");
-  model = GTK_LIST_STORE (gtk_builder_get_object (builder, "input_source_model"));
-
-  gtk_list_store_clear (model);
-  populate_model (model, active_sources_store);
-}
-
-static void
-update_ibus_active_sources (GtkBuilder *builder)
-{
-  GtkTreeView *tv;
-  GtkTreeModel *model;
-  GtkTreeIter iter;
-  gchar *type, *id;
-  gboolean ret;
-
-  tv = GTK_TREE_VIEW (WID ("active_input_sources"));
-  model = gtk_tree_view_get_model (tv);
-
-  ret = gtk_tree_model_get_iter_first (model, &iter);
-  while (ret)
-    {
-      gtk_tree_model_get (model, &iter,
-                          TYPE_COLUMN, &type,
-                          ID_COLUMN, &id,
-                          -1);
-
-      if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
-        {
-          IBusEngineDesc *engine_desc = NULL;
-          gchar *display_name = NULL;
-
-          engine_desc = g_hash_table_lookup (ibus_engines, id);
-          if (engine_desc)
-            {
-              display_name = engine_get_display_name (engine_desc);
-
-              gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-                                  NAME_COLUMN, display_name,
-                                  -1);
-              g_free (display_name);
-            }
-        }
-
-      g_free (type);
-      g_free (id);
-
-      ret = gtk_tree_model_iter_next (model, &iter);
-    }
-
-  input_chooser_repopulate (GTK_LIST_STORE (model));
-}
-
-static void
-fetch_ibus_engines_result (GObject      *object,
-                           GAsyncResult *result,
-                           GtkBuilder   *builder)
-{
-  gboolean show_all_sources;
-  GList *list, *l;
-  GError *error;
-
-  error = NULL;
-  list = ibus_bus_list_engines_async_finish (ibus, result, &error);
-
-  g_clear_object (&ibus_cancellable);
-
-  if (!list && error)
-    {
-      g_warning ("Couldn't finish IBus request: %s", error->message);
-      g_error_free (error);
-      return;
-    }
-
-  show_all_sources = g_settings_get_boolean (input_sources_settings, "show-all-sources");
-
-  /* Maps engine ids to engine description objects */
-  ibus_engines = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
-
-  for (l = list; l; l = l->next)
-    {
-      IBusEngineDesc *engine = l->data;
-      const gchar *engine_id = ibus_engine_desc_get_name (engine);
-
-      if (show_all_sources || strv_contains (supported_ibus_engines, engine_id))
-        g_hash_table_replace (ibus_engines, (gpointer)engine_id, engine);
-      else
-        g_object_unref (engine);
-    }
-  g_list_free (list);
-
-  update_ibus_active_sources (builder);
-}
-
-static void
-fetch_ibus_engines (GtkBuilder *builder)
-{
-  ibus_cancellable = g_cancellable_new ();
-
-  ibus_bus_list_engines_async (ibus,
-                               -1,
-                               ibus_cancellable,
-                               (GAsyncReadyCallback)fetch_ibus_engines_result,
-                               builder);
-
-  /* We've got everything we needed, don't want to be called again. */
-  g_signal_handlers_disconnect_by_func (ibus, fetch_ibus_engines, builder);
-}
-
-static void
-maybe_start_ibus (void)
-{
-  /* IBus doesn't export API in the session bus. The only thing
-   * we have there is a well known name which we can use as a
-   * sure-fire way to activate it. */
-  g_bus_unwatch_name (g_bus_watch_name (G_BUS_TYPE_SESSION,
-                                        IBUS_SERVICE_IBUS,
-                                        G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
-                                        NULL,
-                                        NULL,
-                                        NULL,
-                                        NULL));
-}
-#endif  /* HAVE_IBUS */
-
-static gboolean
-add_source_to_table (GtkTreeModel *model,
-                     GtkTreePath  *path,
-                     GtkTreeIter  *iter,
-                     gpointer      data)
-{
-  GHashTable *hash = data;
-  gchar *type;
-  gchar *id;
-
-  gtk_tree_model_get (model, iter,
-                      TYPE_COLUMN, &type,
-                      ID_COLUMN, &id,
-                      -1);
-
-  g_hash_table_add (hash, g_strconcat (type, id, NULL));
-
-  g_free (type);
-  g_free (id);
-
-  return FALSE;
-}
-
-static void
-populate_model (GtkListStore *store,
-                GtkListStore *active_sources_store)
-{
-  GHashTable *active_sources_table;
-  GtkTreeIter iter;
-  const gchar *name;
-  GList *sources, *tmp;
-  gchar *source_id = NULL;
-
-  active_sources_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
-  gtk_tree_model_foreach (GTK_TREE_MODEL (active_sources_store),
-                          add_source_to_table,
-                          active_sources_table);
-
-  sources = gnome_xkb_info_get_all_layouts (xkb_info);
-
-  for (tmp = sources; tmp; tmp = tmp->next)
-    {
-      g_free (source_id);
-      source_id = g_strconcat (INPUT_SOURCE_TYPE_XKB, tmp->data, NULL);
-
-      if (g_hash_table_contains (active_sources_table, source_id))
-        continue;
-
-      gnome_xkb_info_get_layout_info (xkb_info, (const gchar *)tmp->data,
-                                      &name, NULL, NULL, NULL);
-
-      gtk_list_store_append (store, &iter);
-      gtk_list_store_set (store, &iter,
-                          NAME_COLUMN, name,
-                          TYPE_COLUMN, INPUT_SOURCE_TYPE_XKB,
-                          ID_COLUMN, tmp->data,
-                          -1);
-    }
-  g_free (source_id);
-
-  g_list_free (sources);
-
-#ifdef HAVE_IBUS
-  if (ibus_engines)
-    {
-      gchar *display_name;
-
-      sources = g_hash_table_get_keys (ibus_engines);
-
-      source_id = NULL;
-      for (tmp = sources; tmp; tmp = tmp->next)
-        {
-          g_free (source_id);
-          source_id = g_strconcat (INPUT_SOURCE_TYPE_IBUS, tmp->data, NULL);
-
-          if (g_hash_table_contains (active_sources_table, source_id))
-            continue;
-
-          display_name = engine_get_display_name (g_hash_table_lookup (ibus_engines, tmp->data));
-
-          gtk_list_store_append (store, &iter);
-          gtk_list_store_set (store, &iter,
-                              NAME_COLUMN, display_name,
-                              TYPE_COLUMN, INPUT_SOURCE_TYPE_IBUS,
-                              ID_COLUMN, tmp->data,
-                              -1);
-          g_free (display_name);
-        }
-      g_free (source_id);
-
-      g_list_free (sources);
-    }
-#endif
-
-  g_hash_table_destroy (active_sources_table);
-}
-
-static void
-populate_with_active_sources (GtkListStore *store)
-{
-  GVariant *sources;
-  GVariantIter iter;
-  const gchar *name;
-  const gchar *type;
-  const gchar *id;
-  gchar *display_name;
-  GDesktopAppInfo *app_info;
-  GtkTreeIter tree_iter;
-
-  sources = g_settings_get_value (input_sources_settings, KEY_INPUT_SOURCES);
-
-  g_variant_iter_init (&iter, sources);
-  while (g_variant_iter_next (&iter, "(&s&s)", &type, &id))
-    {
-      display_name = NULL;
-      app_info = NULL;
-
-      if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
-        {
-          gnome_xkb_info_get_layout_info (xkb_info, id, &name, NULL, NULL, NULL);
-          if (!name)
-            {
-              g_warning ("Couldn't find XKB input source '%s'", id);
-              continue;
-            }
-          display_name = g_strdup (name);
-        }
-      else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
-        {
-#ifdef HAVE_IBUS
-          IBusEngineDesc *engine_desc = NULL;
-
-          if (ibus_engines)
-            engine_desc = g_hash_table_lookup (ibus_engines, id);
-
-          if (engine_desc)
-            display_name = engine_get_display_name (engine_desc);
-
-          app_info = setup_app_info_for_id (id);
-#else
-          g_warning ("IBus input source type specified but IBus support was not compiled");
-          continue;
-#endif
-        }
-      else
-        {
-          g_warning ("Unknown input source type '%s'", type);
-          continue;
-        }
-
-      gtk_list_store_append (store, &tree_iter);
-      gtk_list_store_set (store, &tree_iter,
-                          NAME_COLUMN, display_name ? display_name : id,
-                          TYPE_COLUMN, type,
-                          ID_COLUMN, id,
-                          SETUP_COLUMN, app_info,
-                          -1);
-      g_free (display_name);
-      if (app_info)
-        g_object_unref (app_info);
-    }
-
-  g_variant_unref (sources);
-}
-
-static void
-update_configuration (GtkTreeModel *model)
-{
-  GtkTreeIter iter;
-  gchar *type;
-  gchar *id;
-  GVariantBuilder builder;
-  GVariant *old_sources;
-  const gchar *old_current_type;
-  const gchar *old_current_id;
-  guint old_current_index;
-  guint old_n_sources;
-  guint index;
-
-  old_sources = g_settings_get_value (input_sources_settings, KEY_INPUT_SOURCES);
-  old_current_index = g_settings_get_uint (input_sources_settings, KEY_CURRENT_INPUT_SOURCE);
-  old_n_sources = g_variant_n_children (old_sources);
-
-  if (old_n_sources > 0 && old_current_index < old_n_sources)
-    {
-      g_variant_get_child (old_sources,
-                           old_current_index,
-                           "(&s&s)",
-                           &old_current_type,
-                           &old_current_id);
-    }
-  else
-    {
-      old_current_type = "";
-      old_current_id = "";
-    }
-
-  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
-  index = 0;
-  gtk_tree_model_get_iter_first (model, &iter);
-  do
-    {
-      gtk_tree_model_get (model, &iter,
-                          TYPE_COLUMN, &type,
-                          ID_COLUMN, &id,
-                          -1);
-      if (index != old_current_index &&
-          g_str_equal (type, old_current_type) &&
-          g_str_equal (id, old_current_id))
-        {
-          g_settings_set_uint (input_sources_settings, KEY_CURRENT_INPUT_SOURCE, index);
-        }
-      g_variant_builder_add (&builder, "(ss)", type, id);
-      g_free (type);
-      g_free (id);
-      index += 1;
-    }
-  while (gtk_tree_model_iter_next (model, &iter));
-
-  g_settings_set_value (input_sources_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
-  g_settings_apply (input_sources_settings);
-
-  g_variant_unref (old_sources);
-}
-
-static gboolean
-get_selected_iter (GtkBuilder    *builder,
-                   GtkTreeModel **model,
-                   GtkTreeIter   *iter)
-{
-  GtkTreeSelection *selection;
-
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (WID ("active_input_sources")));
-
-  return gtk_tree_selection_get_selected (selection, model, iter);
-}
-
-static gint
-idx_from_model_iter (GtkTreeModel *model,
-                     GtkTreeIter  *iter)
-{
-  GtkTreePath *path;
-  gint idx;
-
-  path = gtk_tree_model_get_path (model, iter);
-  if (path == NULL)
-    return -1;
-
-  idx = gtk_tree_path_get_indices (path)[0];
-  gtk_tree_path_free (path);
-
-  return idx;
-}
-
-static void
-update_button_sensitivity (GtkBuilder *builder)
-{
-  GtkWidget *remove_button;
-  GtkWidget *up_button;
-  GtkWidget *down_button;
-  GtkWidget *show_button;
-  GtkWidget *settings_button;
-  GtkTreeView *tv;
-  GtkTreeModel *model;
-  GtkTreeIter iter;
-  gint n_active;
-  gint index;
-  gboolean settings_sensitive;
-  GDesktopAppInfo *app_info;
-
-  remove_button = WID("input_source_remove");
-  show_button = WID("input_source_show");
-  up_button = WID("input_source_move_up");
-  down_button = WID("input_source_move_down");
-  settings_button = WID("input_source_settings");
-
-  tv = GTK_TREE_VIEW (WID ("active_input_sources"));
-  n_active = gtk_tree_model_iter_n_children (gtk_tree_view_get_model (tv), NULL);
-
-  if (get_selected_iter (builder, &model, &iter))
-    {
-      index = idx_from_model_iter (model, &iter);
-      gtk_tree_model_get (model, &iter, SETUP_COLUMN, &app_info, -1);
-    }
-  else
-    {
-      index = -1;
-      app_info = NULL;
-    }
-
-  settings_sensitive = (index >= 0 && app_info != NULL);
-
-  if (app_info)
-    g_object_unref (app_info);
-
-  gtk_widget_set_sensitive (remove_button, index >= 0 && n_active > 1);
-  gtk_widget_set_sensitive (show_button, index >= 0);
-  gtk_widget_set_sensitive (up_button, index > 0);
-  gtk_widget_set_sensitive (down_button, index >= 0 && index < n_active - 1);
-  gtk_widget_set_sensitive (settings_button, settings_sensitive);
-}
-
-static void
-set_selected_path (GtkBuilder  *builder,
-                   GtkTreePath *path)
-{
-  GtkTreeSelection *selection;
-
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (WID ("active_input_sources")));
-
-  gtk_tree_selection_select_path (selection, path);
-}
-
-static void
-chooser_response (GtkWidget *chooser, gint response_id, gpointer data)
-{
-  GtkBuilder *builder = data;
-
-  if (response_id == GTK_RESPONSE_OK)
-    {
-      GtkTreeModel *model;
-      GtkTreeIter iter;
-
-      if (input_chooser_get_selected (chooser, &model, &iter))
-        {
-          GtkTreeView *tv;
-          GtkListStore *my_model;
-          GtkTreeIter child_iter;
-          gchar *name;
-          gchar *type;
-          gchar *id;
-          GDesktopAppInfo *app_info = NULL;
-
-          gtk_tree_model_get (model, &iter,
-                              NAME_COLUMN, &name,
-                              TYPE_COLUMN, &type,
-                              ID_COLUMN, &id,
-                              -1);
-
-#ifdef HAVE_IBUS
-          if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
-            app_info = setup_app_info_for_id (id);
-#endif
-
-          tv = GTK_TREE_VIEW (WID ("active_input_sources"));
-          my_model = GTK_LIST_STORE (gtk_tree_view_get_model (tv));
-
-          gtk_list_store_insert_with_values (my_model, &child_iter, -1,
-                                             NAME_COLUMN, name,
-                                             TYPE_COLUMN, type,
-                                             ID_COLUMN, id,
-                                             SETUP_COLUMN, app_info,
-                                             -1);
-          g_free (name);
-          g_free (type);
-          g_free (id);
-          if (app_info)
-            g_object_unref (app_info);
-
-          gtk_tree_selection_select_iter (gtk_tree_view_get_selection (tv), &child_iter);
-
-          update_button_sensitivity (builder);
-          update_configuration (GTK_TREE_MODEL (my_model));
-        }
-      else
-        {
-          g_debug ("nothing selected, nothing added");
-        }
-    }
-
-  gtk_widget_destroy (GTK_WIDGET (chooser));
-}
-
-static void
-add_input (GtkButton *button, gpointer data)
-{
-  GtkBuilder *builder = data;
-  GtkWidget *chooser;
-  GtkWidget *toplevel;
-  GtkWidget *treeview;
-  GtkListStore *active_sources;
-
-  g_debug ("add an input source");
-
-  toplevel = gtk_widget_get_toplevel (WID ("region_notebook"));
-  treeview = WID ("active_input_sources");
-  active_sources = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)));
-
-  chooser = input_chooser_new (GTK_WINDOW (toplevel), active_sources);
-  g_signal_connect (chooser, "response",
-                    G_CALLBACK (chooser_response), builder);
-}
-
-static void
-remove_selected_input (GtkButton *button, gpointer data)
-{
-  GtkBuilder *builder = data;
-  GtkTreeModel *model;
-  GtkTreeIter iter;
-  GtkTreePath *path;
-
-  g_debug ("remove selected input source");
-
-  if (get_selected_iter (builder, &model, &iter) == FALSE)
-    return;
-
-  path = gtk_tree_model_get_path (model, &iter);
-
-  gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
-
-  if (!gtk_tree_model_get_iter (model, &iter, path))
-    gtk_tree_path_prev (path);
-
-  set_selected_path (builder, path);
-
-  gtk_tree_path_free (path);
-
-  update_button_sensitivity (builder);
-  update_configuration (model);
-}
-
-static void
-move_selected_input_up (GtkButton *button, gpointer data)
-{
-  GtkBuilder *builder = data;
-  GtkTreeModel *model;
-  GtkTreeIter iter, prev;
-  GtkTreePath *path;
-
-  g_debug ("move selected input source up");
-
-  if (!get_selected_iter (builder, &model, &iter))
-    return;
-
-  prev = iter;
-  if (!gtk_tree_model_iter_previous (model, &prev))
-    return;
-
-  path = gtk_tree_model_get_path (model, &prev);
-
-  gtk_list_store_swap (GTK_LIST_STORE (model), &iter, &prev);
-
-  set_selected_path (builder, path);
-  gtk_tree_path_free (path);
-
-  update_button_sensitivity (builder);
-  update_configuration (model);
-}
-
-static void
-move_selected_input_down (GtkButton *button, gpointer data)
-{
-  GtkBuilder *builder = data;
-  GtkTreeModel *model;
-  GtkTreeIter iter, next;
-  GtkTreePath *path;
-
-  g_debug ("move selected input source down");
-
-  if (!get_selected_iter (builder, &model, &iter))
-    return;
-
-  next = iter;
-  if (!gtk_tree_model_iter_next (model, &next))
-    return;
-
-  path = gtk_tree_model_get_path (model, &next);
-
-  gtk_list_store_swap (GTK_LIST_STORE (model), &iter, &next);
-
-  set_selected_path (builder, path);
-  gtk_tree_path_free (path);
-
-  update_button_sensitivity (builder);
-  update_configuration (model);
-}
-
-static void
-show_selected_layout (GtkButton *button, gpointer data)
-{
-  GtkBuilder *builder = data;
-  GtkTreeModel *model;
-  GtkTreeIter iter;
-  gchar *type;
-  gchar *id;
-  gchar *kbd_viewer_args;
-  const gchar *xkb_layout;
-  const gchar *xkb_variant;
-
-  g_debug ("show selected layout");
-
-  if (!get_selected_iter (builder, &model, &iter))
-    return;
-
-  gtk_tree_model_get (model, &iter,
-                      TYPE_COLUMN, &type,
-                      ID_COLUMN, &id,
-                      -1);
-
-  if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
-    {
-      gnome_xkb_info_get_layout_info (xkb_info, id, NULL, NULL, &xkb_layout, &xkb_variant);
-
-      if (!xkb_layout || !xkb_layout[0])
-        {
-          g_warning ("Couldn't find XKB input source '%s'", id);
-          goto exit;
-        }
-    }
-  else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
-    {
-#ifdef HAVE_IBUS
-      IBusEngineDesc *engine_desc = NULL;
-
-      if (ibus_engines)
-        engine_desc = g_hash_table_lookup (ibus_engines, id);
-
-      if (engine_desc)
-        {
-          xkb_layout = ibus_engine_desc_get_layout (engine_desc);
-          xkb_variant = "";
-        }
-      else
-        {
-          g_warning ("Couldn't find IBus input source '%s'", id);
-          goto exit;
-        }
-#else
-      g_warning ("IBus input source type specified but IBus support was not compiled");
-      goto exit;
-#endif
-    }
-  else
-    {
-      g_warning ("Unknown input source type '%s'", type);
-      goto exit;
-    }
-
-  if (xkb_variant[0])
-    kbd_viewer_args = g_strdup_printf ("gkbd-keyboard-display -l \"%s\t%s\"",
-                                       xkb_layout, xkb_variant);
-  else
-    kbd_viewer_args = g_strdup_printf ("gkbd-keyboard-display -l %s",
-                                       xkb_layout);
-
-  g_spawn_command_line_async (kbd_viewer_args, NULL);
-
-  g_free (kbd_viewer_args);
- exit:
-  g_free (type);
-  g_free (id);
-}
-
-static void
-show_selected_settings (GtkButton *button, gpointer data)
-{
-  GtkBuilder *builder = data;
-  GtkTreeModel *model;
-  GtkTreeIter iter;
-  GdkAppLaunchContext *ctx;
-  GDesktopAppInfo *app_info;
-  gchar *id;
-  GError *error = NULL;
-
-  g_debug ("show selected layout");
-
-  if (!get_selected_iter (builder, &model, &iter))
-    return;
-
-  gtk_tree_model_get (model, &iter, SETUP_COLUMN, &app_info, -1);
-
-  if (!app_info)
-    return;
-
-  ctx = gdk_display_get_app_launch_context (gdk_display_get_default ());
-  gdk_app_launch_context_set_timestamp (ctx, gtk_get_current_event_time ());
-
-  gtk_tree_model_get (model, &iter, ID_COLUMN, &id, -1);
-  g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (ctx),
-                               "IBUS_ENGINE_NAME",
-                               id);
-  g_free (id);
-
-  if (!g_app_info_launch (G_APP_INFO (app_info), NULL, G_APP_LAUNCH_CONTEXT (ctx), &error))
-    {
-      g_warning ("Failed to launch input source setup: %s", error->message);
-      g_error_free (error);
-    }
-
-  g_object_unref (ctx);
-  g_object_unref (app_info);
-}
-
-static gboolean
-go_to_shortcuts (GtkLinkButton *button,
-                 CcRegionPanel *panel)
-{
-  CcShell *shell;
-  const gchar *argv[] = { "shortcuts", "Typing", NULL };
-  GError *error = NULL;
-
-  shell = cc_panel_get_shell (CC_PANEL (panel));
-  if (!cc_shell_set_active_panel_from_id (shell, "keyboard", argv, &error))
-    {
-      g_warning ("Failed to activate Keyboard panel: %s", error->message);
-      g_error_free (error);
-    }
-
-  return TRUE;
-}
-
-static void
-input_sources_changed (GSettings  *settings,
-                       gchar      *key,
-                       GtkBuilder *builder)
-{
-  GtkWidget *treeview;
-  GtkTreeModel *store;
-  GtkTreePath *path;
-  GtkTreeIter iter;
-  GtkTreeModel *model;
-
-  treeview = WID("active_input_sources");
-  store = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
-
-  if (get_selected_iter (builder, &model, &iter))
-    path = gtk_tree_model_get_path (model, &iter);
-  else
-    path = NULL;
-
-  gtk_list_store_clear (GTK_LIST_STORE (store));
-  populate_with_active_sources (GTK_LIST_STORE (store));
-
-  if (path)
-    {
-      set_selected_path (builder, path);
-      gtk_tree_path_free (path);
-    }
-}
-
-static void
-update_shortcut_label (GtkWidget  *widget,
-		       const char *value)
-{
-  char *text;
-  guint accel_key, *keycode;
-  GdkModifierType mods;
-
-  if (value == NULL || *value == '\0')
-    {
-      gtk_label_set_text (GTK_LABEL (widget), "\342\200\224");
-      return;
-    }
-  gtk_accelerator_parse_with_keycode (value, &accel_key, &keycode, &mods);
-  if (accel_key == 0 && keycode == NULL && mods == 0)
-    {
-      gtk_label_set_text (GTK_LABEL (widget), "\342\200\224");
-      g_warning ("Failed to parse keyboard shortcut: '%s'", value);
-      return;
-    }
-
-  text = gtk_accelerator_get_label_with_keycode (gtk_widget_get_display (widget), accel_key, *keycode, mods);
-  g_free (keycode);
-  gtk_label_set_text (GTK_LABEL (widget), text);
-  g_free (text);
-}
-
-static void
-update_shortcuts (GtkBuilder *builder)
-{
-  char **previous, **next;
-  GSettings *settings;
-
-  settings = g_settings_new ("org.gnome.desktop.wm.keybindings");
-
-  previous = g_settings_get_strv (settings, "switch-input-source-backward");
-  next = g_settings_get_strv (settings, "switch-input-source");
-
-  update_shortcut_label (WID ("prev-source-shortcut-label"), previous[0]);
-  update_shortcut_label (WID ("next-source-shortcut-label"), next[0]);
-
-  g_strfreev (previous);
-  g_strfreev (next);
-}
-
-void
-setup_input_tabs (GtkBuilder    *builder,
-                  CcRegionPanel *panel)
-{
-  GtkWidget *treeview;
-  GtkTreeViewColumn *column;
-  GtkCellRenderer *cell;
-  GtkListStore *store;
-  GtkTreeSelection *selection;
-
-  /* set up the list of active inputs */
-  treeview = WID("active_input_sources");
-  column = gtk_tree_view_column_new ();
-  cell = gtk_cell_renderer_text_new ();
-  gtk_tree_view_column_pack_start (column, cell, TRUE);
-  gtk_tree_view_column_add_attribute (column, cell, "text", NAME_COLUMN);
-  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
-
-  store = gtk_list_store_new (N_COLUMNS,
-                              G_TYPE_STRING,
-                              G_TYPE_STRING,
-                              G_TYPE_STRING,
-                              G_TYPE_DESKTOP_APP_INFO);
-
-  gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store));
-
-  input_sources_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
-  g_settings_delay (input_sources_settings);
-  g_object_weak_ref (G_OBJECT (builder), (GWeakNotify) g_object_unref, input_sources_settings);
-
-  if (!xkb_info)
-    xkb_info = gnome_xkb_info_new ();
-
-#ifdef HAVE_IBUS
-  ibus_init ();
-  if (!ibus)
-    {
-      ibus = ibus_bus_new_async ();
-      if (ibus_bus_is_connected (ibus))
-        fetch_ibus_engines (builder);
-      else
-        g_signal_connect_swapped (ibus, "connected",
-                                  G_CALLBACK (fetch_ibus_engines), builder);
-      g_object_weak_ref (G_OBJECT (builder), (GWeakNotify) clear_ibus, NULL);
-    }
-  maybe_start_ibus ();
-#endif
-
-  populate_with_active_sources (store);
-
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
-  g_signal_connect_swapped (selection, "changed",
-                            G_CALLBACK (update_button_sensitivity), builder);
-
-  /* set up the buttons */
-  g_signal_connect (WID("input_source_add"), "clicked",
-                    G_CALLBACK (add_input), builder);
-  g_signal_connect (WID("input_source_remove"), "clicked",
-                    G_CALLBACK (remove_selected_input), builder);
-  g_signal_connect (WID("input_source_move_up"), "clicked",
-                    G_CALLBACK (move_selected_input_up), builder);
-  g_signal_connect (WID("input_source_move_down"), "clicked",
-                    G_CALLBACK (move_selected_input_down), builder);
-  g_signal_connect (WID("input_source_show"), "clicked",
-                    G_CALLBACK (show_selected_layout), builder);
-  g_signal_connect (WID("input_source_settings"), "clicked",
-                    G_CALLBACK (show_selected_settings), builder);
-
-  /* use an em dash is no shortcut */
-  update_shortcuts (builder);
-
-  g_signal_connect (WID("jump-to-shortcuts"), "activate-link",
-                    G_CALLBACK (go_to_shortcuts), panel);
-
-  g_signal_connect (G_OBJECT (input_sources_settings),
-                    "changed::" KEY_INPUT_SOURCES,
-                    G_CALLBACK (input_sources_changed),
-                    builder);
-
-  g_settings_bind (input_sources_settings, "per-window",
-                   WID("per-window-radio-true"), "active",
-                   G_SETTINGS_BIND_DEFAULT);
-  g_settings_bind (input_sources_settings, "per-window",
-                   WID("per-window-radio-false"), "active",
-                   G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_INVERT_BOOLEAN);
-  /* because we are in delay-apply mode */
-  g_signal_connect_swapped (WID("per-window-radio-true"), "clicked",
-                            G_CALLBACK (g_settings_apply), input_sources_settings);
-  g_signal_connect_swapped (WID("per-window-radio-false"), "clicked",
-                            G_CALLBACK (g_settings_apply), input_sources_settings);
-}
-
-static void
-filter_clear (GtkEntry             *entry,
-              GtkEntryIconPosition  icon_pos,
-              GdkEvent             *event,
-              gpointer              user_data)
-{
-  gtk_entry_set_text (entry, "");
-}
-
-static gchar **search_pattern_list;
-
-static void
-filter_changed (GtkBuilder *builder)
-{
-  GtkTreeModelFilter *filtered_model;
-  GtkTreeView *tree_view;
-  GtkTreeSelection *selection;
-  GtkTreeIter selected_iter;
-  GtkWidget *filter_entry;
-  const gchar *pattern;
-  gchar *upattern;
-
-  filter_entry = WID ("input_source_filter");
-  pattern = gtk_entry_get_text (GTK_ENTRY (filter_entry));
-  upattern = g_utf8_strup (pattern, -1);
-  if (!g_strcmp0 (pattern, ""))
-    g_object_set (G_OBJECT (filter_entry),
-                  "secondary-icon-name", "edit-find-symbolic",
-                  "secondary-icon-activatable", FALSE,
-                  "secondary-icon-sensitive", FALSE,
-                  NULL);
-  else
-    g_object_set (G_OBJECT (filter_entry),
-                  "secondary-icon-name", "edit-clear-symbolic",
-                  "secondary-icon-activatable", TRUE,
-                  "secondary-icon-sensitive", TRUE,
-                  NULL);
-
-  if (search_pattern_list != NULL)
-    g_strfreev (search_pattern_list);
-
-  search_pattern_list = g_strsplit (upattern, " ", -1);
-  g_free (upattern);
-
-  filtered_model = GTK_TREE_MODEL_FILTER (gtk_builder_get_object (builder, "filtered_input_source_model"));
-  gtk_tree_model_filter_refilter (filtered_model);
-
-  tree_view = GTK_TREE_VIEW (WID ("filtered_input_source_list"));
-  selection = gtk_tree_view_get_selection (tree_view);
-  if (gtk_tree_selection_get_selected (selection, NULL, &selected_iter))
-    {
-      GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (filtered_model),
-                                                   &selected_iter);
-      gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0.5);
-      gtk_tree_path_free (path);
-    }
-  else
-    {
-      GtkTreeIter iter;
-      if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (filtered_model), &iter))
-        gtk_tree_selection_select_iter (selection, &iter);
-    }
-}
-
-static void
-selection_changed (GtkTreeSelection *selection,
-                   GtkBuilder       *builder)
-{
-  gtk_widget_set_sensitive (WID ("ok-button"),
-                            gtk_tree_selection_get_selected (selection, NULL, NULL));
-}
-
-static void
-row_activated (GtkTreeView       *tree_view,
-               GtkTreePath       *path,
-               GtkTreeViewColumn *column,
-               GtkBuilder        *builder)
-{
-  GtkWidget *add_button;
-  GtkWidget *dialog;
-
-  add_button = WID ("ok-button");
-  dialog = WID ("input_source_chooser");
-  if (gtk_widget_is_sensitive (add_button))
-    gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-}
-
-static void
-entry_activated (GtkBuilder *builder,
-                 gpointer    data)
-{
-  row_activated (NULL, NULL, NULL, builder);
-}
-
-static gboolean
-filter_func (GtkTreeModel *model,
-             GtkTreeIter  *iter,
-             gpointer      data)
-{
-  gchar *name = NULL;
-  gchar **pattern;
-  gboolean rv = TRUE;
-
-  if (search_pattern_list == NULL || search_pattern_list[0] == NULL)
-    return TRUE;
-
-  gtk_tree_model_get (model, iter,
-                      NAME_COLUMN, &name,
-                      -1);
-
-  pattern = search_pattern_list;
-  do {
-    gboolean is_pattern_found = FALSE;
-    gchar *udesc = g_utf8_strup (name, -1);
-    if (udesc != NULL && g_strstr_len (udesc, -1, *pattern))
-      {
-        is_pattern_found = TRUE;
-      }
-    g_free (udesc);
-
-    if (!is_pattern_found)
-      {
-        rv = FALSE;
-        break;
-      }
-
-  } while (*++pattern != NULL);
-
-  g_free (name);
-
-  return rv;
-}
-
-static GtkWidget *
-input_chooser_new (GtkWindow    *main_window,
-                   GtkListStore *active_sources)
-{
-  GtkBuilder *builder;
-  GtkWidget *chooser;
-  GtkWidget *filtered_list;
-  GtkWidget *filter_entry;
-  GtkTreeViewColumn *visible_column;
-  GtkTreeSelection *selection;
-  GtkListStore *model;
-  GtkTreeModelFilter *filtered_model;
-  GtkTreeIter iter;
-
-  builder = gtk_builder_new ();
-  gtk_builder_add_from_resource (builder,
-                                 "/org/gnome/control-center/region/gnome-region-panel-input-chooser.ui",
-                                 NULL);
-  chooser = WID ("input_source_chooser");
-  input_chooser = chooser;
-  g_object_add_weak_pointer (G_OBJECT (chooser), (gpointer *) &input_chooser);
-  g_object_set_data_full (G_OBJECT (chooser), "builder", builder, g_object_unref);
-
-  filtered_list = WID ("filtered_input_source_list");
-  filter_entry = WID ("input_source_filter");
-
-  g_object_set_data (G_OBJECT (chooser),
-                     "filtered_input_source_list", filtered_list);
-  visible_column =
-    gtk_tree_view_column_new_with_attributes ("Input Sources",
-                                              gtk_cell_renderer_text_new (),
-                                              "text", NAME_COLUMN,
-                                              NULL);
-
-  gtk_window_set_transient_for (GTK_WINDOW (chooser), main_window);
-
-  gtk_tree_view_append_column (GTK_TREE_VIEW (filtered_list),
-                               visible_column);
-  /* We handle searching ourselves, thank you. */
-  gtk_tree_view_set_enable_search (GTK_TREE_VIEW (filtered_list), FALSE);
-  gtk_tree_view_set_search_column (GTK_TREE_VIEW (filtered_list), -1);
-
-  g_signal_connect_swapped (G_OBJECT (filter_entry), "activate",
-                            G_CALLBACK (entry_activated), builder);
-  g_signal_connect_swapped (G_OBJECT (filter_entry), "notify::text",
-                            G_CALLBACK (filter_changed), builder);
-
-  g_signal_connect (G_OBJECT (filter_entry), "icon-release",
-                    G_CALLBACK (filter_clear), NULL);
-
-  filtered_model = GTK_TREE_MODEL_FILTER (gtk_builder_get_object (builder, "filtered_input_source_model"));
-  model = GTK_LIST_STORE (gtk_builder_get_object (builder, "input_source_model"));
-
-  populate_model (model, active_sources);
-
-  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-                                        NAME_COLUMN, GTK_SORT_ASCENDING);
-
-  gtk_tree_model_filter_set_visible_func (filtered_model,
-                                          filter_func,
-                                          NULL, NULL);
-
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (filtered_list));
-
-  g_signal_connect (G_OBJECT (selection), "changed",
-                    G_CALLBACK (selection_changed), builder);
-
-  if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (filtered_model), &iter))
-    gtk_tree_selection_select_iter (selection, &iter);
-
-  g_signal_connect (G_OBJECT (filtered_list), "row-activated",
-                    G_CALLBACK (row_activated), builder);
-
-  gtk_widget_grab_focus (filter_entry);
-
-  gtk_widget_show (chooser);
-
-  return chooser;
-}
-
-static gboolean
-input_chooser_get_selected (GtkWidget     *dialog,
-                            GtkTreeModel **model,
-                            GtkTreeIter   *iter)
-{
-  GtkWidget *tv;
-  GtkTreeSelection *selection;
-
-  tv = g_object_get_data (G_OBJECT (dialog), "filtered_input_source_list");
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
-
-  return gtk_tree_selection_get_selected (selection, model, iter);
-}
diff --git a/panels/region/gnome-region-panel-input.h b/panels/region/gnome-region-panel-input.h
deleted file mode 100644
index 47a1f52..0000000
--- a/panels/region/gnome-region-panel-input.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* gnome-region-panel-input.h
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * Written by Matthias Clasen
- *
- * 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, 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 __GNOME_KEYBOARD_PROPERTY_INPUT_H
-#define __GNOME_KEYBOARD_PROPERTY_INPUT_H
-
-#include <gtk/gtk.h>
-
-#include "cc-region-panel.h"
-
-G_BEGIN_DECLS
-
-void setup_input_tabs (GtkBuilder    *builder,
-                       CcRegionPanel *self);
-
-G_END_DECLS
-
-#endif  /* __GNOME_KEYBOARD_PROPERTY_INPUT_H */
diff --git a/panels/region/gnome-region-panel-lang.c b/panels/region/gnome-region-panel-lang.c
deleted file mode 100644
index c9499d1..0000000
--- a/panels/region/gnome-region-panel-lang.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright (C) 2010 Bastien Nocera
- *
- * Written by: Bastien Nocera <hadess@hadess.net>
- *
- * 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, 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <string.h>
-#include <glib/gi18n.h>
-#include <locale.h>
-
-#include "gnome-region-panel-lang.h"
-#include "gnome-region-panel-formats.h"
-#include "gnome-region-panel-system.h"
-#include "cc-common-language.h"
-#include "cc-language-chooser.h"
-
-static GDBusProxy *proxy = NULL;
-static GDBusProxy *sm_proxy = NULL;
-static char *old_locale = NULL;
-
-static void
-logout_requested (GtkButton *button,
-		  gpointer   user_data)
-{
-	GError   *error = NULL;
-	GVariant *res;
-
-	g_return_if_fail (sm_proxy != NULL);
-
-	res = g_dbus_proxy_call_sync (sm_proxy,
-				      "Logout",
-				      g_variant_new ("(u)", 0),
-				      G_DBUS_CALL_FLAGS_NONE,
-				      -1,
-				      NULL,
-				      &error);
-	if (res == NULL) {
-		g_warning ("Logout failed: %s", error->message);
-		g_error_free (error);
-	} else
-		g_variant_unref (res);
-}
-
-static void
-set_old_locale (void)
-{
-	GError *error = NULL;
-	GVariant *variant;
-
-	variant = g_dbus_proxy_call_sync (sm_proxy,
-					  "GetLocale",
-					  g_variant_new ("(i)", LC_MESSAGES),
-					  G_DBUS_CALL_FLAGS_NONE,
-					  -1,
-					  NULL,
-					  &error);
-	if (variant == NULL) {
-		g_warning ("Could not get current locale: %s", error->message);
-		g_error_free (error);
-		return;
-	}
-
-	g_variant_get (variant, "(s)", &old_locale);
-
-	g_variant_unref (variant);
-}
-
-static gboolean
-is_old_locale (const char *new_locale)
-{
-	gboolean ret = FALSE;
-
-	g_debug ("Comparing locale '%s' (old) and '%s' (new)",
-		 old_locale, new_locale);
-	if (g_strcmp0 (old_locale, new_locale) == 0)
-		ret = TRUE;
-
-	return ret;
-}
-
-static void
-update_logout_button (GtkBuilder *builder,
-		      const char *locale)
-{
-	GtkWidget *button, *notebook;
-	char *old_lang;
-
-	/* Offer log out in the new language, unless it is
-	 * the original session language */
-	button = (GtkWidget *)gtk_builder_get_object (builder, "logout_button");
-	notebook = (GtkWidget *)gtk_builder_get_object (builder, "logout_notebook");
-
-	if (is_old_locale (locale) == FALSE) {
-		old_lang = g_strdup (setlocale (LC_MESSAGES, NULL));
-		setlocale (LC_MESSAGES, locale);
-		gtk_button_set_label (GTK_BUTTON (button), _("Log out for changes to take effect"));
-		setlocale (LC_MESSAGES, old_lang);
-		g_free (old_lang);
-
-		gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 1);
-	} else {
-		gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 0);
-	}
-}
-
-static void
-selection_changed (GtkTreeSelection *selection,
-                   GtkBuilder       *builder)
-{
-	GtkTreeModel *model;
-	GtkTreeIter iter;
-	char *locale;
-	GDBusProxy *user;
-	GVariant *variant;
-	GError *error = NULL;
-	char *object_path;
-
-	if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE) {
-		g_warning ("No selected languages, this shouldn't happen");
-		return;
-	}
-
-	user = NULL;
-	variant = NULL;
-
-	gtk_tree_model_get (model, &iter,
-			    LOCALE_COL, &locale,
-			    -1);
-
-	if (proxy == NULL) {
-		g_warning ("Would change the language to '%s', but no D-Bus connection available", locale);
-		goto bail;
-	}
-
-	variant = g_dbus_proxy_call_sync (proxy,
-					  "FindUserByName",
-					  g_variant_new ("(s)", g_get_user_name ()),
-					  G_DBUS_CALL_FLAGS_NONE,
-					  -1,
-					  NULL,
-					  &error);
-	if (variant == NULL) {
-		g_warning ("Could not contact accounts service to look up '%s': %s",
-			   g_get_user_name (), error->message);
-		g_error_free (error);
-		goto bail;
-	}
-
-	g_variant_get (variant, "(o)", &object_path);
-	user = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
-					      G_DBUS_PROXY_FLAGS_NONE,
-					      NULL,
-					      "org.freedesktop.Accounts",
-					      object_path,
-					      "org.freedesktop.Accounts.User",
-					      NULL,
-					      &error);
-	g_free (object_path);
-
-	if (user == NULL) {
-		g_warning ("Could not create proxy for user '%s': %s",
-			   g_variant_get_string (variant, NULL), error->message);
-		g_error_free (error);
-		goto bail;
-	}
-	g_variant_unref (variant);
-
-	variant = g_dbus_proxy_call_sync (user,
-					  "SetLanguage",
-					  g_variant_new ("(s)", locale),
-					  G_DBUS_CALL_FLAGS_NONE,
-					  -1,
-					  NULL,
-					  &error);
-	if (variant == NULL) {
-		g_warning ("Failed to set the language '%s': %s", locale, error->message);
-		g_error_free (error);
-		goto bail;
-	}
-
-        /* Update the other tabs */
-        formats_update_language (builder, locale);
-        system_update_language (builder, locale);
-
-        update_logout_button (builder, locale);
-
-bail:
-	if (variant != NULL)
-		g_variant_unref (variant);
-	if (user != NULL)
-		g_object_unref (user);
-	g_free (locale);
-}
-
-static void
-language_response (GtkDialog *dialog,
-                   gint       response_id,
-                   GtkWidget *treeview)
-{
-        gchar *lang;
-	GtkTreeModel *model;
-	GtkTreeSelection *selection;
-	GtkTreeIter iter;
-
-        gtk_widget_hide (GTK_WIDGET (dialog));
-
-        if (response_id != GTK_RESPONSE_OK) {
-		return;
-	}
-
-        lang = cc_language_chooser_get_language (GTK_WIDGET (dialog));
-
-	if (lang == NULL) {
-		return;
-	}
-
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
-	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
-
-	if (cc_common_language_get_iter_for_language (model, lang, &iter)) {
-		gtk_tree_selection_select_iter (selection, &iter);
-        }
-
-	gtk_widget_grab_focus (treeview);
-
-        g_free (lang);
-}
-
-static void
-add_language (GtkWidget *button, GtkWidget *treeview)
-{
-  	GtkWidget *toplevel;
-	GtkWidget *chooser;
-
-	toplevel = gtk_widget_get_toplevel (button);
-	chooser = g_object_get_data (G_OBJECT (button), "chooser");
-	if (chooser == NULL) {
-		chooser = cc_language_chooser_new (toplevel, FALSE);
-
-       		g_signal_connect (chooser, "response",
-                	          G_CALLBACK (language_response), treeview);
-	        g_signal_connect (chooser, "delete-event",
-        	                  G_CALLBACK (gtk_widget_hide_on_delete), NULL);
-
-		g_object_set_data_full (G_OBJECT (button), "chooser",
-					chooser, (GDestroyNotify)gtk_widget_destroy);
-	}
-	else {
-		cc_language_chooser_clear_filter (chooser);
-	}
-
-        gdk_window_set_cursor (gtk_widget_get_window (toplevel), NULL);
-        gtk_window_present (GTK_WINDOW (chooser));
-}
-
-void
-setup_language (GtkBuilder *builder)
-{
-	GtkWidget *treeview;
-	GHashTable *user_langs, *popular_langs;
-	GError *error = NULL;
-	GtkWidget *widget;
-	GtkStyleContext *context;
-	GtkTreeSelection *selection;
-	char *locale;
-
-        /* Setup junction between toolbar and treeview */
-        widget = (GtkWidget *)gtk_builder_get_object (builder, "language-swindow");
-        context = gtk_widget_get_style_context (widget);
-        gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
-        widget = (GtkWidget *)gtk_builder_get_object (builder, "language-toolbar");
-        context = gtk_widget_get_style_context (widget);
-        gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
-
-	treeview = GTK_WIDGET (gtk_builder_get_object (builder, "display_language_treeview"));
-
-	/* Connect buttons */
-	widget = (GtkWidget *)gtk_builder_get_object (builder, "language_add");
-	g_signal_connect (widget, "clicked",
-			  G_CALLBACK (add_language), treeview);
-
-	widget = (GtkWidget *)gtk_builder_get_object (builder, "logout_button");
-	g_signal_connect (widget, "clicked",
-			  G_CALLBACK (logout_requested), NULL);
-
-	/* Setup accounts service */
-	proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
-					       G_DBUS_PROXY_FLAGS_NONE,
-					       NULL,
-					       "org.freedesktop.Accounts",
-					       "/org/freedesktop/Accounts",
-					       "org.freedesktop.Accounts",
-					       NULL,
-					       &error);
-
-	if (proxy == NULL) {
-		g_warning ("Failed to contact accounts service: %s", error->message);
-		g_clear_error (&error);
-	} else {
-		g_object_weak_ref (G_OBJECT (treeview), (GWeakNotify) g_object_unref, proxy);
-	}
-
-	/* And the session proxy */
-	sm_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
-						  G_DBUS_PROXY_FLAGS_NONE,
-						  NULL,
-						  "org.gnome.SessionManager",
-						  "/org/gnome/SessionManager",
-						  "org.gnome.SessionManager",
-						  NULL,
-						  &error);
-	if (sm_proxy == NULL) {
-		g_warning ("Failed to contact accounts service: %s", error->message);
-		g_error_free (error);
-	} else {
-		g_object_weak_ref (G_OBJECT (treeview), (GWeakNotify) g_object_unref, sm_proxy);
-		set_old_locale ();
-		g_object_weak_ref (G_OBJECT (treeview), (GWeakNotify) g_free, old_locale);
-	}
-
-	/* Add user languages */
-	user_langs = cc_common_language_get_user_languages ();
-	popular_langs = cc_common_language_get_initial_languages ();
-	cc_common_language_setup_list (treeview, user_langs, popular_langs);
-
-	g_object_set_data_full (G_OBJECT (treeview), "user-langs",
-				user_langs, (GDestroyNotify) g_hash_table_destroy);
-	g_object_set_data_full (G_OBJECT (treeview), "popular-langs",
-				popular_langs, (GDestroyNotify) g_hash_table_destroy);
-
-        /* And select the current language */
-        cc_common_language_select_current_language (GTK_TREE_VIEW (treeview));
-
-        /* Show the logout button if necessary */
-        locale = cc_common_language_get_current_language ();
-        update_logout_button (builder, locale);
-
-        /* And now listen for changes */
-        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
-        g_signal_connect (G_OBJECT (selection), "changed",
-                          G_CALLBACK (selection_changed), builder);
-
-	gtk_widget_grab_focus (treeview);
-}
diff --git a/panels/region/gnome-region-panel-lang.h b/panels/region/gnome-region-panel-lang.h
deleted file mode 100644
index 3522ac0..0000000
--- a/panels/region/gnome-region-panel-lang.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2010 Bastien Nocera
- *
- * Written by: Bastien Nocera <hadess@hadess.net>
- *
- * 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, 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 __GNOME_KEYBOARD_PROPERTY_LANG_H
-#define __GNOME_KEYBOARD_PROPERTY_LANG_H
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-void setup_language (GtkBuilder *builder);
-
-G_END_DECLS
-#endif /* __GNOME_KEYBOARD_PROPERTY_LANG_H */
diff --git a/panels/region/gnome-region-panel-system.c b/panels/region/gnome-region-panel-system.c
deleted file mode 100644
index d82aba0..0000000
--- a/panels/region/gnome-region-panel-system.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/*
- * Copyright (C) 2011 Rodrigo Moya
- *
- * Written by: Rodrigo Moya <rodrigo@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, 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <string.h>
-
-#include <polkit/polkit.h>
-
-#include <glib/gi18n.h>
-
-#define GNOME_DESKTOP_USE_UNSTABLE_API
-#include <libgnome-desktop/gnome-languages.h>
-#include <libgnome-desktop/gnome-xkb-info.h>
-
-#include "cc-common-language.h"
-#include "gnome-region-panel-system.h"
-
-#define WID(s) GTK_WIDGET(gtk_builder_get_object (dialog, s))
-
-static GSettings *locale_settings, *input_sources_settings;
-static GDBusProxy *localed_proxy;
-static GPermission *localed_permission;
-
-static void
-update_copy_button (GtkBuilder *dialog)
-{
-        GtkWidget *label;
-        GtkWidget *button;
-        const gchar *user_lang, *system_lang;
-        const gchar *user_region, *system_region;
-        const gchar *user_input_source, *system_input_source;
-        const gchar *user_input_variants, *system_input_variants;
-        gboolean layouts_differ;
-
-        label = WID ("user_display_language");
-        user_lang = g_object_get_data (G_OBJECT (label), "language");
-
-        label = WID ("system_display_language");
-        system_lang = g_object_get_data (G_OBJECT (label), "language");
-
-        label = WID ("user_format");
-        user_region = g_object_get_data (G_OBJECT (label), "region");
-
-        label = WID ("system_format");
-        system_region = g_object_get_data (G_OBJECT (label), "region");
-
-        label = WID ("user_input_source");
-        user_input_source = g_object_get_data (G_OBJECT (label), "input_source");
-        user_input_variants = g_object_get_data (G_OBJECT (label), "input_variants");
-
-        label = WID ("system_input_source");
-        system_input_source = g_object_get_data (G_OBJECT (label), "input_source");
-        system_input_variants = g_object_get_data (G_OBJECT (label), "input_variants");
-
-        button = WID ("copy_settings_button");
-
-        if (user_input_source && user_input_source[0]) {
-                layouts_differ = (g_strcmp0 (user_input_source, system_input_source) != 0);
-                if (layouts_differ == FALSE)
-                        layouts_differ = (g_strcmp0 (user_input_variants, system_input_variants) != 0);
-        } else {
-                /* Nothing to copy */
-                layouts_differ = FALSE;
-        }
-
-        if (g_strcmp0 (user_lang, system_lang) == 0 &&
-            g_strcmp0 (user_region, system_region) == 0 &&
-            !layouts_differ)
-                gtk_widget_set_sensitive (button, FALSE);
-        else
-                gtk_widget_set_sensitive (button, TRUE);
-}
-
-static void
-locale_settings_changed (GSettings *settings,
-                         const gchar *key,
-                         GtkBuilder *dialog)
-{
-        GtkWidget *label;
-        gchar *region, *display_region;
-
-        region = g_settings_get_string (locale_settings, "region");
-        if (!region || !region[0]) {
-                label = WID ("user_display_language");
-                region = g_strdup ((gchar*)g_object_get_data (G_OBJECT (label), "language"));
-        }
-
-        display_region = gnome_get_region_from_name (region, NULL);
-        label = WID ("user_format");
-        gtk_label_set_text (GTK_LABEL (label), display_region);
-        g_object_set_data_full (G_OBJECT (label), "region", g_strdup (region), g_free);
-        g_free (region);
-        g_free (display_region);
-
-        update_copy_button (dialog);
-}
-
-void
-system_update_language (GtkBuilder *dialog, const gchar *language)
-{
-        gchar *display_language;
-        GtkWidget *label;
-
-        display_language = gnome_get_language_from_name (language, NULL);
-        label = WID ("user_display_language");
-        gtk_label_set_text (GTK_LABEL (label), display_language);
-        g_object_set_data_full (G_OBJECT (label), "language", g_strdup (language), g_free);
-        g_free (display_language);
-
-        /* need to update the region display in case the setting is '' */
-        locale_settings_changed (locale_settings, "region", dialog);
-
-        update_copy_button (dialog);
-}
-
-static void
-input_sources_changed (GSettings *settings,
-                       const gchar *key,
-                       GtkBuilder *dialog)
-{
-        GString *disp, *list, *variants;
-        GtkWidget *label;
-        GnomeXkbInfo *xkb_info;
-        GVariantIter iter;
-        GVariant *sources;
-        const gchar *type;
-        const gchar *id;
-
-        sources = g_settings_get_value (input_sources_settings, "sources");
-        xkb_info = gnome_xkb_info_new ();
-
-        label = WID ("user_input_source");
-        disp = g_string_new ("");
-        list = g_string_new ("");
-        variants = g_string_new ("");
-
-        g_variant_iter_init (&iter, sources);
-        while (g_variant_iter_next (&iter, "(&s&s)", &type, &id)) {
-                /* We can't copy non-XKB layouts to the system yet */
-                if (g_str_equal (type, "xkb")) {
-                        char **split;
-                        gchar *layout, *variant;
-                        const char *name;
-
-                        gnome_xkb_info_get_layout_info (xkb_info, id, &name, NULL, NULL, NULL);
-                        if (disp->str[0] != '\0')
-                                g_string_append (disp, ", ");
-                        g_string_append (disp, name);
-
-                        split = g_strsplit (id, "+", 2);
-
-                        if (split == NULL || split[0] == NULL)
-                                continue;
-
-                        layout = split[0];
-                        variant = split[1];
-
-                        if (list->str[0] != '\0') {
-                                g_string_append (list, ",");
-                                g_string_append (variants, ",");
-                        }
-                        g_string_append (list, layout);
-                        g_string_append (variants, variant ? variant : "");
-
-                        g_strfreev (split);
-                }
-        }
-        g_variant_unref (sources);
-        g_object_unref (xkb_info);
-
-        g_object_set_data_full (G_OBJECT (label), "input_source", g_string_free (list, FALSE), g_free);
-        g_object_set_data_full (G_OBJECT (label), "input_variants", g_string_free (variants, FALSE), g_free);
-
-        gtk_label_set_text (GTK_LABEL (label), disp->str);
-        g_string_free (disp, TRUE);
-
-        update_copy_button (dialog);
-}
-
-static void
-update_property (GDBusProxy *proxy,
-                 const char *property)
-{
-        GError *error = NULL;
-        GVariant *variant;
-
-        /* Work around systemd-localed not sending us back
-         * the property value when changing values */
-        variant = g_dbus_proxy_call_sync (proxy,
-                                          "org.freedesktop.DBus.Properties.Get",
-                                          g_variant_new ("(ss)", "org.freedesktop.locale1", property),
-                                          G_DBUS_CALL_FLAGS_NONE,
-                                          -1,
-                                          NULL,
-                                          &error);
-        if (variant == NULL) {
-                g_warning ("Failed to get property '%s': %s", property, error->message);
-                g_error_free (error);
-        } else {
-                GVariant *v;
-
-                g_variant_get (variant, "(v)", &v);
-                g_dbus_proxy_set_cached_property (proxy, property, v);
-                g_variant_unref (variant);
-        }
-}
-
-static void
-on_localed_properties_changed (GDBusProxy   *proxy,
-                               GVariant     *changed_properties,
-                               const gchar **invalidated_properties,
-                               GtkBuilder   *dialog)
-{
-        GVariant *v, *w;
-        GtkWidget *label;
-        GnomeXkbInfo *xkb_info;
-        char **layouts;
-        char **variants;
-        GString *disp;
-        guint i, n;
-
-        if (invalidated_properties != NULL) {
-                guint i;
-                for (i = 0; invalidated_properties[i] != NULL; i++) {
-                        if (g_str_equal (invalidated_properties[i], "Locale"))
-                                update_property (proxy, "Locale");
-                        else if (g_str_equal (invalidated_properties[i], "X11Layout"))
-                                update_property (proxy, "X11Layout");
-                        else if (g_str_equal (invalidated_properties[i], "X11Variant"))
-                                update_property (proxy, "X11Variant");
-                }
-        }
-
-        v = g_dbus_proxy_get_cached_property (proxy, "Locale");
-        if (v) {
-                const gchar **strv;
-                gsize len;
-                gint i;
-                const gchar *lang, *messages, *time;
-                gchar *name;
-                GtkWidget *label;
-
-                strv = g_variant_get_strv (v, &len);
-
-                lang = messages = time = NULL;
-                for (i = 0; strv[i]; i++) {
-                        if (g_str_has_prefix (strv[i], "LANG=")) {
-                                lang = strv[i] + strlen ("LANG=");
-                        }
-                        else if (g_str_has_prefix (strv[i], "LC_MESSAGES=")) {
-                                messages = strv[i] + strlen ("LC_MESSAGES=");
-                        }
-                        else if (g_str_has_prefix (strv[i], "LC_TIME=")) {
-                                time = strv[i] + strlen ("LC_TIME=");
-                        }
-                }
-                if (!messages) {
-                        messages = lang;
-                }
-                if (!time) {
-                        time = lang;
-                }
-
-                if (messages) {
-                        name = gnome_get_language_from_name (messages, NULL);
-                        label = WID ("system_display_language");
-                        gtk_label_set_text (GTK_LABEL (label), name);
-                        g_free (name);
-                        g_object_set_data_full (G_OBJECT (label), "language", g_strdup (lang), g_free);
-                }
-
-                if (time) {
-                        name = gnome_get_region_from_name (time, NULL);
-                        label = WID ("system_format");
-                        gtk_label_set_text (GTK_LABEL (label), name);
-                        g_free (name);
-                        g_object_set_data_full (G_OBJECT (label), "region", g_strdup (time), g_free);
-                }
-                g_variant_unref (v);
-        }
-
-        label = WID ("system_input_source");
-        v = g_dbus_proxy_get_cached_property (proxy, "X11Layout");
-        if (v) {
-                layouts = g_strsplit (g_variant_get_string (v, NULL), ",", -1);
-                g_object_set_data_full (G_OBJECT (label), "input_source",
-                                        g_variant_dup_string (v, NULL), g_free);
-                g_variant_unref (v);
-        } else {
-                g_object_set_data_full (G_OBJECT (label), "input_source", NULL, g_free);
-                update_copy_button (dialog);
-                return;
-        }
-
-        variants = NULL;
-        g_object_set_data_full (G_OBJECT (label), "input_variants", NULL, g_free);
-
-        w = g_dbus_proxy_get_cached_property (proxy, "X11Variant");
-        if (w) {
-                const char *variants_str;
-
-                variants_str = g_variant_get_string (w, NULL);
-                g_debug ("Got variants '%s'", variants_str);
-                if (variants_str && *variants_str != '\0') {
-                        variants = g_strsplit (variants_str, ",", -1);
-                        g_object_set_data_full (G_OBJECT (label), "input_variants",
-                                                g_strdup (variants_str), g_free);
-                }
-                g_variant_unref (w);
-        }
-
-        if (variants && variants[0])
-                n = MIN (g_strv_length (layouts), g_strv_length (variants));
-        else
-                n = g_strv_length (layouts);
-
-        xkb_info = gnome_xkb_info_new ();
-        disp = g_string_new ("");
-        for (i = 0; i < n && layouts[i][0]; i++) {
-                const char *name;
-                char *id;
-
-                if (variants && variants[i] && variants[i][0])
-                        id = g_strdup_printf ("%s+%s", layouts[i], variants[i]);
-                else
-                        id = g_strdup (layouts[i]);
-
-                gnome_xkb_info_get_layout_info (xkb_info, id, &name, NULL, NULL, NULL);
-                if (disp->str[0] != '\0')
-                        disp = g_string_append (disp, ", ");
-                disp = g_string_append (disp, name ? name : id);
-
-                g_free (id);
-        }
-        gtk_label_set_text (GTK_LABEL (label), disp->str);
-        g_string_free (disp, TRUE);
-
-        g_strfreev (variants);
-        g_strfreev (layouts);
-        g_object_unref (xkb_info);
-
-        update_copy_button (dialog);
-}
-
-static void
-localed_proxy_ready (GObject      *source,
-                     GAsyncResult *res,
-                     GtkBuilder   *dialog)
-{
-        GError *error = NULL;
-
-        localed_proxy = g_dbus_proxy_new_finish (res, &error);
-
-        if (!localed_proxy) {
-                g_warning ("Failed to contact localed: %s\n", error->message);
-                g_error_free (error);
-                return;
-        }
-
-        g_object_weak_ref (G_OBJECT (dialog), (GWeakNotify) g_object_unref, localed_proxy);
-
-        g_signal_connect (localed_proxy, "g-properties-changed",
-                          G_CALLBACK (on_localed_properties_changed), dialog);
-
-        on_localed_properties_changed (localed_proxy, NULL, NULL, dialog);
-}
-
-static void
-copy_settings (GtkButton *button, GtkBuilder *dialog)
-{
-        const gchar *language;
-        const gchar *region;
-        const gchar *layout;
-        const gchar *variants;
-        GtkWidget *label;
-        GVariantBuilder *b;
-        gchar *s;
-
-        label = WID ("user_display_language");
-        language = g_object_get_data (G_OBJECT (label), "language");
-        label = WID ("user_format");
-        region = g_object_get_data (G_OBJECT (label), "region");
-
-        b = g_variant_builder_new (G_VARIANT_TYPE ("as"));
-        s = g_strconcat ("LANG=", language, NULL);
-        g_variant_builder_add (b, "s", s);
-        g_free (s);
-        if (g_strcmp0 (language, region) != 0) {
-                s = g_strconcat ("LC_TIME=", region, NULL);
-                g_variant_builder_add (b, "s", s);
-                g_free (s);
-                s = g_strconcat ("LC_NUMERIC=", region, NULL);
-                g_variant_builder_add (b, "s", s);
-                g_free (s);
-                s = g_strconcat ("LC_MONETARY=", region, NULL);
-                g_variant_builder_add (b, "s", s);
-                g_free (s);
-                s = g_strconcat ("LC_MEASUREMENT=", region, NULL);
-                g_variant_builder_add (b, "s", s);
-                g_free (s);
-        }
-
-        g_dbus_proxy_call (localed_proxy,
-                           "SetLocale",
-                           g_variant_new ("(asb)", b, TRUE),
-                           G_DBUS_CALL_FLAGS_NONE,
-                           -1, NULL, NULL, NULL);
-        g_variant_builder_unref (b);
-
-        label = WID ("user_input_source");
-        layout = g_object_get_data (G_OBJECT (label), "input_source");
-        variants = g_object_get_data (G_OBJECT (label), "input_variants");
-
-        if (layout == NULL || layout[0] == '\0') {
-                g_debug ("Not calling SetX11Keyboard, as there are no XKB input sources in the user's settings");
-                return;
-        }
-
-        g_dbus_proxy_call (localed_proxy,
-                           "SetX11Keyboard",
-                           g_variant_new ("(ssssbb)", layout, "", variants ? variants : "", "", TRUE, TRUE),
-                           G_DBUS_CALL_FLAGS_NONE,
-                           -1, NULL, NULL, NULL);
-}
-
-static void
-on_permission_changed (GPermission *permission,
-                       GParamSpec  *pspec,
-                       GtkBuilder  *dialog)
-{
-        GtkWidget *button;
-        GtkWidget *label;
-        gboolean can_acquire;
-        gboolean allowed;
-
-        if (permission) {
-                can_acquire = g_permission_get_can_acquire (permission);
-                allowed = g_permission_get_allowed (permission);
-        }
-        else {
-                can_acquire = FALSE;
-                allowed = FALSE;
-        }
-
-        button = WID ("copy_settings_button");
-        label = WID ("system-title");
-
-        if (!allowed && !can_acquire) {
-                gtk_label_set_text (GTK_LABEL (label),
-                                    _("The login screen, system accounts and new user accounts use the system-wide Region and Language settings."));
-                gtk_widget_hide (button);
-        }
-        else {
-                gtk_label_set_text (GTK_LABEL (label),
-                                    _("The login screen, system accounts and new user accounts use the system-wide Region and Language settings. You may change the system settings to match yours."));
-                gtk_widget_show (button);
-                if (allowed) {
-                        gtk_button_set_label (GTK_BUTTON (button), _("Copy Settings"));
-                }
-                else {
-                        gtk_button_set_label (GTK_BUTTON (button), _("Copy Settings…"));
-                }
-        }
-}
-
-void
-setup_system (GtkBuilder *dialog)
-{
-        gchar *language;
-        GDBusConnection *bus;
-        GtkWidget *button;
-
-        localed_permission = polkit_permission_new_sync ("org.freedesktop.locale1.set-locale", NULL, NULL, NULL);
-        if (localed_permission == NULL) {
-                GtkWidget *tab_widget, *notebook;
-                int num;
-
-                tab_widget = WID ("table3");
-                notebook = WID ("region_notebook");
-                num = gtk_notebook_page_num (GTK_NOTEBOOK (notebook), tab_widget);
-                gtk_notebook_remove_page (GTK_NOTEBOOK (notebook), num);
-                return;
-        }
-
-        g_object_weak_ref (G_OBJECT (dialog), (GWeakNotify) g_object_unref, localed_permission);
-        g_signal_connect (localed_permission, "notify",
-                          G_CALLBACK (on_permission_changed), dialog);
-        on_permission_changed (localed_permission, NULL, dialog);
-
-
-        button = WID ("copy_settings_button");
-        g_signal_connect (button, "clicked",
-                          G_CALLBACK (copy_settings), dialog);
-
-
-        locale_settings = g_settings_new ("org.gnome.system.locale");
-        g_signal_connect (locale_settings, "changed::region",
-                          G_CALLBACK (locale_settings_changed), dialog);
-        g_object_weak_ref (G_OBJECT (dialog), (GWeakNotify) g_object_unref, locale_settings);
-
-        input_sources_settings = g_settings_new ("org.gnome.desktop.input-sources");
-        g_signal_connect (input_sources_settings, "changed::sources",
-                          G_CALLBACK (input_sources_changed), dialog);
-        g_object_weak_ref (G_OBJECT (dialog), (GWeakNotify) g_object_unref, input_sources_settings);
-
-        /* Display user settings */
-        language = cc_common_language_get_current_language ();
-        system_update_language (dialog, language);
-        g_free (language);
-
-        locale_settings_changed (locale_settings, "region", dialog);
-
-        input_sources_changed (input_sources_settings, "sources", dialog);
-
-        bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
-        g_dbus_proxy_new (bus,
-                           G_DBUS_PROXY_FLAGS_NONE,
-                           NULL,
-                           "org.freedesktop.locale1",
-                           "/org/freedesktop/locale1",
-                           "org.freedesktop.locale1",
-                           NULL,
-                           (GAsyncReadyCallback) localed_proxy_ready,
-                           dialog);
-        g_object_unref (bus);
-}
diff --git a/panels/region/gnome-region-panel-system.h b/panels/region/gnome-region-panel-system.h
deleted file mode 100644
index f6b99c9..0000000
--- a/panels/region/gnome-region-panel-system.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2011 Rodrigo Moya
- *
- * Written by: Rodrigo Moya <rodrigo@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, 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 __GNOME_REGION_PANEL_SYSTEM_H
-#define __GNOME_REGION_PANEL_SYSTEM_H
-
-#include <gtk/gtk.h>
-
-void setup_system           (GtkBuilder *builder);
-void system_update_language (GtkBuilder  *builder,
-                             const gchar *language);
-
-#endif
diff --git a/panels/region/gnome-region-panel.ui b/panels/region/gnome-region-panel.ui
deleted file mode 100644
index cf0f170..0000000
--- a/panels/region/gnome-region-panel.ui
+++ /dev/null
@@ -1,1481 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface>
-  <!-- interface-requires gtk+ 3.0 -->
-  <object class="GtkAdjustment" id="adjustment1">
-    <property name="lower">100</property>
-    <property name="upper">2000</property>
-    <property name="value">500</property>
-    <property name="step_increment">10</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="adjustment10">
-    <property name="lower">1</property>
-    <property name="upper">100000</property>
-    <property name="value">1</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="adjustment2">
-    <property name="lower">10</property>
-    <property name="upper">110</property>
-    <property name="value">30</property>
-    <property name="step_increment">10</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="adjustment3">
-    <property name="lower">100</property>
-    <property name="upper">2500</property>
-    <property name="value">1000</property>
-    <property name="step_increment">200</property>
-    <property name="page_increment">200</property>
-  </object>
-  <object class="GtkAdjustment" id="adjustment4">
-    <property name="upper">500</property>
-    <property name="value">0.5</property>
-    <property name="step_increment">10</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="adjustment5">
-    <property name="upper">900</property>
-    <property name="value">0.5</property>
-    <property name="step_increment">10</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="adjustment6">
-    <property name="upper">3000</property>
-    <property name="value">1800</property>
-    <property name="step_increment">10</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="adjustment7">
-    <property name="lower">10</property>
-    <property name="upper">1000</property>
-    <property name="value">300</property>
-    <property name="step_increment">10</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="adjustment8">
-    <property name="lower">10</property>
-    <property name="upper">2000</property>
-    <property name="value">300</property>
-    <property name="step_increment">10</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkAdjustment" id="adjustment9">
-    <property name="lower">1</property>
-    <property name="upper">100000</property>
-    <property name="value">1</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkListStore" id="display_language_liststore"/>
-  <object class="GtkDialog" id="region_dialog">
-    <property name="can_focus">False</property>
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">Region and Language</property>
-    <property name="default_width">600</property>
-    <property name="default_height">430</property>
-    <property name="type_hint">dialog</property>
-    <child internal-child="vbox">
-      <object class="GtkBox" id="dialog-vbox1">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox" id="dialog-action_area1">
-            <property name="can_focus">False</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkVBox" id="region_vbox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="border_width">5</property>
-            <property name="spacing">12</property>
-            <child>
-              <object class="GtkNotebook" id="region_notebook">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="border_width">16</property>
-                <child>
-                  <object class="GtkVBox" id="vbox2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="border_width">12</property>
-                    <property name="spacing">12</property>
-                    <child>
-                      <object class="GtkBox" id="box1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <child>
-                          <object class="GtkLabel" id="label4">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">Select a display language</property>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkNotebook" id="logout_notebook">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="show_tabs">False</property>
-                            <child>
-                              <object class="GtkLabel" id="empty_label">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                              </object>
-                            </child>
-                            <child type="tab">
-                              <object class="GtkLabel" id="label2">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label" translatable="yes">page 1</property>
-                              </object>
-                              <packing>
-                                <property name="tab_fill">False</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkButton" id="logout_button">
-                                <property name="label" translatable="yes">Log out for changes to take effect</property>
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">True</property>
-                              </object>
-                              <packing>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                            <child type="tab">
-                              <object class="GtkLabel" id="label22">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label" translatable="yes">page 2</property>
-                              </object>
-                              <packing>
-                                <property name="position">1</property>
-                                <property name="tab_fill">False</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <placeholder/>
-                            </child>
-                            <child type="tab">
-                              <placeholder/>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkBox" id="hbox1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkScrolledWindow" id="language-swindow">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="hscrollbar_policy">never</property>
-                            <property name="shadow_type">in</property>
-                            <child>
-                              <object class="GtkTreeView" id="display_language_treeview">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="headers_visible">False</property>
-                                <child internal-child="selection">
-                                  <object class="GtkTreeSelection" id="language-treeview-selection"/>
-                                </child>
-                              </object>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkVBox" id="vbox3">
-                            <property name="can_focus">False</property>
-                            <child>
-                              <object class="GtkLabel" id="label23">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label" translatable="yes">Add Language</property>
-                                <property name="use_underline">True</property>
-                              </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkToolbar" id="language-toolbar">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="toolbar_style">icons</property>
-                            <property name="show_arrow">False</property>
-                            <property name="icon_size">1</property>
-                            <style>
-                              <class name="inline-toolbar"/>
-                            </style>
-                            <child>
-                              <object class="GtkToolButton" id="language_add">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label" translatable="yes">Add Language</property>
-                                <property name="use_underline">True</property>
-                                <property name="icon_name">list-add-symbolic</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="homogeneous">True</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                </child>
-                <child type="tab">
-                  <object class="GtkLabel" id="label1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">Language</property>
-                  </object>
-                  <packing>
-                    <property name="tab_fill">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkGrid" id="table1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="margin_left">12</property>
-                    <property name="margin_right">12</property>
-                    <property name="margin_top">12</property>
-                    <property name="margin_bottom">12</property>
-                    <property name="row_spacing">6</property>
-                    <property name="column_spacing">12</property>
-                    <child>
-                      <object class="GtkLabel" id="label5">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="halign">start</property>
-                        <property name="label" translatable="yes">Select a region (change will be applied the next time you log in)</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">0</property>
-                        <property name="width">2</property>
-                        <property name="height">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkBox" id="region-box">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkScrolledWindow" id="region-swindow">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="vexpand">True</property>
-                            <property name="hscrollbar_policy">never</property>
-                            <property name="shadow_type">in</property>
-                            <child>
-                              <object class="GtkTreeView" id="region_selector">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="headers_visible">False</property>
-                                <child internal-child="selection">
-                                  <object class="GtkTreeSelection" id="region-treeview-selection"/>
-                                </child>
-                              </object>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkToolbar" id="region-toolbar">
-                            <property name="toolbar_style">icons</property>
-                            <property name="show_arrow">False</property>
-                            <property name="icon_size">1</property>
-                            <property name="visible">True</property>
-                            <style>
-                              <class name="inline-toolbar"/>
-                            </style>
-                            <child>
-                              <object class="GtkToolButton" id="region_add">
-                                <property name="use_action_appearance">False</property>
-                                <property name="label" translatable="yes">Add Region</property>
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="use_underline">True</property>
-                                <property name="icon_name">list-add-symbolic</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="homogeneous">True</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkToolButton" id="region_remove">
-                                <property name="use_action_appearance">False</property>
-                                <property name="visible">True</property>
-                                <property name="label" translatable="yes">Remove Region</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">False</property>
-                                <property name="use_underline">True</property>
-                                <property name="icon_name">list-remove-symbolic</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="homogeneous">True</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">1</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkFrame" id="frame1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label_xalign">0</property>
-                        <property name="shadow_type">none</property>
-                        <child>
-                          <object class="GtkAlignment" id="alignment2">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="left_padding">12</property>
-                            <child>
-                              <object class="GtkTable" id="table2">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="n_rows">9</property>
-                                <property name="n_columns">2</property>
-                                <child>
-                                  <object class="GtkLabel" id="label7">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">Dates</property>
-                                  </object>
-                                  <packing>
-                                    <property name="x_options">GTK_FILL</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="full_date_format">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="full_day_format">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                    <property name="top_attach">1</property>
-                                    <property name="bottom_attach">2</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="short_day_format">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                    <property name="top_attach">2</property>
-                                    <property name="bottom_attach">3</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="shortest_day_format">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                    <property name="top_attach">3</property>
-                                    <property name="bottom_attach">4</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label8">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">Times</property>
-                                  </object>
-                                  <packing>
-                                    <property name="top_attach">4</property>
-                                    <property name="bottom_attach">5</property>
-                                    <property name="x_options">GTK_FILL</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="full_time_format">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                    <property name="top_attach">4</property>
-                                    <property name="bottom_attach">5</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="short_time_format">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                    <property name="top_attach">5</property>
-                                    <property name="bottom_attach">6</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label9">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">Numbers</property>
-                                  </object>
-                                  <packing>
-                                    <property name="top_attach">6</property>
-                                    <property name="bottom_attach">7</property>
-                                    <property name="x_options">GTK_FILL</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="numbers_format">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                    <property name="top_attach">6</property>
-                                    <property name="bottom_attach">7</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label10">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">Currency</property>
-                                  </object>
-                                  <packing>
-                                    <property name="top_attach">7</property>
-                                    <property name="bottom_attach">8</property>
-                                    <property name="x_options">GTK_FILL</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="currency_format">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                    <property name="top_attach">7</property>
-                                    <property name="bottom_attach">8</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label11">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">Measurement</property>
-                                  </object>
-                                  <packing>
-                                    <property name="top_attach">8</property>
-                                    <property name="bottom_attach">9</property>
-                                    <property name="x_options">GTK_FILL</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="measurement_format">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
-                                  </object>
-                                  <packing>
-                                    <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                    <property name="top_attach">8</property>
-                                    <property name="bottom_attach">9</property>
-                                    <property name="y_options">GTK_FILL</property>
-                                    <property name="x_padding">3</property>
-                                    <property name="y_padding">3</property>
-                                  </packing>
-                                </child>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
-                        <child type="label">
-                          <object class="GtkLabel" id="label6">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">Examples</property>
-                            <attributes>
-                              <attribute name="weight" value="bold"/>
-                            </attributes>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">1</property>
-                        <property name="width">1</property>
-                        <property name="height">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child type="tab">
-                  <object class="GtkLabel" id="label3">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">Formats</property>
-                  </object>
-                  <packing>
-                    <property name="position">1</property>
-                    <property name="tab_fill">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkVBox" id="vbox5">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="border_width">12</property>
-                    <property name="spacing">12</property>
-                    <child>
-                      <object class="GtkLabel" id="label24">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
-                        <property name="label" translatable="yes">Select keyboards or other input sources</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkHBox" id="hbox3">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">12</property>
-                        <child>
-                          <object class="GtkVBox" id="vbox6">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <child>
-                              <object class="GtkScrolledWindow" id="input_sources_swindow">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="shadow_type">in</property>
-                                <child>
-                                  <object class="GtkTreeView" id="active_input_sources">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="headers_visible">False</property>
-                                  </object>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">True</property>
-                                <property name="fill">True</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkToolbar" id="input-toolbar">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="toolbar_style">icons</property>
-                                <property name="show_arrow">False</property>
-                                <property name="icon_size">1</property>
-                                <style>
-                                  <class name="inline-toolbar"/>
-                                </style>
-                                <child>
-                                  <object class="GtkToolItem" id="i_s_ar_item">
-                                    <property name="visible">True</property>
-                                    <child>
-                                      <object class="GtkBox" id="i_s_ar_box">
-                                        <property name="visible">True</property>
-                                        <child>
-                                           <object class="GtkButton" id="input_source_add">
-                                             <property name="visible">True</property>
-                                             <child internal-child="accessible">
-                                               <object class="AtkObject" id="i_s_a_a11y">
-                                                 <property name="accessible-name" translatable="yes">Add Input Source</property>
-                                               </object>
-                                             </child>
-                                             <child>
-                                                <object class="GtkImage" id="i_s_a_image">
-
-                                                  <property name="visible">True</property>
-                                                  <property name="icon-name">list-add-symbolic</property>
-                                                  <property name="icon-size">1</property>
-                                                </object>
-                                             </child>
-                                           </object>
-                                        </child>
-                                        <child>
-                                           <object class="GtkButton" id="input_source_remove">
-                                             <property name="visible">True</property>
-                                             <child internal-child="accessible">
-                                               <object class="AtkObject" id="i_s_r_a11y">
-                                                 <property name="accessible-name" translatable="yes">Remove Input Source</property>
-                                               </object>
-                                             </child>
-                                             <child>
-                                                <object class="GtkImage" id="i_s_r_image">
-                                                  <property name="visible">True</property>
-                                                  <property name="icon-name">list-remove-symbolic</property>
-                                                  <property name="icon-size">1</property>
-                                                </object>
-                                             </child>
-                                           </object>
-                                        </child>
-                                      </object>
-                                    </child>
-                                  </object>
-                                </child>
-
-                                <child>
-                                  <object class="GtkSeparatorToolItem" id="sep1">
-                                    <property name="visible">True</property>
-                                    <property name="draw">False</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">True</property>
-                                  </packing>
-                                </child>
-
-                                <child>
-                                  <object class="GtkToolItem" id="i_s_ud_item">
-                                    <property name="visible">True</property>
-                                    <child>
-                                      <object class="GtkBox" id="i_s_ud_box">
-                                        <property name="visible">True</property>
-                                        <child>
-                                           <object class="GtkButton" id="input_source_move_up">
-                                             <property name="visible">True</property>
-                                             <child internal-child="accessible">
-                                               <object class="AtkObject" id="i_s_u_a11y">
-                                                 <property name="accessible-name" translatable="yes">Move Input Source Up</property>
-                                               </object>
-                                             </child>
-                                             <child>
-                                                <object class="GtkImage" id="i_s_u_image">
-
-                                                  <property name="visible">True</property>
-                                                  <property name="icon-name">go-up-symbolic</property>
-                                                  <property name="icon-size">1</property>
-                                                </object>
-                                             </child>
-                                           </object>
-                                        </child>
-                                        <child>
-                                           <object class="GtkButton" id="input_source_move_down">
-                                             <property name="visible">True</property>
-                                             <child internal-child="accessible">
-                                               <object class="AtkObject" id="i_s_d_a11y">
-                                                 <property name="accessible-name" translatable="yes">Move Input Source Down</property>
-                                               </object>
-                                             </child>
-                                             <child>
-                                                <object class="GtkImage" id="i_s_d_image">
-                                                  <property name="visible">True</property>
-                                                  <property name="icon-name">go-down-symbolic</property>
-                                                  <property name="icon-size">1</property>
-                                                </object>
-                                             </child>
-                                           </object>
-                                        </child>
-                                      </object>
-                                    </child>
-                                  </object>
-                                </child>
-
-                                <child>
-                                  <object class="GtkSeparatorToolItem" id="sep2">
-                                    <property name="visible">True</property>
-                                    <property name="draw">False</property>
-                                    <property name="hexpand">True</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">True</property>
-                                  </packing>
-                                </child>
-
-                                <child>
-                                  <object class="GtkToolItem" id="i_s_sp_item">
-                                    <property name="visible">True</property>
-                                    <child>
-                                      <object class="GtkBox" id="i_s_sp_box">
-                                        <property name="visible">True</property>
-                                        <child>
-                                           <object class="GtkButton" id="input_source_settings">
-                                             <property name="visible">True</property>
-                                             <child internal-child="accessible">
-                                               <object class="AtkObject" id="i_s_s_a11y">
-                                                 <property name="accessible-name" translatable="yes">Input Source Settings</property>
-                                               </object>
-                                             </child>
-                                             <child>
-                                                <object class="GtkImage" id="i_s_s_image">
-
-                                                  <property name="visible">True</property>
-                                                  <property name="icon_name">preferences-system-symbolic</property>
-                                                  <property name="icon_size">1</property>
-                                                  <property name="pixel_size">16</property>
-                                                </object>
-                                             </child>
-                                           </object>
-                                        </child>
-                                        <child>
-                                           <object class="GtkButton" id="input_source_show">
-                                             <property name="visible">True</property>
-                                             <child internal-child="accessible">
-                                               <object class="AtkObject" id="i_s_p_a11y">
-                                                 <property name="accessible-name" translatable="yes">Show Keyboard Layout</property>
-                                               </object>
-                                             </child>
-                                             <child>
-                                                <object class="GtkImage" id="i_s_p_image">
-
-                                                  <property name="visible">True</property>
-                                                  <property name="icon_name">input-keyboard-symbolic</property>
-                                                  <property name="icon-size">1</property>
-                                                </object>
-                                             </child>
-                                           </object>
-                                        </child>
-                                      </object>
-                                    </child>
-                                  </object>
-                                </child>
-
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">True</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkVBox" id="vbox124266413adc">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <child>
-                              <object class="GtkFrame" id="frame4">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label_xalign">0</property>
-                                <property name="shadow_type">none</property>
-                                <child>
-                                  <object class="GtkAlignment" id="alignment3">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="left_padding">12</property>
-                                    <child>
-                                      <object class="GtkGrid" id="shortcuts-grid">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">6</property>
-                                        <property name="row_spacing">6</property>
-                                        <property name="column_spacing">6</property>
-                                        <child>
-                                          <object class="GtkLabel" id="prev-source-label">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="xalign">0</property>
-                                            <property name="label" translatable="yes">Switch to previous source</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">0</property>
-                                            <property name="width">1</property>
-                                            <property name="height">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel" id="prev-source-shortcut-label">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="halign">end</property>
-                                            <property name="hexpand">True</property>
-                                            <property name="label" translatable="yes">Ctrl+Alt+Space</property>
-                                            <style><class name="dim-label"/></style>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">0</property>
-                                            <property name="width">1</property>
-                                            <property name="height">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel" id="next-source-label">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="xalign">0</property>
-                                            <property name="label" translatable="yes">Switch to next source</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">1</property>
-                                            <property name="width">1</property>
-                                            <property name="height">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel" id="next-source-shortcut-label">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">False</property>
-                                            <property name="halign">end</property>
-                                            <property name="hexpand">True</property>
-                                            <property name="label" translatable="yes">Ctrl+Alt+Shift+Space</property>
-                                            <style><class name="dim-label"/></style>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">1</property>
-                                            <property name="width">1</property>
-                                            <property name="height">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLinkButton" id="jump-to-shortcuts">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="label" translatable="yes">Shortcut Settings</property>
-                                            <property name="halign">end</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">1</property>
-                                            <property name="top_attach">2</property>
-                                            <property name="width">1</property>
-                                            <property name="height">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                    </child>
-                                  </object>
-                                </child>
-                                <child type="label">
-                                  <object class="GtkLabel" id="shortcuts-frame-label">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="label" translatable="yes">Shortcuts</property>
-                                    <property name="use_markup">True</property>
-                                    <attributes>
-                                      <attribute name="weight" value="bold"/>
-                                    </attributes>
-                                  </object>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkFrame" id="framea751fbb5f03a">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label_xalign">0</property>
-                                <property name="shadow_type">none</property>
-                                <child>
-                                  <object class="GtkAlignment" id="alignment2a898e7d1ebf">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="left_padding">12</property>
-                                    <child>
-                                      <object class="GtkGrid" id="options-grid">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="margin_top">6</property>
-                                        <property name="row_spacing">6</property>
-                                        <property name="column_spacing">6</property>
-                                        <child>
-                                          <object class="GtkRadioButton" id="per-window-radio-false">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="xalign">0</property>
-                                            <property name="label" translatable="yes">Use the same source for all windows</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">0</property>
-                                            <property name="width">1</property>
-                                            <property name="height">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkRadioButton" id="per-window-radio-true">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="xalign">0</property>
-                                            <property name="label" translatable="yes">Allow different sources for each window</property>
-                                            <property name="group">per-window-radio-false</property>
-                                          </object>
-                                          <packing>
-                                            <property name="left_attach">0</property>
-                                            <property name="top_attach">1</property>
-                                            <property name="width">1</property>
-                                            <property name="height">1</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                    </child>
-                                  </object>
-                                </child>
-                                <child type="label">
-                                  <object class="GtkLabel" id="options-frame-label">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="label" translatable="yes">Options</property>
-                                    <property name="use_markup">True</property>
-                                    <attributes>
-                                      <attribute name="weight" value="bold"/>
-                                    </attributes>
-                                  </object>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">3</property>
-                  </packing>
-                </child>
-                <child type="tab">
-                  <object class="GtkLabel" id="label13">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">Input Sources</property>
-                  </object>
-                  <packing>
-                    <property name="position">3</property>
-                    <property name="tab_fill">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkTable" id="table3">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="n_rows">3</property>
-                    <property name="n_columns">2</property>
-                    <property name="column_spacing">12</property>
-                    <property name="row_spacing">12</property>
-                    <child>
-                      <object class="GtkLabel" id="system-title">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="xalign">0</property>
-                        <property name="xpad">6</property>
-                        <property name="ypad">6</property>
-                        <property name="label" translatable="yes">The login screen, system accounts and new user accounts use the system-wide Region and Language settings. You may change the system settings to match yours.</property>
-                        <property name="wrap">True</property>
-                        <property name="width_chars">60</property>
-                      </object>
-                      <packing>
-                        <property name="right_attach">2</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options">GTK_SHRINK</property>
-                        <property name="x_padding">3</property>
-                        <property name="y_padding">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkFrame" id="frame2">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label_xalign">0</property>
-                        <property name="shadow_type">none</property>
-                        <child>
-                          <object class="GtkTable" id="table4">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="margin_left">12</property>
-                            <property name="margin_top">12</property>
-                            <property name="n_rows">3</property>
-                            <property name="n_columns">2</property>
-                            <property name="column_spacing">3</property>
-                            <property name="row_spacing">3</property>
-                            <child>
-                              <object class="GtkLabel" id="label16">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
-                                <property name="label" translatable="yes" comments="'display' means 'output' here, as in 'translated messages that are displayed to the user'">Display language:</property>
-                              </object>
-                              <packing>
-                                <property name="y_options">GTK_FILL</property>
-                                <property name="x_padding">3</property>
-                                <property name="y_padding">3</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="user_display_language">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="y_options">GTK_FILL</property>
-                                <property name="x_padding">3</property>
-                                <property name="y_padding">3</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label17">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
-                                <property name="yalign">0</property>
-                                <property name="label" translatable="yes">Input source:</property>
-                              </object>
-                              <packing>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="x_padding">3</property>
-                                <property name="y_padding">3</property>
-                                <property name="y_options">GTK_FILL</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="user_input_source">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
-                                <property name="yalign">0</property>
-                                <property name="wrap">True</property>
-                                <property name="width-chars">18</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="x_padding">3</property>
-                                <property name="y_padding">3</property>
-                                <property name="y_options">GTK_FILL</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label18">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
-                                <property name="label" translatable="yes">Format:</property>
-                              </object>
-                              <packing>
-                                <property name="top_attach">2</property>
-                                <property name="bottom_attach">3</property>
-                                <property name="y_options">GTK_FILL</property>
-                                <property name="x_padding">3</property>
-                                <property name="y_padding">3</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="user_format">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">2</property>
-                                <property name="bottom_attach">3</property>
-                                <property name="y_options">GTK_FILL</property>
-                                <property name="x_padding">3</property>
-                                <property name="y_padding">3</property>
-                              </packing>
-                            </child>
-                          </object>
-                        </child>
-                        <child type="label">
-                          <object class="GtkLabel" id="label14">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">Your settings</property>
-                            <attributes>
-                              <attribute name="weight" value="bold"/>
-                            </attributes>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="y_options">GTK_FILL</property>
-                        <property name="x_padding">3</property>
-                        <property name="y_padding">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkFrame" id="frame3">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label_xalign">0</property>
-                        <property name="shadow_type">none</property>
-                        <child>
-                          <object class="GtkTable" id="table5">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="margin_left">12</property>
-                            <property name="margin_top">12</property>
-                            <property name="n_rows">3</property>
-                            <property name="n_columns">2</property>
-                            <property name="column_spacing">3</property>
-                            <property name="row_spacing">3</property>
-                            <child>
-                              <object class="GtkLabel" id="label19">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
-                                <property name="label" translatable="yes">Display language:</property>
-                              </object>
-                              <packing>
-                                <property name="y_options">GTK_FILL</property>
-                                <property name="x_padding">3</property>
-                                <property name="y_padding">3</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="system_display_language">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="y_options">GTK_FILL</property>
-                                <property name="x_padding">3</property>
-                                <property name="y_padding">3</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label20">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
-                                <property name="yalign">0</property>
-                                <property name="label" translatable="yes">Input source:</property>
-                              </object>
-                              <packing>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="x_padding">3</property>
-                                <property name="y_padding">3</property>
-                                <property name="y_options">GTK_FILL</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="system_input_source">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
-                                <property name="yalign">0</property>
-                                <property name="wrap">True</property>
-                                <property name="width-chars">18</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="x_padding">3</property>
-                                <property name="y_padding">3</property>
-                                <property name="y_options">GTK_FILL</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label21">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
-                                <property name="label" translatable="yes">Format:</property>
-                              </object>
-                              <packing>
-                                <property name="top_attach">2</property>
-                                <property name="bottom_attach">3</property>
-                                <property name="y_options">GTK_FILL</property>
-                                <property name="x_padding">3</property>
-                                <property name="y_padding">3</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="system_format">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">2</property>
-                                <property name="bottom_attach">3</property>
-                                <property name="y_options">GTK_FILL</property>
-                                <property name="x_padding">3</property>
-                                <property name="y_padding">3</property>
-                              </packing>
-                            </child>
-                          </object>
-                        </child>
-                        <child type="label">
-                          <object class="GtkLabel" id="label15">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">System settings</property>
-                            <attributes>
-                              <attribute name="weight" value="bold"/>
-                            </attributes>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="y_options">GTK_FILL</property>
-                        <property name="x_padding">3</property>
-                        <property name="y_padding">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkButton" id="copy_settings_button">
-                        <property name="label" translatable="yes">Copy Settings…</property>
-                        <property name="use_action_appearance">False</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">True</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                        <property name="x_options">GTK_SHRINK</property>
-                        <property name="y_options">GTK_SHRINK</property>
-                        <property name="x_padding">3</property>
-                        <property name="y_padding">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="position">4</property>
-                  </packing>
-                </child>
-                <child type="tab">
-                  <object class="GtkLabel" id="label12">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">System</property>
-                  </object>
-                  <packing>
-                    <property name="position">4</property>
-                    <property name="tab_fill">False</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
-  <object class="GtkSizeGroup" id="system-input-source-sizegroup">
-    <property name="mode">vertical</property>
-    <widgets>
-      <widget name="user_input_source"/>
-      <widget name="system_input_source"/>
-    </widgets>
-  </object>
-</interface>
diff --git a/panels/region/input-chooser.ui b/panels/region/input-chooser.ui
new file mode 100644
index 0000000..5d16271
--- /dev/null
+++ b/panels/region/input-chooser.ui
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkDialog" id="input-dialog">
+    <property name="title" translatable="yes">Add an Input Source</property>
+    <property name="modal">True</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="resizable">True</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="vbox">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">0</property>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow">
+            <property name="visible">True</property>
+            <property name="hscrollbar-policy">never</property>
+            <property name="vscrollbar-policy">never</property>
+            <property name="shadow-type">in</property>
+            <property name="margin-left">6</property>
+            <property name="margin-right">6</property>
+            <property name="margin-top">6</property>
+            <property name="margin-bottom">6</property>
+            <child>
+              <object class="GtkViewport" id="viewport">
+                <property name="visible">True</property>
+                <child>
+                  <object class="EggListBox" id="list">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="vexpand">True</property>
+                    <property name="halign">fill</property>
+                    <property name="valign">fill</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkSearchEntry" id="filter-entry">
+            <property name="visible">False</property>
+            <property name="hexpand">True</property>
+            <property name="margin-left">6</property>
+            <property name="margin-right">6</property>
+            <property name="margin-top">6</property>
+            <property name="margin-bottom">6</property>
+          </object>
+        </child>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="action-area">
+            <property name="visible">True</property>
+            <property name="orientation">horizontal</property>
+            <child>
+              <object class="GtkButton" id="cancel-button">
+                <property name="visible">True</property>
+                <property name="label">gtk-cancel</property>
+                <property name="use_stock">True</property>
+                <property name="use_underline" >True</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton" id="add-button">
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="label">gtk-add</property>
+                <property name="use_stock">True</property>
+                <property name="use_underline" >True</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-5">add-button</action-widget>
+      <action-widget response="-6">cancel-button</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/panels/region/input-options.ui b/panels/region/input-options.ui
new file mode 100644
index 0000000..e7cdb55
--- /dev/null
+++ b/panels/region/input-options.ui
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkDialog" id="dialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Input Source Options</property>
+    <property name="type_hint">dialog</property>
+    <property name="modal">True</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="ok-button">
+                <property name="label">gtk-close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid" id="grid1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">6</property>
+            <property name="margin_right">6</property>
+            <property name="margin_top">6</property>
+            <property name="margin_bottom">6</property>
+            <property name="row_spacing">6</property>
+            <property name="column_spacing">6</property>
+            <child>
+              <object class="GtkRadioButton" id="same-source">
+                <property name="label" translatable="yes">Use the _same source for all windows</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_underline">True</property>
+                <property name="xalign">0</property>
+                <property name="active">True</property>
+                <property name="draw_indicator">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkRadioButton" id="per-window-source">
+                <property name="label" translatable="yes">Allow _different sources for each window</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_underline">True</property>
+                <property name="xalign">0</property>
+                <property name="active">True</property>
+                <property name="draw_indicator">True</property>
+                <property name="group">same-source</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_top">6</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Keyboard Shortcuts</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">2</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="previous-source-label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">1</property>
+                <property name="label" translatable="yes">Switch to previous source</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">3</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="previous-source">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Super+Shift+Space</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">3</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="next-source-label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">1</property>
+                <property name="label" translatable="yes">Switch to next source</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">4</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="next-source">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Super+Space</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">4</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_top">6</property>
+                <property name="label" translatable="yes">You can change these shortcuts in the keyboard settings</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">6</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="alt-next-source-label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">1</property>
+                <property name="label" translatable="yes">Alternative switch to next source</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">5</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="alt-next-source">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Left+Right Alt</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">5</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-5">ok-button</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/panels/region/region.gresource.xml b/panels/region/region.gresource.xml
index 02b8d98..4972783 100644
--- a/panels/region/region.gresource.xml
+++ b/panels/region/region.gresource.xml
@@ -1,7 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
   <gresource prefix="/org/gnome/control-center/region">
-    <file preprocess="xml-stripblanks">gnome-region-panel.ui</file>
-    <file preprocess="xml-stripblanks">gnome-region-panel-input-chooser.ui</file>
+    <file preprocess="xml-stripblanks">region.ui</file>
+    <file preprocess="xml-stripblanks">format-chooser.ui</file>
+    <file preprocess="xml-stripblanks">input-options.ui</file>
+    <file preprocess="xml-stripblanks">input-chooser.ui</file>
   </gresource>
 </gresources>
diff --git a/panels/region/region.ui b/panels/region/region.ui
new file mode 100644
index 0000000..f594ab0
--- /dev/null
+++ b/panels/region/region.ui
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkWindow" id="window_region">
+    <property name="can_focus">False</property>
+    <property name="resizable">False</property>
+    <child>
+    <object class="GtkOverlay" id="overlay">
+      <property name="visible">True</property>
+    <child>
+      <object class="GtkBox" id="vbox_region">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkFrame" id="language_section">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">134</property>
+            <property name="margin_right">134</property>
+            <property name="margin_top">24</property>
+            <property name="margin_bottom">24</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="EggListBox" id="language_list">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <child>
+                  <object class="GtkBox" id="language_row">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkLabel" id="language_heading">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">20</property>
+                        <property name="margin_right">20</property>
+                        <property name="margin_top">6</property>
+                        <property name="margin_bottom">6</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Language</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="language_label">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="xalign">1</property>
+                        <property name="margin_left">20</property>
+                        <property name="margin_right">20</property>
+                        <property name="margin_top">6</property>
+                        <property name="margin_bottom">6</property>
+                        <property name="label" translatable="yes">English (United Kingdom)</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox" id="formats_row">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkLabel" id="formats_heading">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">20</property>
+                        <property name="margin_right">20</property>
+                        <property name="margin_top">6</property>
+                        <property name="margin_bottom">6</property>
+                        <property name="xalign">0</property>
+                        <property name="label" translatable="yes">Formats</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="formats_label">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="xalign">1</property>
+                        <property name="margin_left">20</property>
+                        <property name="margin_right">20</property>
+                        <property name="margin_top">6</property>
+                        <property name="margin_bottom">6</property>
+                        <property name="label" translatable="yes">United Kingdom</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label_item">
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="input_section">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">134</property>
+            <property name="margin_right">134</property>
+            <property name="margin_bottom">24</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkBox" id="input_heading_row">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_bottom">6</property>
+                <child>
+                  <object class="GtkLabel" id="input_heading">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="margin_left">6</property>
+                    <property name="margin_right">6</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Input Sources</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="input_options">
+                    <property name="label" translatable="yes">Options</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFrame" id="input_frame">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="EggListBox" id="input_list">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToolbar" id="input_toolbar">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="toolbar_style">icons</property>
+                <property name="show_arrow">False</property>
+                <property name="icon_size">1</property>
+                <style>
+                  <class name="inline-toolbar"/>
+                </style>
+                <child>
+                  <object class="GtkToolItem" id="i_s_ar_item">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkBox" id="i_s_ar_box">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkButton" id="input_source_add">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <child>
+                              <object class="GtkImage" id="i_s_a_image">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="icon_name">list-add-symbolic</property>
+                                <property name="icon-size">1</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkButton" id="input_source_remove">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <child>
+                              <object class="GtkImage" id="i_s_r_image">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="icon_name">list-remove-symbolic</property>
+                                <property name="icon-size">1</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkSeparatorToolItem" id="sep1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="draw">False</property>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkToolItem" id="i_s_sc_item">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkBox" id="i_s_sc_box">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkButton" id="input_source_config">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <child>
+                              <object class="GtkImage" id="i_s_sc_image">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="icon_name">emblem-system-symbolic</property>
+                                <property name="icon-size">1</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkToolItem" id="i_s_sl_item">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkBox" id="i_s_sl_box">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkButton" id="input_source_layout">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <child>
+                              <object class="GtkImage" id="i_s_sl_image">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="icon_name">input-keyboard-symbolic</property>
+                                <property name="icon-size">1</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="login-label">
+           <property name="valign">end</property>
+           <property name="vexpand">True</property>
+           <property name="label" translatable="yes">Login settings are used by all users when logging into the system</property>
+           <property name="margin_bottom">12</property>
+           <style>
+             <class name="dim-label"/>
+           </style>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+    </child>
+  </object>
+</interface>
diff --git a/panels/user-accounts/um-user-panel.c b/panels/user-accounts/um-user-panel.c
index 71aeae8..89797c7 100644
--- a/panels/user-accounts/um-user-panel.c
+++ b/panels/user-accounts/um-user-panel.c
@@ -641,7 +641,7 @@ show_user (ActUser *user, CcUserPanelPrivate *d)
 
         widget = get_widget (d, "account-language-combo");
         model = um_editable_combo_get_model (UM_EDITABLE_COMBO (widget));
-        cc_add_user_languages (model);
+        cc_common_language_add_user_languages (model);
 
         lang = g_strdup (act_user_get_language (user));
         if (!lang)
@@ -766,13 +766,14 @@ language_response (GtkDialog         *dialog,
         model = um_editable_combo_get_model (UM_EDITABLE_COMBO (combo));
 
         if (response_id == GTK_RESPONSE_OK) {
-                lang = cc_language_chooser_get_language (GTK_WIDGET (dialog));
+                lang = g_strdup (cc_language_chooser_get_language (GTK_WIDGET (dialog)));
                 act_user_set_language (user, lang);
         }
         else {
-                lang = g_strdup (act_user_get_language (user));
-                if (!lang)
+                lang = act_user_get_language (user);
+                if (!lang) {
                         lang = cc_common_language_get_current_language ();
+                }
         }
         cc_common_language_get_iter_for_language (model, lang, &iter);
         um_editable_combo_set_active_iter (UM_EDITABLE_COMBO (combo), &iter);
@@ -816,7 +817,7 @@ language_changed (UmEditableCombo    *combo,
                 goto out;
         }
 
-        d->language_chooser = cc_language_chooser_new (gtk_widget_get_toplevel (d->main_box), FALSE);
+        d->language_chooser = cc_language_chooser_new (gtk_widget_get_toplevel (d->main_box));
 
         g_signal_connect (d->language_chooser, "response",
                           G_CALLBACK (language_response), d);
@@ -1201,6 +1202,7 @@ setup_main_window (CcUserPanelPrivate *d)
         GIcon *icon;
         GError *error = NULL;
         gchar *names[3];
+        gboolean loaded;
 
         userlist = get_widget (d, "list-treeview");
         store = gtk_list_store_new (NUM_USER_LIST_COLS,
@@ -1220,8 +1222,6 @@ setup_main_window (CcUserPanelPrivate *d)
                                              match_user, NULL, NULL);
         g_object_unref (model);
 
-        g_signal_connect (d->um, "notify::is-loaded", G_CALLBACK (users_loaded), d);
-
         gtk_widget_style_get (userlist, "expander-size", &expander_size, NULL);
         gtk_tree_view_set_level_indentation (GTK_TREE_VIEW (userlist), - (expander_size + 6));
 
@@ -1325,6 +1325,12 @@ setup_main_window (CcUserPanelPrivate *d)
                                           "*",
                                           icon);
         g_object_unref (icon);
+
+        g_object_get (d->um, "is-loaded", &loaded, NULL);
+        if (loaded)
+                users_loaded (d->um, NULL, d);
+        else
+                g_signal_connect (d->um, "notify::is-loaded", G_CALLBACK (users_loaded), d);
 }
 
 static void
@@ -1358,13 +1364,13 @@ cc_user_panel_init (CcUserPanel *self)
                 return;
         }
 
-        setup_main_window (d);
         d->password_dialog = um_password_dialog_new ();
         button = get_widget (d, "user-icon-button");
         d->photo_dialog = um_photo_dialog_new (button);
         d->main_box = get_widget (d, "accounts-vbox");
         gtk_widget_reparent (d->main_box, GTK_WIDGET (self));
         d->history_dialog = um_history_dialog_new ();
+        setup_main_window (d);
 
         context = gtk_widget_get_style_context (get_widget (d, "list-scrolledwindow"));
         gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 723fc6a..94d70a1 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -2,6 +2,7 @@ INCLUDES =					\
 	-I$(top_srcdir)				\
 	$(SHELL_CFLAGS)				\
 	$(CHEESE_CFLAGS)			\
+	-I$(top_srcdir)/panels/common/		\
 	-I$(top_srcdir)/libgd
 
 all-local: check-local
@@ -33,8 +34,6 @@ gnome_control_center_SOURCES =			\
 	cc-panel.h				\
 	cc-shell.c				\
 	cc-shell.h				\
-	cc-util.c				\
-	cc-util.h				\
 	hostname-helper.c			\
 	hostname-helper.h			\
 	cc-hostname-entry.c			\
@@ -47,6 +46,7 @@ gnome_control_center_LDADD =						\
 	$(SHELL_LIBS)							\
 	$(CHEESE_LIBS)							\
 	$(top_builddir)/libgd/libgd.la					\
+	$(top_builddir)/panels/common/liblanguage.la			\
 	$(top_builddir)/panels/background/libbackground.la		\
 	$(top_builddir)/panels/color/libcolor.la			\
 	$(top_builddir)/panels/datetime/libdate_time.la			\
diff --git a/shell/cc-util.c b/shell/cc-util.c
deleted file mode 100644
index e51a9d2..0000000
--- a/shell/cc-util.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
- *
- * The Control Center 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.
- *
- * The Control Center 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 the Control Center; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include "config.h"
-
-#include <string.h>
-
-
-#include "cc-util.h"
-
-/* Combining diacritical mark?
- *  Basic range: [0x0300,0x036F]
- *  Supplement:  [0x1DC0,0x1DFF]
- *  For Symbols: [0x20D0,0x20FF]
- *  Half marks:  [0xFE20,0xFE2F]
- */
-#define IS_CDM_UCS4(c) (((c) >= 0x0300 && (c) <= 0x036F)  || \
-                        ((c) >= 0x1DC0 && (c) <= 0x1DFF)  || \
-                        ((c) >= 0x20D0 && (c) <= 0x20FF)  || \
-                        ((c) >= 0xFE20 && (c) <= 0xFE2F))
-
-/* Copied from tracker/src/libtracker-fts/tracker-parser-glib.c under the GPL
- * And then from gnome-shell/src/shell-util.c
- *
- * Originally written by Aleksander Morgado <aleksander@gnu.org>
- */
-char *
-cc_util_normalize_casefold_and_unaccent (const char *str)
-{
-  char *normalized, *tmp;
-  int i = 0, j = 0, ilen;
-
-  if (str == NULL)
-    return NULL;
-
-  normalized = g_utf8_normalize (str, -1, G_NORMALIZE_NFKD);
-  tmp = g_utf8_casefold (normalized, -1);
-  g_free (normalized);
-
-  ilen = strlen (tmp);
-
-  while (i < ilen)
-    {
-      gunichar unichar;
-      gchar *next_utf8;
-      gint utf8_len;
-
-      /* Get next character of the word as UCS4 */
-      unichar = g_utf8_get_char_validated (&tmp[i], -1);
-
-      /* Invalid UTF-8 character or end of original string. */
-      if (unichar == (gunichar) -1 ||
-          unichar == (gunichar) -2)
-        {
-          break;
-        }
-
-      /* Find next UTF-8 character */
-      next_utf8 = g_utf8_next_char (&tmp[i]);
-      utf8_len = next_utf8 - &tmp[i];
-
-      if (IS_CDM_UCS4 ((guint32) unichar))
-        {
-          /* If the given unichar is a combining diacritical mark,
-           * just update the original index, not the output one */
-          i += utf8_len;
-          continue;
-        }
-
-      /* If already found a previous combining
-       * diacritical mark, indexes are different so
-       * need to copy characters. As output and input
-       * buffers may overlap, need to use memmove
-       * instead of memcpy */
-      if (i != j)
-        {
-          memmove (&tmp[j], &tmp[i], utf8_len);
-        }
-
-      /* Update both indexes */
-      i += utf8_len;
-      j += utf8_len;
-    }
-
-  /* Force proper string end */
-  tmp[j] = '\0';
-
-  return tmp;
-}
diff --git a/shell/cc-util.h b/shell/cc-util.h
deleted file mode 100644
index 42b09ff..0000000
--- a/shell/cc-util.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
- *
- * The Control Center 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.
- *
- * The Control Center 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 the Control Center; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-
-#ifndef _CC_UTIL_H
-#define _CC_UTIL_H
-
-#include <glib.h>
-
-char *cc_util_normalize_casefold_and_unaccent (const char *str);
-
-#endif
