~ubuntu-branches/ubuntu/trusty/unity-control-center/trusty

« back to all changes in this revision

Viewing changes to panels/region/gnome-region-panel-input.c

  • Committer: Package Import Robot
  • Author(s): Robert Ancell
  • Date: 2014-01-08 16:29:18 UTC
  • Revision ID: package-import@ubuntu.com-20140108162918-g29dd08tr913y2qh
Tags: upstream-14.04.0
ImportĀ upstreamĀ versionĀ 14.04.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2011 Red Hat, Inc.
 
3
 *
 
4
 * Written by: Matthias Clasen <mclasen@redhat.com>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2, or (at your option)
 
9
 * any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
19
 * 02111-1307, USA.
 
20
 */
 
21
 
 
22
#include <config.h>
 
23
 
 
24
#include <string.h>
 
25
 
 
26
#include <glib.h>
 
27
#include <glib/gi18n.h>
 
28
#include <gio/gdesktopappinfo.h>
 
29
 
 
30
#define GNOME_DESKTOP_USE_UNSTABLE_API
 
31
#include <libgnome-desktop/gnome-xkb-info.h>
 
32
 
 
33
#ifdef HAVE_IBUS
 
34
#include <ibus.h>
 
35
#endif
 
36
 
 
37
#include "gdm-languages.h"
 
38
#include "gnome-region-panel-input.h"
 
39
#include "keyboard-shortcuts.h"
 
40
#include "gtkentryaccel.h"
 
41
 
 
42
#define WID(s) GTK_WIDGET(gtk_builder_get_object (builder, s))
 
43
 
 
44
#define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources"
 
45
#define KEY_CURRENT_INPUT_SOURCE        "current"
 
46
#define KEY_INPUT_SOURCES               "sources"
 
47
#define INPUT_SOURCE_TYPE_XKB           "xkb"
 
48
#define INPUT_SOURCE_TYPE_IBUS          "ibus"
 
49
 
 
50
#define MEDIA_KEYS_SCHEMA_ID  "org.gnome.desktop.wm.keybindings"
 
51
#define KEY_PREV_INPUT_SOURCE "switch-input-source-backward"
 
52
#define KEY_NEXT_INPUT_SOURCE "switch-input-source"
 
53
 
 
54
#define INDICATOR_KEYBOARD_SCHEMA_ID "com.canonical.indicator.keyboard"
 
55
#define KEY_VISIBLE                  "visible"
 
56
 
 
57
#define LIBGNOMEKBD_DESKTOP_SCHEMA_ID "org.gnome.libgnomekbd.desktop"
 
58
#define KEY_GROUP_PER_WINDOW          "group-per-window"
 
59
#define KEY_DEFAULT_GROUP             "default-group"
 
60
 
 
61
#define IBUS_PANEL_SECTION       "panel"
 
62
#define IBUS_ORIENTATION_KEY     "lookup_table_orientation"
 
63
#define IBUS_USE_CUSTOM_FONT_KEY "use_custom_font"
 
64
#define IBUS_CUSTOM_FONT_KEY     "custom_font"
 
65
 
 
66
enum {
 
67
  NAME_COLUMN,
 
68
  TYPE_COLUMN,
 
69
  ID_COLUMN,
 
70
  SETUP_COLUMN,
 
71
  N_COLUMNS
 
72
};
 
73
 
 
74
static GSettings *input_sources_settings = NULL;
 
75
static GSettings *libgnomekbd_settings = NULL;
 
76
static GSettings *media_key_settings = NULL;
 
77
static GSettings *indicator_settings = NULL;
 
78
static GnomeXkbInfo *xkb_info = NULL;
 
79
static GtkBuilder *builder = NULL; /* weak pointer */
 
80
static GtkWidget *input_chooser = NULL; /* weak pointer */
 
81
static CcRegionKeyboardItem *prev_source_item = NULL;
 
82
static CcRegionKeyboardItem *next_source_item = NULL;
 
83
 
 
84
#ifdef HAVE_IBUS
 
85
static IBusBus *ibus = NULL;
 
86
static GHashTable *ibus_engines = NULL;
 
87
static GCancellable *ibus_cancellable = NULL;
 
88
static guint shell_name_watch_id = 0;
 
89
 
 
90
#endif  /* HAVE_IBUS */
 
91
 
 
92
static void       populate_model             (GtkListStore  *store,
 
93
                                              GtkListStore  *active_sources_store);
 
94
static GtkWidget *input_chooser_new          (GtkWindow     *main_window,
 
95
                                              GtkListStore  *active_sources);
 
96
static gboolean   input_chooser_get_selected (GtkWidget     *chooser,
 
97
                                              GtkTreeModel **model,
 
98
                                              GtkTreeIter   *iter);
 
99
static GtkTreeModel *tree_view_get_actual_model (GtkTreeView *tv);
 
100
 
 
101
static gboolean
 
102
is_unity (void)
 
103
{
 
104
  return g_strcmp0 (g_getenv ("XDG_CURRENT_DESKTOP"), "Unity") == 0;
 
105
}
 
106
 
 
107
static gboolean
 
108
has_indicator_keyboard (void)
 
109
{
 
110
  if (is_unity ())
 
111
    {
 
112
      const gchar * const *schemas = g_settings_list_schemas ();
 
113
 
 
114
      while (*schemas != NULL)
 
115
        {
 
116
          if (g_strcmp0 (*schemas, INDICATOR_KEYBOARD_SCHEMA_ID) == 0)
 
117
            return TRUE;
 
118
 
 
119
          schemas++;
 
120
        }
 
121
    }
 
122
 
 
123
  return FALSE;
 
124
}
 
125
 
 
126
static gboolean
 
127
strv_contains (const gchar * const *strv,
 
128
               const gchar         *str)
 
129
{
 
130
  const gchar * const *p = strv;
 
131
  for (p = strv; *p; p++)
 
132
    if (g_strcmp0 (*p, str) == 0)
 
133
      return TRUE;
 
134
 
 
135
  return FALSE;
 
136
}
 
137
 
 
138
#ifdef HAVE_IBUS
 
139
static void
 
140
clear_ibus (void)
 
141
{
 
142
  if (shell_name_watch_id > 0)
 
143
    {
 
144
      g_bus_unwatch_name (shell_name_watch_id);
 
145
      shell_name_watch_id = 0;
 
146
    }
 
147
  g_cancellable_cancel (ibus_cancellable);
 
148
  g_clear_object (&ibus_cancellable);
 
149
  g_clear_pointer (&ibus_engines, g_hash_table_destroy);
 
150
  g_clear_object (&ibus);
 
151
}
 
152
 
 
153
static gchar *
 
154
engine_get_display_name (IBusEngineDesc *engine_desc)
 
155
{
 
156
  const gchar *name;
 
157
  const gchar *language_code;
 
158
  const gchar *language;
 
159
  gchar *display_name;
 
160
 
 
161
  name = ibus_engine_desc_get_longname (engine_desc);
 
162
  language_code = ibus_engine_desc_get_language (engine_desc);
 
163
  language = ibus_get_language_name (language_code);
 
164
 
 
165
  display_name = g_strdup_printf ("%s (%s)", language, name);
 
166
 
 
167
  return display_name;
 
168
}
 
169
 
 
170
static GDesktopAppInfo *
 
171
setup_app_info_for_id (const gchar *id)
 
172
{
 
173
  GDesktopAppInfo *app_info;
 
174
  gchar *desktop_file_name;
 
175
  gchar **strv;
 
176
 
 
177
  strv = g_strsplit (id, ":", 2);
 
178
  desktop_file_name = g_strdup_printf ("ibus-setup-%s.desktop", strv[0]);
 
179
  g_strfreev (strv);
 
180
 
 
181
  app_info = g_desktop_app_info_new (desktop_file_name);
 
182
  g_free (desktop_file_name);
 
183
 
 
184
  return app_info;
 
185
}
 
186
 
 
187
static void
 
188
input_chooser_repopulate (GtkListStore *active_sources_store)
 
189
{
 
190
  GtkBuilder *builder;
 
191
  GtkListStore *model;
 
192
 
 
193
  if (!input_chooser)
 
194
    return;
 
195
 
 
196
  builder = g_object_get_data (G_OBJECT (input_chooser), "builder");
 
197
  model = GTK_LIST_STORE (gtk_builder_get_object (builder, "input_source_model"));
 
198
 
 
199
  gtk_list_store_clear (model);
 
200
  populate_model (model, active_sources_store);
 
201
}
 
202
 
 
203
static void
 
204
update_ibus_active_sources (GtkBuilder *builder)
 
205
{
 
206
  GtkTreeView *tv;
 
207
  GtkTreeModel *model;
 
208
  GtkTreeIter iter;
 
209
  gchar *type, *id;
 
210
  gboolean ret;
 
211
 
 
212
  tv = GTK_TREE_VIEW (WID ("active_input_sources"));
 
213
  model = tree_view_get_actual_model (tv);
 
214
 
 
215
  ret = gtk_tree_model_get_iter_first (model, &iter);
 
216
  while (ret)
 
217
    {
 
218
      gtk_tree_model_get (model, &iter,
 
219
                          TYPE_COLUMN, &type,
 
220
                          ID_COLUMN, &id,
 
221
                          -1);
 
222
 
 
223
      if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
 
224
        {
 
225
          IBusEngineDesc *engine_desc = NULL;
 
226
          GDesktopAppInfo *app_info = NULL;
 
227
          gchar *display_name = NULL;
 
228
 
 
229
          engine_desc = g_hash_table_lookup (ibus_engines, id);
 
230
          if (engine_desc)
 
231
            {
 
232
              display_name = engine_get_display_name (engine_desc);
 
233
              app_info = setup_app_info_for_id (id);
 
234
 
 
235
              gtk_list_store_set (GTK_LIST_STORE (model), &iter,
 
236
                                  NAME_COLUMN, display_name,
 
237
                                  SETUP_COLUMN, app_info,
 
238
                                  -1);
 
239
              g_free (display_name);
 
240
              if (app_info)
 
241
                g_object_unref (app_info);
 
242
            }
 
243
        }
 
244
 
 
245
      g_free (type);
 
246
      g_free (id);
 
247
 
 
248
      ret = gtk_tree_model_iter_next (model, &iter);
 
249
    }
 
250
 
 
251
  input_chooser_repopulate (GTK_LIST_STORE (model));
 
252
}
 
253
 
 
254
static void
 
255
fetch_ibus_engines_result (GObject      *object,
 
256
                           GAsyncResult *result,
 
257
                           GtkBuilder   *builder)
 
258
{
 
259
  gboolean show_all_sources;
 
260
  GList *list, *l;
 
261
  GError *error;
 
262
 
 
263
  error = NULL;
 
264
  list = ibus_bus_list_engines_async_finish (ibus, result, &error);
 
265
 
 
266
  g_clear_object (&ibus_cancellable);
 
267
 
 
268
  if (!list && error)
 
269
    {
 
270
      g_warning ("Couldn't finish IBus request: %s", error->message);
 
271
      g_error_free (error);
 
272
      return;
 
273
    }
 
274
 
 
275
  show_all_sources = g_settings_get_boolean (input_sources_settings, "show-all-sources");
 
276
 
 
277
  /* Maps engine ids to engine description objects */
 
278
  ibus_engines = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
 
279
 
 
280
  for (l = list; l; l = l->next)
 
281
    {
 
282
      IBusEngineDesc *engine = l->data;
 
283
      const gchar *engine_id = ibus_engine_desc_get_name (engine);
 
284
 
 
285
      if (g_str_has_prefix (engine_id, "xkb:"))
 
286
        g_object_unref (engine);
 
287
      else
 
288
        g_hash_table_replace (ibus_engines, (gpointer)engine_id, engine);
 
289
    }
 
290
  g_list_free (list);
 
291
 
 
292
  update_ibus_active_sources (builder);
 
293
}
 
294
 
 
295
static void
 
296
fetch_ibus_engines (GtkBuilder *builder)
 
297
{
 
298
  ibus_cancellable = g_cancellable_new ();
 
299
 
 
300
  ibus_bus_list_engines_async (ibus,
 
301
                               -1,
 
302
                               ibus_cancellable,
 
303
                               (GAsyncReadyCallback)fetch_ibus_engines_result,
 
304
                               builder);
 
305
}
 
306
 
 
307
static void
 
308
maybe_start_ibus (void)
 
309
{
 
310
  /* IBus doesn't export API in the session bus. The only thing
 
311
   * we have there is a well known name which we can use as a
 
312
   * sure-fire way to activate it. */
 
313
  g_bus_unwatch_name (g_bus_watch_name (G_BUS_TYPE_SESSION,
 
314
                                        IBUS_SERVICE_IBUS,
 
315
                                        G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
 
316
                                        NULL,
 
317
                                        NULL,
 
318
                                        NULL,
 
319
                                        NULL));
 
320
}
 
321
 
 
322
static void
 
323
update_source_radios (GtkBuilder *builder)
 
324
{
 
325
  GtkWidget *same_source_radio = WID ("same-source-radio");
 
326
  GtkWidget *different_source_radio = WID ("different-source-radio");
 
327
  GtkWidget *default_source_radio = WID ("default-source-radio");
 
328
  GtkWidget *current_source_radio = WID ("current-source-radio");
 
329
  gboolean group_per_window = g_settings_get_boolean (libgnomekbd_settings, KEY_GROUP_PER_WINDOW);
 
330
  gboolean default_group = g_settings_get_int (libgnomekbd_settings, KEY_DEFAULT_GROUP) >= 0;
 
331
 
 
332
  gtk_widget_set_sensitive (default_source_radio, group_per_window);
 
333
  gtk_widget_set_sensitive (current_source_radio, group_per_window);
 
334
 
 
335
  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (different_source_radio)) != group_per_window)
 
336
    {
 
337
      if (group_per_window)
 
338
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (different_source_radio), TRUE);
 
339
      else
 
340
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (same_source_radio), TRUE);
 
341
    }
 
342
 
 
343
  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (default_source_radio)) != default_group)
 
344
    {
 
345
      if (default_group)
 
346
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (default_source_radio), TRUE);
 
347
      else
 
348
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (current_source_radio), TRUE);
 
349
    }
 
350
}
 
351
 
 
352
static void
 
353
update_orientation_combo (GtkBuilder *builder)
 
354
{
 
355
#ifdef HAVE_IBUS
 
356
  if (ibus != NULL)
 
357
    {
 
358
      IBusConfig *config = ibus_bus_get_config (ibus);
 
359
      GVariant *variant = ibus_config_get_value (config, IBUS_PANEL_SECTION, IBUS_ORIENTATION_KEY);
 
360
 
 
361
      g_return_if_fail (variant != NULL);
 
362
 
 
363
      if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32))
 
364
        {
 
365
          GtkComboBox *orientation_combo = GTK_COMBO_BOX (WID ("orientation-combo"));
 
366
          gint orientation = g_variant_get_int32 (variant);
 
367
 
 
368
          if (gtk_combo_box_get_active (orientation_combo) != orientation)
 
369
            gtk_combo_box_set_active (orientation_combo, orientation);
 
370
        }
 
371
      else
 
372
        g_warning ("Orientation setting has type '%s', expected type 'i'",
 
373
                   g_variant_get_type_string (variant));
 
374
 
 
375
      g_variant_unref (variant);
 
376
    }
 
377
#endif
 
378
}
 
379
 
 
380
static void
 
381
update_custom_font_buttons (GtkBuilder *builder)
 
382
{
 
383
#ifdef HAVE_IBUS
 
384
  if (ibus != NULL)
 
385
    {
 
386
      IBusConfig *config = ibus_bus_get_config (ibus);
 
387
      GVariant *variant = ibus_config_get_value (config, IBUS_PANEL_SECTION, IBUS_USE_CUSTOM_FONT_KEY);
 
388
      GtkToggleButton *custom_font_check = GTK_TOGGLE_BUTTON (WID ("custom-font-check"));
 
389
      GtkFontButton *custom_font_button = GTK_FONT_BUTTON (WID ("custom-font-button"));
 
390
 
 
391
      if (variant != NULL)
 
392
        {
 
393
          if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN))
 
394
            {
 
395
              gboolean use_custom_font = g_variant_get_boolean (variant);
 
396
 
 
397
              if (gtk_toggle_button_get_active (custom_font_check) != use_custom_font)
 
398
                gtk_toggle_button_set_active (custom_font_check, use_custom_font);
 
399
            }
 
400
          else
 
401
            g_warning ("Use custom font setting has type '%s', expected type 'b'",
 
402
                       g_variant_get_type_string (variant));
 
403
 
 
404
          g_variant_unref (variant);
 
405
        }
 
406
      else
 
407
        g_warning ("No use custom font setting '" IBUS_USE_CUSTOM_FONT_KEY "'");
 
408
 
 
409
      variant = ibus_config_get_value (config, IBUS_PANEL_SECTION, IBUS_CUSTOM_FONT_KEY);
 
410
 
 
411
      if (variant != NULL)
 
412
        {
 
413
          if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING))
 
414
            {
 
415
              const gchar *custom_font = g_variant_get_string (variant, NULL);
 
416
 
 
417
              if (g_strcmp0 (gtk_font_button_get_font_name (custom_font_button), custom_font))
 
418
                gtk_font_button_set_font_name (custom_font_button, custom_font);
 
419
            }
 
420
          else
 
421
            g_warning ("Custom font setting has type '%s', expected type 's'",
 
422
                       g_variant_get_type_string (variant));
 
423
 
 
424
          g_variant_unref (variant);
 
425
        }
 
426
      else
 
427
        g_warning ("No custom font setting '" IBUS_CUSTOM_FONT_KEY "'");
 
428
 
 
429
      gtk_widget_set_sensitive (GTK_WIDGET (custom_font_button),
 
430
                                gtk_toggle_button_get_active (custom_font_check));
 
431
    }
 
432
#endif
 
433
}
 
434
 
 
435
static void
 
436
source_radio_toggled (GtkToggleButton *widget,
 
437
                      gpointer         user_data)
 
438
{
 
439
  GtkWidget *same_source_radio = WID ("same-source-radio");
 
440
  GtkWidget *different_source_radio = WID ("different-source-radio");
 
441
  GtkWidget *default_source_radio = WID ("default-source-radio");
 
442
  GtkWidget *current_source_radio = WID ("current-source-radio");
 
443
  gboolean different_source_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (different_source_radio));
 
444
  gboolean default_source_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (default_source_radio));
 
445
  gboolean group_per_window = g_settings_get_boolean (libgnomekbd_settings, KEY_GROUP_PER_WINDOW);
 
446
  gboolean default_group = g_settings_get_int (libgnomekbd_settings, KEY_DEFAULT_GROUP) >= 0;
 
447
 
 
448
  if (different_source_active != group_per_window)
 
449
    g_settings_set_boolean (libgnomekbd_settings, KEY_GROUP_PER_WINDOW, different_source_active);
 
450
 
 
451
  if (default_source_active != default_group)
 
452
    g_settings_set_int (libgnomekbd_settings, KEY_DEFAULT_GROUP, default_source_active ? 0 : -1);
 
453
 
 
454
  gtk_widget_set_sensitive (default_source_radio, different_source_active);
 
455
  gtk_widget_set_sensitive (current_source_radio, different_source_active);
 
456
}
 
457
 
 
458
static void
 
459
orientation_combo_changed (GtkComboBox *widget,
 
460
                           gpointer     user_data)
 
461
{
 
462
#ifdef HAVE_IBUS
 
463
  if (ibus != NULL)
 
464
    {
 
465
      GtkBuilder *builder = user_data;
 
466
      GtkComboBox *orientation_combo = GTK_COMBO_BOX (WID ("orientation-combo"));
 
467
      IBusConfig *config = ibus_bus_get_config (ibus);
 
468
      gint orientation = -1;
 
469
      GVariant *variant = ibus_config_get_value (config, IBUS_PANEL_SECTION, IBUS_ORIENTATION_KEY);
 
470
 
 
471
      if (variant != NULL)
 
472
        {
 
473
          if (g_variant_is_of_type (variant, G_VARIANT_TYPE_INT32))
 
474
            orientation = g_variant_get_int32 (variant);
 
475
 
 
476
          g_variant_unref (variant);
 
477
        }
 
478
 
 
479
      if (gtk_combo_box_get_active (orientation_combo) != orientation)
 
480
        {
 
481
          orientation = gtk_combo_box_get_active (orientation_combo);
 
482
          variant = g_variant_new_int32 (orientation);
 
483
 
 
484
          ibus_config_set_value (config, IBUS_PANEL_SECTION, IBUS_ORIENTATION_KEY, variant);
 
485
        }
 
486
    }
 
487
#endif
 
488
}
 
489
 
 
490
static void
 
491
custom_font_changed (GtkWidget *widget,
 
492
                     gpointer   user_data)
 
493
{
 
494
#ifdef HAVE_IBUS
 
495
  if (ibus != NULL)
 
496
    {
 
497
      GtkBuilder *builder = user_data;
 
498
      GtkToggleButton *custom_font_check = GTK_TOGGLE_BUTTON (WID ("custom-font-check"));
 
499
      GtkFontButton *custom_font_button = GTK_FONT_BUTTON (WID ("custom-font-button"));
 
500
      IBusConfig *config = ibus_bus_get_config (ibus);
 
501
      gboolean update_setting = TRUE;
 
502
      gboolean use_custom_font;
 
503
      const gchar *custom_font;
 
504
      GVariant *variant = ibus_config_get_value (config, IBUS_PANEL_SECTION, IBUS_USE_CUSTOM_FONT_KEY);
 
505
 
 
506
      if (variant != NULL)
 
507
        {
 
508
          if (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN))
 
509
            {
 
510
              use_custom_font = g_variant_get_boolean (variant);
 
511
              update_setting = gtk_toggle_button_get_active (custom_font_check) != use_custom_font;
 
512
            }
 
513
 
 
514
          g_variant_unref (variant);
 
515
        }
 
516
 
 
517
      if (update_setting)
 
518
        {
 
519
          use_custom_font = gtk_toggle_button_get_active (custom_font_check);
 
520
          variant = g_variant_new_boolean (use_custom_font);
 
521
 
 
522
          ibus_config_set_value (config, IBUS_PANEL_SECTION, IBUS_USE_CUSTOM_FONT_KEY, variant);
 
523
        }
 
524
 
 
525
      update_setting = TRUE;
 
526
      variant = ibus_config_get_value (config, IBUS_PANEL_SECTION, IBUS_CUSTOM_FONT_KEY);
 
527
 
 
528
      if (variant != NULL)
 
529
        {
 
530
          if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING))
 
531
            {
 
532
              custom_font = g_variant_get_string (variant, NULL);
 
533
              update_setting = g_strcmp0 (gtk_font_button_get_font_name (custom_font_button), custom_font);
 
534
            }
 
535
 
 
536
          g_variant_unref (variant);
 
537
        }
 
538
 
 
539
      if (update_setting)
 
540
        {
 
541
          custom_font = gtk_font_button_get_font_name (custom_font_button);
 
542
          variant = g_variant_new_string (custom_font);
 
543
 
 
544
          ibus_config_set_value (config, IBUS_PANEL_SECTION, IBUS_CUSTOM_FONT_KEY, variant);
 
545
        }
 
546
 
 
547
      gtk_widget_set_sensitive (GTK_WIDGET (custom_font_button),
 
548
                                gtk_toggle_button_get_active (custom_font_check));
 
549
    }
 
550
#endif
 
551
}
 
552
 
 
553
static void
 
554
ibus_config_value_changed (IBusConfig *config,
 
555
                           gchar      *section,
 
556
                           gchar      *name,
 
557
                           GVariant   *value,
 
558
                           gpointer    user_data)
 
559
{
 
560
  if (g_strcmp0 (section, IBUS_PANEL_SECTION) == 0)
 
561
    {
 
562
      if (g_strcmp0 (name, IBUS_ORIENTATION_KEY) == 0)
 
563
        update_orientation_combo (builder);
 
564
      else if (g_strcmp0 (name, IBUS_USE_CUSTOM_FONT_KEY) == 0 ||
 
565
               g_strcmp0 (name, IBUS_CUSTOM_FONT_KEY) == 0)
 
566
        update_custom_font_buttons (builder);
 
567
    }
 
568
}
 
569
 
 
570
static void
 
571
ibus_connected (IBusBus  *bus,
 
572
                gpointer  user_data)
 
573
{
 
574
  GtkBuilder *builder = user_data;
 
575
  IBusConfig *config = ibus_bus_get_config (bus);
 
576
 
 
577
  g_signal_connect (config, "value-changed",
 
578
                    G_CALLBACK (ibus_config_value_changed), NULL);
 
579
 
 
580
  fetch_ibus_engines (builder);
 
581
 
 
582
  if (has_indicator_keyboard ())
 
583
    {
 
584
      update_source_radios (builder);
 
585
      update_orientation_combo (builder);
 
586
      update_custom_font_buttons (builder);
 
587
    }
 
588
 
 
589
  /* We've got everything we needed, don't want to be called again. */
 
590
  g_signal_handlers_disconnect_by_func (ibus, ibus_connected, builder);
 
591
}
 
592
 
 
593
static void
 
594
on_shell_appeared (GDBusConnection *connection,
 
595
                   const gchar     *name,
 
596
                   const gchar     *name_owner,
 
597
                   gpointer         data)
 
598
{
 
599
  GtkBuilder *builder = data;
 
600
 
 
601
  if (!ibus)
 
602
    {
 
603
      ibus = ibus_bus_new_async ();
 
604
      if (ibus_bus_is_connected (ibus))
 
605
        ibus_connected (ibus, builder);
 
606
      else
 
607
        g_signal_connect (ibus, "connected", G_CALLBACK (ibus_connected), builder);
 
608
    }
 
609
  maybe_start_ibus ();
 
610
}
 
611
#endif  /* HAVE_IBUS */
 
612
 
 
613
static gboolean
 
614
add_source_to_table (GtkTreeModel *model,
 
615
                     GtkTreePath  *path,
 
616
                     GtkTreeIter  *iter,
 
617
                     gpointer      data)
 
618
{
 
619
  GHashTable *hash = data;
 
620
  gchar *type;
 
621
  gchar *id;
 
622
 
 
623
  gtk_tree_model_get (model, iter,
 
624
                      TYPE_COLUMN, &type,
 
625
                      ID_COLUMN, &id,
 
626
                      -1);
 
627
 
 
628
  g_hash_table_add (hash, g_strconcat (type, id, NULL));
 
629
 
 
630
  g_free (type);
 
631
  g_free (id);
 
632
 
 
633
  return FALSE;
 
634
}
 
635
 
 
636
static void
 
637
populate_model (GtkListStore *store,
 
638
                GtkListStore *active_sources_store)
 
639
{
 
640
  GHashTable *active_sources_table;
 
641
  GtkTreeIter iter;
 
642
  const gchar *name;
 
643
  GList *sources, *tmp;
 
644
  gchar *source_id = NULL;
 
645
 
 
646
  active_sources_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
647
 
 
648
  gtk_tree_model_foreach (GTK_TREE_MODEL (active_sources_store),
 
649
                          add_source_to_table,
 
650
                          active_sources_table);
 
651
 
 
652
  sources = gnome_xkb_info_get_all_layouts (xkb_info);
 
653
 
 
654
  for (tmp = sources; tmp; tmp = tmp->next)
 
655
    {
 
656
      g_free (source_id);
 
657
      source_id = g_strconcat (INPUT_SOURCE_TYPE_XKB, tmp->data, NULL);
 
658
 
 
659
      if (g_hash_table_contains (active_sources_table, source_id))
 
660
        continue;
 
661
 
 
662
      gnome_xkb_info_get_layout_info (xkb_info, (const gchar *)tmp->data,
 
663
                                      &name, NULL, NULL, NULL);
 
664
 
 
665
      gtk_list_store_append (store, &iter);
 
666
      gtk_list_store_set (store, &iter,
 
667
                          NAME_COLUMN, name,
 
668
                          TYPE_COLUMN, INPUT_SOURCE_TYPE_XKB,
 
669
                          ID_COLUMN, tmp->data,
 
670
                          -1);
 
671
    }
 
672
  g_free (source_id);
 
673
 
 
674
  g_list_free (sources);
 
675
 
 
676
#ifdef HAVE_IBUS
 
677
  if (ibus_engines)
 
678
    {
 
679
      gchar *display_name;
 
680
 
 
681
      sources = g_hash_table_get_keys (ibus_engines);
 
682
 
 
683
      source_id = NULL;
 
684
      for (tmp = sources; tmp; tmp = tmp->next)
 
685
        {
 
686
          g_free (source_id);
 
687
          source_id = g_strconcat (INPUT_SOURCE_TYPE_IBUS, tmp->data, NULL);
 
688
 
 
689
          if (g_hash_table_contains (active_sources_table, source_id))
 
690
            continue;
 
691
 
 
692
          display_name = engine_get_display_name (g_hash_table_lookup (ibus_engines, tmp->data));
 
693
 
 
694
          gtk_list_store_append (store, &iter);
 
695
          gtk_list_store_set (store, &iter,
 
696
                              NAME_COLUMN, display_name,
 
697
                              TYPE_COLUMN, INPUT_SOURCE_TYPE_IBUS,
 
698
                              ID_COLUMN, tmp->data,
 
699
                              -1);
 
700
          g_free (display_name);
 
701
        }
 
702
      g_free (source_id);
 
703
 
 
704
      g_list_free (sources);
 
705
    }
 
706
#endif
 
707
 
 
708
  g_hash_table_destroy (active_sources_table);
 
709
}
 
710
 
 
711
static void
 
712
populate_with_active_sources (GtkListStore *store)
 
713
{
 
714
  GVariant *sources;
 
715
  GVariantIter iter;
 
716
  const gchar *name;
 
717
  const gchar *type;
 
718
  const gchar *id;
 
719
  gchar *display_name;
 
720
  GDesktopAppInfo *app_info;
 
721
  GtkTreeIter tree_iter;
 
722
 
 
723
  sources = g_settings_get_value (input_sources_settings, KEY_INPUT_SOURCES);
 
724
 
 
725
  g_variant_iter_init (&iter, sources);
 
726
  while (g_variant_iter_next (&iter, "(&s&s)", &type, &id))
 
727
    {
 
728
      display_name = NULL;
 
729
      app_info = NULL;
 
730
 
 
731
      if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
 
732
        {
 
733
          gnome_xkb_info_get_layout_info (xkb_info, id, &name, NULL, NULL, NULL);
 
734
          if (!name)
 
735
            {
 
736
              g_warning ("Couldn't find XKB input source '%s'", id);
 
737
              continue;
 
738
            }
 
739
          display_name = g_strdup (name);
 
740
        }
 
741
      else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
 
742
        {
 
743
#ifdef HAVE_IBUS
 
744
          IBusEngineDesc *engine_desc = NULL;
 
745
 
 
746
          if (ibus_engines)
 
747
            engine_desc = g_hash_table_lookup (ibus_engines, id);
 
748
 
 
749
          if (engine_desc)
 
750
            {
 
751
              display_name = engine_get_display_name (engine_desc);
 
752
              app_info = setup_app_info_for_id (id);
 
753
            }
 
754
#else
 
755
          g_warning ("IBus input source type specified but IBus support was not compiled");
 
756
          continue;
 
757
#endif
 
758
        }
 
759
      else
 
760
        {
 
761
          g_warning ("Unknown input source type '%s'", type);
 
762
          continue;
 
763
        }
 
764
 
 
765
      gtk_list_store_append (store, &tree_iter);
 
766
      gtk_list_store_set (store, &tree_iter,
 
767
                          NAME_COLUMN, display_name,
 
768
                          TYPE_COLUMN, type,
 
769
                          ID_COLUMN, id,
 
770
                          SETUP_COLUMN, app_info,
 
771
                          -1);
 
772
      g_free (display_name);
 
773
      if (app_info)
 
774
        g_object_unref (app_info);
 
775
    }
 
776
 
 
777
  g_variant_unref (sources);
 
778
}
 
779
 
 
780
static void
 
781
update_configuration (GtkTreeModel *model)
 
782
{
 
783
  GtkTreeIter iter;
 
784
  gchar *type;
 
785
  gchar *id;
 
786
  GVariantBuilder builder;
 
787
  GVariant *old_sources;
 
788
  const gchar *old_current_type;
 
789
  const gchar *old_current_id;
 
790
  guint old_current_index;
 
791
  guint old_n_sources;
 
792
  guint index;
 
793
 
 
794
  old_sources = g_settings_get_value (input_sources_settings, KEY_INPUT_SOURCES);
 
795
  old_current_index = g_settings_get_uint (input_sources_settings, KEY_CURRENT_INPUT_SOURCE);
 
796
  old_n_sources = g_variant_n_children (old_sources);
 
797
 
 
798
  if (old_n_sources > 0 && old_current_index < old_n_sources)
 
799
    {
 
800
      g_variant_get_child (old_sources,
 
801
                           old_current_index,
 
802
                           "(&s&s)",
 
803
                           &old_current_type,
 
804
                           &old_current_id);
 
805
    }
 
806
  else
 
807
    {
 
808
      old_current_type = "";
 
809
      old_current_id = "";
 
810
    }
 
811
 
 
812
  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
 
813
  index = 0;
 
814
  gtk_tree_model_get_iter_first (model, &iter);
 
815
  do
 
816
    {
 
817
      gtk_tree_model_get (model, &iter,
 
818
                          TYPE_COLUMN, &type,
 
819
                          ID_COLUMN, &id,
 
820
                          -1);
 
821
      if (index != old_current_index &&
 
822
          g_str_equal (type, old_current_type) &&
 
823
          g_str_equal (id, old_current_id))
 
824
        {
 
825
          g_settings_set_uint (input_sources_settings, KEY_CURRENT_INPUT_SOURCE, index);
 
826
        }
 
827
      g_variant_builder_add (&builder, "(ss)", type, id);
 
828
      g_free (type);
 
829
      g_free (id);
 
830
      index += 1;
 
831
    }
 
832
  while (gtk_tree_model_iter_next (model, &iter));
 
833
 
 
834
  g_settings_set_value (input_sources_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
 
835
  g_settings_apply (input_sources_settings);
 
836
 
 
837
  g_variant_unref (old_sources);
 
838
}
 
839
 
 
840
static gboolean
 
841
get_selected_iter (GtkBuilder    *builder,
 
842
                   GtkTreeModel **model,
 
843
                   GtkTreeIter   *iter)
 
844
{
 
845
  GtkTreeSelection *selection;
 
846
 
 
847
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (WID ("active_input_sources")));
 
848
 
 
849
  return gtk_tree_selection_get_selected (selection, model, iter);
 
850
}
 
851
 
 
852
static gint
 
853
idx_from_model_iter (GtkTreeModel *model,
 
854
                     GtkTreeIter  *iter)
 
855
{
 
856
  GtkTreePath *path;
 
857
  gint idx;
 
858
 
 
859
  path = gtk_tree_model_get_path (model, iter);
 
860
  if (path == NULL)
 
861
    return -1;
 
862
 
 
863
  idx = gtk_tree_path_get_indices (path)[0];
 
864
  gtk_tree_path_free (path);
 
865
 
 
866
  return idx;
 
867
}
 
868
 
 
869
static void
 
870
update_button_sensitivity (GtkBuilder *builder)
 
871
{
 
872
  GtkWidget *remove_button;
 
873
  GtkWidget *up_button;
 
874
  GtkWidget *down_button;
 
875
  GtkWidget *show_button;
 
876
  GtkWidget *settings_button;
 
877
  GtkTreeView *tv;
 
878
  GtkTreeModel *model;
 
879
  GtkTreeIter iter;
 
880
  gint n_active;
 
881
  gint index;
 
882
  gboolean settings_sensitive;
 
883
  GDesktopAppInfo *app_info;
 
884
 
 
885
  remove_button = WID("input_source_remove");
 
886
  show_button = WID("input_source_show");
 
887
  up_button = WID("input_source_move_up");
 
888
  down_button = WID("input_source_move_down");
 
889
  settings_button = WID("input_source_settings");
 
890
 
 
891
  tv = GTK_TREE_VIEW (WID ("active_input_sources"));
 
892
  n_active = gtk_tree_model_iter_n_children (gtk_tree_view_get_model (tv), NULL);
 
893
 
 
894
  if (get_selected_iter (builder, &model, &iter))
 
895
    {
 
896
      index = idx_from_model_iter (model, &iter);
 
897
      gtk_tree_model_get (model, &iter, SETUP_COLUMN, &app_info, -1);
 
898
    }
 
899
  else
 
900
    {
 
901
      index = -1;
 
902
      app_info = NULL;
 
903
    }
 
904
 
 
905
  settings_sensitive = (index >= 0 && app_info != NULL);
 
906
 
 
907
  if (app_info)
 
908
    g_object_unref (app_info);
 
909
 
 
910
  gtk_widget_set_sensitive (remove_button, index >= 0 && n_active > 1);
 
911
  gtk_widget_set_sensitive (show_button, index >= 0);
 
912
  gtk_widget_set_sensitive (up_button, index > 0);
 
913
  gtk_widget_set_sensitive (down_button, index >= 0 && index < n_active - 1);
 
914
  gtk_widget_set_visible (settings_button, settings_sensitive);
 
915
}
 
916
 
 
917
static void
 
918
set_selected_path (GtkBuilder  *builder,
 
919
                   GtkTreePath *path)
 
920
{
 
921
  GtkTreeSelection *selection;
 
922
 
 
923
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (WID ("active_input_sources")));
 
924
 
 
925
  gtk_tree_selection_select_path (selection, path);
 
926
}
 
927
 
 
928
static GtkTreeModel *
 
929
tree_view_get_actual_model (GtkTreeView *tv)
 
930
{
 
931
  GtkTreeModel *filtered_store;
 
932
 
 
933
  filtered_store = gtk_tree_view_get_model (tv);
 
934
 
 
935
  return gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filtered_store));
 
936
}
 
937
 
 
938
static void
 
939
chooser_response (GtkWidget *chooser, gint response_id, gpointer data)
 
940
{
 
941
  GtkBuilder *builder = data;
 
942
 
 
943
  if (response_id == GTK_RESPONSE_OK)
 
944
    {
 
945
      GtkTreeModel *model;
 
946
      GtkTreeIter iter;
 
947
 
 
948
      if (input_chooser_get_selected (chooser, &model, &iter))
 
949
        {
 
950
          GtkTreeView *tv;
 
951
          GtkListStore *child_model;
 
952
          GtkTreeIter child_iter, filter_iter;
 
953
          gchar *name;
 
954
          gchar *type;
 
955
          gchar *id;
 
956
          GDesktopAppInfo *app_info = NULL;
 
957
 
 
958
          gtk_tree_model_get (model, &iter,
 
959
                              NAME_COLUMN, &name,
 
960
                              TYPE_COLUMN, &type,
 
961
                              ID_COLUMN, &id,
 
962
                              -1);
 
963
 
 
964
#ifdef HAVE_IBUS
 
965
          if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
 
966
            app_info = setup_app_info_for_id (id);
 
967
#endif
 
968
 
 
969
          tv = GTK_TREE_VIEW (WID ("active_input_sources"));
 
970
          child_model = GTK_LIST_STORE (tree_view_get_actual_model (tv));
 
971
 
 
972
          gtk_list_store_append (child_model, &child_iter);
 
973
 
 
974
          gtk_list_store_set (child_model, &child_iter,
 
975
                              NAME_COLUMN, name,
 
976
                              TYPE_COLUMN, type,
 
977
                              ID_COLUMN, id,
 
978
                              SETUP_COLUMN, app_info,
 
979
                              -1);
 
980
          g_free (name);
 
981
          g_free (type);
 
982
          g_free (id);
 
983
          if (app_info)
 
984
            g_object_unref (app_info);
 
985
 
 
986
          gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (tv)),
 
987
                                                            &filter_iter,
 
988
                                                            &child_iter);
 
989
          gtk_tree_selection_select_iter (gtk_tree_view_get_selection (tv), &filter_iter);
 
990
 
 
991
          update_button_sensitivity (builder);
 
992
          update_configuration (GTK_TREE_MODEL (child_model));
 
993
        }
 
994
      else
 
995
        {
 
996
          g_debug ("nothing selected, nothing added");
 
997
        }
 
998
    }
 
999
 
 
1000
  gtk_widget_destroy (GTK_WIDGET (chooser));
 
1001
}
 
1002
 
 
1003
static void
 
1004
add_input (GtkButton *button, gpointer data)
 
1005
{
 
1006
  GtkBuilder *builder = data;
 
1007
  GtkWidget *chooser;
 
1008
  GtkWidget *toplevel;
 
1009
  GtkWidget *treeview;
 
1010
  GtkListStore *active_sources;
 
1011
 
 
1012
  g_debug ("add an input source");
 
1013
 
 
1014
  toplevel = gtk_widget_get_toplevel (WID ("active_input_sources"));
 
1015
  treeview = WID ("active_input_sources");
 
1016
  active_sources = GTK_LIST_STORE (tree_view_get_actual_model (GTK_TREE_VIEW (treeview)));
 
1017
 
 
1018
  chooser = input_chooser_new (GTK_WINDOW (toplevel), active_sources);
 
1019
  g_signal_connect (chooser, "response",
 
1020
                    G_CALLBACK (chooser_response), builder);
 
1021
}
 
1022
 
 
1023
static void
 
1024
remove_selected_input (GtkButton *button, gpointer data)
 
1025
{
 
1026
  GtkBuilder *builder = data;
 
1027
  GtkTreeModel *model;
 
1028
  GtkTreeModel *child_model;
 
1029
  GtkTreeIter iter;
 
1030
  GtkTreeIter child_iter;
 
1031
  GtkTreePath *path;
 
1032
 
 
1033
  g_debug ("remove selected input source");
 
1034
 
 
1035
  if (get_selected_iter (builder, &model, &iter) == FALSE)
 
1036
    return;
 
1037
 
 
1038
  path = gtk_tree_model_get_path (model, &iter);
 
1039
 
 
1040
  child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
 
1041
  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
 
1042
                                                    &child_iter,
 
1043
                                                    &iter);
 
1044
  gtk_list_store_remove (GTK_LIST_STORE (child_model), &child_iter);
 
1045
 
 
1046
  if (!gtk_tree_model_get_iter (model, &iter, path))
 
1047
    gtk_tree_path_prev (path);
 
1048
 
 
1049
  set_selected_path (builder, path);
 
1050
 
 
1051
  gtk_tree_path_free (path);
 
1052
 
 
1053
  update_button_sensitivity (builder);
 
1054
  update_configuration (child_model);
 
1055
}
 
1056
 
 
1057
static void
 
1058
move_selected_input_up (GtkButton *button, gpointer data)
 
1059
{
 
1060
  GtkBuilder *builder = data;
 
1061
  GtkTreeModel *model;
 
1062
  GtkTreeModel *child_model;
 
1063
  GtkTreeIter iter, prev;
 
1064
  GtkTreeIter child_iter, child_prev;
 
1065
  GtkTreePath *path;
 
1066
 
 
1067
  g_debug ("move selected input source up");
 
1068
 
 
1069
  if (!get_selected_iter (builder, &model, &iter))
 
1070
    return;
 
1071
 
 
1072
  prev = iter;
 
1073
  if (!gtk_tree_model_iter_previous (model, &prev))
 
1074
    return;
 
1075
 
 
1076
  path = gtk_tree_model_get_path (model, &prev);
 
1077
 
 
1078
  child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
 
1079
  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
 
1080
                                                    &child_iter,
 
1081
                                                    &iter);
 
1082
  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
 
1083
                                                    &child_prev,
 
1084
                                                    &prev);
 
1085
  gtk_list_store_swap (GTK_LIST_STORE (child_model), &child_iter, &child_prev);
 
1086
 
 
1087
  set_selected_path (builder, path);
 
1088
  gtk_tree_path_free (path);
 
1089
 
 
1090
  update_button_sensitivity (builder);
 
1091
  update_configuration (child_model);
 
1092
}
 
1093
 
 
1094
static void
 
1095
move_selected_input_down (GtkButton *button, gpointer data)
 
1096
{
 
1097
  GtkBuilder *builder = data;
 
1098
  GtkTreeModel *model;
 
1099
  GtkTreeModel *child_model;
 
1100
  GtkTreeIter iter, next;
 
1101
  GtkTreeIter child_iter, child_next;
 
1102
  GtkTreePath *path;
 
1103
 
 
1104
  g_debug ("move selected input source down");
 
1105
 
 
1106
  if (!get_selected_iter (builder, &model, &iter))
 
1107
    return;
 
1108
 
 
1109
  next = iter;
 
1110
  if (!gtk_tree_model_iter_next (model, &next))
 
1111
    return;
 
1112
 
 
1113
  path = gtk_tree_model_get_path (model, &next);
 
1114
 
 
1115
  child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
 
1116
  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
 
1117
                                                    &child_iter,
 
1118
                                                    &iter);
 
1119
  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
 
1120
                                                    &child_next,
 
1121
                                                    &next);
 
1122
  gtk_list_store_swap (GTK_LIST_STORE (child_model), &child_iter, &child_next);
 
1123
 
 
1124
  set_selected_path (builder, path);
 
1125
  gtk_tree_path_free (path);
 
1126
 
 
1127
  update_button_sensitivity (builder);
 
1128
  update_configuration (child_model);
 
1129
}
 
1130
 
 
1131
static void
 
1132
show_selected_layout (GtkButton *button, gpointer data)
 
1133
{
 
1134
  GtkBuilder *builder = data;
 
1135
  GtkTreeModel *model;
 
1136
  GtkTreeIter iter;
 
1137
  gchar *type;
 
1138
  gchar *id;
 
1139
  gchar *kbd_viewer_args;
 
1140
  const gchar *xkb_layout;
 
1141
  const gchar *xkb_variant;
 
1142
 
 
1143
  g_debug ("show selected layout");
 
1144
 
 
1145
  if (!get_selected_iter (builder, &model, &iter))
 
1146
    return;
 
1147
 
 
1148
  gtk_tree_model_get (model, &iter,
 
1149
                      TYPE_COLUMN, &type,
 
1150
                      ID_COLUMN, &id,
 
1151
                      -1);
 
1152
 
 
1153
  if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
 
1154
    {
 
1155
      gnome_xkb_info_get_layout_info (xkb_info, id, NULL, NULL, &xkb_layout, &xkb_variant);
 
1156
 
 
1157
      if (!xkb_layout || !xkb_layout[0])
 
1158
        {
 
1159
          g_warning ("Couldn't find XKB input source '%s'", id);
 
1160
          goto exit;
 
1161
        }
 
1162
    }
 
1163
  else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
 
1164
    {
 
1165
#ifdef HAVE_IBUS
 
1166
      IBusEngineDesc *engine_desc = NULL;
 
1167
 
 
1168
      if (ibus_engines)
 
1169
        engine_desc = g_hash_table_lookup (ibus_engines, id);
 
1170
 
 
1171
      if (engine_desc)
 
1172
        {
 
1173
          xkb_layout = ibus_engine_desc_get_layout (engine_desc);
 
1174
          xkb_variant = "";
 
1175
        }
 
1176
      else
 
1177
        {
 
1178
          g_warning ("Couldn't find IBus input source '%s'", id);
 
1179
          goto exit;
 
1180
        }
 
1181
#else
 
1182
      g_warning ("IBus input source type specified but IBus support was not compiled");
 
1183
      goto exit;
 
1184
#endif
 
1185
    }
 
1186
  else
 
1187
    {
 
1188
      g_warning ("Unknown input source type '%s'", type);
 
1189
      goto exit;
 
1190
    }
 
1191
 
 
1192
  if (xkb_variant[0])
 
1193
    kbd_viewer_args = g_strdup_printf ("gkbd-keyboard-display -l \"%s\t%s\"",
 
1194
                                       xkb_layout, xkb_variant);
 
1195
  else
 
1196
    kbd_viewer_args = g_strdup_printf ("gkbd-keyboard-display -l %s",
 
1197
                                       xkb_layout);
 
1198
 
 
1199
  g_spawn_command_line_async (kbd_viewer_args, NULL);
 
1200
 
 
1201
  g_free (kbd_viewer_args);
 
1202
 exit:
 
1203
  g_free (type);
 
1204
  g_free (id);
 
1205
}
 
1206
 
 
1207
static void
 
1208
show_selected_settings (GtkButton *button, gpointer data)
 
1209
{
 
1210
  GtkBuilder *builder = data;
 
1211
  GtkTreeModel *model;
 
1212
  GtkTreeIter iter;
 
1213
  GdkAppLaunchContext *ctx;
 
1214
  GDesktopAppInfo *app_info;
 
1215
  gchar *id;
 
1216
  GError *error = NULL;
 
1217
 
 
1218
  g_debug ("show selected layout");
 
1219
 
 
1220
  if (!get_selected_iter (builder, &model, &iter))
 
1221
    return;
 
1222
 
 
1223
  gtk_tree_model_get (model, &iter, SETUP_COLUMN, &app_info, -1);
 
1224
 
 
1225
  if (!app_info)
 
1226
    return;
 
1227
 
 
1228
  ctx = gdk_display_get_app_launch_context (gdk_display_get_default ());
 
1229
  gdk_app_launch_context_set_timestamp (ctx, gtk_get_current_event_time ());
 
1230
 
 
1231
  gtk_tree_model_get (model, &iter, ID_COLUMN, &id, -1);
 
1232
  g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (ctx),
 
1233
                               "IBUS_ENGINE_NAME",
 
1234
                               id);
 
1235
  g_free (id);
 
1236
 
 
1237
  if (!g_app_info_launch (G_APP_INFO (app_info), NULL, G_APP_LAUNCH_CONTEXT (ctx), &error))
 
1238
    {
 
1239
      g_warning ("Failed to launch input source setup: %s", error->message);
 
1240
      g_error_free (error);
 
1241
    }
 
1242
 
 
1243
  g_object_unref (ctx);
 
1244
  g_object_unref (app_info);
 
1245
}
 
1246
 
 
1247
static gboolean
 
1248
go_to_shortcuts (GtkLinkButton *button,
 
1249
                 CcRegionPanel *panel)
 
1250
{
 
1251
  CcShell *shell;
 
1252
  const gchar *argv[] = { "shortcuts", "Typing", NULL };
 
1253
  GError *error = NULL;
 
1254
 
 
1255
  g_clear_object (&input_sources_settings);
 
1256
 
 
1257
  shell = cc_panel_get_shell (CC_PANEL (panel));
 
1258
  if (!cc_shell_set_active_panel_from_id (shell, "keyboard", argv, &error))
 
1259
    {
 
1260
      g_warning ("Failed to activate Keyboard panel: %s", error->message);
 
1261
      g_error_free (error);
 
1262
    }
 
1263
 
 
1264
  return TRUE;
 
1265
}
 
1266
 
 
1267
static void
 
1268
input_sources_changed (GSettings  *settings,
 
1269
                       gchar      *key,
 
1270
                       GtkBuilder *builder)
 
1271
{
 
1272
  GtkWidget *treeview;
 
1273
  GtkTreeModel *store;
 
1274
  GtkTreePath *path;
 
1275
  GtkTreeIter iter;
 
1276
  GtkTreeModel *model;
 
1277
 
 
1278
  treeview = WID("active_input_sources");
 
1279
  store = tree_view_get_actual_model (GTK_TREE_VIEW (treeview));
 
1280
 
 
1281
  if (get_selected_iter (builder, &model, &iter))
 
1282
    path = gtk_tree_model_get_path (model, &iter);
 
1283
  else
 
1284
    path = NULL;
 
1285
 
 
1286
  gtk_list_store_clear (GTK_LIST_STORE (store));
 
1287
  populate_with_active_sources (GTK_LIST_STORE (store));
 
1288
 
 
1289
  if (path)
 
1290
    {
 
1291
      set_selected_path (builder, path);
 
1292
      gtk_tree_path_free (path);
 
1293
    }
 
1294
}
 
1295
 
 
1296
static void
 
1297
update_shortcut_label (GtkWidget  *widget,
 
1298
                       const char *value)
 
1299
{
 
1300
  char *text;
 
1301
  guint accel_key, *keycode;
 
1302
  GdkModifierType mods;
 
1303
 
 
1304
  if (value == NULL || *value == '\0')
 
1305
    {
 
1306
      gtk_label_set_text (GTK_LABEL (widget), "\342\200\224");
 
1307
      return;
 
1308
    }
 
1309
  gtk_accelerator_parse_with_keycode (value, &accel_key, &keycode, &mods);
 
1310
  if (accel_key == 0 && keycode == NULL && mods == 0)
 
1311
    {
 
1312
      gtk_label_set_text (GTK_LABEL (widget), "\342\200\224");
 
1313
      g_warning ("Failed to parse keyboard shortcut: '%s'", value);
 
1314
      return;
 
1315
    }
 
1316
 
 
1317
  text = gtk_accelerator_get_label_with_keycode (gtk_widget_get_display (widget), accel_key, *keycode, mods);
 
1318
  g_free (keycode);
 
1319
  gtk_label_set_text (GTK_LABEL (widget), text);
 
1320
  g_free (text);
 
1321
}
 
1322
 
 
1323
static void
 
1324
update_shortcuts (GtkBuilder *builder)
 
1325
{
 
1326
  char **previous, **next;
 
1327
  GSettings *settings;
 
1328
 
 
1329
  settings = g_settings_new ("org.gnome.desktop.wm.keybindings");
 
1330
 
 
1331
  previous = g_settings_get_strv (settings, "switch-input-source-backward");
 
1332
  next = g_settings_get_strv (settings, "switch-input-source");
 
1333
 
 
1334
  update_shortcut_label (WID ("prev-source-shortcut-label"), previous[0]);
 
1335
  update_shortcut_label (WID ("next-source-shortcut-label"), next[0]);
 
1336
 
 
1337
  g_strfreev (previous);
 
1338
  g_strfreev (next);
 
1339
}
 
1340
 
 
1341
static void
 
1342
libgnomekbd_settings_changed (GSettings *settings,
 
1343
                              gchar     *key,
 
1344
                              gpointer   user_data)
 
1345
{
 
1346
  if (g_strcmp0 (key, KEY_GROUP_PER_WINDOW) == 0 || g_strcmp0 (key, KEY_DEFAULT_GROUP) == 0)
 
1347
    update_source_radios (user_data);
 
1348
}
 
1349
 
 
1350
static gboolean
 
1351
active_sources_visible_func (GtkTreeModel *model,
 
1352
                             GtkTreeIter  *iter,
 
1353
                             gpointer      data)
 
1354
{
 
1355
  gchar *display_name;
 
1356
 
 
1357
  gtk_tree_model_get (model, iter, NAME_COLUMN, &display_name, -1);
 
1358
 
 
1359
  if (!display_name)
 
1360
    return FALSE;
 
1361
 
 
1362
  g_free (display_name);
 
1363
 
 
1364
  return TRUE;
 
1365
}
 
1366
 
 
1367
static GtkEntryAccelPostAction
 
1368
shortcut_key_pressed (GtkEntryAccel   *entry,
 
1369
                      guint           *key,
 
1370
                      guint           *code,
 
1371
                      GdkModifierType *mask,
 
1372
                      gpointer         user_data)
 
1373
{
 
1374
  GtkBuilder *builder = user_data;
 
1375
  CcRegionKeyboardItem *item = NULL;
 
1376
  gboolean edited;
 
1377
 
 
1378
  if (entry == GTK_ENTRY_ACCEL (WID ("prev-source-entry")))
 
1379
    item = prev_source_item;
 
1380
  else if (entry == GTK_ENTRY_ACCEL (WID ("next-source-entry")))
 
1381
    item = next_source_item;
 
1382
 
 
1383
  if (*mask == 0 && *key == GDK_KEY_Escape)
 
1384
    return GTK_ENTRY_ACCEL_CANCEL;
 
1385
 
 
1386
  if (*mask == 0 && *key == GDK_KEY_BackSpace)
 
1387
    {
 
1388
      *key = 0;
 
1389
      *code = 0;
 
1390
      *mask = 0;
 
1391
 
 
1392
      return GTK_ENTRY_ACCEL_UPDATE;
 
1393
    }
 
1394
 
 
1395
  if ((*mask & ~GDK_LOCK_MASK) == 0 &&
 
1396
      (*key == GDK_KEY_Tab ||
 
1397
       *key == GDK_KEY_KP_Tab ||
 
1398
       *key == GDK_KEY_ISO_Left_Tab ||
 
1399
       *key == GDK_KEY_3270_BackTab))
 
1400
    return GTK_ENTRY_ACCEL_IGNORE;
 
1401
 
 
1402
  edited = keyboard_shortcuts_accel_edited (item,
 
1403
                                            *key,
 
1404
                                            *code,
 
1405
                                            *mask,
 
1406
                                            gtk_widget_get_toplevel (GTK_WIDGET (entry)));
 
1407
 
 
1408
  return edited ? GTK_ENTRY_ACCEL_UPDATE : GTK_ENTRY_ACCEL_IGNORE;
 
1409
}
 
1410
 
 
1411
static void
 
1412
builder_finalized (gpointer  data,
 
1413
                   GObject  *where_the_object_was)
 
1414
{
 
1415
  keyboard_shortcuts_dispose ();
 
1416
 
 
1417
  g_clear_object (&input_sources_settings);
 
1418
  g_clear_object (&libgnomekbd_settings);
 
1419
  g_clear_object (&indicator_settings);
 
1420
  g_clear_object (&media_key_settings);
 
1421
  g_clear_object (&next_source_item);
 
1422
  g_clear_object (&prev_source_item);
 
1423
 
 
1424
#ifdef HAVE_IBUS
 
1425
  clear_ibus ();
 
1426
#endif
 
1427
}
 
1428
 
 
1429
static gboolean
 
1430
get_key_setting (GValue   *value,
 
1431
                 GVariant *variant,
 
1432
                 gpointer  user_data)
 
1433
{
 
1434
    gchar **switch_key;
 
1435
 
 
1436
    switch_key = g_variant_get_strv (variant, NULL);
 
1437
    g_value_set_string (value, switch_key[0]);
 
1438
 
 
1439
 
 
1440
    return TRUE;
 
1441
}
 
1442
 
 
1443
static GVariant *
 
1444
set_key_setting (const GValue   *value,
 
1445
                 const GVariantType *expected_type,
 
1446
                 gpointer  user_data)
 
1447
{
 
1448
    gchar *switch_key;
 
1449
    gchar **switch_strv;
 
1450
    GVariant *ret = NULL;
 
1451
 
 
1452
    switch_strv = g_settings_get_strv(media_key_settings, user_data);
 
1453
    switch_key = g_value_get_string (value);
 
1454
    switch_strv[0] = g_strdup (switch_key);
 
1455
 
 
1456
    ret = g_variant_new_strv ((const gchar * const *) switch_strv, -1);
 
1457
 
 
1458
    return ret;
 
1459
}
 
1460
 
 
1461
 
 
1462
void
 
1463
setup_input_tabs (GtkBuilder    *builder_,
 
1464
                  CcRegionPanel *panel)
 
1465
{
 
1466
  GtkWidget *treeview;
 
1467
  GtkTreeViewColumn *column;
 
1468
  GtkCellRenderer *cell;
 
1469
  GtkListStore *store;
 
1470
  GtkTreeModel *filtered_store;
 
1471
  GtkTreeSelection *selection;
 
1472
 
 
1473
  builder = builder_;
 
1474
 
 
1475
  g_object_weak_ref (G_OBJECT (builder), builder_finalized, NULL);
 
1476
 
 
1477
  keyboard_shortcuts_init ();
 
1478
 
 
1479
  prev_source_item = g_object_ref (keyboard_shortcuts_get_item (MEDIA_KEYS_SCHEMA_ID,
 
1480
                                                                KEY_PREV_INPUT_SOURCE));
 
1481
  next_source_item = g_object_ref (keyboard_shortcuts_get_item (MEDIA_KEYS_SCHEMA_ID,
 
1482
                                                                KEY_NEXT_INPUT_SOURCE));
 
1483
 
 
1484
  /* set up the list of active inputs */
 
1485
  treeview = WID("active_input_sources");
 
1486
  column = gtk_tree_view_column_new ();
 
1487
  cell = gtk_cell_renderer_text_new ();
 
1488
  gtk_tree_view_column_pack_start (column, cell, TRUE);
 
1489
  gtk_tree_view_column_add_attribute (column, cell, "text", NAME_COLUMN);
 
1490
  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
 
1491
 
 
1492
  store = gtk_list_store_new (N_COLUMNS,
 
1493
                              G_TYPE_STRING,
 
1494
                              G_TYPE_STRING,
 
1495
                              G_TYPE_STRING,
 
1496
                              G_TYPE_DESKTOP_APP_INFO);
 
1497
 
 
1498
  gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store));
 
1499
 
 
1500
  input_sources_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
 
1501
 
 
1502
  g_settings_delay (input_sources_settings);
 
1503
 
 
1504
  if (!xkb_info)
 
1505
    xkb_info = gnome_xkb_info_new ();
 
1506
 
 
1507
#ifdef HAVE_IBUS
 
1508
  ibus_init ();
 
1509
  shell_name_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
 
1510
                                          "org.gnome.Shell",
 
1511
                                          G_BUS_NAME_WATCHER_FLAGS_NONE,
 
1512
                                          on_shell_appeared,
 
1513
                                          NULL,
 
1514
                                          builder,
 
1515
                                          NULL);
 
1516
#endif
 
1517
 
 
1518
  populate_with_active_sources (store);
 
1519
 
 
1520
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
 
1521
  g_signal_connect_swapped (selection, "changed",
 
1522
                            G_CALLBACK (update_button_sensitivity), builder);
 
1523
 
 
1524
  /* Some input source types might have their info loaded
 
1525
   * asynchronously. In that case we don't want to show them
 
1526
   * immediately so we use a filter model on top of the real model
 
1527
   * which mirrors the GSettings key. */
 
1528
  filtered_store = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
 
1529
  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filtered_store),
 
1530
                                          active_sources_visible_func,
 
1531
                                          NULL,
 
1532
                                          NULL);
 
1533
  gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), filtered_store);
 
1534
 
 
1535
  /* set up the buttons */
 
1536
  g_signal_connect (WID("input_source_add"), "clicked",
 
1537
                    G_CALLBACK (add_input), builder);
 
1538
  g_signal_connect (WID("input_source_remove"), "clicked",
 
1539
                    G_CALLBACK (remove_selected_input), builder);
 
1540
  g_signal_connect (WID("input_source_move_up"), "clicked",
 
1541
                    G_CALLBACK (move_selected_input_up), builder);
 
1542
  g_signal_connect (WID("input_source_move_down"), "clicked",
 
1543
                    G_CALLBACK (move_selected_input_down), builder);
 
1544
  g_signal_connect (WID("input_source_show"), "clicked",
 
1545
                    G_CALLBACK (show_selected_layout), builder);
 
1546
  g_signal_connect (WID("input_source_settings"), "clicked",
 
1547
                    G_CALLBACK (show_selected_settings), builder);
 
1548
  g_signal_connect (WID("jump-to-shortcuts"), "activate-link",
 
1549
                    G_CALLBACK (go_to_shortcuts), panel);
 
1550
  g_signal_connect (G_OBJECT (input_sources_settings),
 
1551
                    "changed::" KEY_INPUT_SOURCES,
 
1552
                    G_CALLBACK (input_sources_changed),
 
1553
                    builder);
 
1554
 
 
1555
  if (has_indicator_keyboard ())
 
1556
    {
 
1557
      libgnomekbd_settings = g_settings_new (LIBGNOMEKBD_DESKTOP_SCHEMA_ID);
 
1558
      indicator_settings = g_settings_new (INDICATOR_KEYBOARD_SCHEMA_ID);
 
1559
      media_key_settings = g_settings_new (MEDIA_KEYS_SCHEMA_ID);
 
1560
 
 
1561
      update_source_radios (builder);
 
1562
      update_orientation_combo (builder);
 
1563
      update_custom_font_buttons (builder);
 
1564
 
 
1565
      g_settings_bind (indicator_settings,
 
1566
                       KEY_VISIBLE,
 
1567
                       WID ("show-indicator-check"),
 
1568
                       "active",
 
1569
                       G_SETTINGS_BIND_DEFAULT);
 
1570
      g_settings_bind_with_mapping (media_key_settings,
 
1571
                                    KEY_PREV_INPUT_SOURCE,
 
1572
                                    WID ("prev-source-entry"),
 
1573
                                    "accel",
 
1574
                                    G_SETTINGS_BIND_DEFAULT,
 
1575
                                    get_key_setting,
 
1576
                                    set_key_setting,
 
1577
                                    KEY_PREV_INPUT_SOURCE, NULL);
 
1578
      g_settings_bind_with_mapping (media_key_settings,
 
1579
                                    KEY_NEXT_INPUT_SOURCE,
 
1580
                                    WID ("next-source-entry"),
 
1581
                                    "accel",
 
1582
                                    G_SETTINGS_BIND_DEFAULT,
 
1583
                                    get_key_setting,
 
1584
                                    set_key_setting,
 
1585
                                    KEY_NEXT_INPUT_SOURCE, NULL);
 
1586
 
 
1587
      g_signal_connect (WID ("prev-source-entry"), "key-pressed",
 
1588
                        G_CALLBACK (shortcut_key_pressed), builder);
 
1589
      g_signal_connect (WID ("next-source-entry"), "key-pressed",
 
1590
                        G_CALLBACK (shortcut_key_pressed), builder);
 
1591
      g_signal_connect (WID ("same-source-radio"), "toggled",
 
1592
                        G_CALLBACK (source_radio_toggled), builder);
 
1593
      g_signal_connect (WID ("different-source-radio"), "toggled",
 
1594
                        G_CALLBACK (source_radio_toggled), builder);
 
1595
      g_signal_connect (WID ("default-source-radio"), "toggled",
 
1596
                        G_CALLBACK (source_radio_toggled), builder);
 
1597
      g_signal_connect (WID ("current-source-radio"), "toggled",
 
1598
                        G_CALLBACK (source_radio_toggled), builder);
 
1599
      g_signal_connect (WID ("orientation-combo"), "changed",
 
1600
                        G_CALLBACK (orientation_combo_changed), builder);
 
1601
      g_signal_connect (WID ("custom-font-check"), "toggled",
 
1602
                        G_CALLBACK (custom_font_changed), builder);
 
1603
      g_signal_connect (WID ("custom-font-button"), "font-set",
 
1604
                        G_CALLBACK (custom_font_changed), builder);
 
1605
      g_signal_connect (libgnomekbd_settings,
 
1606
                        "changed",
 
1607
                        G_CALLBACK (libgnomekbd_settings_changed),
 
1608
                        builder);
 
1609
    }
 
1610
  else
 
1611
    {
 
1612
      g_settings_bind (input_sources_settings, "per-window",
 
1613
                       WID("per-window-radio-true"), "active",
 
1614
                       G_SETTINGS_BIND_DEFAULT);
 
1615
      g_settings_bind (input_sources_settings, "per-window",
 
1616
                       WID("per-window-radio-false"), "active",
 
1617
                       G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_INVERT_BOOLEAN);
 
1618
      /* because we are in delay-apply mode */
 
1619
      g_signal_connect_swapped (WID("per-window-radio-true"), "clicked",
 
1620
                                G_CALLBACK (g_settings_apply), input_sources_settings);
 
1621
      g_signal_connect_swapped (WID("per-window-radio-false"), "clicked",
 
1622
                                G_CALLBACK (g_settings_apply), input_sources_settings);
 
1623
 
 
1624
      update_shortcuts (builder);
 
1625
    }
 
1626
}
 
1627
 
 
1628
static void
 
1629
filter_clear (GtkEntry             *entry,
 
1630
              GtkEntryIconPosition  icon_pos,
 
1631
              GdkEvent             *event,
 
1632
              gpointer              user_data)
 
1633
{
 
1634
  gtk_entry_set_text (entry, "");
 
1635
}
 
1636
 
 
1637
static gchar **search_pattern_list;
 
1638
 
 
1639
static void
 
1640
filter_changed (GtkBuilder *builder)
 
1641
{
 
1642
  GtkTreeModelFilter *filtered_model;
 
1643
  GtkTreeView *tree_view;
 
1644
  GtkTreeSelection *selection;
 
1645
  GtkTreeIter selected_iter;
 
1646
  GtkWidget *filter_entry;
 
1647
  const gchar *pattern;
 
1648
  gchar *upattern;
 
1649
 
 
1650
  filter_entry = WID ("input_source_filter");
 
1651
  pattern = gtk_entry_get_text (GTK_ENTRY (filter_entry));
 
1652
  upattern = g_utf8_strup (pattern, -1);
 
1653
  if (!g_strcmp0 (pattern, ""))
 
1654
    g_object_set (G_OBJECT (filter_entry),
 
1655
                  "secondary-icon-name", "edit-find-symbolic",
 
1656
                  "secondary-icon-activatable", FALSE,
 
1657
                  "secondary-icon-sensitive", FALSE,
 
1658
                  NULL);
 
1659
  else
 
1660
    g_object_set (G_OBJECT (filter_entry),
 
1661
                  "secondary-icon-name", "edit-clear-symbolic",
 
1662
                  "secondary-icon-activatable", TRUE,
 
1663
                  "secondary-icon-sensitive", TRUE,
 
1664
                  NULL);
 
1665
 
 
1666
  if (search_pattern_list != NULL)
 
1667
    g_strfreev (search_pattern_list);
 
1668
 
 
1669
  search_pattern_list = g_strsplit (upattern, " ", -1);
 
1670
  g_free (upattern);
 
1671
 
 
1672
  filtered_model = GTK_TREE_MODEL_FILTER (gtk_builder_get_object (builder, "filtered_input_source_model"));
 
1673
  gtk_tree_model_filter_refilter (filtered_model);
 
1674
 
 
1675
  tree_view = GTK_TREE_VIEW (WID ("filtered_input_source_list"));
 
1676
  selection = gtk_tree_view_get_selection (tree_view);
 
1677
  if (gtk_tree_selection_get_selected (selection, NULL, &selected_iter))
 
1678
    {
 
1679
      GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (filtered_model),
 
1680
                                                   &selected_iter);
 
1681
      gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0.5);
 
1682
      gtk_tree_path_free (path);
 
1683
    }
 
1684
  else
 
1685
    {
 
1686
      GtkTreeIter iter;
 
1687
      if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (filtered_model), &iter))
 
1688
        gtk_tree_selection_select_iter (selection, &iter);
 
1689
    }
 
1690
}
 
1691
 
 
1692
static void
 
1693
selection_changed (GtkTreeSelection *selection,
 
1694
                   GtkBuilder       *builder)
 
1695
{
 
1696
  gtk_widget_set_sensitive (WID ("ok-button"),
 
1697
                            gtk_tree_selection_get_selected (selection, NULL, NULL));
 
1698
}
 
1699
 
 
1700
static void
 
1701
row_activated (GtkTreeView       *tree_view,
 
1702
               GtkTreePath       *path,
 
1703
               GtkTreeViewColumn *column,
 
1704
               GtkBuilder        *builder)
 
1705
{
 
1706
  GtkWidget *add_button;
 
1707
  GtkWidget *dialog;
 
1708
 
 
1709
  add_button = WID ("ok-button");
 
1710
  dialog = WID ("input_source_chooser");
 
1711
  if (gtk_widget_is_sensitive (add_button))
 
1712
    gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
 
1713
}
 
1714
 
 
1715
static void
 
1716
entry_activated (GtkBuilder *builder,
 
1717
                 gpointer    data)
 
1718
{
 
1719
  row_activated (NULL, NULL, NULL, builder);
 
1720
}
 
1721
 
 
1722
static gboolean
 
1723
filter_func (GtkTreeModel *model,
 
1724
             GtkTreeIter  *iter,
 
1725
             gpointer      data)
 
1726
{
 
1727
  gchar *name = NULL;
 
1728
  gchar **pattern;
 
1729
  gboolean rv = TRUE;
 
1730
 
 
1731
  if (search_pattern_list == NULL || search_pattern_list[0] == NULL)
 
1732
    return TRUE;
 
1733
 
 
1734
  gtk_tree_model_get (model, iter,
 
1735
                      NAME_COLUMN, &name,
 
1736
                      -1);
 
1737
 
 
1738
  pattern = search_pattern_list;
 
1739
  do {
 
1740
    gboolean is_pattern_found = FALSE;
 
1741
    gchar *udesc = g_utf8_strup (name, -1);
 
1742
    if (udesc != NULL && g_strstr_len (udesc, -1, *pattern))
 
1743
      {
 
1744
        is_pattern_found = TRUE;
 
1745
      }
 
1746
    g_free (udesc);
 
1747
 
 
1748
    if (!is_pattern_found)
 
1749
      {
 
1750
        rv = FALSE;
 
1751
        break;
 
1752
      }
 
1753
 
 
1754
  } while (*++pattern != NULL);
 
1755
 
 
1756
  g_free (name);
 
1757
 
 
1758
  return rv;
 
1759
}
 
1760
 
 
1761
static GtkWidget *
 
1762
input_chooser_new (GtkWindow    *main_window,
 
1763
                   GtkListStore *active_sources)
 
1764
{
 
1765
  GtkBuilder *builder;
 
1766
  GtkWidget *chooser;
 
1767
  GtkWidget *filtered_list;
 
1768
  GtkWidget *filter_entry;
 
1769
  GtkTreeViewColumn *visible_column;
 
1770
  GtkTreeSelection *selection;
 
1771
  GtkListStore *model;
 
1772
  GtkTreeModelFilter *filtered_model;
 
1773
  GtkTreeIter iter;
 
1774
 
 
1775
  builder = gtk_builder_new ();
 
1776
  gtk_builder_add_from_file (builder,
 
1777
                             GNOMECC_UI_DIR "/gnome-region-panel-input-chooser.ui",
 
1778
                             NULL);
 
1779
  chooser = WID ("input_source_chooser");
 
1780
  input_chooser = chooser;
 
1781
  g_object_add_weak_pointer (G_OBJECT (chooser), (gpointer *) &input_chooser);
 
1782
  g_object_set_data_full (G_OBJECT (chooser), "builder", builder, g_object_unref);
 
1783
 
 
1784
  filtered_list = WID ("filtered_input_source_list");
 
1785
  filter_entry = WID ("input_source_filter");
 
1786
 
 
1787
  g_object_set_data (G_OBJECT (chooser),
 
1788
                     "filtered_input_source_list", filtered_list);
 
1789
  visible_column =
 
1790
    gtk_tree_view_column_new_with_attributes ("Input Sources",
 
1791
                                              gtk_cell_renderer_text_new (),
 
1792
                                              "text", NAME_COLUMN,
 
1793
                                              NULL);
 
1794
 
 
1795
  gtk_window_set_transient_for (GTK_WINDOW (chooser), main_window);
 
1796
 
 
1797
  gtk_tree_view_append_column (GTK_TREE_VIEW (filtered_list),
 
1798
                               visible_column);
 
1799
  /* We handle searching ourselves, thank you. */
 
1800
  gtk_tree_view_set_enable_search (GTK_TREE_VIEW (filtered_list), FALSE);
 
1801
  gtk_tree_view_set_search_column (GTK_TREE_VIEW (filtered_list), -1);
 
1802
 
 
1803
  g_signal_connect_swapped (G_OBJECT (filter_entry), "activate",
 
1804
                            G_CALLBACK (entry_activated), builder);
 
1805
  g_signal_connect_swapped (G_OBJECT (filter_entry), "notify::text",
 
1806
                            G_CALLBACK (filter_changed), builder);
 
1807
 
 
1808
  g_signal_connect (G_OBJECT (filter_entry), "icon-release",
 
1809
                    G_CALLBACK (filter_clear), NULL);
 
1810
 
 
1811
  filtered_model = GTK_TREE_MODEL_FILTER (gtk_builder_get_object (builder, "filtered_input_source_model"));
 
1812
  model = GTK_LIST_STORE (gtk_builder_get_object (builder, "input_source_model"));
 
1813
 
 
1814
  populate_model (model, active_sources);
 
1815
 
 
1816
  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
 
1817
                                        NAME_COLUMN, GTK_SORT_ASCENDING);
 
1818
 
 
1819
  gtk_tree_model_filter_set_visible_func (filtered_model,
 
1820
                                          filter_func,
 
1821
                                          NULL, NULL);
 
1822
 
 
1823
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (filtered_list));
 
1824
 
 
1825
  g_signal_connect (G_OBJECT (selection), "changed",
 
1826
                    G_CALLBACK (selection_changed), builder);
 
1827
 
 
1828
  if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (filtered_model), &iter))
 
1829
    gtk_tree_selection_select_iter (selection, &iter);
 
1830
 
 
1831
  g_signal_connect (G_OBJECT (filtered_list), "row-activated",
 
1832
                    G_CALLBACK (row_activated), builder);
 
1833
 
 
1834
  gtk_widget_grab_focus (filter_entry);
 
1835
 
 
1836
  gtk_widget_show (chooser);
 
1837
 
 
1838
  return chooser;
 
1839
}
 
1840
 
 
1841
static gboolean
 
1842
input_chooser_get_selected (GtkWidget     *dialog,
 
1843
                            GtkTreeModel **model,
 
1844
                            GtkTreeIter   *iter)
 
1845
{
 
1846
  GtkWidget *tv;
 
1847
  GtkTreeSelection *selection;
 
1848
 
 
1849
  tv = g_object_get_data (G_OBJECT (dialog), "filtered_input_source_list");
 
1850
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
 
1851
 
 
1852
  return gtk_tree_selection_get_selected (selection, model, iter);
 
1853
}