[gnome-initial-setup/shell/4765: 335/362] Use keyboard page design from GNOME 3.14.0
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-initial-setup/shell/4765: 335/362] Use keyboard page design from GNOME 3.14.0
- Date: Thu, 19 Mar 2015 01:49:15 +0000 (UTC)
commit f45938524d7018e4a05181a89f0b99e0e3cf23e7
Author: Juan A. Suarez Romero <jasuarez igalia com>
Date: Mon Feb 2 12:18:27 2015 +0100
Use keyboard page design from GNOME 3.14.0
This new design helps to select only one keyboard layout during the
first boot experience.
[endlessm/eos-shell#3364]
gnome-initial-setup/pages/keyboard/Makefile.am | 2 +
.../pages/keyboard/cc-common-language.c | 325 ++++
.../pages/keyboard/cc-common-language.h | 36 +
gnome-initial-setup/pages/keyboard/cc-ibus-utils.c | 8 +-
gnome-initial-setup/pages/keyboard/cc-ibus-utils.h | 4 +-
.../pages/keyboard/cc-input-chooser.c | 1661 ++++++++------------
.../pages/keyboard/cc-input-chooser.h | 52 +-
gnome-initial-setup/pages/keyboard/cc-util.c | 105 ++
gnome-initial-setup/pages/keyboard/cc-util.h | 28 +
.../pages/keyboard/gis-keyboard-page.c | 1195 ++-------------
.../pages/keyboard/gis-keyboard-page.h | 3 +-
.../pages/keyboard/gis-keyboard-page.ui | 297 +---
.../pages/keyboard/input-chooser.ui | 92 +-
13 files changed, 1385 insertions(+), 2423 deletions(-)
---
diff --git a/gnome-initial-setup/pages/keyboard/Makefile.am b/gnome-initial-setup/pages/keyboard/Makefile.am
index 28b3fbd..545a8de 100644
--- a/gnome-initial-setup/pages/keyboard/Makefile.am
+++ b/gnome-initial-setup/pages/keyboard/Makefile.am
@@ -17,10 +17,12 @@ BUILT_SOURCES += keyboard-resources.c keyboard-resources.h
libgiskeyboard_la_SOURCES = \
cc-input-chooser.c cc-input-chooser.h \
+ cc-common-language.c cc-common-language.h \
cc-ibus-utils.c cc-ibus-utils.h \
cc-keyboard-detector.c cc-keyboard-detector.h \
cc-keyboard-query.c cc-keyboard-query.h \
cc-key-row.c cc-key-row.h \
+ cc-util.c cc-util.h \
gis-keyboard-page.c gis-keyboard-page.h \
$(BUILT_SOURCES)
diff --git a/gnome-initial-setup/pages/keyboard/cc-common-language.c
b/gnome-initial-setup/pages/keyboard/cc-common-language.c
new file mode 100644
index 0000000..c1d1399
--- /dev/null
+++ b/gnome-initial-setup/pages/keyboard/cc-common-language.c
@@ -0,0 +1,325 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by: Matthias Clasen <mclasen redhat com>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <fontconfig/fontconfig.h>
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-languages.h>
+
+#include "cc-common-language.h"
+
+static char *get_lang_for_user_object_path (const char *path);
+
+gboolean
+cc_common_language_has_font (const gchar *locale)
+{
+ const FcCharSet *charset;
+ FcPattern *pattern;
+ FcObjectSet *object_set;
+ FcFontSet *font_set;
+ gchar *language_code;
+ gboolean is_displayable;
+
+ is_displayable = FALSE;
+ pattern = NULL;
+ object_set = NULL;
+ font_set = NULL;
+
+ if (!gnome_parse_locale (locale, &language_code, NULL, NULL, NULL))
+ return FALSE;
+
+ charset = FcLangGetCharSet ((FcChar8 *) language_code);
+ if (!charset) {
+ /* fontconfig does not know about this language */
+ is_displayable = TRUE;
+ }
+ else {
+ /* see if any fonts support rendering it */
+ pattern = FcPatternBuild (NULL, FC_LANG, FcTypeString, language_code, NULL);
+
+ if (pattern == NULL)
+ goto done;
+
+ object_set = FcObjectSetCreate ();
+
+ if (object_set == NULL)
+ goto done;
+
+ font_set = FcFontList (NULL, pattern, object_set);
+
+ if (font_set == NULL)
+ goto done;
+
+ is_displayable = (font_set->nfont > 0);
+ }
+
+ done:
+ if (font_set != NULL)
+ FcFontSetDestroy (font_set);
+
+ if (object_set != NULL)
+ FcObjectSetDestroy (object_set);
+
+ if (pattern != NULL)
+ FcPatternDestroy (pattern);
+
+ g_free (language_code);
+
+ return is_displayable;
+}
+
+gchar *
+cc_common_language_get_current_language (void)
+{
+ gchar *language;
+ char *path;
+ const gchar *locale;
+
+ path = g_strdup_printf ("/org/freedesktop/Accounts/User%d", getuid ());
+ language = get_lang_for_user_object_path (path);
+ g_free (path);
+ if (language != NULL && *language != '\0')
+ return language;
+
+ locale = (const gchar *) setlocale (LC_MESSAGES, NULL);
+ if (locale)
+ language = gnome_normalize_locale (locale);
+ else
+ language = NULL;
+
+ return language;
+}
+
+static gboolean
+user_language_has_translations (const char *locale)
+{
+ char *name, *language_code, *territory_code;
+ gboolean ret;
+
+ gnome_parse_locale (locale,
+ &language_code,
+ &territory_code,
+ NULL, NULL);
+ name = g_strdup_printf ("%s%s%s",
+ language_code,
+ territory_code != NULL? "_" : "",
+ territory_code != NULL? territory_code : "");
+ g_free (language_code);
+ g_free (territory_code);
+ ret = gnome_language_has_translations (name);
+ g_free (name);
+
+ return ret;
+}
+
+static char *
+get_lang_for_user_object_path (const char *path)
+{
+ GError *error = NULL;
+ GDBusProxy *user;
+ GVariant *props;
+ char *lang;
+
+ user = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.Accounts",
+ path,
+ "org.freedesktop.Accounts.User",
+ NULL,
+ &error);
+ if (user == NULL) {
+ g_warning ("Failed to get proxy for user '%s': %s",
+ path, error->message);
+ g_error_free (error);
+ return NULL;
+ }
+ props = g_dbus_proxy_get_cached_property (user, "Language");
+ lang = g_variant_dup_string (props, NULL);
+
+ g_variant_unref (props);
+ g_object_unref (user);
+ return lang;
+}
+
+static void
+add_other_users_language (GHashTable *ht)
+{
+ GVariant *variant;
+ GVariantIter *vi;
+ GError *error = NULL;
+ const char *str;
+ GDBusProxy *proxy;
+
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.Accounts",
+ "/org/freedesktop/Accounts",
+ "org.freedesktop.Accounts",
+ NULL,
+ NULL);
+
+ if (proxy == NULL)
+ return;
+
+ variant = g_dbus_proxy_call_sync (proxy,
+ "ListCachedUsers",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if (variant == NULL) {
+ g_warning ("Failed to list existing users: %s", error->message);
+ g_error_free (error);
+ g_object_unref (proxy);
+ return;
+ }
+ g_variant_get (variant, "(ao)", &vi);
+ while (g_variant_iter_loop (vi, "o", &str)) {
+ char *lang;
+ char *name;
+ char *language;
+
+ lang = get_lang_for_user_object_path (str);
+ if (lang != NULL && *lang != '\0' &&
+ cc_common_language_has_font (lang) &&
+ user_language_has_translations (lang)) {
+ name = gnome_normalize_locale (lang);
+ if (!g_hash_table_lookup (ht, name)) {
+ language = gnome_get_language_from_locale (name, NULL);
+ g_hash_table_insert (ht, name, language);
+ }
+ else {
+ g_free (name);
+ }
+ }
+ g_free (lang);
+ }
+ g_variant_iter_free (vi);
+ g_variant_unref (variant);
+
+ g_object_unref (proxy);
+}
+
+static void
+insert_language_internal (GHashTable *ht,
+ const char *lang)
+{
+ gboolean has_translations;
+ char *label_own_lang;
+ char *label_current_lang;
+ char *label_untranslated;
+ char *key;
+
+ has_translations = gnome_language_has_translations (lang);
+ if (!has_translations) {
+ char *lang_code = g_strndup (lang, 2);
+ has_translations = gnome_language_has_translations (lang_code);
+ g_free (lang_code);
+
+ if (!has_translations)
+ return;
+ }
+
+ g_debug ("We have translations for %s", lang);
+
+ key = g_strdup (lang);
+
+ label_own_lang = gnome_get_language_from_locale (key, key);
+ label_current_lang = gnome_get_language_from_locale (key, NULL);
+ label_untranslated = gnome_get_language_from_locale (key, "C");
+
+ /* We don't have a translation for the label in
+ * its own language? */
+ if (g_strcmp0 (label_own_lang, label_untranslated) == 0) {
+ if (g_strcmp0 (label_current_lang, label_untranslated) == 0)
+ g_hash_table_insert (ht, key, g_strdup (label_untranslated));
+ else
+ g_hash_table_insert (ht, key, g_strdup (label_current_lang));
+ } else {
+ g_hash_table_insert (ht, key, g_strdup (label_own_lang));
+ }
+
+ g_free (label_own_lang);
+ g_free (label_current_lang);
+ g_free (label_untranslated);
+}
+
+static void
+insert_language (GHashTable *ht,
+ const char *lang)
+{
+ char *utf8_variant = g_strconcat (lang, ".utf8", NULL);
+ insert_language_internal (ht, lang);
+ insert_language_internal (ht, utf8_variant);
+ g_free (utf8_variant);
+}
+
+static void
+insert_user_languages (GHashTable *ht)
+{
+ char *name;
+ char *language;
+
+ /* Add the languages used by other users on the system */
+ add_other_users_language (ht);
+
+ /* Add current locale */
+ name = cc_common_language_get_current_language ();
+ if (g_hash_table_lookup (ht, name) == NULL) {
+ language = gnome_get_language_from_locale (name, NULL);
+ g_hash_table_insert (ht, name, language);
+ } else {
+ g_free (name);
+ }
+}
+
+GHashTable *
+cc_common_language_get_initial_languages (void)
+{
+ GHashTable *ht;
+
+ ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ insert_language (ht, "en_US");
+ insert_language (ht, "en_GB");
+ insert_language (ht, "de_DE");
+ insert_language (ht, "fr_FR");
+ insert_language (ht, "es_ES");
+ insert_language (ht, "zh_CN");
+ insert_language (ht, "ja_JP");
+ insert_language (ht, "ru_RU");
+ insert_language (ht, "ar_EG");
+
+ insert_user_languages (ht);
+
+ return ht;
+}
diff --git a/gnome-initial-setup/pages/keyboard/cc-common-language.h
b/gnome-initial-setup/pages/keyboard/cc-common-language.h
new file mode 100644
index 0000000..7f32cab
--- /dev/null
+++ b/gnome-initial-setup/pages/keyboard/cc-common-language.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2009-2010 Red Hat, Inc,
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ * Written by: Matthias Clasen <mclasen redhat com>
+ */
+
+#ifndef __CC_COMMON_LANGUAGE_H__
+#define __CC_COMMON_LANGUAGE_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+gboolean cc_common_language_has_font (const gchar *locale);
+gchar *cc_common_language_get_current_language (void);
+GHashTable *cc_common_language_get_initial_languages (void);
+
+G_END_DECLS
+
+#endif
diff --git a/gnome-initial-setup/pages/keyboard/cc-ibus-utils.c
b/gnome-initial-setup/pages/keyboard/cc-ibus-utils.c
index 54f9fb7..424c69e 100644
--- a/gnome-initial-setup/pages/keyboard/cc-ibus-utils.c
+++ b/gnome-initial-setup/pages/keyboard/cc-ibus-utils.c
@@ -12,9 +12,7 @@
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
@@ -28,11 +26,15 @@ engine_get_display_name (IBusEngineDesc *engine_desc)
const gchar *name;
const gchar *language_code;
const gchar *language;
+ const gchar *textdomain;
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);
+ textdomain = ibus_engine_desc_get_textdomain (engine_desc);
+ if (*textdomain != '\0' && *name != '\0')
+ name = g_dgettext (textdomain, name);
display_name = g_strdup_printf ("%s (%s)", language, name);
return display_name;
diff --git a/gnome-initial-setup/pages/keyboard/cc-ibus-utils.h
b/gnome-initial-setup/pages/keyboard/cc-ibus-utils.h
index bcd0c68..da3d996 100644
--- a/gnome-initial-setup/pages/keyboard/cc-ibus-utils.h
+++ b/gnome-initial-setup/pages/keyboard/cc-ibus-utils.h
@@ -12,9 +12,7 @@
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GIS_IBUS_UTILS_H__
diff --git a/gnome-initial-setup/pages/keyboard/cc-input-chooser.c
b/gnome-initial-setup/pages/keyboard/cc-input-chooser.c
index d96f21d..83aa4ce 100644
--- a/gnome-initial-setup/pages/keyboard/cc-input-chooser.c
+++ b/gnome-initial-setup/pages/keyboard/cc-input-chooser.c
@@ -12,1202 +12,855 @@
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Jasper St. Pierre <jstpierre mecheye net>
+ * Matthias Clasen <mclasen redhat com>
*/
-#include <config.h>
+#include "config.h"
+#include "cc-input-chooser.h"
+
#include <locale.h>
#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include <gtk/gtk.h>
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <libgnome-desktop/gnome-languages.h>
-
-#include <egg-list-box.h>
-
-#include <../language/cc-common-language.h>
-#include <../language/cc-util.h>
-#include "cc-input-chooser.h"
+#include <libgnome-desktop/gnome-xkb-info.h>
#ifdef HAVE_IBUS
#include <ibus.h>
#include "cc-ibus-utils.h"
-#endif /* HAVE_IBUS */
+#endif
+
+#include "cc-common-language.h"
+#include "cc-util.h"
+
+#include <glib-object.h>
#define INPUT_SOURCE_TYPE_XKB "xkb"
#define INPUT_SOURCE_TYPE_IBUS "ibus"
-#define ARROW_NEXT "go-next-symbolic"
-#define ARROW_PREV "go-previous-symbolic"
+#define MIN_ROWS 6
-#define MAIN_WINDOW_WIDTH_RATIO 0.60
+struct _CcInputChooserPrivate
+{
+ GtkWidget *filter_entry;
+ GtkWidget *input_list;
+ GHashTable *inputs;
-typedef enum {
- ROW_TRAVEL_DIRECTION_NONE,
- ROW_TRAVEL_DIRECTION_FORWARD,
- ROW_TRAVEL_DIRECTION_BACKWARD
-} RowTravelDirection;
+ GtkWidget *scrolled_window;
+ GtkWidget *no_results;
+ GtkWidget *more_item;
-typedef enum {
- ROW_LABEL_POSITION_START,
- ROW_LABEL_POSITION_CENTER,
- ROW_LABEL_POSITION_END
-} RowLabelPosition;
+ gboolean showing_extra;
+ gchar *locale;
+ gchar *id;
+ gchar *type;
+ GnomeXkbInfo *xkb_info;
+#ifdef HAVE_IBUS
+ IBusBus *ibus;
+ GHashTable *ibus_engines;
+ GCancellable *ibus_cancellable;
+#endif
+};
+typedef struct _CcInputChooserPrivate CcInputChooserPrivate;
+G_DEFINE_TYPE_WITH_PRIVATE (CcInputChooser, cc_input_chooser, GTK_TYPE_BOX);
+
+enum {
+ PROP_0,
+ PROP_SHOWING_EXTRA,
+ PROP_LAST
+};
+
+static GParamSpec *obj_props[PROP_LAST];
+
+enum {
+ CHANGED,
+ CONFIRM,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
typedef struct {
- /* Not owned */
- GtkWidget *add_button;
- GtkWidget *filter_entry;
- GtkWidget *list;
- GtkWidget *scrolledwindow;
- GtkAdjustment *adjustment;
- GnomeXkbInfo *xkb_info;
- GHashTable *ibus_engines;
-
- /* Owned */
- GtkWidget *more_item;
- GtkWidget *no_results;
- GHashTable *locales;
- GHashTable *locales_by_language;
- gboolean showing_extra;
- gchar **filter_words;
-} CcInputChooserPrivate;
-
-#define GET_PRIVATE(chooser) ((CcInputChooserPrivate *) g_object_get_data (G_OBJECT (chooser), "private"))
-#define WID(name) ((GtkWidget *) gtk_builder_get_object (builder, name))
+ GtkWidget *box;
+ GtkWidget *label;
+ GtkWidget *checkmark;
-typedef struct {
- gchar *id;
- gchar *name;
- gchar *unaccented_name;
- gchar *untranslated_name;
- GtkWidget *default_input_source_widget;
- GtkWidget *locale_widget;
- GtkWidget *back_widget;
- GHashTable *layout_widgets_by_id;
- GHashTable *engine_widgets_by_id;
-} LocaleInfo;
+ gchar *id;
+ gchar *type;
+ gchar *name;
+ gboolean is_extra;
+} InputWidget;
-static void
-locale_info_free (gpointer data)
+static InputWidget *
+get_input_widget (GtkWidget *widget)
{
- LocaleInfo *info = data;
-
- g_free (info->id);
- g_free (info->name);
- g_free (info->unaccented_name);
- g_free (info->untranslated_name);
- g_object_unref (info->default_input_source_widget);
- g_object_unref (info->locale_widget);
- g_object_unref (info->back_widget);
- g_hash_table_destroy (info->layout_widgets_by_id);
- g_hash_table_destroy (info->engine_widgets_by_id);
- g_free (info);
+ return g_object_get_data (G_OBJECT (widget), "input-widget");
}
-static void
-set_row_widget_margins (GtkWidget *widget)
+static GtkWidget *
+padded_label_new (char *text)
{
- gtk_widget_set_margin_left (widget, 20);
- gtk_widget_set_margin_right (widget, 20);
- gtk_widget_set_margin_top (widget, 6);
- gtk_widget_set_margin_bottom (widget, 6);
+ GtkWidget *widget;
+ widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
+ gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_top (widget, 10);
+ gtk_widget_set_margin_bottom (widget, 10);
+ gtk_box_pack_start (GTK_BOX (widget), gtk_label_new (text), FALSE, FALSE, 0);
+ return widget;
}
-static GtkWidget *
-padded_label_new (const gchar *text,
- RowLabelPosition position,
- RowTravelDirection direction,
- gboolean dim_label)
+static void
+input_widget_free (gpointer data)
{
- GtkWidget *widget;
- GtkWidget *label;
- GtkWidget *arrow;
- gdouble alignment;
- gboolean rtl;
-
- rtl = (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL);
-
- if (position == ROW_LABEL_POSITION_START)
- alignment = 0.0;
- else if (position == ROW_LABEL_POSITION_CENTER)
- alignment = 0.5;
- else
- alignment = 1.0;
-
- widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-
- if (direction == ROW_TRAVEL_DIRECTION_BACKWARD)
- {
- arrow = gtk_image_new_from_icon_name (rtl ? ARROW_NEXT : ARROW_PREV,
- GTK_ICON_SIZE_MENU);
- gtk_box_pack_start (GTK_BOX (widget), arrow, FALSE, TRUE, 0);
- }
-
- label = gtk_label_new (text);
- gtk_misc_set_alignment (GTK_MISC (label), alignment, 0.5);
- set_row_widget_margins (label);
- gtk_box_pack_start (GTK_BOX (widget), label, TRUE, TRUE, 0);
- if (dim_label)
- gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");
-
- if (direction == ROW_TRAVEL_DIRECTION_FORWARD)
- {
- arrow = gtk_image_new_from_icon_name (rtl ? ARROW_PREV : ARROW_NEXT,
- GTK_ICON_SIZE_MENU);
- gtk_box_pack_start (GTK_BOX (widget), arrow, FALSE, TRUE, 0);
- }
-
- return widget;
+ InputWidget *widget = data;
+
+ g_free (widget->id);
+ g_free (widget->type);
+ g_free (widget->name);
+ g_free (widget);
}
-static GtkWidget *
-more_widget_new (void)
-{
- GtkWidget *widget;
- GtkWidget *arrow;
+static gboolean
+get_layout (CcInputChooser *chooser,
+ const gchar *type,
+ const gchar *id,
+ const gchar **layout,
+ const gchar **variant)
+{
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+
+ if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) {
+ gnome_xkb_info_get_layout_info (priv->xkb_info,
+ id, NULL, NULL,
+ layout, variant);
+ return TRUE;
+ }
+#ifdef HAVE_IBUS
+ if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) {
+ IBusEngineDesc *engine_desc = NULL;
- widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_set_tooltip_text (widget, _("More…"));
+ if (priv->ibus_engines)
+ engine_desc = g_hash_table_lookup (priv->ibus_engines, id);
- arrow = gtk_image_new_from_icon_name ("view-more-symbolic", GTK_ICON_SIZE_MENU);
- gtk_style_context_add_class (gtk_widget_get_style_context (arrow), "dim-label");
- set_row_widget_margins (arrow);
- gtk_misc_set_alignment (GTK_MISC (arrow), 0.5, 0.5);
- gtk_box_pack_start (GTK_BOX (widget), arrow, TRUE, TRUE, 0);
+ if (!engine_desc)
+ return FALSE;
- return widget;
+ *layout = ibus_engine_desc_get_layout (engine_desc);
+ *variant = "";
+ return TRUE;
+ }
+#endif
+ g_assert_not_reached ();
+ return FALSE;
}
-static GtkWidget *
-no_results_widget_new (void)
+static gboolean
+preview_cb (GtkLabel *label,
+ const gchar *uri,
+ CcInputChooser *chooser)
{
- return padded_label_new (_("No input sources found"), ROW_LABEL_POSITION_CENTER,
ROW_TRAVEL_DIRECTION_NONE, TRUE);
-}
+ GtkWidget *row;
+ InputWidget *widget;
+ const gchar *layout;
+ const gchar *variant;
+ gchar *commandline;
-static GtkWidget *
-back_widget_new (const gchar *text)
-{
- return padded_label_new (text, ROW_LABEL_POSITION_CENTER, ROW_TRAVEL_DIRECTION_BACKWARD, TRUE);
-}
+ row = gtk_widget_get_parent (GTK_WIDGET (label));
+ widget = get_input_widget (row);
-static GtkWidget *
-locale_widget_new (const gchar *text)
-{
- return padded_label_new (text, ROW_LABEL_POSITION_CENTER, ROW_TRAVEL_DIRECTION_NONE, FALSE);
-}
+ if (!get_layout (chooser, widget->type, widget->id, &layout, &variant))
+ return TRUE;
-static GtkWidget *
-locale_separator_widget_new (const gchar *text)
-{
- GtkWidget *widget;
-
- widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_box_pack_start (GTK_BOX (widget),
- gtk_separator_new (GTK_ORIENTATION_HORIZONTAL),
- FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (widget),
- padded_label_new (text, ROW_LABEL_POSITION_CENTER, ROW_TRAVEL_DIRECTION_NONE, TRUE),
- FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (widget),
- gtk_separator_new (GTK_ORIENTATION_HORIZONTAL),
- FALSE, FALSE, 0);
- return widget;
+ if (variant[0])
+ commandline = g_strdup_printf ("gkbd-keyboard-display -l \"%s\t%s\"", layout, variant);
+ else
+ commandline = g_strdup_printf ("gkbd-keyboard-display -l %s", layout);
+ g_spawn_command_line_async (commandline, NULL);
+ g_free (commandline);
+
+ return TRUE;
}
static GtkWidget *
-input_source_widget_new (GtkWidget *chooser,
- const gchar *type,
- const gchar *id)
-{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- GtkWidget *widget = NULL;
-
- if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
- {
- const gchar *display_name;
-
- gnome_xkb_info_get_layout_info (priv->xkb_info, id, &display_name, NULL, NULL, NULL);
-
- widget = padded_label_new (display_name,
- ROW_LABEL_POSITION_START,
- ROW_TRAVEL_DIRECTION_NONE,
- FALSE);
- g_object_set_data (G_OBJECT (widget), "name", (gpointer) display_name);
- g_object_set_data_full (G_OBJECT (widget), "unaccented-name",
- cc_util_normalize_casefold_and_unaccent (display_name), g_free);
- }
- else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
- {
+input_widget_new (CcInputChooser *chooser,
+ const char *type,
+ const char *id,
+ gboolean is_extra)
+{
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ GtkWidget *label;
+ InputWidget *widget = g_new0 (InputWidget, 1);
+ const gchar *name;
+ gchar *text;
+
+ if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) {
+ gnome_xkb_info_get_layout_info (priv->xkb_info, id, &name, NULL, NULL, NULL);
+ }
#ifdef HAVE_IBUS
- gchar *display_name;
- GtkWidget *image;
-
- display_name = engine_get_display_name (g_hash_table_lookup (priv->ibus_engines, id));
-
- widget = padded_label_new (display_name,
- ROW_LABEL_POSITION_START,
- ROW_TRAVEL_DIRECTION_NONE,
- FALSE);
- image = gtk_image_new_from_icon_name ("system-run-symbolic", GTK_ICON_SIZE_MENU);
- set_row_widget_margins (image);
- gtk_style_context_add_class (gtk_widget_get_style_context (image), "dim-label");
- gtk_box_pack_start (GTK_BOX (widget), image, FALSE, TRUE, 0);
-
- g_object_set_data_full (G_OBJECT (widget), "name", display_name, g_free);
- g_object_set_data_full (G_OBJECT (widget), "unaccented-name",
- cc_util_normalize_casefold_and_unaccent (display_name), g_free);
-#else
- widget = NULL;
-#endif /* HAVE_IBUS */
- }
-
- if (widget)
- {
- g_object_set_data (G_OBJECT (widget), "type", (gpointer) type);
- g_object_set_data (G_OBJECT (widget), "id", (gpointer) id);
- }
-
- return widget;
+ else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) {
+ if (priv->ibus_engines)
+ name = engine_get_display_name (g_hash_table_lookup (priv->ibus_engines, id));
+ else
+ name = id;
+ }
+#endif
+ else {
+ name = "ERROR";
+ }
+
+ widget->id = g_strdup (id);
+ widget->type = g_strdup (type);
+ widget->name = g_strdup (name);
+ widget->is_extra = is_extra;
+
+ widget->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
+ gtk_widget_set_halign (widget->box, GTK_ALIGN_FILL);
+ gtk_widget_set_margin_top (widget->box, 10);
+ gtk_widget_set_margin_bottom (widget->box, 10);
+ gtk_widget_set_margin_start (widget->box, 10);
+ gtk_widget_set_margin_end (widget->box, 10);
+ widget->label = gtk_label_new (name);
+ gtk_misc_set_alignment (GTK_MISC (widget->label), 0, 0.5);
+ gtk_label_set_ellipsize (GTK_LABEL (widget->label), PANGO_ELLIPSIZE_END);
+ gtk_label_set_max_width_chars (GTK_LABEL (widget->label), 40);
+ gtk_label_set_width_chars (GTK_LABEL (widget->label), 40);
+ gtk_box_pack_start (GTK_BOX (widget->box), widget->label, FALSE, FALSE, 0);
+ widget->checkmark = gtk_image_new_from_icon_name ("object-select-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_box_pack_start (GTK_BOX (widget->box), widget->checkmark, TRUE, TRUE, 0);
+ gtk_widget_set_margin_start (widget->checkmark, 10);
+ gtk_widget_set_margin_end (widget->checkmark, 10);
+ gtk_widget_set_halign (widget->box, GTK_ALIGN_START);
+
+ text = g_strdup_printf ("<a href='preview'>%s</a>", _("Preview"));
+ label = gtk_label_new ("");
+ gtk_label_set_markup (GTK_LABEL (label), text);
+ g_free (text);
+ g_signal_connect (label, "activate-link",
+ G_CALLBACK (preview_cb), chooser);
+ gtk_box_pack_start (GTK_BOX (widget->box), label, TRUE, TRUE, 0);
+
+ gtk_widget_show_all (widget->box);
+
+ g_object_set_data_full (G_OBJECT (widget->box), "input-widget", widget,
+ input_widget_free);
+
+ return widget->box;
}
static void
-remove_all_children (GtkContainer *container)
+sync_checkmark (GtkWidget *row,
+ gpointer user_data)
{
- GList *list, *l;
+ CcInputChooser *chooser = user_data;
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ GtkWidget *child;
+ InputWidget *widget;
+ gboolean should_be_visible;
- list = gtk_container_get_children (container);
- for (l = list; l; l = l->next)
- gtk_container_remove (container, (GtkWidget *) l->data);
- g_list_free (list);
-}
+ child = gtk_bin_get_child (GTK_BIN (row));
+ widget = get_input_widget (child);
-static void
-set_fixed_size (GtkWidget *chooser)
-{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- GtkPolicyType policy;
- gint width, height;
-
- gtk_scrolled_window_get_policy (GTK_SCROLLED_WINDOW (priv->scrolledwindow), &policy, NULL);
- if (policy == GTK_POLICY_AUTOMATIC)
- return;
-
- /* Don't let it automatically get wider than the main GIS window nor
- get taller than the initial height */
- gtk_window_get_size (gtk_window_get_transient_for (GTK_WINDOW (chooser)),
- &width, NULL);
- gtk_window_get_size (GTK_WINDOW (chooser), NULL, &height);
- gtk_widget_set_size_request (chooser, width * MAIN_WINDOW_WIDTH_RATIO, height);
-
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolledwindow),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_AUTOMATIC);
-}
+ if (widget == NULL)
+ return;
-static void
-update_separator (GtkWidget **separator,
- GtkWidget *child,
- GtkWidget *before,
- gpointer user_data)
-{
- if (*separator && !GTK_IS_SEPARATOR (*separator))
- {
- gtk_widget_destroy (*separator);
- *separator = NULL;
- }
-
- if (*separator == NULL)
- {
- *separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
- g_object_ref_sink (*separator);
- gtk_widget_show (*separator);
- }
+ if (priv->id == NULL || priv->type == NULL)
+ should_be_visible = FALSE;
+ else
+ should_be_visible = g_str_equal (widget->id, priv->id) && g_str_equal (widget->type,
priv->type);
+ gtk_widget_set_opacity (widget->checkmark, should_be_visible ? 1.0 : 0.0);
}
static void
-add_input_source_widgets_for_locale (GtkWidget *chooser,
- LocaleInfo *info)
+sync_all_checkmarks (CcInputChooser *chooser)
{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- GtkWidget *widget;
- GHashTableIter iter;
- const gchar *id;
-
- if (info->default_input_source_widget)
- gtk_container_add (GTK_CONTAINER (priv->list), info->default_input_source_widget);
-
- g_hash_table_iter_init (&iter, info->layout_widgets_by_id);
- while (g_hash_table_iter_next (&iter, (gpointer *) &id, (gpointer *) &widget))
- gtk_container_add (GTK_CONTAINER (priv->list), widget);
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
- g_hash_table_iter_init (&iter, info->engine_widgets_by_id);
- while (g_hash_table_iter_next (&iter, (gpointer *) &id, (gpointer *) &widget))
- gtk_container_add (GTK_CONTAINER (priv->list), widget);
+ gtk_container_foreach (GTK_CONTAINER (priv->input_list),
+ sync_checkmark, chooser);
}
-static void
-show_input_sources_for_locale (GtkWidget *chooser,
- LocaleInfo *info)
+static GtkWidget *
+more_widget_new (void)
{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+ GtkWidget *widget;
+ GtkWidget *arrow;
- set_fixed_size (chooser);
+ widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
+ gtk_widget_set_tooltip_text (widget, _("More…"));
- remove_all_children (GTK_CONTAINER (priv->list));
+ arrow = gtk_image_new_from_icon_name ("view-more-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_style_context_add_class (gtk_widget_get_style_context (arrow), "dim-label");
+ gtk_widget_set_margin_top (widget, 10);
+ gtk_widget_set_margin_bottom (widget, 10);
+ gtk_misc_set_alignment (GTK_MISC (arrow), 0.5, 0.5);
+ gtk_box_pack_start (GTK_BOX (widget), arrow, TRUE, TRUE, 0);
+ gtk_widget_show_all (widget);
- if (!info->back_widget)
- {
- info->back_widget = g_object_ref_sink (back_widget_new (info->name));
- g_object_set_data (G_OBJECT (info->back_widget), "back", GINT_TO_POINTER (TRUE));
- g_object_set_data (G_OBJECT (info->back_widget), "locale-info", info);
- }
- gtk_container_add (GTK_CONTAINER (priv->list), info->back_widget);
-
- add_input_source_widgets_for_locale (chooser, info);
+ return widget;
+}
- gtk_widget_show_all (priv->list);
+static GtkWidget *
+no_results_widget_new (void)
+{
+ GtkWidget *widget;
- gtk_adjustment_set_value (priv->adjustment,
- gtk_adjustment_get_lower (priv->adjustment));
- egg_list_box_set_separator_funcs (EGG_LIST_BOX (priv->list), update_separator, NULL, NULL);
- egg_list_box_refilter (EGG_LIST_BOX (priv->list));
- egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->list), GTK_SELECTION_SINGLE);
+ /* Translators: a search for input methods or keyboard layouts
+ * did not yield any results
+ */
+ widget = padded_label_new (_("No inputs found"));
+ gtk_widget_set_sensitive (widget, FALSE);
+ gtk_widget_show_all (widget);
+ return widget;
+}
- if (gtk_widget_is_visible (priv->filter_entry))
- gtk_widget_grab_focus (priv->filter_entry);
+static void
+add_rows_to_list (CcInputChooser *chooser,
+ GList *list,
+ const gchar *type,
+ const gchar *default_id)
+{
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ const gchar *id;
+ GtkWidget *widget;
+ gboolean is_extra;
+ gchar *key;
+
+ for (; list; list = list->next) {
+ id = (const gchar *) list->data;
+
+ if (g_strcmp0 (id, default_id) == 0)
+ continue;
+
+ key = g_strdup_printf ("%s::%s", type, id);
+ if (g_hash_table_contains (priv->inputs, key)) {
+ g_free (key);
+ continue;
+ }
+ g_hash_table_add (priv->inputs, key);
+
+ if (g_hash_table_size (priv->inputs) > MIN_ROWS)
+ is_extra = TRUE;
+ else
+ is_extra = FALSE;
+ widget = input_widget_new (chooser, type, id, is_extra);
+ gtk_container_add (GTK_CONTAINER (priv->input_list), widget);
+ }
}
-static gboolean
-is_current_locale (const gchar *locale)
+static void
+add_row_to_list (CcInputChooser *chooser,
+ const gchar *type,
+ const gchar *id)
{
- return g_strcmp0 (setlocale (LC_CTYPE, NULL), locale) == 0;
+ GList tmp = { 0 };
+ tmp.data = (gpointer)id;
+ add_rows_to_list (chooser, &tmp, type, NULL);
}
static void
-show_locale_widgets (GtkWidget *chooser)
+get_locale_infos (CcInputChooser *chooser)
{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- GHashTable *initial = NULL;
- LocaleInfo *info;
- GHashTableIter iter;
-
- remove_all_children (GTK_CONTAINER (priv->list));
-
- if (!priv->showing_extra)
- initial = cc_common_language_get_initial_languages ();
-
- g_hash_table_iter_init (&iter, priv->locales);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info))
- {
- if (!info->default_input_source_widget &&
- !g_hash_table_size (info->layout_widgets_by_id) &&
- !g_hash_table_size (info->engine_widgets_by_id))
- continue;
-
- if (!info->locale_widget)
- {
- info->locale_widget = g_object_ref_sink (locale_widget_new (info->name));
- g_object_set_data (G_OBJECT (info->locale_widget), "locale-info", info);
-
- if (!priv->showing_extra &&
- !g_hash_table_contains (initial, info->id) &&
- !is_current_locale (info->id))
- g_object_set_data (G_OBJECT (info->locale_widget), "is-extra", GINT_TO_POINTER (TRUE));
- }
- gtk_container_add (GTK_CONTAINER (priv->list), info->locale_widget);
- }
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ const gchar *type, *id;
+ gchar *lang, *country;
+ GList *list;
- gtk_container_add (GTK_CONTAINER (priv->list), priv->more_item);
+ if (gnome_get_input_source_from_locale (priv->locale, &type, &id)) {
+ add_row_to_list (chooser, type, id);
+ if (!priv->id) {
+ priv->id = g_strdup (id);
+ priv->type = g_strdup (type);
+ }
+ }
- gtk_widget_show_all (priv->list);
+ if (!gnome_parse_locale (priv->locale, &lang, &country, NULL, NULL))
+ goto out;
- gtk_adjustment_set_value (priv->adjustment,
- gtk_adjustment_get_lower (priv->adjustment));
- egg_list_box_set_separator_funcs (EGG_LIST_BOX (priv->list), update_separator, NULL, NULL);
- egg_list_box_refilter (EGG_LIST_BOX (priv->list));
- egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->list), GTK_SELECTION_NONE);
+ list = gnome_xkb_info_get_layouts_for_language (priv->xkb_info, lang);
+ add_rows_to_list (chooser, list, INPUT_SOURCE_TYPE_XKB, id);
+ g_list_free (list);
- if (gtk_widget_is_visible (priv->filter_entry))
- gtk_widget_grab_focus (priv->filter_entry);
+ list = gnome_xkb_info_get_layouts_for_country (priv->xkb_info, country);
+ add_rows_to_list (chooser, list, INPUT_SOURCE_TYPE_XKB, id);
+ g_list_free (list);
- if (!priv->showing_extra)
- g_hash_table_destroy (initial);
+ list = gnome_xkb_info_get_all_layouts (priv->xkb_info);
+ add_rows_to_list (chooser, list, INPUT_SOURCE_TYPE_XKB, id);
+ g_list_free (list);
- return;
-}
+ gtk_widget_show_all (priv->input_list);
-static gint
-list_sort (GtkWidget *a,
- GtkWidget *b,
- gpointer data)
-{
- GtkWidget *chooser = data;
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- LocaleInfo *ia;
- LocaleInfo *ib;
- const gchar *la;
- const gchar *lb;
- gint retval;
-
- /* Always goes at the start */
- if (a == priv->no_results)
- return -1;
- if (b == priv->no_results)
- return 1;
-
- /* Always goes at the end */
- if (a == priv->more_item)
- return 1;
- if (b == priv->more_item)
- return -1;
-
- ia = g_object_get_data (G_OBJECT (a), "locale-info");
- ib = g_object_get_data (G_OBJECT (b), "locale-info");
-
- /* The "Other" locale always goes at the end */
- if (!ia->id[0] && ib->id[0])
- return 1;
- else if (ia->id[0] && !ib->id[0])
- return -1;
-
- retval = g_strcmp0 (ia->name, ib->name);
- if (retval)
- return retval;
-
- la = g_object_get_data (G_OBJECT (a), "name");
- lb = g_object_get_data (G_OBJECT (b), "name");
-
- /* Only input sources have a "name" property and they should always
- go after their respective heading */
- if (la && !lb)
- return 1;
- else if (!la && lb)
- return -1;
- else if (!la && !lb)
- return 0; /* Shouldn't happen */
-
- /* The default input source always goes first in its group */
- if (g_object_get_data (G_OBJECT (a), "default"))
- return -1;
- if (g_object_get_data (G_OBJECT (b), "default"))
- return 1;
-
- return g_strcmp0 (la, lb);
+out:
+ g_free (lang);
+ g_free (country);
}
static gboolean
-match_all (gchar **words,
- const gchar *str)
+input_visible (GtkListBoxRow *row,
+ gpointer user_data)
{
- gchar **w;
+ CcInputChooser *chooser = user_data;
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ InputWidget *widget;
+ gboolean visible;
+ GtkWidget *child;
+ const char *search_term;
- for (w = words; *w; ++w)
- if (!strstr (str, *w))
- return FALSE;
-
- return TRUE;
-}
+ child = gtk_bin_get_child (GTK_BIN (row));
+ if (child == priv->more_item)
+ return !priv->showing_extra && g_hash_table_size (priv->inputs) > MIN_ROWS;
-static gboolean
-list_filter (GtkWidget *child,
- gpointer user_data)
-{
- GtkDialog *chooser = user_data;
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- LocaleInfo *info;
- gboolean is_extra;
- const gchar *source_name;
+ widget = get_input_widget (child);
- if (child == priv->more_item)
- return !priv->showing_extra;
+ if (!priv->showing_extra && widget->is_extra)
+ return FALSE;
- /* We hide this in the after-refilter handler below. */
- if (child == priv->no_results)
- return TRUE;
+ search_term = gtk_entry_get_text (GTK_ENTRY (priv->filter_entry));
+ if (!search_term || !*search_term)
+ return TRUE;
- is_extra = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (child), "is-extra"));
+ visible = g_str_match_string (search_term, widget->name, TRUE);
+ return visible;
+}
- if (!priv->showing_extra && is_extra)
- return FALSE;
+static gint
+sort_inputs (GtkListBoxRow *a,
+ GtkListBoxRow *b,
+ gpointer data)
+{
+ InputWidget *la, *lb;
- if (!priv->filter_words)
- return TRUE;
+ la = get_input_widget (gtk_bin_get_child (GTK_BIN (a)));
+ lb = get_input_widget (gtk_bin_get_child (GTK_BIN (b)));
- info = g_object_get_data (G_OBJECT (child), "locale-info");
+ if (la == NULL)
+ return 1;
- if (match_all (priv->filter_words, info->unaccented_name))
- return TRUE;
+ if (lb == NULL)
+ return -1;
- if (match_all (priv->filter_words, info->untranslated_name))
- return TRUE;
+ if (la->is_extra && !lb->is_extra)
+ return 1;
- source_name = g_object_get_data (G_OBJECT (child), "unaccented-name");
- if (source_name && match_all (priv->filter_words, source_name))
- return TRUE;
+ if (!la->is_extra && lb->is_extra)
+ return -1;
- return FALSE;
+ return strcmp (la->name, lb->name);
}
static void
-update_separator_filter (GtkWidget **separator,
- GtkWidget *child,
- GtkWidget *before,
- gpointer user_data)
+filter_changed (GtkEntry *entry,
+ CcInputChooser *chooser)
{
- LocaleInfo *child_info = NULL;
- LocaleInfo *before_info = NULL;
-
- if (child)
- child_info = g_object_get_data (G_OBJECT (child), "locale-info");
-
- if (before)
- before_info = g_object_get_data (G_OBJECT (before), "locale-info");
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ gtk_list_box_invalidate_filter (GTK_LIST_BOX (priv->input_list));
+}
- if (!child_info || !before_info)
- return;
+static void
+show_more (CcInputChooser *chooser)
+{
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
- if (child_info == before_info)
- {
- /* Create a regular separator if we don't have one */
- if (*separator && !GTK_IS_SEPARATOR (*separator))
- {
- gtk_widget_destroy (*separator);
- *separator = NULL;
- }
+ if (g_hash_table_size (priv->inputs) <= MIN_ROWS)
+ return;
- if (*separator == NULL)
- *separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
- }
- else
- {
- /* Create a locale heading separator if we don't have one */
- if (*separator && GTK_IS_SEPARATOR (*separator))
- {
- gtk_widget_destroy (*separator);
- *separator = NULL;
- }
+ gtk_widget_show (priv->filter_entry);
+ gtk_widget_grab_focus (priv->filter_entry);
- if (*separator == NULL)
- *separator = locale_separator_widget_new (child_info->name);
- }
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scrolled_window),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+ gtk_widget_set_valign (GTK_WIDGET (chooser), GTK_ALIGN_FILL);
- g_object_ref_sink (*separator);
- gtk_widget_show_all (*separator);
+ priv->showing_extra = TRUE;
+ gtk_list_box_invalidate_filter (GTK_LIST_BOX (priv->input_list));
+ g_object_notify_by_pspec (G_OBJECT (chooser), obj_props[PROP_SHOWING_EXTRA]);
}
static void
-show_filter_widgets (GtkWidget *chooser)
+set_input (CcInputChooser *chooser,
+ const gchar *id,
+ const gchar *type)
{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- LocaleInfo *info;
- GHashTableIter iter;
-
- remove_all_children (GTK_CONTAINER (priv->list));
-
- gtk_container_add (GTK_CONTAINER (priv->list), priv->no_results);
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
- g_hash_table_iter_init (&iter, priv->locales);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info))
- add_input_source_widgets_for_locale (chooser, info);
+ if (g_strcmp0 (priv->id, id) == 0 &&
+ g_strcmp0 (priv->type, type) == 0)
+ return;
- gtk_widget_show_all (priv->list);
+ g_free (priv->id);
+ g_free (priv->type);
+ priv->id = g_strdup (id);
+ priv->type = g_strdup (type);
- gtk_adjustment_set_value (priv->adjustment,
- gtk_adjustment_get_lower (priv->adjustment));
- egg_list_box_set_separator_funcs (EGG_LIST_BOX (priv->list),
- update_separator_filter, NULL, NULL);
- egg_list_box_refilter (EGG_LIST_BOX (priv->list));
- egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->list), GTK_SELECTION_SINGLE);
+ sync_all_checkmarks (chooser);
- if (gtk_widget_is_visible (priv->filter_entry))
- gtk_widget_grab_focus (priv->filter_entry);
+ g_signal_emit (chooser, signals[CHANGED], 0);
}
static gboolean
-strvs_differ (gchar **av,
- gchar **bv)
+confirm_choice (gpointer data)
{
- gchar **a, **b;
+ GtkWidget *widget = data;
- for (a = av, b = bv; *a && *b; ++a, ++b)
- if (!g_str_equal (*a, *b))
- return TRUE;
+ g_signal_emit (widget, signals[CONFIRM], 0);
- if (*a == NULL && *b == NULL)
- return FALSE;
+ return G_SOURCE_REMOVE;
+}
- return TRUE;
+static void
+row_activated (GtkListBox *box,
+ GtkListBoxRow *row,
+ CcInputChooser *chooser)
+{
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ GtkWidget *child;
+ InputWidget *widget;
+
+ if (row == NULL)
+ return;
+
+ child = gtk_bin_get_child (GTK_BIN (row));
+ if (child == priv->more_item) {
+ show_more (chooser);
+ } else {
+ widget = get_input_widget (child);
+ if (widget == NULL)
+ return;
+ if (g_strcmp0 (priv->id, widget->id) == 0 &&
+ g_strcmp0 (priv->type, widget->type) == 0)
+ confirm_choice (chooser);
+ else
+ set_input (chooser, widget->id, widget->type);
+ }
}
static void
-filter_changed (GtkWidget *chooser)
+update_header_func (GtkListBoxRow *child,
+ GtkListBoxRow *before,
+ gpointer user_data)
{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- gboolean was_filtering;
- gchar **previous_words;
- gchar *filter_contents = NULL;
-
- previous_words = priv->filter_words;
- was_filtering = previous_words != NULL;
-
- filter_contents =
- cc_util_normalize_casefold_and_unaccent (gtk_entry_get_text (GTK_ENTRY (priv->filter_entry)));
-
- if (filter_contents)
- {
- priv->filter_words = g_strsplit_set (g_strstrip (filter_contents), " ", 0);
- g_free (filter_contents);
- }
-
- if (!priv->filter_words || !priv->filter_words[0])
- {
- g_clear_pointer (&priv->filter_words, g_strfreev);
- if (was_filtering)
- show_locale_widgets (chooser);
- }
- else
- {
- if (!was_filtering)
- show_filter_widgets (chooser);
- else if (strvs_differ (priv->filter_words, previous_words))
- egg_list_box_refilter (EGG_LIST_BOX (priv->list));
- }
-
- g_strfreev (previous_words);
-}
+ GtkWidget *header;
-typedef struct {
- gint count;
- GtkWidget *ignore;
-} CountChildrenData;
+ if (before == NULL)
+ return;
+
+ header = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+ gtk_list_box_row_set_header (child, header);
+ gtk_widget_show (header);
+}
+#ifdef HAVE_IBUS
static void
-count_visible_children (GtkWidget *widget,
- gpointer user_data)
-{
- CountChildrenData *data = user_data;
- if (widget != data->ignore &&
- gtk_widget_get_child_visible (widget) &&
- gtk_widget_get_visible (widget))
- data->count++;
+update_ibus_active_sources (CcInputChooser *chooser)
+{
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ GList *rows, *l;
+ InputWidget *row;
+ const gchar *type;
+ const gchar *id;
+ IBusEngineDesc *engine_desc;
+ gchar *name;
+
+ rows = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
+ for (l = rows; l; l = l->next) {
+ row = get_input_widget (gtk_bin_get_child (GTK_BIN (l->data)));
+ if (row == NULL)
+ continue;
+
+ type = row->type;
+ id = row->id;
+ if (g_strcmp0 (type, INPUT_SOURCE_TYPE_IBUS) != 0)
+ continue;
+
+ engine_desc = g_hash_table_lookup (priv->ibus_engines, id);
+ if (engine_desc) {
+ name = engine_get_display_name (engine_desc);
+ gtk_label_set_text (GTK_LABEL (row->label), name);
+ g_free (name);
+ }
+ }
+ g_list_free (rows);
}
static void
-end_refilter (EggListBox *list_box,
- gpointer user_data)
+get_ibus_locale_infos (CcInputChooser *chooser)
{
- GtkDialog *chooser = user_data;
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- CountChildrenData data = { 0 };
- gboolean visible;
-
- data.ignore = priv->no_results;
-
- gtk_container_foreach (GTK_CONTAINER (list_box),
- count_visible_children, &data);
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ GHashTableIter iter;
+ const gchar *engine_id;
+ IBusEngineDesc *engine;
- visible = (data.count == 0);
+ if (!priv->ibus_engines)
+ return;
- gtk_widget_set_visible (priv->no_results, visible);
- egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->list),
- visible ? GTK_SELECTION_NONE : GTK_SELECTION_SINGLE);
+ g_hash_table_iter_init (&iter, priv->ibus_engines);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &engine_id, (gpointer *) &engine))
+ add_row_to_list (chooser, INPUT_SOURCE_TYPE_IBUS, engine_id);
}
static void
-show_more (GtkWidget *chooser)
-{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+fetch_ibus_engines_result (GObject *object,
+ GAsyncResult *result,
+ CcInputChooser *chooser)
+{
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ GList *list, *l;
+ GError *error;
+
+ error = NULL;
+ list = ibus_bus_list_engines_async_finish (priv->ibus, result, &error);
+ g_clear_object (&priv->ibus_cancellable);
+ if (!list && error) {
+ g_warning ("Couldn't finish IBus request: %s", error->message);
+ g_error_free (error);
+ return;
+ }
- set_fixed_size (chooser);
+ /* Maps engine ids to engine description objects */
+ priv->ibus_engines = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
- gtk_widget_show (priv->filter_entry);
- gtk_widget_grab_focus (priv->filter_entry);
+ for (l = list; l; l = l->next) {
+ IBusEngineDesc *engine = l->data;
+ const gchar *engine_id;
- priv->showing_extra = TRUE;
+ engine_id = ibus_engine_desc_get_name (engine);
+ if (g_str_has_prefix (engine_id, "xkb:"))
+ g_object_unref (engine);
+ else
+ g_hash_table_replace (priv->ibus_engines, (gpointer)engine_id, engine);
+ }
+ g_list_free (list);
- egg_list_box_refilter (EGG_LIST_BOX (priv->list));
-}
+ update_ibus_active_sources (chooser);
+ get_ibus_locale_infos (chooser);
-static void
-child_activated (EggListBox *box,
- GtkWidget *child,
- GtkWidget *chooser)
-{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- gpointer data;
-
- if (!child)
- return;
-
- if (child == priv->more_item)
- {
- show_more (chooser);
- return;
- }
-
- data = g_object_get_data (G_OBJECT (child), "back");
- if (data)
- {
- show_locale_widgets (chooser);
- return;
- }
-
- data = g_object_get_data (G_OBJECT (child), "name");
- if (data)
- {
- /* It's an input source, we just want to select it */
- return;
- }
-
- data = g_object_get_data (G_OBJECT (child), "locale-info");
- if (data)
- {
- show_input_sources_for_locale (chooser, (LocaleInfo *) data);
- return;
- }
+ sync_all_checkmarks (chooser);
}
static void
-child_selected (EggListBox *box,
- GtkWidget *child,
- GtkWidget *chooser)
+fetch_ibus_engines (CcInputChooser *chooser)
{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
- gtk_widget_set_sensitive (priv->add_button, child != NULL);
-}
+ priv->ibus_cancellable = g_cancellable_new ();
-static void
-add_default_widget (GtkWidget *chooser,
- LocaleInfo *info,
- const gchar *type,
- const gchar *id)
-{
- info->default_input_source_widget = input_source_widget_new (chooser, type, id);
- if (info->default_input_source_widget)
- {
- g_object_ref_sink (info->default_input_source_widget);
- g_object_set_data (G_OBJECT (info->default_input_source_widget), "default", GINT_TO_POINTER (TRUE));
- g_object_set_data (G_OBJECT (info->default_input_source_widget), "locale-info", info);
- }
-}
+ ibus_bus_list_engines_async (priv->ibus,
+ -1,
+ priv->ibus_cancellable,
+ (GAsyncReadyCallback)fetch_ibus_engines_result,
+ chooser);
-static void
-add_widgets_to_table (GtkWidget *chooser,
- LocaleInfo *info,
- GList *list,
- const gchar *type,
- const gchar *default_id)
-{
- GHashTable *table;
- GtkWidget *widget;
- const gchar *id;
-
- if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
- table = info->layout_widgets_by_id;
- else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
- table = info->engine_widgets_by_id;
- else
- return;
-
- while (list)
- {
- id = (const gchar *) list->data;
-
- /* The widget for the default input source lives elsewhere */
- if (g_strcmp0 (id, default_id))
- {
- widget = input_source_widget_new (chooser, type, id);
- if (widget)
- {
- g_object_set_data (G_OBJECT (widget), "locale-info", info);
- g_hash_table_replace (table, (gpointer) id, g_object_ref_sink (widget));
- }
- }
- list = list->next;
- }
+ /* We've got everything we needed, don't want to be called again. */
+ g_signal_handlers_disconnect_by_func (priv->ibus, fetch_ibus_engines, chooser);
}
static void
-add_widget (GtkWidget *chooser,
- LocaleInfo *info,
- const gchar *type,
- const gchar *id)
-{
- GList tmp = { 0 };
- tmp.data = (gpointer) id;
- add_widgets_to_table (chooser, info, &tmp, type, NULL);
-}
+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
static void
-add_widget_other (GtkWidget *chooser,
- const gchar *type,
- const gchar *id)
+cc_input_chooser_constructed (GObject *object)
{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- LocaleInfo *info = g_hash_table_lookup (priv->locales, "");
- add_widget (chooser, info, type, id);
-}
+ CcInputChooser *chooser = CC_INPUT_CHOOSER (object);
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+
+ G_OBJECT_CLASS (cc_input_chooser_parent_class)->constructed (object);
+
+ priv->xkb_info = gnome_xkb_info_new ();
#ifdef HAVE_IBUS
-static gboolean
-maybe_set_as_default (GtkWidget *chooser,
- LocaleInfo *info,
- const gchar *engine_id)
-{
- const gchar *type, *id;
+ ibus_init ();
+ if (!priv->ibus) {
+ priv->ibus = ibus_bus_new_async ();
+ if (ibus_bus_is_connected (priv->ibus))
+ fetch_ibus_engines (chooser);
+ else
+ g_signal_connect_swapped (priv->ibus, "connected",
+ G_CALLBACK (fetch_ibus_engines), chooser);
+ }
+ maybe_start_ibus ();
+#endif
+
+ priv->inputs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ priv->more_item = more_widget_new ();
+ priv->no_results = no_results_widget_new ();
+
+ gtk_list_box_set_sort_func (GTK_LIST_BOX (priv->input_list),
+ sort_inputs, chooser, NULL);
+ gtk_list_box_set_filter_func (GTK_LIST_BOX (priv->input_list),
+ input_visible, chooser, NULL);
+ gtk_list_box_set_header_func (GTK_LIST_BOX (priv->input_list),
+ update_header_func, chooser, NULL);
+ gtk_list_box_set_selection_mode (GTK_LIST_BOX (priv->input_list),
+ GTK_SELECTION_NONE);
+
+ if (priv->locale == NULL) {
+ priv->locale = cc_common_language_get_current_language ();
+ }
+
+ get_locale_infos (chooser);
+#ifdef HAVE_IBUS
+ get_ibus_locale_infos (chooser);
+#endif
- if (!gnome_get_input_source_from_locale (info->id, &type, &id))
- return FALSE;
+ gtk_container_add (GTK_CONTAINER (priv->input_list), priv->more_item);
+ gtk_list_box_set_placeholder (GTK_LIST_BOX (priv->input_list), priv->no_results);
- if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS) &&
- g_str_equal (id, engine_id) &&
- info->default_input_source_widget == NULL)
- {
- add_default_widget (chooser, info, type, id);
- return TRUE;
- }
+ g_signal_connect (priv->filter_entry, "changed",
+ G_CALLBACK (filter_changed),
+ chooser);
- return FALSE;
+ g_signal_connect (priv->input_list, "row-activated",
+ G_CALLBACK (row_activated), chooser);
+
+ sync_all_checkmarks (chooser);
}
static void
-get_ibus_locale_infos (GtkWidget *chooser)
+cc_input_chooser_finalize (GObject *object)
{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- GHashTableIter iter;
- LocaleInfo *info;
- const gchar *engine_id;
- IBusEngineDesc *engine;
-
- if (!priv->ibus_engines)
- return;
-
- g_hash_table_iter_init (&iter, priv->ibus_engines);
- while (g_hash_table_iter_next (&iter, (gpointer *) &engine_id, (gpointer *) &engine))
- {
- gchar *lang_code = NULL;
- gchar *country_code = NULL;
- const gchar *ibus_locale = ibus_engine_desc_get_language (engine);
-
- if (gnome_parse_locale (ibus_locale, &lang_code, &country_code, NULL, NULL) &&
- lang_code != NULL &&
- country_code != NULL)
- {
- gchar *locale = g_strdup_printf ("%s_%s.utf8", lang_code, country_code);
-
- info = g_hash_table_lookup (priv->locales, locale);
- if (info)
- {
- const gchar *type, *id;
-
- if (gnome_get_input_source_from_locale (locale, &type, &id) &&
- g_str_equal (type, INPUT_SOURCE_TYPE_IBUS) &&
- g_str_equal (id, engine_id))
- {
- add_default_widget (chooser, info, type, id);
- }
- else
- {
- add_widget (chooser, info, INPUT_SOURCE_TYPE_IBUS, engine_id);
- }
- }
- else
- {
- add_widget_other (chooser, INPUT_SOURCE_TYPE_IBUS, engine_id);
- }
+ CcInputChooser *chooser = CC_INPUT_CHOOSER (object);
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
- g_free (locale);
- }
- else if (lang_code != NULL)
- {
- GHashTableIter iter;
- GHashTable *locales_for_language;
- gchar *language;
-
- /* Most IBus engines only specify the language so we try to
- add them to all locales for that language. */
-
- language = gnome_get_language_from_code (lang_code, NULL);
- if (language)
- locales_for_language = g_hash_table_lookup (priv->locales_by_language, language);
- else
- locales_for_language = NULL;
- g_free (language);
-
- if (locales_for_language)
- {
- g_hash_table_iter_init (&iter, locales_for_language);
- while (g_hash_table_iter_next (&iter, (gpointer *) &info, NULL))
- if (!maybe_set_as_default (chooser, info, engine_id))
- add_widget (chooser, info, INPUT_SOURCE_TYPE_IBUS, engine_id);
- }
- else
- {
- add_widget_other (chooser, INPUT_SOURCE_TYPE_IBUS, engine_id);
- }
- }
- else
- {
- add_widget_other (chooser, INPUT_SOURCE_TYPE_IBUS, engine_id);
- }
+ g_clear_object (&priv->xkb_info);
+ g_hash_table_unref (priv->inputs);
+#ifdef HAVE_IBUS
+ g_clear_object (&priv->ibus);
+ if (priv->ibus_cancellable)
+ g_cancellable_cancel (priv->ibus_cancellable);
+ g_clear_object (&priv->ibus_cancellable);
+ g_clear_pointer (&priv->ibus_engines, g_hash_table_destroy);
+#endif
+
+ G_OBJECT_CLASS (cc_input_chooser_parent_class)->finalize (object);
+}
- g_free (country_code);
- g_free (lang_code);
- }
+static void
+cc_input_chooser_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CcInputChooser *chooser = CC_INPUT_CHOOSER (object);
+ switch (prop_id) {
+ case PROP_SHOWING_EXTRA:
+ g_value_set_boolean (value, cc_input_chooser_get_showing_extra (chooser));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
-#endif /* HAVE_IBUS */
static void
-add_locale_to_table (GHashTable *table,
- const gchar *lang_code,
- LocaleInfo *info)
+cc_input_chooser_class_init (CcInputChooserClass *klass)
{
- GHashTable *set;
- gchar *language;
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
"/org/gnome/initial-setup/input-chooser.ui");
+
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), CcInputChooser,
filter_entry);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), CcInputChooser, input_list);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), CcInputChooser,
scrolled_window);
+
+ object_class->finalize = cc_input_chooser_finalize;
+ object_class->get_property = cc_input_chooser_get_property;
+ object_class->constructed = cc_input_chooser_constructed;
+
+ obj_props[PROP_SHOWING_EXTRA] =
+ g_param_spec_string ("showing-extra", "", "", "",
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- language = gnome_get_language_from_code (lang_code, NULL);
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
- set = g_hash_table_lookup (table, language);
- if (!set)
- {
- set = g_hash_table_new (NULL, NULL);
- g_hash_table_replace (table, g_strdup (language), set);
- }
- g_hash_table_add (set, info);
+ signals[CONFIRM] =
+ g_signal_new ("confirm",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
- g_free (language);
+ g_object_class_install_properties (object_class, PROP_LAST, obj_props);
}
static void
-add_ids_to_set (GHashTable *set,
- GList *list)
+cc_input_chooser_init (CcInputChooser *chooser)
{
- while (list)
- {
- g_hash_table_add (set, list->data);
- list = list->next;
- }
+ gtk_widget_init_template (GTK_WIDGET (chooser));
}
-static void
-get_locale_infos (GtkWidget *chooser)
+void
+cc_input_chooser_clear_filter (CcInputChooser *chooser)
{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- GHashTable *layouts_with_locale;
- LocaleInfo *info;
- gchar **locale_ids;
- gchar **locale;
- GList *list, *l;
-
- priv->locales = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, locale_info_free);
- priv->locales_by_language = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify) g_hash_table_destroy);
-
- layouts_with_locale = g_hash_table_new (g_str_hash, g_str_equal);
-
- locale_ids = gnome_get_all_locales ();
- for (locale = locale_ids; *locale; ++locale)
- {
- gchar *lang_code, *country_code;
- gchar *simple_locale;
- gchar *untranslated_locale;
- const gchar *type = NULL;
- const gchar *id = NULL;
-
- if (!gnome_parse_locale (*locale, &lang_code, &country_code, NULL, NULL))
- continue;
-
- simple_locale = g_strdup_printf ("%s_%s.utf8", lang_code, country_code);
- if (g_hash_table_contains (priv->locales, simple_locale))
- goto free_and_continue;
-
- /* We are not interested in locales whose name we can't display */
- untranslated_locale = gnome_get_language_from_locale (simple_locale, "C");
- if (!untranslated_locale)
- goto free_and_continue;
-
- info = g_new0 (LocaleInfo, 1);
- info->id = g_strdup (simple_locale);
- info->name = gnome_get_language_from_locale (simple_locale, NULL);
- info->unaccented_name = cc_util_normalize_casefold_and_unaccent (info->name);
- info->untranslated_name = cc_util_normalize_casefold_and_unaccent (untranslated_locale);
- g_free (untranslated_locale);
-
- g_hash_table_replace (priv->locales, simple_locale, info);
- add_locale_to_table (priv->locales_by_language, lang_code, info);
-
- if (gnome_get_input_source_from_locale (simple_locale, &type, &id) &&
- g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
- {
- add_default_widget (chooser, info, type, id);
- g_hash_table_add (layouts_with_locale, (gpointer) id);
- }
-
- /* We don't own these ids */
- info->layout_widgets_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, g_object_unref);
- info->engine_widgets_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, g_object_unref);
-
- list = gnome_xkb_info_get_layouts_for_language (priv->xkb_info, lang_code);
- add_widgets_to_table (chooser, info, list, INPUT_SOURCE_TYPE_XKB, id);
- add_ids_to_set (layouts_with_locale, list);
- g_list_free (list);
-
- list = gnome_xkb_info_get_layouts_for_country (priv->xkb_info, country_code);
- add_widgets_to_table (chooser, info, list, INPUT_SOURCE_TYPE_XKB, id);
- add_ids_to_set (layouts_with_locale, list);
- g_list_free (list);
-
- free_and_continue:
- g_free (lang_code);
- g_free (country_code);
- g_free (simple_locale);
- }
- g_strfreev (locale_ids);
-
- /* Add a "Other" locale to hold the remaining input sources */
- info = g_new0 (LocaleInfo, 1);
- info->id = g_strdup ("");
- info->name = g_strdup (_("Other"));
- info->unaccented_name = g_strdup ("");
- info->untranslated_name = g_strdup ("");
- g_hash_table_replace (priv->locales, info->id, info);
-
- info->layout_widgets_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, g_object_unref);
- info->engine_widgets_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, g_object_unref);
-
- list = gnome_xkb_info_get_all_layouts (priv->xkb_info);
- for (l = list; l; l = l->next)
- if (!g_hash_table_contains (layouts_with_locale, l->data))
- add_widget_other (chooser, INPUT_SOURCE_TYPE_XKB, l->data);
-
- g_list_free (list);
-
- g_hash_table_destroy (layouts_with_locale);
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ gtk_entry_set_text (GTK_ENTRY (priv->filter_entry), "");
}
-static void
-cc_input_chooser_private_free (gpointer data)
+const gchar *
+cc_input_chooser_get_input_id (CcInputChooser *chooser)
{
- CcInputChooserPrivate *priv = data;
-
- g_object_unref (priv->more_item);
- g_object_unref (priv->no_results);
- g_hash_table_destroy (priv->locales);
- g_hash_table_destroy (priv->locales_by_language);
- g_strfreev (priv->filter_words);
- g_free (priv);
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ return priv->id;
}
-GtkWidget *
-cc_input_chooser_new (GtkWindow *main_window,
- GnomeXkbInfo *xkb_info,
- GHashTable *ibus_engines)
+const gchar *
+cc_input_chooser_get_input_type (CcInputChooser *chooser)
{
- GtkBuilder *builder;
- GtkWidget *chooser;
- CcInputChooserPrivate *priv;
- gint width;
- GError *error = NULL;
-
- builder = gtk_builder_new ();
- if (gtk_builder_add_from_resource (builder, "/org/gnome/initial-setup/input-chooser.ui", &error) == 0)
- {
- g_object_unref (builder);
- g_warning ("failed to load input chooser: %s", error->message);
- g_error_free (error);
- return NULL;
- }
- chooser = WID ("input-dialog");
- priv = g_new0 (CcInputChooserPrivate, 1);
- g_object_set_data_full (G_OBJECT (chooser), "private", priv, cc_input_chooser_private_free);
- g_object_set_data_full (G_OBJECT (chooser), "builder", builder, g_object_unref);
-
- priv->xkb_info = xkb_info;
- priv->ibus_engines = ibus_engines;
-
- priv->add_button = WID ("add-button");
- priv->filter_entry = WID ("filter-entry");
- priv->list = WID ("list");
- priv->scrolledwindow = WID ("scrolledwindow");
- priv->adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
-
- priv->more_item = g_object_ref_sink (more_widget_new ());
- priv->no_results = g_object_ref_sink (no_results_widget_new ());
-
- egg_list_box_set_adjustment (EGG_LIST_BOX (priv->list), priv->adjustment);
- egg_list_box_set_filter_func (EGG_LIST_BOX (priv->list), list_filter, chooser, NULL);
- egg_list_box_set_sort_func (EGG_LIST_BOX (priv->list), list_sort, chooser, NULL);
- g_signal_connect (priv->list, "child-activated", G_CALLBACK (child_activated), chooser);
- g_signal_connect (priv->list, "child-selected", G_CALLBACK (child_selected), chooser);
- g_signal_connect_after (priv->list, "refilter", G_CALLBACK (end_refilter), chooser);
-
- g_signal_connect_swapped (priv->filter_entry, "changed", G_CALLBACK (filter_changed), chooser);
-
- get_locale_infos (chooser);
-#ifdef HAVE_IBUS
- get_ibus_locale_infos (chooser);
-#endif /* HAVE_IBUS */
- show_locale_widgets (chooser);
-
- /* Try to come up with a sensible width */
- gtk_window_get_size (main_window, &width, NULL);
- gtk_widget_set_size_request (chooser, width * MAIN_WINDOW_WIDTH_RATIO, -1);
- gtk_window_set_resizable (GTK_WINDOW (chooser), TRUE);
-
- gtk_window_set_transient_for (GTK_WINDOW (chooser), main_window);
-
- return chooser;
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ return priv->type;
}
void
-cc_input_chooser_set_ibus_engines (GtkWidget *chooser,
- GHashTable *ibus_engines)
+cc_input_chooser_get_layout (CcInputChooser *chooser,
+ const gchar **layout,
+ const gchar **variant)
{
-#ifdef HAVE_IBUS
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
- /* This should only be called once when IBus shows up in case it
- wasn't up yet when the user opened the input chooser dialog. */
- g_return_if_fail (priv->ibus_engines == NULL);
+ get_layout (chooser, priv->type, priv->id, layout, variant);
+}
- priv->ibus_engines = ibus_engines;
- get_ibus_locale_infos (chooser);
- show_locale_widgets (chooser);
-#endif /* HAVE_IBUS */
+void
+cc_input_chooser_set_input (CcInputChooser *chooser,
+ const gchar *id,
+ const gchar *type)
+{
+ set_input (chooser, id, type);
}
gboolean
-cc_input_chooser_get_selected (GtkWidget *chooser,
- gchar **type,
- gchar **id,
- gchar **name)
+cc_input_chooser_get_showing_extra (CcInputChooser *chooser)
{
- CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
- GtkWidget *selected;
- const gchar *t, *i, *n;
-
- selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->list));
- if (!selected)
- return FALSE;
-
- t = g_object_get_data (G_OBJECT (selected), "type");
- i = g_object_get_data (G_OBJECT (selected), "id");
- n = g_object_get_data (G_OBJECT (selected), "name");
-
- if (!t || !i || !n)
- return FALSE;
-
- *type = g_strdup (t);
- *id = g_strdup (i);
- *name = g_strdup (n);
-
- return TRUE;
+ CcInputChooserPrivate *priv = cc_input_chooser_get_instance_private (chooser);
+ return priv->showing_extra;
}
diff --git a/gnome-initial-setup/pages/keyboard/cc-input-chooser.h
b/gnome-initial-setup/pages/keyboard/cc-input-chooser.h
index a9edc65..dfd6a28 100644
--- a/gnome-initial-setup/pages/keyboard/cc-input-chooser.h
+++ b/gnome-initial-setup/pages/keyboard/cc-input-chooser.h
@@ -12,31 +12,53 @@
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Jasper St. Pierre <jstpierre mecheye net>
+ * Matthias Clasen <mclasen redhat com>
*/
#ifndef __GIS_INPUT_CHOOSER_H__
#define __GIS_INPUT_CHOOSER_H__
#include <gtk/gtk.h>
+#include <glib-object.h>
-#define GNOME_DESKTOP_USE_UNSTABLE_API
-#include <libgnome-desktop/gnome-xkb-info.h>
-
+#define CC_TYPE_INPUT_CHOOSER (cc_input_chooser_get_type ())
+#define CC_INPUT_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CC_TYPE_INPUT_CHOOSER,
CcInputChooser))
+#define CC_INPUT_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CC_TYPE_INPUT_CHOOSER,
CcInputChooserClass))
+#define CC_IS_INPUT_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CC_TYPE_INPUT_CHOOSER))
+#define CC_IS_INPUT_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CC_TYPE_INPUT_CHOOSER))
+#define CC_INPUT_CHOOSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CC_TYPE_INPUT_CHOOSER,
CcInputChooserClass))
G_BEGIN_DECLS
-GtkWidget *cc_input_chooser_new (GtkWindow *parent,
- GnomeXkbInfo *xkb_info,
- GHashTable *ibus_engines);
-void cc_input_chooser_set_ibus_engines (GtkWidget *chooser,
- GHashTable *ibus_engines);
-gboolean cc_input_chooser_get_selected (GtkWidget *chooser,
- gchar **type,
- gchar **id,
- gchar **name);
+typedef struct _CcInputChooser CcInputChooser;
+typedef struct _CcInputChooserClass CcInputChooserClass;
+
+struct _CcInputChooser
+{
+ GtkBox parent;
+};
+
+struct _CcInputChooserClass
+{
+ GtkBoxClass parent_class;
+};
+
+GType cc_input_chooser_get_type (void);
+
+void cc_input_chooser_clear_filter (CcInputChooser *chooser);
+const gchar * cc_input_chooser_get_input_id (CcInputChooser *chooser);
+const gchar * cc_input_chooser_get_input_type (CcInputChooser *chooser);
+void cc_input_chooser_set_input (CcInputChooser *chooser,
+ const gchar *id,
+ const gchar *type);
+void cc_input_chooser_get_layout (CcInputChooser *chooser,
+ const gchar **layout,
+ const gchar **variant);
+gboolean cc_input_chooser_get_showing_extra (CcInputChooser *chooser);
G_END_DECLS
diff --git a/gnome-initial-setup/pages/keyboard/cc-util.c b/gnome-initial-setup/pages/keyboard/cc-util.c
new file mode 100644
index 0000000..e51a9d2
--- /dev/null
+++ b/gnome-initial-setup/pages/keyboard/cc-util.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012 Giovanni Campagna <scampa giovanni gmail com>
+ *
+ * The Control Center is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * The Control Center is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with the Control Center; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+
+#include "cc-util.h"
+
+/* Combining diacritical mark?
+ * Basic range: [0x0300,0x036F]
+ * Supplement: [0x1DC0,0x1DFF]
+ * For Symbols: [0x20D0,0x20FF]
+ * Half marks: [0xFE20,0xFE2F]
+ */
+#define IS_CDM_UCS4(c) (((c) >= 0x0300 && (c) <= 0x036F) || \
+ ((c) >= 0x1DC0 && (c) <= 0x1DFF) || \
+ ((c) >= 0x20D0 && (c) <= 0x20FF) || \
+ ((c) >= 0xFE20 && (c) <= 0xFE2F))
+
+/* Copied from tracker/src/libtracker-fts/tracker-parser-glib.c under the GPL
+ * And then from gnome-shell/src/shell-util.c
+ *
+ * Originally written by Aleksander Morgado <aleksander gnu org>
+ */
+char *
+cc_util_normalize_casefold_and_unaccent (const char *str)
+{
+ char *normalized, *tmp;
+ int i = 0, j = 0, ilen;
+
+ if (str == NULL)
+ return NULL;
+
+ normalized = g_utf8_normalize (str, -1, G_NORMALIZE_NFKD);
+ tmp = g_utf8_casefold (normalized, -1);
+ g_free (normalized);
+
+ ilen = strlen (tmp);
+
+ while (i < ilen)
+ {
+ gunichar unichar;
+ gchar *next_utf8;
+ gint utf8_len;
+
+ /* Get next character of the word as UCS4 */
+ unichar = g_utf8_get_char_validated (&tmp[i], -1);
+
+ /* Invalid UTF-8 character or end of original string. */
+ if (unichar == (gunichar) -1 ||
+ unichar == (gunichar) -2)
+ {
+ break;
+ }
+
+ /* Find next UTF-8 character */
+ next_utf8 = g_utf8_next_char (&tmp[i]);
+ utf8_len = next_utf8 - &tmp[i];
+
+ if (IS_CDM_UCS4 ((guint32) unichar))
+ {
+ /* If the given unichar is a combining diacritical mark,
+ * just update the original index, not the output one */
+ i += utf8_len;
+ continue;
+ }
+
+ /* If already found a previous combining
+ * diacritical mark, indexes are different so
+ * need to copy characters. As output and input
+ * buffers may overlap, need to use memmove
+ * instead of memcpy */
+ if (i != j)
+ {
+ memmove (&tmp[j], &tmp[i], utf8_len);
+ }
+
+ /* Update both indexes */
+ i += utf8_len;
+ j += utf8_len;
+ }
+
+ /* Force proper string end */
+ tmp[j] = '\0';
+
+ return tmp;
+}
diff --git a/gnome-initial-setup/pages/keyboard/cc-util.h b/gnome-initial-setup/pages/keyboard/cc-util.h
new file mode 100644
index 0000000..42b09ff
--- /dev/null
+++ b/gnome-initial-setup/pages/keyboard/cc-util.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2012 Giovanni Campagna <scampa giovanni gmail com>
+ *
+ * The Control Center is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * The Control Center is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with the Control Center; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+
+#ifndef _CC_UTIL_H
+#define _CC_UTIL_H
+
+#include <glib.h>
+
+char *cc_util_normalize_casefold_and_unaccent (const char *str);
+
+#endif
diff --git a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
index f95619e..aa497b3 100644
--- a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
+++ b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
@@ -12,8 +12,7 @@
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Sergey Udaltsov <svu gnome org>
* Michael Wood <michael g wood intel com>
@@ -28,1184 +27,222 @@
#include <locale.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
-#include <gio/gdesktopappinfo.h>
#include <gtk/gtk.h>
#include <polkit/polkit.h>
#include "gis-keyboard-page.h"
#include "keyboard-resources.h"
#include "cc-input-chooser.h"
-#include "cc-keyboard-query.h"
-
-#define GNOME_DESKTOP_USE_UNSTABLE_API
-#include <libgnome-desktop/gnome-xkb-info.h>
-#include <libgnome-desktop/gnome-languages.h>
-
-#ifdef HAVE_IBUS
-#include <ibus.h>
-#include "cc-ibus-utils.h"
-#endif
-
-#include <act/act.h>
-#include <unistd.h>
-#include <egg-list-box.h>
#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"
-
-#define MAX_INPUT_ROWS_VISIBLE 5
-
struct _GisKeyboardPagePrivate {
- GDBusProxy *localed;
- GCancellable *cancellable;
-
- GtkWidget *input_section;
- GtkWidget *input_list;
- GtkWidget *add_input;
- GtkWidget *remove_input;
- GtkWidget *show_config;
- GtkWidget *show_layout;
- GtkWidget *auto_detect;
- GtkWidget *input_scrolledwindow;
- GList *selected_input_sorted;
- guint n_input_rows;
- GPid gkbd_pid;
- GPermission *permission;
-
+ GtkWidget *input_chooser;
+ GDBusProxy *localed;
+ GCancellable *cancellable;
+ GPermission *permission;
GSettings *input_settings;
- GnomeXkbInfo *xkb_info;
-#ifdef HAVE_IBUS
- IBusBus *ibus;
- GHashTable *ibus_engines;
- GCancellable *ibus_cancellable;
-#endif
-
- guint next_page_id;
};
typedef struct _GisKeyboardPagePrivate GisKeyboardPagePrivate;
-#define OBJ(type,name) ((type)gtk_builder_get_object(GIS_PAGE (self)->builder,(name)))
-#define WID(name) OBJ(GtkWidget*,name)
-
G_DEFINE_TYPE_WITH_PRIVATE (GisKeyboardPage, gis_keyboard_page, GIS_TYPE_PAGE);
static void
-gis_keyboard_page_dispose (GObject *gobject)
-{
- GisKeyboardPage *page = GIS_KEYBOARD_PAGE (gobject);
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (page);
-
- if (priv->cancellable)
- {
- g_cancellable_cancel (priv->cancellable);
- g_clear_object (&priv->cancellable);
- }
-
- if (priv->input_settings)
- {
- g_signal_handlers_disconnect_by_data (priv->input_settings, page);
- g_clear_object (&priv->input_settings);
- }
-
- if (priv->next_page_id != 0)
- {
- g_signal_handler_disconnect (gis_driver_get_assistant (GIS_PAGE (page)->driver),
- priv->next_page_id);
- priv->next_page_id = 0;
- }
-
- g_clear_object (&priv->permission);
- g_clear_object (&priv->localed);
- g_clear_object (&priv->xkb_info);
-
-#ifdef HAVE_IBUS
- g_clear_object (&priv->ibus);
- if (priv->ibus_cancellable)
- g_cancellable_cancel (priv->ibus_cancellable);
- g_clear_object (&priv->ibus_cancellable);
-#endif
-
- G_OBJECT_CLASS (gis_keyboard_page_parent_class)->dispose (gobject);
-}
-
-static void
gis_keyboard_page_finalize (GObject *object)
{
GisKeyboardPage *self = GIS_KEYBOARD_PAGE (object);
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
-#ifdef HAVE_IBUS
- g_clear_pointer (&priv->ibus_engines, g_hash_table_destroy);
- g_clear_pointer (&priv->selected_input_sorted, g_list_free);
-#endif
-
- G_OBJECT_CLASS (gis_keyboard_page_parent_class)->finalize (object);
-}
-
-static void localed_proxy_ready (GObject *source, GAsyncResult *res, gpointer data);
-static void setup_input_section (GisKeyboardPage *self);
-static void update_input (GisKeyboardPage *self);
-
-static void
-next_page_cb (GisAssistant *assistant,
- GisPage *which_page,
- GisPage *this_page)
-{
- if (which_page == this_page)
- update_input (GIS_KEYBOARD_PAGE (this_page));
-}
-
-static void
-gis_keyboard_page_constructed (GObject *object)
-{
- GisKeyboardPage *self = GIS_KEYBOARD_PAGE (object);
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
-
- G_OBJECT_CLASS (gis_keyboard_page_parent_class)->constructed (object);
-
- gtk_container_add (GTK_CONTAINER (self), WID ("keyboard_page"));
-
- setup_input_section (self);
-
- priv->cancellable = g_cancellable_new ();
-
- g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
- G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
- NULL,
- "org.freedesktop.locale1",
- "/org/freedesktop/locale1",
- "org.freedesktop.locale1",
- priv->cancellable,
- (GAsyncReadyCallback) localed_proxy_ready,
- self);
-
- /* If we're in new user mode then we're manipulating system settings */
- if (gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER)
- priv->permission = polkit_permission_new_sync ("org.freedesktop.locale1.set-keyboard", NULL,
NULL, NULL);
-
- priv->next_page_id = g_signal_connect (gis_driver_get_assistant (GIS_PAGE (self)->driver),
- "next-page",
- G_CALLBACK (next_page_cb),
- self);
-
- gis_page_set_complete (GIS_PAGE (self), TRUE);
- gtk_widget_show (GTK_WIDGET (self));
-}
-
-static void
-gis_keyboard_page_locale_changed (GisPage *page)
-{
- gis_page_set_title (GIS_PAGE (page), _("Keyboard Layouts"));
-}
-
-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;
- page_class->locale_changed = gis_keyboard_page_locale_changed;
-
- object_class->constructed = gis_keyboard_page_constructed;
- object_class->dispose = gis_keyboard_page_dispose;
- object_class->finalize = gis_keyboard_page_finalize;
-}
-
-static void
-update_separator_func (GtkWidget **separator,
- GtkWidget *child,
- GtkWidget *before,
- gpointer user_data)
-{
- if (before == NULL)
- return;
-
- if (*separator == NULL) {
- *separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
- g_object_ref_sink (*separator);
- gtk_widget_show (*separator);
- }
-}
-
-
-static void show_input_chooser (GisKeyboardPage *self);
-static void remove_selected_input (GisKeyboardPage *self);
-
-#ifdef HAVE_IBUS
-static void
-update_ibus_active_sources (GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GList *rows, *l;
- GtkWidget *row;
- const gchar *type;
- const gchar *id;
- IBusEngineDesc *engine_desc;
- gchar *display_name;
- GtkWidget *label;
-
- rows = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
- for (l = rows; l; l = l->next) {
- row = l->data;
- type = g_object_get_data (G_OBJECT (row), "type");
- id = g_object_get_data (G_OBJECT (row), "id");
- if (g_strcmp0 (type, INPUT_SOURCE_TYPE_IBUS) != 0)
- continue;
-
- engine_desc = g_hash_table_lookup (priv->ibus_engines, id);
- if (engine_desc) {
- display_name = engine_get_display_name (engine_desc);
- label = GTK_WIDGET (g_object_get_data (G_OBJECT (row), "label"));
- gtk_label_set_text (GTK_LABEL (label), display_name);
- g_free (display_name);
- }
- }
- g_list_free (rows);
-}
-
-static void
-update_input_chooser (GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GtkWidget *chooser;
-
- chooser = g_object_get_data (G_OBJECT (self), "input-chooser");
- if (!chooser)
- return;
-
- cc_input_chooser_set_ibus_engines (chooser, priv->ibus_engines);
-}
-
-static void
-fetch_ibus_engines_result (GObject *object,
- GAsyncResult *result,
- GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GList *list, *l;
- GError *error;
-
- error = NULL;
- list = ibus_bus_list_engines_async_finish (priv->ibus, result, &error);
- g_clear_object (&priv->ibus_cancellable);
- if (!list && error) {
- g_warning ("Couldn't finish IBus request: %s", error->message);
- g_error_free (error);
- return;
- }
-
- /* Maps engine ids to engine description objects */
- priv->ibus_engines = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
-
- for (l = list; l; l = l->next) {
- IBusEngineDesc *engine = l->data;
- const gchar *engine_id = ibus_engine_desc_get_name (engine);
-
- if (g_str_has_prefix (engine_id, "xkb:"))
- g_object_unref (engine);
- else
- g_hash_table_replace (priv->ibus_engines, (gpointer)engine_id, engine);
- }
- g_list_free (list);
-
- update_ibus_active_sources (self);
- update_input_chooser (self);
-}
-
-static void
-fetch_ibus_engines (GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
-
- priv->ibus_cancellable = g_cancellable_new ();
-
- ibus_bus_list_engines_async (priv->ibus,
- -1,
- priv->ibus_cancellable,
- (GAsyncReadyCallback)fetch_ibus_engines_result,
- self);
-
- /* We've got everything we needed, don't want to be called again. */
- g_signal_handlers_disconnect_by_func (priv->ibus, fetch_ibus_engines, self);
-}
-
-static void
-maybe_start_ibus (void)
-{
- /* IBus doesn't export API in the session bus. The only thing
- * we have there is a well known name which we can use as a
- * sure-fire way to activate it.
- */
- g_bus_unwatch_name (g_bus_watch_name (G_BUS_TYPE_SESSION,
- IBUS_SERVICE_IBUS,
- G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
- NULL,
- NULL,
- NULL,
- NULL));
-}
-
-static GDesktopAppInfo *
-setup_app_info_for_id (const gchar *id)
-{
- GDesktopAppInfo *app_info;
- gchar *desktop_file_name;
- gchar **strv;
-
- strv = g_strsplit (id, ":", 2);
- desktop_file_name = g_strdup_printf ("ibus-setup-%s.desktop", strv[0]);
- g_strfreev (strv);
-
- app_info = g_desktop_app_info_new (desktop_file_name);
- g_free (desktop_file_name);
-
- return app_info;
-}
-#endif
-
-static void
-adjust_input_list_scrolling (GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
-
- if (priv->n_input_rows >= MAX_INPUT_ROWS_VISIBLE) {
- GtkWidget *parent;
- gint height;
+ if (priv->cancellable)
+ g_cancellable_cancel (priv->cancellable);
+ g_clear_object (&priv->cancellable);
- parent = gtk_widget_get_parent (priv->input_scrolledwindow);
- gtk_widget_get_preferred_height (parent, NULL, &height);
- gtk_widget_set_size_request (parent, -1, height);
+ g_clear_object (&priv->permission);
+ g_clear_object (&priv->localed);
+ g_clear_object (&priv->input_settings);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->input_scrolledwindow),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- } else {
- gtk_widget_set_size_request (gtk_widget_get_parent (priv->input_scrolledwindow), -1, -1);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->input_scrolledwindow),
- GTK_POLICY_NEVER, GTK_POLICY_NEVER);
- }
-}
-
-static GtkWidget *
-add_input_row (GisKeyboardPage *self,
- const gchar *type,
- const gchar *id,
- const gchar *name,
- GDesktopAppInfo *app_info)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GtkWidget *row;
- GtkWidget *label;
- GtkWidget *image;
-
- row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
- label = gtk_label_new (name);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
- gtk_widget_set_margin_left (label, 20);
- gtk_widget_set_margin_right (label, 20);
- gtk_widget_set_margin_top (label, 6);
- gtk_widget_set_margin_bottom (label, 6);
- gtk_box_pack_start (GTK_BOX (row), label, TRUE, TRUE, 0);
-
- if (strcmp (type, INPUT_SOURCE_TYPE_IBUS) == 0) {
- image = gtk_image_new_from_icon_name ("system-run-symbolic", GTK_ICON_SIZE_BUTTON);
- gtk_widget_set_margin_left (image, 20);
- gtk_widget_set_margin_right (image, 20);
- gtk_widget_set_margin_top (image, 6);
- gtk_widget_set_margin_bottom (image, 6);
- gtk_style_context_add_class (gtk_widget_get_style_context (image), "dim-label");
- gtk_box_pack_start (GTK_BOX (row), image, FALSE, TRUE, 0);
- }
-
- gtk_widget_show_all (row);
- gtk_container_add (GTK_CONTAINER (priv->input_list), row);
- priv->selected_input_sorted = g_list_prepend (priv->selected_input_sorted, row);
-
- g_object_set_data (G_OBJECT (row), "label", label);
- g_object_set_data (G_OBJECT (row), "type", (gpointer)type);
- g_object_set_data_full (G_OBJECT (row), "id", g_strdup (id), g_free);
- if (app_info) {
- g_object_set_data_full (G_OBJECT (row), "app-info", g_object_ref (app_info), g_object_unref);
- }
-
- priv->n_input_rows += 1;
- adjust_input_list_scrolling (self);
-
- return row;
-}
-
-static void
-add_input_source (GisKeyboardPage *self,
- const gchar *type,
- const gchar *id)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- const gchar *name;
- gchar *display_name;
- GDesktopAppInfo *app_info;
-
- display_name = NULL;
- app_info = NULL;
-
- if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) {
- gnome_xkb_info_get_layout_info (priv->xkb_info, id, &name, NULL, NULL, NULL);
- if (!name) {
- g_warning ("Couldn't find XKB input source '%s'", id);
- return;
- }
- display_name = g_strdup (name);
- type = INPUT_SOURCE_TYPE_XKB;
-#ifdef HAVE_IBUS
- } else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) {
- IBusEngineDesc *engine_desc = NULL;
-
- if (priv->ibus_engines)
- engine_desc = g_hash_table_lookup (priv->ibus_engines, id);
- if (engine_desc)
- display_name = engine_get_display_name (engine_desc);
-
- app_info = setup_app_info_for_id (id);
- type = INPUT_SOURCE_TYPE_IBUS;
-#endif
- } else {
- g_warning ("Unhandled input source type '%s'", type);
- return;
- }
-
- add_input_row (self, type, id, display_name ? display_name : id, app_info);
- g_free (display_name);
- g_clear_object (&app_info);
-}
-
-static void
-add_input_sources (GisKeyboardPage *self,
- GVariant *sources)
-{
- GVariantIter iter;
- const gchar *type;
- const gchar *id;
-
- g_variant_iter_init (&iter, sources);
- while (g_variant_iter_next (&iter, "(&s&s)", &type, &id))
- add_input_source (self, type, id);
-}
-
-static void
-add_input_sources_from_settings (GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GVariant *sources;
- sources = g_settings_get_value (priv->input_settings, "sources");
- add_input_sources (self, sources);
- g_variant_unref (sources);
-}
-
-static void
-clear_input_sources (GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GList *list, *l;
- list = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
- for (l = list; l; l = l->next) {
- gtk_container_remove (GTK_CONTAINER (priv->input_list), GTK_WIDGET (l->data));
- }
- g_list_free (list);
- g_clear_pointer (&priv->selected_input_sorted, g_list_free);
-
- priv->n_input_rows = 0;
- adjust_input_list_scrolling (self);
-}
-
-static void
-select_by_id (GtkWidget *row,
- gpointer data)
-{
- const gchar *id = data;
- const gchar *row_id;
-
- row_id = (const gchar *)g_object_get_data (G_OBJECT (row), "id");
- if (g_strcmp0 (row_id, id) == 0)
- egg_list_box_select_child (EGG_LIST_BOX (gtk_widget_get_parent (row)), row);
-}
-
-static void
-select_input (GisKeyboardPage *self,
- const gchar *id)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
-
- gtk_container_foreach (GTK_CONTAINER (priv->input_list),
- select_by_id, (gpointer)id);
-}
-
-static void
-input_sources_changed (GSettings *settings,
- const gchar *key,
- GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GtkWidget *selected;
- gchar *id = NULL;
-
- selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->input_list));
- if (selected)
- id = g_strdup (g_object_get_data (G_OBJECT (selected), "id"));
- clear_input_sources (self);
- add_input_sources_from_settings (self);
- if (id) {
- select_input (self, id);
- g_free (id);
- }
-}
-
-static void
-current_input_source_changed (GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GList *all_inputs;
- GtkWidget *current_input;
- guint current_input_index;
-
- current_input_index = g_settings_get_uint (priv->input_settings, KEY_CURRENT_INPUT_SOURCE);
- all_inputs = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
- current_input = g_list_nth_data (all_inputs, current_input_index);
- if (current_input)
- egg_list_box_select_child (EGG_LIST_BOX (priv->input_list), current_input);
-
- g_list_free (all_inputs);
+ G_OBJECT_CLASS (gis_keyboard_page_parent_class)->finalize (object);
}
-
static void
-update_buttons (GisKeyboardPage *self)
+set_input_settings (GisKeyboardPage *self)
{
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GtkWidget *selected;
- GList *children;
- gboolean multiple_sources;
-
- children = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
- multiple_sources = g_list_next (children) != NULL;
- g_list_free (children);
-
- selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->input_list));
- if (selected == NULL) {
- gtk_widget_set_visible (priv->show_config, FALSE);
- gtk_widget_set_sensitive (priv->remove_input, FALSE);
- gtk_widget_set_sensitive (priv->show_layout, FALSE);
- } else {
- GDesktopAppInfo *app_info;
-
- app_info = (GDesktopAppInfo *)g_object_get_data (G_OBJECT (selected), "app-info");
-
- gtk_widget_set_visible (priv->show_config, app_info != NULL);
- gtk_widget_set_sensitive (priv->show_layout, TRUE);
- gtk_widget_set_sensitive (priv->remove_input, multiple_sources);
- }
-}
+ GVariantBuilder builder;
-static void
-update_current_input (GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GtkWidget *selected;
- GList *children;
- guint index;
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
+ g_variant_builder_add (&builder, "(ss)",
+ cc_input_chooser_get_input_type (CC_INPUT_CHOOSER (priv->input_chooser)),
+ cc_input_chooser_get_input_id (CC_INPUT_CHOOSER (priv->input_chooser)));
- selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->input_list));
- if (selected) {
- children = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
- index = g_list_index (children, selected);
- g_settings_set_uint (priv->input_settings, KEY_CURRENT_INPUT_SOURCE, index);
- g_settings_apply (priv->input_settings);
- g_list_free (children);
+ g_settings_set_value (priv->input_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
+ g_settings_set_uint (priv->input_settings, KEY_CURRENT_INPUT_SOURCE, 0);
- /* Put the selected input in the head */
- priv->selected_input_sorted = g_list_remove (priv->selected_input_sorted, selected);
- priv->selected_input_sorted = g_list_prepend (priv->selected_input_sorted, selected);
- }
+ g_settings_apply (priv->input_settings);
}
static void
-set_input_settings (GisKeyboardPage *self)
+set_localed_input (GisKeyboardPage *self)
{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- const gchar *type;
- const gchar *id;
- GVariantBuilder builder;
- GVariant *old_sources;
- const gchar *old_current_type;
- const gchar *old_current_id;
- guint old_current;
- guint old_n_sources;
- guint index;
- GList *list, *l;
+ GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
+ const gchar *layout, *variant;
- old_sources = g_settings_get_value (priv->input_settings, KEY_INPUT_SOURCES);
- old_current = g_settings_get_uint (priv->input_settings, KEY_CURRENT_INPUT_SOURCE);
- old_n_sources = g_variant_n_children (old_sources);
+ cc_input_chooser_get_layout (CC_INPUT_CHOOSER (priv->input_chooser), &layout, &variant);
- if (old_n_sources > 0 && old_current < old_n_sources) {
- g_variant_get_child (old_sources, old_current,
- "(&s&s)", &old_current_type, &old_current_id);
- } else {
- old_current_type = "";
- old_current_id = "";
- }
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
- index = 0;
- list = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
- for (l = list; l; l = l->next) {
- type = (const gchar *)g_object_get_data (G_OBJECT (l->data), "type");
- id = (const gchar *)g_object_get_data (G_OBJECT (l->data), "id");
- if (index != old_current &&
- g_str_equal (type, old_current_type) &&
- g_str_equal (id, old_current_id)) {
- g_settings_set_uint (priv->input_settings, KEY_CURRENT_INPUT_SOURCE, index);
- }
- g_variant_builder_add (&builder, "(ss)", type, id);
- index += 1;
- }
- g_list_free (list);
-
- g_settings_set_value (priv->input_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
- g_settings_apply (priv->input_settings);
-
- g_variant_unref (old_sources);
+ g_dbus_proxy_call (priv->localed,
+ "SetX11Keyboard",
+ g_variant_new ("(ssssbb)", layout, "", variant, "", TRUE, TRUE),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, NULL, NULL);
}
-
-static void set_localed_input (GisKeyboardPage *self);
-
static void
change_locale_permission_acquired (GObject *source,
- GAsyncResult *res,
- gpointer data)
+ GAsyncResult *res,
+ gpointer data)
{
- GisKeyboardPage *page = GIS_KEYBOARD_PAGE (data);
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (page);
- GError *error = NULL;
- gboolean allowed;
+ GisKeyboardPage *page = GIS_KEYBOARD_PAGE (data);
+ GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (page);
+ GError *error = NULL;
+ gboolean allowed;
- allowed = g_permission_acquire_finish (priv->permission, res, &error);
- if (error) {
- if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
- g_warning ("Failed to acquire permission: %s\n", error->message);
- g_error_free (error);
- return;
- }
+ allowed = g_permission_acquire_finish (priv->permission, res, &error);
+ if (error) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to acquire permission: %s\n", error->message);
+ g_error_free (error);
+ return;
+ }
- if (allowed)
- set_localed_input (GIS_KEYBOARD_PAGE (data));
+ if (allowed)
+ set_localed_input (GIS_KEYBOARD_PAGE (data));
}
-
static void
update_input (GisKeyboardPage *self)
{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
+ GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- set_input_settings (self);
+ set_input_settings (self);
- if (gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER) {
- if (g_permission_get_allowed (priv->permission)) {
- set_localed_input (self);
- }
- else if (g_permission_get_can_acquire (priv->permission)) {
- g_permission_acquire_async (priv->permission,
- NULL,
- change_locale_permission_acquired,
- self);
- }
- }
+ if (gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER) {
+ if (g_permission_get_allowed (priv->permission)) {
+ set_localed_input (self);
+ } else if (g_permission_get_can_acquire (priv->permission)) {
+ g_permission_acquire_async (priv->permission,
+ NULL,
+ change_locale_permission_acquired,
+ self);
+ }
+ }
}
static gboolean
-input_source_already_added (GisKeyboardPage *self,
- const gchar *id)
+gis_keyboard_page_apply (GisPage *page,
+ GCancellable *cancellable)
{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GList *list, *l;
- gboolean retval = FALSE;
-
- list = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
- for (l = list; l; l = l->next)
- if (g_str_equal (id, (const gchar *) g_object_get_data (G_OBJECT (l->data), "id"))) {
- retval = TRUE;
- break;
- }
- g_list_free (list);
-
- return retval;
+ update_input (GIS_KEYBOARD_PAGE (page));
+ return FALSE;
}
static void
-input_response (GtkWidget *chooser, gint response_id, gpointer data)
+localed_proxy_ready (GObject *source,
+ GAsyncResult *res,
+ gpointer data)
{
GisKeyboardPage *self = data;
- gchar *type;
- gchar *id;
- gchar *name;
- GDesktopAppInfo *app_info = NULL;
+ GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
+ GDBusProxy *proxy;
+ GError *error = NULL;
- if (response_id == GTK_RESPONSE_OK) {
- if (cc_input_chooser_get_selected (chooser, &type, &id, &name) &&
- !input_source_already_added (self, id)) {
- if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) {
- g_free (type);
- type = INPUT_SOURCE_TYPE_IBUS;
-#ifdef HAVE_IBUS
- app_info = setup_app_info_for_id (id);
-#endif
- } else {
- g_free (type);
- type = INPUT_SOURCE_TYPE_XKB;
- }
+ proxy = g_dbus_proxy_new_finish (res, &error);
- add_input_row (self, type, id, name, app_info);
- update_buttons (self);
- update_input (self);
- select_input (self, id);
+ if (!proxy) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to contact localed: %s\n", error->message);
+ g_error_free (error);
+ return;
+ }
- g_free (id);
- g_free (name);
- g_clear_object (&app_info);
- }
- }
- gtk_widget_destroy (chooser);
- g_object_set_data (G_OBJECT (self), "input-chooser", NULL);
+ priv->localed = proxy;
}
static void
-show_input_chooser (GisKeyboardPage *self)
+input_confirmed (CcInputChooser *chooser,
+ GisKeyboardPage *self)
{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GtkWidget *chooser;
- GtkWidget *toplevel;
-
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
- chooser = cc_input_chooser_new (GTK_WINDOW (toplevel),
- priv->xkb_info,
-#ifdef HAVE_IBUS
- priv->ibus_engines
-#else
- NULL
-#endif
- );
- g_signal_connect (chooser, "response",
- G_CALLBACK (input_response), self);
- gtk_window_present (GTK_WINDOW (chooser));
-
- g_object_set_data (G_OBJECT (self), "input-chooser", chooser);
-}
-
-static void
-add_input (GisKeyboardPage *self)
-{
- show_input_chooser (self);
+ gis_assistant_next_page (gis_driver_get_assistant (GIS_PAGE (self)->driver));
}
static void
-do_remove_selected_input (GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GtkWidget *selected;
-
- selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->input_list));
- if (selected == NULL)
- return;
-
- priv->selected_input_sorted = g_list_delete_link (priv->selected_input_sorted,
- priv->selected_input_sorted);
- gtk_container_remove (GTK_CONTAINER (priv->input_list), selected);
- if (priv->selected_input_sorted)
- egg_list_box_select_child (EGG_LIST_BOX (priv->input_list),
priv->selected_input_sorted->data);
- else
- egg_list_box_select_child (EGG_LIST_BOX (priv->input_list), NULL);
-
- priv->n_input_rows -= 1;
- adjust_input_list_scrolling (self);
-
- update_buttons (self);
- update_input (self);
-}
-
-static void
-remove_selected_input (GisKeyboardPage *self)
-{
- do_remove_selected_input (self);
-}
-
-static void
-show_selected_settings (GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GtkWidget *selected;
- GdkAppLaunchContext *ctx;
- GDesktopAppInfo *app_info;
- const gchar *id;
- GError *error = NULL;
-
- selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->input_list));
- if (selected == NULL)
- return;
-
- app_info = (GDesktopAppInfo *)g_object_get_data (G_OBJECT (selected), "app-info");
- if (app_info == NULL)
- return;
-
- ctx = gdk_display_get_app_launch_context (gdk_display_get_default ());
- gdk_app_launch_context_set_timestamp (ctx, gtk_get_current_event_time ());
-
- id = (const gchar *)g_object_get_data (G_OBJECT (selected), "id");
- g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (ctx),
- "IBUS_ENGINE_NAME", id);
-
- if (!g_app_info_launch (G_APP_INFO (app_info), NULL, G_APP_LAUNCH_CONTEXT (ctx), &error)) {
- g_warning ("Failed to launch input source setup: %s", error->message);
- g_error_free (error);
- }
-
- g_object_unref (ctx);
-}
-
-static void
-show_selected_layout (GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GtkWidget *selected;
- const gchar *type;
- const gchar *id;
- const gchar *layout;
- const gchar *variant;
- gchar *commandline;
- gchar **argv = NULL;
-
- selected = egg_list_box_get_selected_child (EGG_LIST_BOX (priv->input_list));
- if (selected == NULL)
- return;
-
- type = (const gchar *)g_object_get_data (G_OBJECT (selected), "type");
- id = (const gchar *)g_object_get_data (G_OBJECT (selected), "id");
-
- if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) {
- gnome_xkb_info_get_layout_info (priv->xkb_info,
- id, NULL, NULL,
- &layout, &variant);
-
- if (!layout || !layout[0]) {
- g_warning ("Couldn't find XKB input source '%s'", id);
- return;
- }
-#ifdef HAVE_IBUS
- } else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) {
- IBusEngineDesc *engine_desc = NULL;
-
- if (priv->ibus_engines)
- engine_desc = g_hash_table_lookup (priv->ibus_engines, id);
-
- if (engine_desc) {
- layout = ibus_engine_desc_get_layout (engine_desc);
- variant = "";
- } else {
- g_warning ("Couldn't find IBus input source '%s'", id);
- return;
- }
-#endif
- } else {
- g_warning ("Unhandled input source type '%s'", type);
- return;
- }
-
- if (variant[0])
- commandline = g_strdup_printf ("gkbd-keyboard-display -l \"%s\t%s\"",
- layout, variant);
- else
- commandline = g_strdup_printf ("gkbd-keyboard-display -l %s",
- layout);
-
- if (!g_shell_parse_argv (commandline,
- NULL,
- &argv,
- NULL))
- goto out;
-
- if (priv->gkbd_pid)
- {
- kill (priv->gkbd_pid, 9);
- priv->gkbd_pid = 0;
- }
-
- g_spawn_async (NULL,
- argv,
- NULL,
- G_SPAWN_SEARCH_PATH,
- NULL,
- NULL,
- &priv->gkbd_pid,
- NULL);
- g_strfreev (argv);
- out:
- g_free (commandline);
-}
-
-static void
-detector_response (GtkDialog *detector, gint response_id, gpointer data)
-{
- GisKeyboardPage *self = data;
- const char *type;
- char *id;
- char *name;
-
- if (response_id == GTK_RESPONSE_OK)
- {
- if (cc_keyboard_query_get_selected (CC_KEYBOARD_QUERY (detector), &id, &name))
- {
- if (name == NULL)
- name = g_strdup (id);
- if (!input_source_already_added (self, id))
- {
- type = INPUT_SOURCE_TYPE_XKB;
- add_input_row (self, type, id, name, NULL);
- update_buttons (self);
- update_input (self);
- }
- select_input (self, id);
-
- g_free (id);
- g_free (name);
- }
- }
- gtk_widget_destroy (GTK_WIDGET (detector));
-}
-
-static void
-show_keyboard_detector (GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GtkWidget *detector;
- GtkWidget *toplevel;
-
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
- detector = cc_keyboard_query_new (GTK_WINDOW (toplevel), priv->xkb_info);
- g_signal_connect (detector, "response", G_CALLBACK (detector_response), self);
- cc_keyboard_query_run (CC_KEYBOARD_QUERY (detector));
-}
-
-static void
-add_default_input_source_for_locale (GisKeyboardPage *self)
-{
- const gchar *locale;
- const gchar *type;
- const gchar *id;
-
- locale = gis_driver_get_user_language (GIS_PAGE (self)->driver);
-
- if (!gnome_get_input_source_from_locale (locale, &type, &id))
- return;
-
- add_input_source (self, type, id);
-}
-
-static void
-setup_input_section (GisKeyboardPage *self)
-{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
-
- priv->input_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
- g_settings_delay (priv->input_settings);
-
- priv->xkb_info = gnome_xkb_info_new ();
-
-#ifdef HAVE_IBUS
- ibus_init ();
- if (!priv->ibus) {
- priv->ibus = ibus_bus_new_async ();
- if (ibus_bus_is_connected (priv->ibus))
- fetch_ibus_engines (self);
- else
- g_signal_connect_swapped (priv->ibus, "connected",
- G_CALLBACK (fetch_ibus_engines), self);
- }
- maybe_start_ibus ();
-#endif
-
- priv->input_section = WID ("input_section");
- priv->input_list = WID ("input_list");
- priv->add_input = WID ("input_source_add");
- priv->remove_input = WID ("input_source_remove");
- priv->show_config = WID ("input_source_config");
- priv->show_layout = WID ("input_source_layout");
- priv->auto_detect = WID ("input_auto_detect");
- priv->input_scrolledwindow = WID ("input_scrolledwindow");
-
- g_signal_connect_swapped (priv->add_input, "clicked",
- G_CALLBACK (add_input), self);
- g_signal_connect_swapped (priv->remove_input, "clicked",
- G_CALLBACK (remove_selected_input), self);
- g_signal_connect_swapped (priv->show_config, "clicked",
- G_CALLBACK (show_selected_settings), self);
- g_signal_connect_swapped (priv->show_layout, "clicked",
- G_CALLBACK (show_selected_layout), self);
- g_signal_connect_swapped (priv->auto_detect, "clicked",
- G_CALLBACK (show_keyboard_detector), self);
-
- egg_list_box_set_selection_mode (EGG_LIST_BOX (priv->input_list),
- GTK_SELECTION_SINGLE);
- egg_list_box_set_separator_funcs (EGG_LIST_BOX (priv->input_list),
- update_separator_func,
- NULL, NULL);
- g_signal_connect_swapped (priv->input_list, "child-selected",
- G_CALLBACK (update_buttons), self);
-
- g_signal_connect_swapped (priv->input_list, "child-selected",
- G_CALLBACK (update_current_input), self);
-
- g_signal_connect (priv->input_settings, "changed::" KEY_INPUT_SOURCES,
- G_CALLBACK (input_sources_changed), self);
-
- g_signal_connect_swapped (priv->input_settings, "changed::" KEY_CURRENT_INPUT_SOURCE,
- G_CALLBACK (current_input_source_changed), self);
-
- add_default_input_source_for_locale (self);
- set_input_settings (self);
- current_input_source_changed (self);
-}
-
-static void
-add_input_sources_from_localed (GisKeyboardPage *self)
+gis_keyboard_page_constructed (GObject *object)
{
+ GisKeyboardPage *self = GIS_KEYBOARD_PAGE (object);
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GVariant *v;
- const gchar *s;
- gchar **layouts = NULL;
- gchar **variants = NULL;
- gint i, n;
- if (!priv->localed)
- return;
+ g_type_ensure (CC_TYPE_INPUT_CHOOSER);
- v = g_dbus_proxy_get_cached_property (priv->localed, "X11Layout");
- if (v) {
- s = g_variant_get_string (v, NULL);
- layouts = g_strsplit (s, ",", -1);
- g_variant_unref (v);
- }
-
- v = g_dbus_proxy_get_cached_property (priv->localed, "X11Variant");
- if (v) {
- s = g_variant_get_string (v, NULL);
- if (s && *s)
- variants = g_strsplit (s, ",", -1);
- g_variant_unref (v);
- }
+ G_OBJECT_CLASS (gis_keyboard_page_parent_class)->constructed (object);
- if (variants && variants[0])
- n = MIN (g_strv_length (layouts), g_strv_length (variants));
- else if (layouts && layouts[0])
- n = g_strv_length (layouts);
- else
- n = 0;
+ g_signal_connect (priv->input_chooser, "confirm",
+ G_CALLBACK (input_confirmed), self);
- for (i = 0; i < n && layouts[i][0]; i++) {
- const gchar *name;
- gchar *id;
+ priv->input_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
+ g_settings_delay (priv->input_settings);
- if (variants && variants[i] && variants[i][0])
- id = g_strdup_printf ("%s+%s", layouts[i], variants[i]);
- else
- id = g_strdup (layouts[i]);
+ priv->cancellable = g_cancellable_new ();
- if (!input_source_already_added (self, id)) {
- gnome_xkb_info_get_layout_info (priv->xkb_info, id, &name, NULL, NULL, NULL);
- add_input_row (self, INPUT_SOURCE_TYPE_XKB, id, name ? name : id, NULL);
- }
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+ NULL,
+ "org.freedesktop.locale1",
+ "/org/freedesktop/locale1",
+ "org.freedesktop.locale1",
+ priv->cancellable,
+ (GAsyncReadyCallback) localed_proxy_ready,
+ self);
- g_free (id);
- }
+ /* If we're in new user mode then we're manipulating system settings */
+ if (gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER)
+ priv->permission = polkit_permission_new_sync ("org.freedesktop.locale1.set-keyboard", NULL,
NULL, NULL);
- g_strfreev (variants);
- g_strfreev (layouts);
+ gis_page_set_complete (GIS_PAGE (self), TRUE);
+ gtk_widget_show (GTK_WIDGET (self));
}
static void
-set_localed_input (GisKeyboardPage *self)
+gis_keyboard_page_locale_changed (GisPage *page)
{
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GString *layouts;
- GString *variants;
- const gchar *type, *id;
- GList *list, *li;
- const gchar *l, *v;
-
- layouts = g_string_new ("");
- variants = g_string_new ("");
-
- list = gtk_container_get_children (GTK_CONTAINER (priv->input_list));
- for (li = list; li; li = li->next) {
- type = (const gchar *)g_object_get_data (G_OBJECT (li->data), "type");
- id = (const gchar *)g_object_get_data (G_OBJECT (li->data), "id");
- if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
- continue;
-
- if (gnome_xkb_info_get_layout_info (priv->xkb_info, id, NULL, NULL, &l, &v)) {
- if (layouts->str[0]) {
- g_string_append_c (layouts, ',');
- g_string_append_c (variants, ',');
- }
- g_string_append (layouts, l);
- g_string_append (variants, v);
- }
- }
- g_list_free (list);
-
- g_dbus_proxy_call (priv->localed,
- "SetX11Keyboard",
- g_variant_new ("(ssssbb)", layouts->str, "", variants->str, "", TRUE, TRUE),
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, NULL, NULL);
-
- g_string_free (layouts, TRUE);
- g_string_free (variants, TRUE);
+ gis_page_set_title (GIS_PAGE (page), _("Typing"));
}
static void
-localed_proxy_ready (GObject *source,
- GAsyncResult *res,
- gpointer data)
+gis_keyboard_page_class_init (GisKeyboardPageClass * klass)
{
- GisKeyboardPage *self = data;
- GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
- GDBusProxy *proxy;
- GError *error = NULL;
-
- proxy = g_dbus_proxy_new_finish (res, &error);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GisPageClass * page_class = GIS_PAGE_CLASS (klass);
- if (!proxy) {
- if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
- g_warning ("Failed to contact localed: %s\n", error->message);
- g_error_free (error);
- return;
- }
+ gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
"/org/gnome/initial-setup/gis-keyboard-page.ui");
- priv->localed = proxy;
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisKeyboardPage,
input_chooser);
- add_input_sources_from_localed (self);
- update_input (self);
- current_input_source_changed (self);
- update_buttons (self);
+ page_class->page_id = PAGE_ID;
+ page_class->apply = gis_keyboard_page_apply;
+ page_class->locale_changed = gis_keyboard_page_locale_changed;
+ object_class->constructed = gis_keyboard_page_constructed;
+ object_class->finalize = gis_keyboard_page_finalize;
}
static void
gis_keyboard_page_init (GisKeyboardPage *self)
{
g_resources_register (keyboard_get_resource ());
+ g_type_ensure (CC_TYPE_INPUT_CHOOSER);
+
+ gtk_widget_init_template (GTK_WIDGET (self));
}
void
diff --git a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.h
b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.h
index 798836d..832473f 100644
--- a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.h
+++ b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.h
@@ -12,8 +12,7 @@
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Sergey Udaltsov <svu gnome org>
*
diff --git a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.ui
b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.ui
index b803ffc..063f6de 100644
--- a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.ui
+++ b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.ui
@@ -1,261 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <object class="GtkBox" id="keyboard_page">
+ <template class="GisKeyboardPage" parent="GisPage">
+ <child>
+ <object class="GtkBox" id="page">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">fill</property>
<property name="orientation">vertical</property>
<child>
- <object class="GtkBox" id="input_section">
+ <object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin_left">80</property>
- <property name="margin_right">80</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox" id="input_heading_row">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_bottom">6</property>
- <child>
- <object class="GtkLabel" id="input_heading">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_left">6</property>
- <property name="margin_right">6</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Select keyboard layouts</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- <attribute name="scale" value="1.2"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame" id="input_frame">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkScrolledWindow" id="input_scrolledwindow">
- <property name="visible">True</property>
- <property name="hscrollbar-policy">never</property>
- <property name="vscrollbar-policy">never</property>
- <child>
- <object class="GtkViewport" id="input_viewport">
- <property name="visible">True</property>
- <child>
- <object class="EggListBox" id="input_list">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolbar" id="input_toolbar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="toolbar_style">icons</property>
- <property name="show_arrow">False</property>
- <property name="icon_size">1</property>
- <style>
- <class name="inline-toolbar"/>
- </style>
- <child>
- <object class="GtkToolItem" id="i_s_ar_item">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkBox" id="i_s_ar_box">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkButton" id="input_source_add">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <child>
- <object class="GtkImage" id="i_s_a_image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">list-add-symbolic</property>
- <property name="icon-size">1</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="input_source_remove">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <child>
- <object class="GtkImage" id="i_s_r_image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">list-remove-symbolic</property>
- <property name="icon-size">1</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkSeparatorToolItem" id="sep1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="draw">False</property>
- </object>
- <packing>
- <property name="expand">True</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="i_s_sc_item">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkBox" id="i_s_sc_box">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkButton" id="input_source_config">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <child>
- <object class="GtkImage" id="i_s_sc_image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">emblem-system-symbolic</property>
- <property name="icon-size">1</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="i_s_sl_item">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkBox" id="i_s_sl_box">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkButton" id="input_source_layout">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <child>
- <object class="GtkImage" id="i_s_sl_image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">input-keyboard-symbolic</property>
- <property name="icon-size">1</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkButtonBox" id="i_a_d_box">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkButton" id="input_auto_detect">
- <property name="label" translatable="yes">Help detect my keyboard layout</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">10</property>
- <property name="position">3</property>
- </packing>
- </child>
+ <property name="margin_top">40</property>
+ <property name="pixel_size">96</property>
+ <property name="icon_name">input-keyboard-symbolic</property>
+ <style>
+ <class name="dim-label" />
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="title">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">18</property>
+ <property name="halign">center</property>
+ <property name="valign">start</property>
+ <property name="label" translatable="yes">Typing</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.8"/>
+ </attributes>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="subtitle">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">6</property>
+ <property name="label" translatable="yes">Select your keyboard layout or an input
method.</property>
+ <property name="justify">left</property>
+ <property name="wrap">True</property>
+ <property name="max-width-chars">50</property>
+ </object>
+ </child>
+ <child>
+ <object class="CcInputChooser" id="input_chooser">
+ <property name="margin_top">18</property>
+ <property name="margin_bottom">18</property>
+ <property name="visible">True</property>
+ <property name="halign">center</property>
+ <property name="valign">start</property>
</object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
</child>
</object>
+ </child>
+ </template>
</interface>
diff --git a/gnome-initial-setup/pages/keyboard/input-chooser.ui
b/gnome-initial-setup/pages/keyboard/input-chooser.ui
index 49be542..01b2bb0 100644
--- a/gnome-initial-setup/pages/keyboard/input-chooser.ui
+++ b/gnome-initial-setup/pages/keyboard/input-chooser.ui
@@ -1,81 +1,37 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0"?>
<interface>
- <!-- interface-requires gtk+ 3.0 -->
- <object class="GtkDialog" id="input-dialog">
- <property name="title" translatable="yes">Add a Keyboard Layout</property>
- <property name="default_height">350</property>
- <property name="modal">True</property>
- <property name="destroy_with_parent">True</property>
- <property name="resizable">True</property>
- <child internal-child="vbox">
- <object class="GtkBox" id="vbox">
+ <requires lib="gtk+" version="3.0"/>
+ <template class="CcInputChooser" parent="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolled_window">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">0</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="vscrollbar-policy">never</property>
+ <property name="shadow-type">in</property>
<child>
- <object class="GtkScrolledWindow" id="scrolledwindow">
+ <object class="GtkViewport" id="viewport">
<property name="visible">True</property>
- <property name="hscrollbar-policy">never</property>
- <property name="vscrollbar-policy">never</property>
- <property name="shadow-type">in</property>
- <property name="margin-left">6</property>
- <property name="margin-right">6</property>
- <property name="margin-top">6</property>
- <property name="margin-bottom">6</property>
<child>
- <object class="GtkViewport" id="viewport">
+ <object class="GtkListBox" id="input_list">
<property name="visible">True</property>
- <child>
- <object class="EggListBox" id="list">
- <property name="visible">True</property>
- <property name="can-focus">True</property>
- <property name="vexpand">True</property>
- <property name="halign">fill</property>
- <property name="valign">fill</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkSearchEntry" id="filter-entry">
- <property name="visible">False</property>
- <property name="hexpand">True</property>
- <property name="margin-left">6</property>
- <property name="margin-right">6</property>
- <property name="margin-top">6</property>
- <property name="margin-bottom">6</property>
- </object>
- </child>
- <child internal-child="action_area">
- <object class="GtkButtonBox" id="action-area">
- <property name="visible">True</property>
- <property name="orientation">horizontal</property>
- <child>
- <object class="GtkButton" id="cancel-button">
- <property name="visible">True</property>
- <property name="label">gtk-cancel</property>
- <property name="use_stock">True</property>
- <property name="use_underline" >True</property>
- </object>
- </child>
- <child>
- <object class="GtkButton" id="add-button">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="label">gtk-add</property>
- <property name="use_stock">True</property>
- <property name="use_underline" >True</property>
+ <property name="can-focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="halign">fill</property>
+ <property name="valign">fill</property>
</object>
</child>
</object>
</child>
</object>
</child>
- <action-widgets>
- <action-widget response="-5">add-button</action-widget>
- <action-widget response="-6">cancel-button</action-widget>
- </action-widgets>
- </object>
+ <child>
+ <object class="GtkSearchEntry" id="filter_entry">
+ <property name="visible">False</property>
+ <property name="hexpand">True</property>
+ </object>
+ </child>
+ </template>
</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]