[gnome-flashback] input-sources: implement sources_changed_cb



commit 6f342bce1f1e94cecd553ab2ab54c9871bf8b254
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Wed Sep 23 03:49:52 2015 +0300

    input-sources: implement sources_changed_cb

 gnome-flashback/libinput-sources/gf-ibus-manager.c |   19 +
 gnome-flashback/libinput-sources/gf-ibus-manager.h |   10 +-
 .../libinput-sources/gf-input-source-manager.c     |  476 +++++++++++++++++++-
 gnome-flashback/libinput-sources/gf-input-source.c |   43 ++
 gnome-flashback/libinput-sources/gf-input-source.h |   25 +-
 .../libinput-sources/gf-input-sources.c            |    9 +
 6 files changed, 572 insertions(+), 10 deletions(-)
---
diff --git a/gnome-flashback/libinput-sources/gf-ibus-manager.c 
b/gnome-flashback/libinput-sources/gf-ibus-manager.c
index 257f6e6..a9f0321 100644
--- a/gnome-flashback/libinput-sources/gf-ibus-manager.c
+++ b/gnome-flashback/libinput-sources/gf-ibus-manager.c
@@ -34,6 +34,8 @@ enum
   SIGNAL_PROPERTY_UPDATED,
   SIGNAL_SET_CONTENT_TYPE,
 
+  SIGNAL_ENGINE_SET,
+
   LAST_SIGNAL
 };
 
@@ -81,6 +83,10 @@ gf_ibus_manager_class_init (GfIBusManagerClass *manager_class)
     g_signal_new ("set-content-type", G_TYPE_FROM_CLASS (manager_class),
                   G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
                   G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
+
+  signals[SIGNAL_ENGINE_SET] =
+    g_signal_new ("engine-set", G_TYPE_FROM_CLASS (manager_class),
+                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
 }
 
 static void
@@ -101,3 +107,16 @@ gf_ibus_manager_get_engine_desc (GfIBusManager *manager,
 {
   return NULL;
 }
+
+void
+gf_ibus_manager_set_engine (GfIBusManager *manager,
+                            const gchar   *id)
+{
+  g_signal_emit (manager, signals[SIGNAL_ENGINE_SET], 0);
+}
+
+void
+gf_ibus_manager_preload_engines (GfIBusManager  *manager,
+                                 gchar         **engines)
+{
+}
diff --git a/gnome-flashback/libinput-sources/gf-ibus-manager.h 
b/gnome-flashback/libinput-sources/gf-ibus-manager.h
index aa2201d..c6558eb 100644
--- a/gnome-flashback/libinput-sources/gf-ibus-manager.h
+++ b/gnome-flashback/libinput-sources/gf-ibus-manager.h
@@ -27,7 +27,13 @@ G_DECLARE_FINAL_TYPE (GfIBusManager, gf_ibus_manager,
 
 GfIBusManager  *gf_ibus_manager_new             (void);
 
-IBusEngineDesc *gf_ibus_manager_get_engine_desc (GfIBusManager *manager,
-                                                 const gchar   *id);
+IBusEngineDesc *gf_ibus_manager_get_engine_desc (GfIBusManager  *manager,
+                                                 const gchar    *id);
+
+void            gf_ibus_manager_set_engine      (GfIBusManager  *manager,
+                                                 const gchar    *id);
+
+void            gf_ibus_manager_preload_engines (GfIBusManager  *manager,
+                                                 gchar         **engines);
 
 #endif
diff --git a/gnome-flashback/libinput-sources/gf-input-source-manager.c 
b/gnome-flashback/libinput-sources/gf-input-source-manager.c
index e070c8d..7c57603 100644
--- a/gnome-flashback/libinput-sources/gf-input-source-manager.c
+++ b/gnome-flashback/libinput-sources/gf-input-source-manager.c
@@ -18,13 +18,15 @@
 
 #include "config.h"
 
+#include <gdk/gdk.h>
 #include <gio/gio.h>
 #include <glib/gi18n.h>
 #include <libcommon/gf-keybindings.h>
 
+#include "gf-ibus-manager.h"
+#include "gf-input-source.h"
 #include "gf-input-source-manager.h"
 #include "gf-input-source-settings.h"
-#include "gf-ibus-manager.h"
 #include "gf-keyboard-manager.h"
 
 #define DESKTOP_WM_KEYBINDINGS_SCHEMA "org.gnome.desktop.wm.keybindings"
@@ -60,11 +62,27 @@ struct _GfInputSourceManager
   GfKeyboardManager     *keyboard_manager;
 
   GfIBusManager         *ibus_manager;
+  gboolean               ibus_ready;
   gboolean               disable_ibus;
+
+  GHashTable            *input_sources;
+  GHashTable            *ibus_sources;
+
+  GList                 *mru_sources;
+  GList                 *mru_sources_backup;
 };
 
 enum
 {
+  SIGNAL_SOURCES_CHANGED,
+
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+enum
+{
   PROP_0,
 
   PROP_IBUS_MANAGER,
@@ -76,6 +94,18 @@ static GParamSpec *properties[LAST_PROP] = { NULL };
 
 G_DEFINE_TYPE (GfInputSourceManager, gf_input_source_manager, G_TYPE_OBJECT)
 
+static gchar *
+get_symbol_from_char_code (gunichar code)
+{
+  gchar buffer[6];
+  gint length;
+
+  length = g_unichar_to_utf8 (code, buffer);
+  buffer[length] = '\0';
+
+  return g_strdup_printf ("%s", buffer);
+}
+
 static SourceInfo *
 source_info_new (const gchar *type,
                  const gchar *id,
@@ -237,7 +267,7 @@ make_engine_short_name (IBusEngineDesc *engine_desc)
 
   g_strfreev (codes);
 
-  return g_strdup_printf ("\u2328");
+  return get_symbol_from_char_code (0x2328);
 }
 
 static GList *
@@ -342,21 +372,330 @@ get_source_info_list (GfInputSourceManager *manager)
 }
 
 static void
+current_input_source_changed (GfInputSourceManager *manager,
+                              GfInputSource        *new_source)
+{
+}
+
+static void
+engine_set_cb (GfIBusManager *manager,
+               gpointer       user_data)
+{
+  GfInputSourceManager *source_manager;
+
+  source_manager = GF_INPUT_SOURCE_MANAGER (user_data);
+
+  gf_keyboard_manager_ungrab (source_manager->keyboard_manager,
+                              GDK_CURRENT_TIME);
+}
+
+static void
+activate_cb (GfInputSource *source,
+             gpointer       user_data)
+{
+  GfInputSourceManager *manager;
+  const gchar *xkb_id;
+  const gchar *type;
+  const gchar *engine;
+
+  manager = GF_INPUT_SOURCE_MANAGER (user_data);
+  xkb_id = gf_input_source_get_xkb_id (source);
+
+  gf_keyboard_manager_grab (manager->keyboard_manager, GDK_CURRENT_TIME);
+  gf_keyboard_manager_apply (manager->keyboard_manager, xkb_id);
+
+  if (manager->ibus_manager == NULL)
+    {
+      current_input_source_changed (manager, source);
+      return;
+    }
+
+  type = gf_input_source_get_source_type (source);
+
+  /*
+   * All the "xkb:..." IBus engines simply "echo" back symbols, despite their
+   * naming implying differently, so we always set one in order for XIM
+   * applications to work given that we set XMODIFIERS= im=ibus in the first
+   * place so that they can work without restarting when/if the user adds an
+   * IBus input source.
+   */
+  if (g_strcmp0 (type, INPUT_SOURCE_TYPE_IBUS) == 0)
+    engine = gf_input_source_get_id (source);
+  else
+    engine = "xkb:us::eng";
+
+  g_signal_connect (manager->ibus_manager, "engine-set",
+                    G_CALLBACK (engine_set_cb), manager);
+
+  gf_ibus_manager_set_engine (manager->ibus_manager, engine);
+  current_input_source_changed (manager, source);
+}
+
+static gchar **
+get_ibus_engine_list (GHashTable *sources)
+{
+  GList *list;
+  guint size;
+  guint i;
+  gchar **engines;
+  GList *l;
+
+  list = g_hash_table_get_keys (sources);
+  size = g_hash_table_size (sources);
+  i = 0;
+
+  engines = g_new0 (gchar *, size + 1);
+
+  for (l = list; l != NULL; l = g_list_next (l))
+    {
+      const gchar *engine;
+
+      engine = (const gchar *) l->data;
+      engines[i++] = g_strdup (engine);
+    }
+
+  engines[i] = NULL;
+
+  g_list_free (list);
+
+  return engines;
+}
+
+static void
+sources_by_name_add (GHashTable    *sources,
+                     GfInputSource *source)
+{
+  const gchar *short_name;
+  GList *list;
+
+  short_name = gf_input_source_get_short_name (source);
+  list = g_hash_table_lookup (sources, short_name);
+
+  if (list == NULL)
+    g_hash_table_insert (sources, g_strdup (short_name), list);
+
+  list = g_list_append (list, source);
+  g_hash_table_replace (sources, g_strdup (short_name), list);
+}
+
+static void
+sources_by_name_update (GHashTable *input_sources,
+                        GHashTable *sources_by_name)
+{
+  GHashTableIter iter;
+  gpointer value;
+
+  g_hash_table_iter_init (&iter, input_sources);
+
+  while (g_hash_table_iter_next (&iter, NULL, &value))
+    {
+      GfInputSource *source;
+      const gchar *short_name;
+      GList *list;
+
+      source = (GfInputSource *) value;
+      short_name = gf_input_source_get_short_name (source);
+
+      list = g_hash_table_lookup (sources_by_name, short_name);
+      if (list == NULL)
+        continue;
+
+      if (g_list_length (list) > 1)
+        {
+          guint index;
+          gchar *symbol;
+          gchar *new_name;
+
+          index = g_list_index (list, source);
+
+          symbol = get_symbol_from_char_code (0x2080 + index + 1);
+          new_name = g_strdup_printf ("%s%s", short_name, symbol);
+          g_free (symbol);
+
+          gf_input_source_set_short_name (source, new_name);
+          g_free (new_name);
+        }
+    }
+}
+
+static gboolean
+sources_by_name_free (gpointer key,
+                      gpointer value,
+                      gpointer user_data)
+{
+  GList *list;
+
+  list = (GList *) value;
+
+  g_list_free (list);
+
+  return TRUE;
+}
+
+static gboolean
+compare_sources (GfInputSource *source1,
+                 GfInputSource *source2)
+{
+  const gchar *type1;
+  const gchar *type2;
+  const gchar *id1;
+  const gchar *id2;
+
+  type1 = gf_input_source_get_source_type (source1);
+  type2 = gf_input_source_get_source_type (source2);
+
+  id1 = gf_input_source_get_id (source1);
+  id2 = gf_input_source_get_id (source2);
+
+  if (g_strcmp0 (type1, type2) == 0 && g_strcmp0 (id1, id2) == 0)
+    return TRUE;
+
+  return FALSE;
+}
+
+static void
+update_mru_sources_list (GfInputSourceManager *manager)
+{
+  GList *sources;
+  GList *mru_sources;
+  GList *l1;
+  GList *l2;
+
+  if (manager->mru_sources != NULL)
+    {
+      g_list_free (manager->mru_sources);
+      manager->mru_sources = NULL;
+    }
+
+  if (!manager->disable_ibus && manager->mru_sources_backup != NULL)
+    {
+      manager->mru_sources = manager->mru_sources_backup;
+      manager->mru_sources_backup = NULL;
+    }
+
+  sources = g_hash_table_get_values (manager->input_sources);
+  sources = g_list_reverse (sources);
+
+  mru_sources = NULL;
+  for (l1 = manager->mru_sources; l1 != NULL; l1 = g_list_next (l1))
+    {
+      for (l2 = sources; l2 != NULL; l2 = g_list_next (l2))
+        {
+          GfInputSource *source1;
+          GfInputSource *source2;
+          GList *source;
+
+          source1 = (GfInputSource *) l1->data;
+          source2 = (GfInputSource *) l2->data;
+
+          if (!compare_sources (source1, source2))
+            continue;
+
+          g_warning ("equal...");
+
+          source = g_list_remove_link (sources, l2);
+          mru_sources = g_list_concat (mru_sources, source);
+
+          break;
+        }
+    }
+
+  mru_sources = g_list_concat (mru_sources, sources);
+
+  g_list_free (manager->mru_sources);
+  manager->mru_sources = mru_sources;
+
+  if (manager->mru_sources != NULL)
+    {
+      GfInputSource *source;
+
+      source = (GfInputSource *) g_list_nth_data (manager->mru_sources, 0);
+
+      gf_input_source_activate (source);
+    }
+}
+
+static void
 sources_changed_cb (GfInputSourceSettings *settings,
                     gpointer               user_data)
 {
   GfInputSourceManager *manager;
   GList *source_infos;
   GList *l;
+  GHashTable *sources_by_name;
+  guint length;
+  gchar **ids;
 
   manager = GF_INPUT_SOURCE_MANAGER (user_data);
   source_infos = get_source_info_list (manager);
 
+  if (manager->input_sources != NULL)
+    g_hash_table_destroy (manager->input_sources);
+  manager->input_sources = g_hash_table_new_full (NULL, NULL, NULL,
+                                                  g_object_unref);
+
+  if (manager->ibus_sources != NULL)
+    g_hash_table_destroy (manager->ibus_sources);
+  manager->ibus_sources = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                 g_free, g_object_unref);
+
+  sources_by_name = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                           g_free, NULL);
+
+  length = g_list_length (source_infos);
+  ids = g_new0 (gchar *, length + 1);
+
   for (l = source_infos; l != NULL; l = g_list_next (l))
     {
+      SourceInfo *info;
+      gint position;
+      GfInputSource *source;
+
+      info = (SourceInfo *) l->data;
+      position = g_list_position (source_infos, l);
+
+      source = gf_input_source_new (manager->ibus_manager, info->type,
+                                    info->id, info->display_name,
+                                    info->short_name, position);
+
+      g_signal_connect (source, "activate",
+                        G_CALLBACK (activate_cb), manager);
+
+      g_hash_table_insert (manager->input_sources, GINT_TO_POINTER (position),
+                           g_object_ref (source));
+
+      if (g_strcmp0 (info->type, INPUT_SOURCE_TYPE_IBUS) == 0)
+        g_hash_table_insert (manager->ibus_sources, g_strdup (info->id),
+                             g_object_ref (source));
+
+      sources_by_name_add (sources_by_name, source);
+
+      ids[position] = g_strdup (gf_input_source_get_xkb_id (source));
+      g_object_unref (source);
     }
 
+  ids[length] = NULL;
+
   g_list_free_full (source_infos, source_info_free);
+
+  sources_by_name_update (manager->input_sources, sources_by_name);
+  g_hash_table_foreach_remove (sources_by_name, sources_by_name_free, NULL);
+  g_hash_table_destroy (sources_by_name);
+
+  g_signal_emit (manager, signals[SIGNAL_SOURCES_CHANGED], 0);
+
+  gf_keyboard_manager_set_user_layouts (manager->keyboard_manager, ids);
+  g_strfreev (ids);
+
+  update_mru_sources_list (manager);
+
+  /*
+   * All IBus engines are preloaded here to reduce the launching time when
+   * users switch the input sources.
+   */
+  ids = get_ibus_engine_list (manager->ibus_sources);
+  gf_ibus_manager_preload_engines (manager->ibus_manager, ids);
+  g_strfreev (ids);
 }
 
 static void
@@ -396,6 +735,110 @@ input_source_settings_init (GfInputSourceManager *manager)
 }
 
 static void
+ready_cb (GfIBusManager *ibus_manager,
+          gboolean       ready,
+          gpointer       user_data)
+{
+  GfInputSourceManager *manager;
+
+  manager = GF_INPUT_SOURCE_MANAGER (user_data);
+
+  if (manager->ibus_ready == ready)
+    return;
+
+  manager->ibus_ready = ready;
+
+  if (manager->mru_sources != NULL)
+    {
+      g_list_free (manager->mru_sources);
+      manager->mru_sources = NULL;
+    }
+
+  sources_changed_cb (manager->settings, manager);
+}
+
+static void
+properties_registered_cb (GfIBusManager *ibus_manager,
+                          const gchar   *engine_name,
+                          IBusPropList  *prop_list,
+                          gpointer       user_data)
+{
+}
+
+static void
+property_updated_cb (GfIBusManager *ibus_manager,
+                     const gchar   *engine_name,
+                     IBusProperty  *property,
+                     gpointer       user_data)
+{
+}
+
+static void
+set_content_type_cb (GfIBusManager *ibus_manager,
+                     guint          purpose,
+                     guint          hints,
+                     gpointer       user_data)
+{
+  GfInputSourceManager *manager;
+
+  manager = GF_INPUT_SOURCE_MANAGER (user_data);
+
+  if (purpose == IBUS_INPUT_PURPOSE_PASSWORD)
+    {
+      GList *keys1;
+      GList *keys2;
+
+      keys1 = g_hash_table_get_keys (manager->input_sources);
+      keys2 = g_hash_table_get_keys (manager->ibus_sources);
+
+      if (g_list_length (keys1) == g_list_length (keys2))
+        {
+          g_list_free (keys1);
+          g_list_free (keys2);
+
+          return;
+        }
+
+      g_list_free (keys1);
+      g_list_free (keys2);
+
+      if (manager->disable_ibus)
+        return;
+
+      manager->disable_ibus = TRUE;
+      manager->mru_sources_backup = g_list_copy (manager->mru_sources);
+    }
+  else
+    {
+      if (!manager->disable_ibus)
+        return;
+
+      manager->disable_ibus = FALSE;
+    }
+
+  gf_input_source_manager_reload (manager);
+}
+
+static void
+gf_input_source_manager_constructed (GObject *object)
+{
+  GfInputSourceManager *manager;
+
+  manager = GF_INPUT_SOURCE_MANAGER (object);
+
+  G_OBJECT_CLASS (gf_input_source_manager_parent_class)->constructed (object);
+
+  g_signal_connect (manager->ibus_manager, "ready",
+                    G_CALLBACK (ready_cb), manager);
+  g_signal_connect (manager->ibus_manager, "properties-registered",
+                    G_CALLBACK (properties_registered_cb), manager);
+  g_signal_connect (manager->ibus_manager, "property-updated",
+                    G_CALLBACK (property_updated_cb), manager);
+  g_signal_connect (manager->ibus_manager, "set-content-type",
+                    G_CALLBACK (set_content_type_cb), manager);
+}
+
+static void
 gf_input_source_manager_dispose (GObject *object)
 {
   GfInputSourceManager *manager;
@@ -409,6 +852,30 @@ gf_input_source_manager_dispose (GObject *object)
 
   g_clear_object (&manager->keyboard_manager);
 
+  if (manager->input_sources != 0)
+    {
+      g_hash_table_destroy (manager->input_sources);
+      manager->input_sources = NULL;
+    }
+
+  if (manager->ibus_sources != 0)
+    {
+      g_hash_table_destroy (manager->ibus_sources);
+      manager->ibus_sources = NULL;
+    }
+
+  if (manager->mru_sources != NULL)
+    {
+      g_list_free (manager->mru_sources);
+      manager->mru_sources = NULL;
+    }
+
+  if (manager->mru_sources_backup != NULL)
+    {
+      g_list_free (manager->mru_sources_backup);
+      manager->mru_sources_backup = NULL;
+    }
+
   G_OBJECT_CLASS (gf_input_source_manager_parent_class)->dispose (object);
 }
 
@@ -463,10 +930,15 @@ gf_input_source_manager_class_init (GfInputSourceManagerClass *manager_class)
 
   object_class = G_OBJECT_CLASS (manager_class);
 
+  object_class->constructed = gf_input_source_manager_constructed;
   object_class->dispose = gf_input_source_manager_dispose;
   object_class->get_property = gf_input_source_manager_get_property;
   object_class->set_property = gf_input_source_manager_set_property;
 
+  signals[SIGNAL_SOURCES_CHANGED] =
+    g_signal_new ("sources-changed", G_TYPE_FROM_CLASS (manager_class),
+                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
+
   properties[PROP_IBUS_MANAGER] =
     g_param_spec_object ("ibus-manager", "IBus Manager",
                          "An instance of GfIBusManager",
diff --git a/gnome-flashback/libinput-sources/gf-input-source.c 
b/gnome-flashback/libinput-sources/gf-input-source.c
index 6918c46..90f373d 100644
--- a/gnome-flashback/libinput-sources/gf-input-source.c
+++ b/gnome-flashback/libinput-sources/gf-input-source.c
@@ -282,3 +282,46 @@ gf_input_source_new (GfIBusManager *ibus_manager,
                        "index", index,
                        NULL);
 }
+
+const gchar *
+gf_input_source_get_source_type (GfInputSource *source)
+{
+  return source->type;
+}
+
+const gchar *
+gf_input_source_get_id (GfInputSource *source)
+{
+  return source->id;
+}
+
+const gchar *
+gf_input_source_get_short_name (GfInputSource *source)
+{
+  return source->short_name;
+}
+
+void
+gf_input_source_set_short_name  (GfInputSource *source,
+                                 const gchar   *short_name)
+{
+  if (g_strcmp0 (source->short_name, short_name) == 0)
+    return;
+
+  g_free (source->short_name);
+  source->short_name = g_strdup (short_name);
+
+  g_signal_emit (source, signals[SIGNAL_CHANGED], 0);
+}
+
+const gchar *
+gf_input_source_get_xkb_id (GfInputSource *source)
+{
+  return source->xkb_id;
+}
+
+void
+gf_input_source_activate (GfInputSource *source)
+{
+  g_signal_emit (source, signals[SIGNAL_ACTIVATE], 0);
+}
diff --git a/gnome-flashback/libinput-sources/gf-input-source.h 
b/gnome-flashback/libinput-sources/gf-input-source.h
index ebf32c7..e2c4af7 100644
--- a/gnome-flashback/libinput-sources/gf-input-source.h
+++ b/gnome-flashback/libinput-sources/gf-input-source.h
@@ -25,11 +25,24 @@
 G_DECLARE_FINAL_TYPE (GfInputSource, gf_input_source,
                       GF, INPUT_SOURCE, GObject)
 
-GfInputSource *gf_input_source_new (GfIBusManager *ibus_manager,
-                                    const gchar   *type,
-                                    const gchar   *id,
-                                    const gchar   *display_name,
-                                    const gchar   *short_name,
-                                    guint          index);
+GfInputSource *gf_input_source_new             (GfIBusManager *ibus_manager,
+                                                const gchar   *type,
+                                                const gchar   *id,
+                                                const gchar   *display_name,
+                                                const gchar   *short_name,
+                                                guint          index);
+
+const gchar   *gf_input_source_get_source_type (GfInputSource *source);
+
+const gchar   *gf_input_source_get_id          (GfInputSource *source);
+
+const gchar   *gf_input_source_get_short_name  (GfInputSource *source);
+
+void           gf_input_source_set_short_name  (GfInputSource *source,
+                                                const gchar   *short_name);
+
+const gchar   *gf_input_source_get_xkb_id      (GfInputSource *source);
+
+void           gf_input_source_activate        (GfInputSource *source);
 
 #endif
diff --git a/gnome-flashback/libinput-sources/gf-input-sources.c 
b/gnome-flashback/libinput-sources/gf-input-sources.c
index 9e47de2..ce708ad 100644
--- a/gnome-flashback/libinput-sources/gf-input-sources.c
+++ b/gnome-flashback/libinput-sources/gf-input-sources.c
@@ -32,6 +32,12 @@ struct _GfInputSources
 G_DEFINE_TYPE (GfInputSources, gf_input_sources, G_TYPE_OBJECT)
 
 static void
+sources_changed_cb (GfInputSourceManager *manager,
+                    gpointer              user_data)
+{
+}
+
+static void
 gf_input_sources_dispose (GObject *object)
 {
   GfInputSources *sources;
@@ -60,6 +66,9 @@ gf_input_sources_init (GfInputSources *sources)
   sources->ibus_manager = gf_ibus_manager_new ();
   sources->input_source_manager = gf_input_source_manager_new (sources->ibus_manager);
 
+  g_signal_connect (sources->input_source_manager, "sources-changed",
+                    G_CALLBACK (sources_changed_cb), sources);
+
   gf_input_source_manager_reload (sources->input_source_manager);
 }
 


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