[gnome-initial-setup] Add keyboard layout selection page
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-initial-setup] Add keyboard layout selection page
- Date: Wed, 9 Jan 2013 23:01:40 +0000 (UTC)
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]