[gnome-initial-setup] Add keyboard layout selection page



commit 0054708141e5a8a9110271d51e978ea67dbffc48
Author: Michael Wood <michael g wood intel com>
Date:   Fri Dec 7 17:43:00 2012 +0000

    Add keyboard layout selection page
    
    This is a first pass at adding the keyboard selection page.
    Currently the ui is directly copied from gnome-control-center.

 configure.ac                                       |   20 +
 gnome-initial-setup/Makefile.am                    |    5 +-
 gnome-initial-setup/gnome-initial-setup.c          |    2 +
 gnome-initial-setup/pages/Makefile.am              |    3 +-
 gnome-initial-setup/pages/keyboard/Makefile.am     |   15 +
 .../pages/keyboard/gis-keyboard-page.c             |   80 ++
 .../pages/keyboard/gis-keyboard-page.h             |   79 ++
 .../pages/keyboard/gis-keyboard-page.ui            |  275 ++++
 .../keyboard/gnome-region-panel-input-chooser.ui   |  144 ++
 .../pages/keyboard/gnome-region-panel-input.c      | 1406 ++++++++++++++++++++
 .../pages/keyboard/gnome-region-panel-input.h      |   35 +
 gnome-initial-setup/setup.gresource.xml            |    2 +
 12 files changed, 2064 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 464e480..7355a99 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,6 +19,7 @@ GLIB_REQUIRED_VERSION=2.29.4
 GTK_REQUIRED_VERSION=3.1.2
 CLUTTER_REQUIRED_VERSION=1.11.3
 PANGO_REQUIRED_VERSION=1.32.5
+IBUS_REQUIRED_VERSION=1.4.99
 
 # EggListBox submodule
 prev_top_build_prefix=$ac_top_build_prefix
@@ -62,6 +63,24 @@ if test x$have_clutter = xyes; then
   AC_DEFINE(HAVE_CLUTTER, 1, [Build with Clutter support?])
 fi
 
+AC_ARG_ENABLE(ibus,
+        AS_HELP_STRING([--disable-ibus],
+                       [Disable IBus support]),
+        enable_ibus=$enableval,
+        enable_ibus=yes)
+
+AS_IF([test x$enable_ibus = xyes],
+      [PKG_CHECK_MODULES(IBUS,
+                        ibus-1.0 >= $IBUS_REQUIRED_VERSION,
+                        have_ibus=yes, have_ibus=no)],
+      [have_ibus=no])
+
+if test x$have_ibus = xyes; then
+  INITIAL_SETUP_CFLAGS="$INITIAL_SETUP_CFLAGS $IBUS_CFLAGS"
+  INITIAL_SETUP_LIBS="$INITIAL_SETUP_LIBS $IBUS_LIBS"
+  AC_DEFINE(HAVE_IBUS, 1, [Build with IBus support?])
+fi
+
 # Kerberos kerberos support
 AC_PATH_PROG(KRB5_CONFIG, krb5-config, no)
 if test "$KRB5_CONFIG" = "no"; then
@@ -125,6 +144,7 @@ gnome-initial-setup/pages/location/Makefile
 gnome-initial-setup/pages/network/Makefile
 gnome-initial-setup/pages/goa/Makefile
 gnome-initial-setup/pages/summary/Makefile
+gnome-initial-setup/pages/keyboard/Makefile
 po/Makefile.in
 player/Makefile
 ])
diff --git a/gnome-initial-setup/Makefile.am b/gnome-initial-setup/Makefile.am
index fd4f658..048cfe1 100644
--- a/gnome-initial-setup/Makefile.am
+++ b/gnome-initial-setup/Makefile.am
@@ -19,7 +19,9 @@ UI_FILES = \
 	pages/account/gis-account-page.ui \
 	pages/location/gis-location-page.ui \
 	pages/goa/gis-goa-page.ui \
-	pages/summary/gis-summary-page.ui
+	pages/summary/gis-summary-page.ui \
+	pages/keyboard/gis-keyboard-page.ui \
+	pages/keyboard/gnome-region-panel-input-chooser.ui
 
 setup_resources.c: setup.gresource.xml $(UI_FILES)
 	$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --generate-source $(srcdir)/setup.gresource.xml
@@ -49,6 +51,7 @@ gnome_initial_setup_LDADD =	\
 	pages/account/libgisaccount.la \
 	pages/goa/libgisgoa.la \
 	pages/summary/libgissummary.la \
+	pages/keyboard/libgiskeyboard.la \
 	$(INITIAL_SETUP_LIBS) \
 	-lm
 
diff --git a/gnome-initial-setup/gnome-initial-setup.c b/gnome-initial-setup/gnome-initial-setup.c
index 11c0345..e63584d 100644
--- a/gnome-initial-setup/gnome-initial-setup.c
+++ b/gnome-initial-setup/gnome-initial-setup.c
@@ -44,6 +44,7 @@
 #include "pages/network/gis-network-page.h"
 #include "pages/goa/gis-goa-page.h"
 #include "pages/summary/gis-summary-page.h"
+#include "pages/keyboard/gis-keyboard-page.h"
 
 /* main {{{1 */
 
@@ -52,6 +53,7 @@ rebuild_pages_cb (GisDriver *driver)
 {
   gis_assistant_destroy_all_pages (gis_driver_get_assistant (driver));
   gis_prepare_language_page (driver);
+  gis_prepare_keyboard_page (driver);
   gis_prepare_eula_pages (driver);
   gis_prepare_network_page (driver);
   gis_prepare_account_page (driver);
diff --git a/gnome-initial-setup/pages/Makefile.am b/gnome-initial-setup/pages/Makefile.am
index 4534a47..710528c 100644
--- a/gnome-initial-setup/pages/Makefile.am
+++ b/gnome-initial-setup/pages/Makefile.am
@@ -6,4 +6,5 @@ SUBDIRS = \
 	location \
 	network \
 	goa \
-	summary
+	summary \
+	keyboard
diff --git a/gnome-initial-setup/pages/keyboard/Makefile.am b/gnome-initial-setup/pages/keyboard/Makefile.am
new file mode 100644
index 0000000..60fd40f
--- /dev/null
+++ b/gnome-initial-setup/pages/keyboard/Makefile.am
@@ -0,0 +1,15 @@
+
+noinst_LTLIBRARIES = libgiskeyboard.la
+
+AM_CPPFLAGS = \
+	$(INITIAL_SETUP_CFLAGS) \
+	-DLOCALSTATEDIR="\"$(localstatedir)\"" \
+	-DUIDIR="\"$(uidir)\""
+
+libgiskeyboard_la_SOURCES =	\
+	gis-keyboard-page.c gis-keyboard-page.h \
+	gnome-region-panel-input.c gnome-region-panel-input.h
+
+libgiskeyboard_la_CFLAGS = $(INITIAL_SETUP_CFLAGS) -I "$(srcdir)/../.."
+libgiskeyboard_la_LIBADD = $(INITIAL_SETUP_LIBS)
+libgiskeyboard_la_LDFLAGS = -export_dynamic -avoid-version -module -no-undefined
diff --git a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
new file mode 100644
index 0000000..4ed0ce6
--- /dev/null
+++ b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 Intel, Inc
+ * 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.
+ *
+ * Authors:
+ *   Michael Wood <michael g wood intel com>
+ *   Jasper St. Pierre <jstpierre mecheye net>
+ *
+ * Based on gnome-control-center region page by:
+ *  Sergey Udaltsov <svu gnome org>
+ *
+ */
+
+#define PAGE_ID "keyboard"
+
+#include "config.h"
+#include "gis-keyboard-page.h"
+#include <gtk/gtk.h>
+
+#include "gnome-region-panel-input.h"
+
+G_DEFINE_TYPE (GisKeyboardPage, gis_keyboard_page, GIS_TYPE_PAGE)
+
+#define OBJ(type,name) ((type)gtk_builder_get_object(GIS_PAGE(page)->builder,(name)))
+#define WID(name) OBJ(GtkWidget*,name)
+
+static void
+gis_keyboard_page_constructed (GObject *object)
+{
+  GisKeyboardPage *page = GIS_KEYBOARD_PAGE (object);
+
+  G_OBJECT_CLASS (gis_keyboard_page_parent_class)->constructed (object);
+
+  setup_input_tabs (GIS_PAGE (page)->builder, GIS_KEYBOARD_PAGE (page));
+
+  gtk_container_add (GTK_CONTAINER (page), WID("keyboard-page"));
+
+  gis_page_set_title (GIS_PAGE (page), _("Keyboard Layout"));
+  gis_page_set_complete (GIS_PAGE (page), TRUE);
+
+  gtk_widget_show (GTK_WIDGET (page));
+}
+
+static void
+gis_keyboard_page_class_init (GisKeyboardPageClass * klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GisPageClass * page_class = GIS_PAGE_CLASS (klass);
+
+  page_class->page_id = PAGE_ID;
+  object_class->constructed = gis_keyboard_page_constructed;
+}
+
+static void
+gis_keyboard_page_init (GisKeyboardPage * self)
+{
+}
+
+void
+gis_prepare_keyboard_page (GisDriver *driver)
+{
+  gis_driver_add_page (driver,
+                       g_object_new (GIS_TYPE_KEYBOARD_PAGE,
+                                     "driver", driver,
+                                     NULL));
+}
diff --git a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.h b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.h
new file mode 100644
index 0000000..e215e34
--- /dev/null
+++ b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 Intel, Inc
+ * 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.
+ *
+ * Authors:
+ *   Michael Wood <michael g wood intel com>
+ *   Jasper St. Pierre <jstpierre mecheye net>
+ *
+ * Based on gnome-control-center region page by:
+ *  Sergey Udaltsov <svu gnome org>
+ *
+ */
+
+#ifndef _GIS_KEYBOARD_PAGE_H
+#define _GIS_KEYBOARD_PAGE_H
+
+#include "gnome-initial-setup.h"
+
+G_BEGIN_DECLS
+
+#define GIS_TYPE_KEYBOARD_PAGE gis_keyboard_page_get_type()
+
+#define GIS_KEYBOARD_PAGE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  GIS_TYPE_KEYBOARD_PAGE, GisKeyboardPage))
+
+#define GIS_KEYBOARD_PAGE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+  GIS_TYPE_KEYBOARD_PAGE, GisKeyboardPageClass))
+
+#define GIS_IS_KEYBOARD_PAGE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  GIS_TYPE_KEYBOARD_PAGE))
+
+#define GIS_IS_KEYBOARD_PAGE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+  GIS_TYPE_KEYBOARD_PAGE))
+
+#define GIS_KEYBOARD_PAGE_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+  GIS_TYPE_KEYBOARD_PAGE, GisKeyboardPageClass))
+
+typedef struct _GisKeyboardPage GisKeyboardPage;
+typedef struct _GisKeyboardPageClass GisKeyboardPageClass;
+typedef struct _GisKeyboardPagePrivate GisKeyboardPagePrivate;
+
+struct _GisKeyboardPage
+{
+  GisPage parent;
+
+  GisKeyboardPagePrivate *priv;
+};
+
+struct _GisKeyboardPageClass
+{
+  GisPageClass parent_class;
+};
+
+GType gis_keyboard_page_get_type (void) G_GNUC_CONST;
+
+void  gis_prepare_keyboard_page (GisDriver *driver);
+
+G_END_DECLS
+
+#endif /* _GIS_KEYBOARD_PAGE_H */
diff --git a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.ui b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.ui
new file mode 100644
index 0000000..38be528
--- /dev/null
+++ b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.ui
@@ -0,0 +1,275 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkVBox" id="keyboard-page">
+    <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="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>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection" id="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="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>
+            <child>
+              <object class="GtkToolItem" id="i_s_ar_item">
+                <property name="use_action_appearance">False</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="use_action_appearance">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="use_action_appearance">False</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="use_action_appearance">False</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="use_action_appearance">False</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="use_action_appearance">False</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_ud_item">
+                <property name="use_action_appearance">False</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="use_action_appearance">False</property>
+                <child>
+                  <object class="GtkBox" id="i_s_ud_box">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkButton" id="input_source_move_up">
+                        <property name="use_action_appearance">False</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <child>
+                          <object class="GtkImage" id="i_s_u_image">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="icon_name">go-up-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_move_down">
+                        <property name="use_action_appearance">False</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <child>
+                          <object class="GtkImage" id="i_s_d_image">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="icon_name">go-down-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="sep2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="draw">False</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToolItem" id="i_s_sp_item">
+                <property name="use_action_appearance">False</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="use_action_appearance">False</property>
+                <child>
+                  <object class="GtkBox" id="i_s_sp_box">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkButton" id="input_source_settings">
+                        <property name="use_action_appearance">False</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <child>
+                          <object class="GtkImage" id="i_s_s_image">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="pixel_size">16</property>
+                            <property name="icon_name">preferences-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>
+                    <child>
+                      <object class="GtkButton" id="input_source_show">
+                        <property name="use_action_appearance">False</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="use_action_appearance">False</property>
+                        <child>
+                          <object class="GtkImage" id="i_s_p_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">1</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">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/gnome-initial-setup/pages/keyboard/gnome-region-panel-input-chooser.ui b/gnome-initial-setup/pages/keyboard/gnome-region-panel-input-chooser.ui
new file mode 100644
index 0000000..0a3f346
--- /dev/null
+++ b/gnome-initial-setup/pages/keyboard/gnome-region-panel-input-chooser.ui
@@ -0,0 +1,144 @@
+<?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/gnome-initial-setup/pages/keyboard/gnome-region-panel-input.c b/gnome-initial-setup/pages/keyboard/gnome-region-panel-input.c
new file mode 100644
index 0000000..4e4ab5c
--- /dev/null
+++ b/gnome-initial-setup/pages/keyboard/gnome-region-panel-input.c
@@ -0,0 +1,1406 @@
+/*
+ * 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 "gdm-languages.h"
+#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 ("keyboard-page"));
+  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 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);
+    }
+}
+
+void
+setup_input_tabs (GtkBuilder      *builder,
+                  GisKeyboardPage *page)
+{
+  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);
+
+  g_signal_connect (G_OBJECT (input_sources_settings),
+                    "changed::" KEY_INPUT_SOURCES,
+                    G_CALLBACK (input_sources_changed),
+                    builder);
+}
+
+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;
+  GError *error = NULL;
+
+  builder = gtk_builder_new ();
+  gtk_builder_add_from_resource (builder,
+                                 "/ui/gnome-region-panel-input-chooser.ui",
+                                 &error);
+
+  if (error)
+    g_error ("Problem parsing ui file %s", error->message);
+
+  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/gnome-initial-setup/pages/keyboard/gnome-region-panel-input.h b/gnome-initial-setup/pages/keyboard/gnome-region-panel-input.h
new file mode 100644
index 0000000..4aed62b
--- /dev/null
+++ b/gnome-initial-setup/pages/keyboard/gnome-region-panel-input.h
@@ -0,0 +1,35 @@
+/* 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 "gis-keyboard-page.h"
+
+G_BEGIN_DECLS
+
+void setup_input_tabs (GtkBuilder      *builder,
+                       GisKeyboardPage *self);
+
+G_END_DECLS
+
+#endif  /* __GNOME_KEYBOARD_PROPERTY_INPUT_H */
diff --git a/gnome-initial-setup/setup.gresource.xml b/gnome-initial-setup/setup.gresource.xml
index 771c622..fba5715 100644
--- a/gnome-initial-setup/setup.gresource.xml
+++ b/gnome-initial-setup/setup.gresource.xml
@@ -7,6 +7,8 @@
     <file preprocess="xml-stripblanks" alias="gis-network-page.ui">pages/network/gis-network-page.ui</file>
     <file preprocess="xml-stripblanks" alias="gis-goa-page.ui">pages/goa/gis-goa-page.ui</file>
     <file preprocess="xml-stripblanks" alias="gis-summary-page.ui">pages/summary/gis-summary-page.ui</file>
+    <file preprocess="xml-stripblanks" alias="gis-keyboard-page.ui">pages/keyboard/gis-keyboard-page.ui</file>
+    <file preprocess="xml-stripblanks" alias="gnome-region-panel-input-chooser.ui">pages/keyboard/gnome-region-panel-input-chooser.ui</file>
   </gresource>
 </gresources>
 



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