Description: add support for “org.gnome.desktop.input-sources current” key
 This key is deprecated, but still used by indicator-keyboard.
 .
 Now the indices of GfInputSources are not necessarily continuous, and
 correspond to their indices in the “input-methods” list in GSettings.
Author: Dmitry Shachnev <mitya57@ubuntu.com>
Forwarded: not-needed
Last-Update: 2017-10-06

--- a/gnome-flashback/libinput-sources/gf-input-source-manager.c
+++ b/gnome-flashback/libinput-sources/gf-input-source-manager.c
@@ -418,6 +418,9 @@
 
   info = (SourceInfo *) data;
 
+  if (info == NULL)
+    return;
+
   g_free (info->type);
   g_free (info->id);
   g_free (info->display_name);
@@ -518,7 +521,9 @@
   guint size;
   GfInputSource *source;
   GList *keys;
-  guint next_index;
+  GList *current_key;
+  GList *next_key;
+  guint current_index;
 
   manager = GF_INPUT_SOURCE_MANAGER (user_data);
 
@@ -537,12 +542,14 @@
   keys = g_hash_table_get_keys (manager->input_sources);
   keys = g_list_sort (keys, compare_indexes);
 
-  next_index = gf_input_source_get_index (source ) + 1;
-  if (next_index > GPOINTER_TO_UINT (g_list_nth_data (keys, size - 1)))
-    next_index = 0;
+  current_index = gf_input_source_get_index (source);
+  current_key = g_list_find (keys, GUINT_TO_POINTER (current_index));
+  next_key = g_list_next (current_key);
+  if (!next_key)
+    next_key = keys;
 
   source = (GfInputSource *) g_hash_table_lookup (manager->input_sources,
-                                                  GUINT_TO_POINTER (next_index));
+                                                  next_key->data);
 
   gf_input_source_activate (source, TRUE);
   g_list_free (keys);
@@ -695,13 +702,19 @@
           gchar *short_name;
 
           if (manager->disable_ibus)
-            continue;
+            {
+              list = g_list_append (list, NULL);
+              continue;
+            }
 
           engine_desc = gf_ibus_manager_get_engine_desc (manager->ibus_manager,
                                                          id);
 
           if (engine_desc == NULL)
-            continue;
+            {
+              list = g_list_append (list, NULL);
+              continue;
+            }
 
           language_code = ibus_engine_desc_get_language (engine_desc);
           language = ibus_get_language_name (language_code);
@@ -720,8 +733,7 @@
           g_free (short_name);
         }
 
-      if (info != NULL)
-        list = g_list_append (list, info);
+      list = g_list_append (list, info);
     }
 
   g_variant_unref (sources);
@@ -1099,6 +1111,7 @@
   GList *l;
   GHashTable *sources_by_name;
   guint length;
+  guint i;
   gchar **ids;
 
   manager = GF_INPUT_SOURCE_MANAGER (user_data);
@@ -1132,6 +1145,9 @@
       GfInputSource *source;
 
       info = (SourceInfo *) l->data;
+      if (info == NULL)
+        continue;
+
       position = g_list_position (source_infos, l);
 
       source = gf_input_source_new (manager->ibus_manager, info->type,
@@ -1165,7 +1181,10 @@
   g_signal_emit (manager, signals[SIGNAL_SOURCES_CHANGED], 0);
 
   gf_keyboard_manager_set_user_layouts (manager->keyboard_manager, ids);
-  g_strfreev (ids);
+
+  for (i = 0; i < length; ++i)
+    if (ids[i] != NULL)
+      g_free (ids[i]);
 
   update_mru_sources_list (manager);
 
@@ -1227,6 +1246,23 @@
 }
 
 static void
+current_changed_cb (GfInputSourceSettings *settings,
+                    gpointer               user_data)
+{
+  GfInputSourceManager *manager;
+  GfInputSource *source;
+  guint new_current;
+
+  manager = GF_INPUT_SOURCE_MANAGER (user_data);
+  new_current = gf_input_source_settings_get_current (settings);
+
+  source = (GfInputSource *) g_hash_table_lookup (manager->input_sources,
+                                                  GUINT_TO_POINTER (new_current));
+  if (source != manager->current_source)
+    gf_input_source_activate (source, TRUE);
+}
+
+static void
 input_source_settings_init (GfInputSourceManager *manager)
 {
   manager->settings = gf_input_source_settings_new ();
@@ -1237,6 +1273,8 @@
                     G_CALLBACK (xkb_options_changed_cb), manager);
   g_signal_connect (manager->settings, "per-window-changed",
                     G_CALLBACK (per_window_changed_cb), manager);
+  g_signal_connect (manager->settings, "current-changed",
+                    G_CALLBACK (current_changed_cb), manager);
 
   per_window_changed_cb (manager->settings, manager);
 }
@@ -1607,3 +1645,15 @@
 
   return sources;
 }
+
+void
+gf_input_source_manager_write_current (GfInputSourceManager *manager)
+{
+  guint index;
+
+  if (manager->current_source != NULL)
+    {
+      index = gf_input_source_get_index (manager->current_source);
+      gf_input_source_settings_set_current (manager->settings, index);
+    }
+}
--- a/gnome-flashback/libinput-sources/gf-input-source-manager.h
+++ b/gnome-flashback/libinput-sources/gf-input-source-manager.h
@@ -37,4 +37,6 @@
 
 GList                *gf_input_source_manager_get_input_sources  (GfInputSourceManager *manager);
 
+void                  gf_input_source_manager_write_current      (GfInputSourceManager *manager);
+
 #endif
--- a/gnome-flashback/libinput-sources/gf-input-source-settings.c
+++ b/gnome-flashback/libinput-sources/gf-input-source-settings.c
@@ -27,6 +27,7 @@
 #define KEY_MRU_SOURCES "mru-sources"
 #define KEY_XKB_OPTIONS "xkb-options"
 #define KEY_PER_WINDOW "per-window"
+#define KEY_CURRENT "current"
 
 struct _GfInputSourceSettings
 {
@@ -40,6 +41,7 @@
   SIGNAL_SOURCES_CHANGED,
   SIGNAL_XKB_OPTIONS_CHANGED,
   SIGNAL_PER_WINDOW_CHANGED,
+  SIGNAL_CURRENT_CHANGED,
 
   LAST_SIGNAL
 };
@@ -63,6 +65,8 @@
     g_signal_emit (source_settings, signals[SIGNAL_XKB_OPTIONS_CHANGED], 0);
   else if (g_strcmp0 (key, KEY_PER_WINDOW) == 0)
     g_signal_emit (source_settings, signals[SIGNAL_PER_WINDOW_CHANGED], 0);
+  else if (g_strcmp0 (key, KEY_CURRENT) == 0)
+    g_signal_emit (source_settings, signals[SIGNAL_CURRENT_CHANGED], 0);
 }
 
 static void
@@ -118,6 +122,17 @@
   signals[SIGNAL_PER_WINDOW_CHANGED] =
     g_signal_new ("per-window-changed", G_TYPE_FROM_CLASS (settings_class),
                   G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
+
+  /**
+   * GfInputSourceSettings::current-changed:
+   * @settings: the object on which the signal is emitted
+   *
+   * The ::current-changed signal is emitted each time when current
+   * setting has changed.
+   */
+  signals[SIGNAL_CURRENT_CHANGED] =
+    g_signal_new ("current-changed", G_TYPE_FROM_CLASS (settings_class),
+                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
 }
 
 static void
@@ -205,3 +220,16 @@
 {
   return g_settings_get_boolean (settings->settings, KEY_PER_WINDOW);
 }
+
+guint
+gf_input_source_settings_get_current (GfInputSourceSettings *settings)
+{
+  return g_settings_get_uint (settings->settings, KEY_CURRENT);
+}
+
+void
+gf_input_source_settings_set_current (GfInputSourceSettings *settings,
+                                      guint                  current)
+{
+  g_settings_set_uint (settings->settings, KEY_CURRENT, current);
+}
--- a/gnome-flashback/libinput-sources/gf-input-source-settings.h
+++ b/gnome-flashback/libinput-sources/gf-input-source-settings.h
@@ -39,6 +39,11 @@
 
 gboolean                gf_input_source_settings_get_per_window  (GfInputSourceSettings *settings);
 
+void                    gf_input_source_settings_set_current     (GfInputSourceSettings *settings,
+                                                                  guint                  current);
+
+guint                   gf_input_source_settings_get_current     (GfInputSourceSettings *settings);
+
 G_END_DECLS
 
 #endif
--- a/gnome-flashback/libinput-sources/gf-input-sources.c
+++ b/gnome-flashback/libinput-sources/gf-input-sources.c
@@ -877,6 +877,8 @@
                            GfInputSource        *old_source,
                            GfInputSources       *sources)
 {
+  gf_input_source_manager_write_current (manager);
+
   update_status_icon (sources);
 }
 
