~ctf/unity-settings-daemon/bug1389099_mic_volume_icons

« back to all changes in this revision

Viewing changes to plugins/keyboard/gsd-keyboard-manager.c

  • Committer: Package Import Robot
  • Author(s): Robert Ancell
  • Date: 2014-02-07 11:44:36 UTC
  • Revision ID: package-import@ubuntu.com-20140207114436-7t5u3yvwc4ul7w3e
Tags: upstream-14.04.0
ImportĀ upstreamĀ versionĀ 14.04.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright Ā© 2001 Ximian, Inc.
 
4
 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
 
5
 * Written by Sergey V. Oudaltsov <svu@users.sourceforge.net>
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
20
 *
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
 
 
25
#include <sys/types.h>
 
26
#include <sys/wait.h>
 
27
#include <stdlib.h>
 
28
#include <stdio.h>
 
29
#include <unistd.h>
 
30
#include <string.h>
 
31
#include <errno.h>
 
32
 
 
33
#include <locale.h>
 
34
 
 
35
#include <glib.h>
 
36
#include <glib/gi18n.h>
 
37
#include <gdk/gdk.h>
 
38
#include <gdk/gdkx.h>
 
39
#include <gtk/gtk.h>
 
40
 
 
41
#include <X11/XKBlib.h>
 
42
#include <X11/keysym.h>
 
43
#include <X11/extensions/XKBrules.h>
 
44
 
 
45
#define GNOME_DESKTOP_USE_UNSTABLE_API
 
46
#include <libgnome-desktop/gnome-languages.h>
 
47
#include <libgnome-desktop/gnome-xkb-info.h>
 
48
 
 
49
#ifdef HAVE_IBUS
 
50
#include <ibus.h>
 
51
#endif
 
52
 
 
53
#include <act/act.h>
 
54
 
 
55
#include "gnome-settings-session.h"
 
56
#include "gnome-settings-profile.h"
 
57
#include "gsd-keyboard-manager.h"
 
58
#include "gsd-input-helper.h"
 
59
#include "gsd-enums.h"
 
60
 
 
61
#define GSD_KEYBOARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_KEYBOARD_MANAGER, GsdKeyboardManagerPrivate))
 
62
 
 
63
#define GSD_KEYBOARD_DIR "org.gnome.settings-daemon.peripherals.keyboard"
 
64
 
 
65
#define KEY_REPEAT         "repeat"
 
66
#define KEY_CLICK          "click"
 
67
#define KEY_INTERVAL       "repeat-interval"
 
68
#define KEY_DELAY          "delay"
 
69
#define KEY_CLICK_VOLUME   "click-volume"
 
70
#define KEY_REMEMBER_NUMLOCK_STATE "remember-numlock-state"
 
71
#define KEY_NUMLOCK_STATE  "numlock-state"
 
72
 
 
73
#define KEY_BELL_VOLUME    "bell-volume"
 
74
#define KEY_BELL_PITCH     "bell-pitch"
 
75
#define KEY_BELL_DURATION  "bell-duration"
 
76
#define KEY_BELL_MODE      "bell-mode"
 
77
 
 
78
#define GNOME_DESKTOP_INTERFACE_DIR "org.gnome.desktop.interface"
 
79
 
 
80
#define KEY_GTK_IM_MODULE    "gtk-im-module"
 
81
#define GTK_IM_MODULE_SIMPLE "gtk-im-context-simple"
 
82
#define GTK_IM_MODULE_IBUS   "ibus"
 
83
 
 
84
#define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources"
 
85
 
 
86
#define KEY_CURRENT_INPUT_SOURCE "current"
 
87
#define KEY_INPUT_SOURCES        "sources"
 
88
#define KEY_KEYBOARD_OPTIONS     "xkb-options"
 
89
 
 
90
#define INPUT_SOURCE_TYPE_XKB  "xkb"
 
91
#define INPUT_SOURCE_TYPE_IBUS "ibus"
 
92
 
 
93
#define DEFAULT_LANGUAGE "en_US"
 
94
#define DEFAULT_LAYOUT "us"
 
95
 
 
96
#define GSD_KEYBOARD_DBUS_NAME  "org.gnome.SettingsDaemon.Keyboard"
 
97
#define GSD_KEYBOARD_DBUS_PATH  "/org/gnome/SettingsDaemon/Keyboard"
 
98
 
 
99
struct GsdKeyboardManagerPrivate
 
100
{
 
101
        guint      start_idle_id;
 
102
        GSettings *settings;
 
103
        GSettings *input_sources_settings;
 
104
        GSettings *interface_settings;
 
105
        GnomeXkbInfo *xkb_info;
 
106
        GDBusProxy *localed;
 
107
        GCancellable *cancellable;
 
108
#ifdef HAVE_IBUS
 
109
        IBusBus   *ibus;
 
110
        GHashTable *ibus_engines;
 
111
        GCancellable *ibus_cancellable;
 
112
#endif
 
113
        gint       xkb_event_base;
 
114
        GsdNumLockState old_state;
 
115
        GdkDeviceManager *device_manager;
 
116
        guint device_added_id;
 
117
        guint device_removed_id;
 
118
 
 
119
        GDBusConnection *dbus_connection;
 
120
        GDBusNodeInfo *dbus_introspection;
 
121
        guint dbus_own_name_id;
 
122
        guint dbus_register_object_id;
 
123
 
 
124
        GDBusMethodInvocation *invocation;
 
125
        guint pending_ops;
 
126
};
 
127
 
 
128
static void     gsd_keyboard_manager_class_init  (GsdKeyboardManagerClass *klass);
 
129
static void     gsd_keyboard_manager_init        (GsdKeyboardManager      *keyboard_manager);
 
130
static void     gsd_keyboard_manager_finalize    (GObject                 *object);
 
131
static gboolean apply_input_sources_settings     (GSettings               *settings,
 
132
                                                  gpointer                 keys,
 
133
                                                  gint                     n_keys,
 
134
                                                  GsdKeyboardManager      *manager);
 
135
static void     set_gtk_im_module                (GsdKeyboardManager      *manager,
 
136
                                                  GVariant                *sources);
 
137
static void     maybe_return_from_set_input_source (GsdKeyboardManager    *manager);
 
138
static void     increment_set_input_source_ops   (GsdKeyboardManager      *manager);
 
139
 
 
140
G_DEFINE_TYPE (GsdKeyboardManager, gsd_keyboard_manager, G_TYPE_OBJECT)
 
141
 
 
142
static const gchar introspection_xml[] =
 
143
        "<node>"
 
144
        "  <interface name='org.gnome.SettingsDaemon.Keyboard'>"
 
145
        "    <method name='SetInputSource'>"
 
146
        "      <arg type='u' name='idx' direction='in'/>"
 
147
        "    </method>"
 
148
        "  </interface>"
 
149
        "</node>";
 
150
 
 
151
static gpointer manager_object = NULL;
 
152
 
 
153
static void
 
154
init_builder_with_sources (GVariantBuilder *builder,
 
155
                           GSettings       *settings)
 
156
{
 
157
        const gchar *type;
 
158
        const gchar *id;
 
159
        GVariantIter iter;
 
160
        GVariant *sources;
 
161
 
 
162
        sources = g_settings_get_value (settings, KEY_INPUT_SOURCES);
 
163
 
 
164
        g_variant_builder_init (builder, G_VARIANT_TYPE ("a(ss)"));
 
165
 
 
166
        g_variant_iter_init (&iter, sources);
 
167
        while (g_variant_iter_next (&iter, "(&s&s)", &type, &id))
 
168
                g_variant_builder_add (builder, "(ss)", type, id);
 
169
 
 
170
        g_variant_unref (sources);
 
171
}
 
172
 
 
173
static gboolean
 
174
schema_is_installed (const gchar *name)
 
175
{
 
176
        const gchar * const *schemas;
 
177
        const gchar * const *s;
 
178
 
 
179
        schemas = g_settings_list_schemas ();
 
180
        for (s = schemas; *s; ++s)
 
181
                if (g_str_equal (*s, name))
 
182
                        return TRUE;
 
183
 
 
184
        return FALSE;
 
185
}
 
186
 
 
187
#ifdef HAVE_IBUS
 
188
static void
 
189
clear_ibus (GsdKeyboardManager *manager)
 
190
{
 
191
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
192
 
 
193
        g_cancellable_cancel (priv->ibus_cancellable);
 
194
        g_clear_object (&priv->ibus_cancellable);
 
195
        g_clear_pointer (&priv->ibus_engines, g_hash_table_destroy);
 
196
        g_clear_object (&priv->ibus);
 
197
}
 
198
 
 
199
static void
 
200
fetch_ibus_engines_result (GObject            *object,
 
201
                           GAsyncResult       *result,
 
202
                           GsdKeyboardManager *manager)
 
203
{
 
204
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
205
        GList *list, *l;
 
206
        GError *error = NULL;
 
207
 
 
208
        /* engines shouldn't be there yet */
 
209
        g_return_if_fail (priv->ibus_engines == NULL);
 
210
 
 
211
        g_clear_object (&priv->ibus_cancellable);
 
212
 
 
213
        list = ibus_bus_list_engines_async_finish (priv->ibus,
 
214
                                                   result,
 
215
                                                   &error);
 
216
        if (!list && error) {
 
217
                if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 
218
                        g_warning ("Couldn't finish IBus request: %s", error->message);
 
219
                g_error_free (error);
 
220
 
 
221
                clear_ibus (manager);
 
222
                return;
 
223
        }
 
224
 
 
225
        /* Maps IBus engine ids to engine description objects */
 
226
        priv->ibus_engines = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
 
227
 
 
228
        for (l = list; l; l = l->next) {
 
229
                IBusEngineDesc *engine = l->data;
 
230
                const gchar *engine_id = ibus_engine_desc_get_name (engine);
 
231
 
 
232
                g_hash_table_replace (priv->ibus_engines, (gpointer)engine_id, engine);
 
233
        }
 
234
        g_list_free (list);
 
235
 
 
236
        apply_input_sources_settings (priv->input_sources_settings, NULL, 0, manager);
 
237
}
 
238
 
 
239
static void
 
240
fetch_ibus_engines (GsdKeyboardManager *manager)
 
241
{
 
242
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
243
 
 
244
        /* engines shouldn't be there yet */
 
245
        g_return_if_fail (priv->ibus_engines == NULL);
 
246
        g_return_if_fail (priv->ibus_cancellable == NULL);
 
247
 
 
248
        priv->ibus_cancellable = g_cancellable_new ();
 
249
 
 
250
        ibus_bus_list_engines_async (priv->ibus,
 
251
                                     -1,
 
252
                                     priv->ibus_cancellable,
 
253
                                     (GAsyncReadyCallback)fetch_ibus_engines_result,
 
254
                                     manager);
 
255
}
 
256
 
 
257
static void
 
258
maybe_start_ibus (GsdKeyboardManager *manager)
 
259
{
 
260
        if (!manager->priv->ibus) {
 
261
                ibus_init ();
 
262
                manager->priv->ibus = ibus_bus_new_async ();
 
263
                g_signal_connect_swapped (manager->priv->ibus, "connected",
 
264
                                          G_CALLBACK (fetch_ibus_engines), manager);
 
265
                g_signal_connect_swapped (manager->priv->ibus, "disconnected",
 
266
                                          G_CALLBACK (clear_ibus), manager);
 
267
        }
 
268
        /* IBus doesn't export API in the session bus. The only thing
 
269
         * we have there is a well known name which we can use as a
 
270
         * sure-fire way to activate it. */
 
271
        g_bus_unwatch_name (g_bus_watch_name (G_BUS_TYPE_SESSION,
 
272
                                              IBUS_SERVICE_IBUS,
 
273
                                              G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
 
274
                                              NULL,
 
275
                                              NULL,
 
276
                                              NULL,
 
277
                                              NULL));
 
278
}
 
279
 
 
280
static void
 
281
set_ibus_engine_finish (GObject            *object,
 
282
                        GAsyncResult       *res,
 
283
                        GsdKeyboardManager *manager)
 
284
{
 
285
        gboolean result;
 
286
        IBusBus *ibus = IBUS_BUS (object);
 
287
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
288
        GError *error = NULL;
 
289
 
 
290
        g_clear_object (&priv->ibus_cancellable);
 
291
 
 
292
        result = ibus_bus_set_global_engine_async_finish (ibus, res, &error);
 
293
        if (!result) {
 
294
                if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 
295
                        g_warning ("Couldn't set IBus engine: %s", error->message);
 
296
                g_error_free (error);
 
297
                return;
 
298
        }
 
299
 
 
300
        maybe_return_from_set_input_source (manager);
 
301
}
 
302
 
 
303
static void
 
304
set_ibus_engine (GsdKeyboardManager *manager,
 
305
                 const gchar        *engine_id)
 
306
{
 
307
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
308
 
 
309
        g_return_if_fail (priv->ibus != NULL);
 
310
        g_return_if_fail (priv->ibus_engines != NULL);
 
311
 
 
312
        g_cancellable_cancel (priv->ibus_cancellable);
 
313
        g_clear_object (&priv->ibus_cancellable);
 
314
        priv->ibus_cancellable = g_cancellable_new ();
 
315
 
 
316
        increment_set_input_source_ops (manager);
 
317
 
 
318
        ibus_bus_set_global_engine_async (priv->ibus,
 
319
                                          engine_id,
 
320
                                          -1,
 
321
                                          priv->ibus_cancellable,
 
322
                                          (GAsyncReadyCallback)set_ibus_engine_finish,
 
323
                                          manager);
 
324
}
 
325
 
 
326
static void
 
327
set_ibus_xkb_engine (GsdKeyboardManager *manager)
 
328
{
 
329
        IBusEngineDesc *engine;
 
330
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
331
 
 
332
        if (!priv->ibus_engines)
 
333
                return;
 
334
 
 
335
        /* All the "xkb:..." IBus engines simply "echo" back symbols,
 
336
           despite their naming implying differently, so we always set
 
337
           one in order for XIM applications to work given that we set
 
338
           XMODIFIERS=@im=ibus in the first place so that they can
 
339
           work without restarting when/if the user adds an IBus
 
340
           input source. */
 
341
        engine = g_hash_table_lookup (priv->ibus_engines, "xkb:us::eng");
 
342
        if (!engine)
 
343
                return;
 
344
 
 
345
        set_ibus_engine (manager, ibus_engine_desc_get_name (engine));
 
346
}
 
347
 
 
348
static gboolean
 
349
need_ibus (GVariant *sources)
 
350
{
 
351
        GVariantIter iter;
 
352
        const gchar *type;
 
353
 
 
354
        g_variant_iter_init (&iter, sources);
 
355
        while (g_variant_iter_next (&iter, "(&s&s)", &type, NULL))
 
356
                if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS))
 
357
                        return TRUE;
 
358
 
 
359
        return FALSE;
 
360
}
 
361
 
 
362
 
 
363
static void
 
364
set_gtk_im_module (GsdKeyboardManager *manager,
 
365
                   GVariant           *sources)
 
366
{
 
367
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
368
        const gchar *new_module;
 
369
        gchar *current_module;
 
370
 
 
371
        if (!sources || need_ibus (sources))
 
372
                new_module = GTK_IM_MODULE_IBUS;
 
373
        else
 
374
                new_module = GTK_IM_MODULE_SIMPLE;
 
375
 
 
376
        current_module = g_settings_get_string (priv->interface_settings,
 
377
                                                KEY_GTK_IM_MODULE);
 
378
        if (!g_str_equal (current_module, new_module))
 
379
                g_settings_set_string (priv->interface_settings,
 
380
                                       KEY_GTK_IM_MODULE,
 
381
                                       new_module);
 
382
        g_free (current_module);
 
383
}
 
384
 
 
385
/* XXX: See upstream bug:
 
386
 * https://codereview.appspot.com/6586075/ */
 
387
static gchar *
 
388
layout_from_ibus_layout (const gchar *ibus_layout)
 
389
{
 
390
        const gchar *p;
 
391
 
 
392
        /* we get something like "layout(variant)[option1,option2]" */
 
393
 
 
394
        p = ibus_layout;
 
395
        while (*p) {
 
396
                if (*p == '(' || *p == '[')
 
397
                        break;
 
398
                p += 1;
 
399
        }
 
400
 
 
401
        return g_strndup (ibus_layout, p - ibus_layout);
 
402
}
 
403
 
 
404
static gchar *
 
405
variant_from_ibus_layout (const gchar *ibus_layout)
 
406
{
 
407
        const gchar *a, *b;
 
408
 
 
409
        /* we get something like "layout(variant)[option1,option2]" */
 
410
 
 
411
        a = ibus_layout;
 
412
        while (*a) {
 
413
                if (*a == '(')
 
414
                        break;
 
415
                a += 1;
 
416
        }
 
417
        if (!*a)
 
418
                return NULL;
 
419
 
 
420
        a += 1;
 
421
        b = a;
 
422
        while (*b) {
 
423
                if (*b == ')')
 
424
                        break;
 
425
                b += 1;
 
426
        }
 
427
        if (!*b)
 
428
                return NULL;
 
429
 
 
430
        return g_strndup (a, b - a);
 
431
}
 
432
 
 
433
static gchar **
 
434
options_from_ibus_layout (const gchar *ibus_layout)
 
435
{
 
436
        const gchar *a, *b;
 
437
        GPtrArray *opt_array;
 
438
 
 
439
        /* we get something like "layout(variant)[option1,option2]" */
 
440
 
 
441
        a = ibus_layout;
 
442
        while (*a) {
 
443
                if (*a == '[')
 
444
                        break;
 
445
                a += 1;
 
446
        }
 
447
        if (!*a)
 
448
                return NULL;
 
449
 
 
450
        opt_array = g_ptr_array_new ();
 
451
 
 
452
        do {
 
453
                a += 1;
 
454
                b = a;
 
455
                while (*b) {
 
456
                        if (*b == ',' || *b == ']')
 
457
                                break;
 
458
                        b += 1;
 
459
                }
 
460
                if (!*b)
 
461
                        goto out;
 
462
 
 
463
                g_ptr_array_add (opt_array, g_strndup (a, b - a));
 
464
 
 
465
                a = b;
 
466
        } while (*a && *a == ',');
 
467
 
 
468
out:
 
469
        g_ptr_array_add (opt_array, NULL);
 
470
        return (gchar **) g_ptr_array_free (opt_array, FALSE);
 
471
}
 
472
 
 
473
static const gchar *
 
474
engine_from_locale (void)
 
475
{
 
476
        const gchar *locale;
 
477
        const gchar *locale_engine[][2] = {
 
478
                { "as_IN", "m17n:as:phonetic" },
 
479
                { "bn_IN", "m17n:bn:inscript" },
 
480
                { "gu_IN", "m17n:gu:inscript" },
 
481
                { "hi_IN", "m17n:hi:inscript" },
 
482
                { "ja_JP", "anthy" },
 
483
                { "kn_IN", "m17n:kn:kgp" },
 
484
                { "ko_KR", "hangul" },
 
485
                { "mai_IN", "m17n:mai:inscript" },
 
486
                { "ml_IN", "m17n:ml:inscript" },
 
487
                { "mr_IN", "m17n:mr:inscript" },
 
488
                { "or_IN", "m17n:or:inscript" },
 
489
                { "pa_IN", "m17n:pa:inscript" },
 
490
                { "sd_IN", "m17n:sd:inscript" },
 
491
                { "ta_IN", "m17n:ta:tamil99" },
 
492
                { "te_IN", "m17n:te:inscript" },
 
493
                { "zh_CN", "pinyin" },
 
494
                { "zh_HK", "cangjie3" },
 
495
                { "zh_TW", "chewing" },
 
496
        };
 
497
        gint i;
 
498
 
 
499
        locale = setlocale (LC_CTYPE, NULL);
 
500
        if (!locale)
 
501
                return NULL;
 
502
 
 
503
        for (i = 0; i < G_N_ELEMENTS (locale_engine); ++i)
 
504
                if (g_str_has_prefix (locale, locale_engine[i][0]))
 
505
                        return locale_engine[i][1];
 
506
 
 
507
        return NULL;
 
508
}
 
509
 
 
510
static void
 
511
add_ibus_sources_from_locale (GSettings *settings)
 
512
{
 
513
        const gchar *locale_engine;
 
514
        GVariantBuilder builder;
 
515
 
 
516
        locale_engine = engine_from_locale ();
 
517
        if (!locale_engine)
 
518
                return;
 
519
 
 
520
        init_builder_with_sources (&builder, settings);
 
521
        g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_IBUS, locale_engine);
 
522
        g_settings_set_value (settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
 
523
}
 
524
 
 
525
static void
 
526
convert_ibus (GSettings *settings)
 
527
{
 
528
        GVariantBuilder builder;
 
529
        GSettings *ibus_settings;
 
530
        gchar **engines, **e;
 
531
 
 
532
        if (!schema_is_installed ("org.freedesktop.ibus.general"))
 
533
                return;
 
534
 
 
535
        init_builder_with_sources (&builder, settings);
 
536
 
 
537
        ibus_settings = g_settings_new ("org.freedesktop.ibus.general");
 
538
        engines = g_settings_get_strv (ibus_settings, "preload-engines");
 
539
        for (e = engines; *e; ++e) {
 
540
                if (g_str_has_prefix (*e, "xkb:"))
 
541
                        continue;
 
542
                g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_IBUS, *e);
 
543
        }
 
544
 
 
545
        g_settings_set_value (settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
 
546
 
 
547
        g_strfreev (engines);
 
548
        g_object_unref (ibus_settings);
 
549
}
 
550
#endif  /* HAVE_IBUS */
 
551
 
 
552
static gboolean
 
553
xkb_set_keyboard_autorepeat_rate (guint delay, guint interval)
 
554
{
 
555
        return XkbSetAutoRepeatRate (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
 
556
                                     XkbUseCoreKbd,
 
557
                                     delay,
 
558
                                     interval);
 
559
}
 
560
 
 
561
static gboolean
 
562
check_xkb_extension (GsdKeyboardManager *manager)
 
563
{
 
564
        Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
565
        int opcode, error_base, major, minor;
 
566
        gboolean have_xkb;
 
567
 
 
568
        have_xkb = XkbQueryExtension (dpy,
 
569
                                      &opcode,
 
570
                                      &manager->priv->xkb_event_base,
 
571
                                      &error_base,
 
572
                                      &major,
 
573
                                      &minor);
 
574
        return have_xkb;
 
575
}
 
576
 
 
577
static void
 
578
xkb_init (GsdKeyboardManager *manager)
 
579
{
 
580
        Display *dpy;
 
581
 
 
582
        dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
583
        XkbSelectEventDetails (dpy,
 
584
                               XkbUseCoreKbd,
 
585
                               XkbStateNotify,
 
586
                               XkbModifierLockMask,
 
587
                               XkbModifierLockMask);
 
588
}
 
589
 
 
590
static unsigned
 
591
numlock_NumLock_modifier_mask (void)
 
592
{
 
593
        Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
594
        return XkbKeysymToModifiers (dpy, XK_Num_Lock);
 
595
}
 
596
 
 
597
static void
 
598
numlock_set_xkb_state (GsdNumLockState new_state)
 
599
{
 
600
        unsigned int num_mask;
 
601
        Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
602
        if (new_state != GSD_NUM_LOCK_STATE_ON && new_state != GSD_NUM_LOCK_STATE_OFF)
 
603
                return;
 
604
        num_mask = numlock_NumLock_modifier_mask ();
 
605
        XkbLockModifiers (dpy, XkbUseCoreKbd, num_mask, new_state == GSD_NUM_LOCK_STATE_ON ? num_mask : 0);
 
606
}
 
607
 
 
608
static const char *
 
609
num_lock_state_to_string (GsdNumLockState numlock_state)
 
610
{
 
611
        switch (numlock_state) {
 
612
        case GSD_NUM_LOCK_STATE_UNKNOWN:
 
613
                return "GSD_NUM_LOCK_STATE_UNKNOWN";
 
614
        case GSD_NUM_LOCK_STATE_ON:
 
615
                return "GSD_NUM_LOCK_STATE_ON";
 
616
        case GSD_NUM_LOCK_STATE_OFF:
 
617
                return "GSD_NUM_LOCK_STATE_OFF";
 
618
        default:
 
619
                return "UNKNOWN";
 
620
        }
 
621
}
 
622
 
 
623
static GdkFilterReturn
 
624
xkb_events_filter (GdkXEvent *xev_,
 
625
                   GdkEvent  *gdkev_,
 
626
                   gpointer   user_data)
 
627
{
 
628
        XEvent *xev = (XEvent *) xev_;
 
629
        XkbEvent *xkbev = (XkbEvent *) xev;
 
630
        GsdKeyboardManager *manager = (GsdKeyboardManager *) user_data;
 
631
 
 
632
        if (xev->type != manager->priv->xkb_event_base ||
 
633
            xkbev->any.xkb_type != XkbStateNotify)
 
634
                return GDK_FILTER_CONTINUE;
 
635
 
 
636
        if (xkbev->state.changed & XkbModifierLockMask) {
 
637
                unsigned num_mask = numlock_NumLock_modifier_mask ();
 
638
                unsigned locked_mods = xkbev->state.locked_mods;
 
639
                GsdNumLockState numlock_state;
 
640
 
 
641
                numlock_state = (num_mask & locked_mods) ? GSD_NUM_LOCK_STATE_ON : GSD_NUM_LOCK_STATE_OFF;
 
642
 
 
643
                if (numlock_state != manager->priv->old_state) {
 
644
                        g_debug ("New num-lock state '%s' != Old num-lock state '%s'",
 
645
                                 num_lock_state_to_string (numlock_state),
 
646
                                 num_lock_state_to_string (manager->priv->old_state));
 
647
                        g_settings_set_enum (manager->priv->settings,
 
648
                                             KEY_NUMLOCK_STATE,
 
649
                                             numlock_state);
 
650
                        manager->priv->old_state = numlock_state;
 
651
                }
 
652
        }
 
653
 
 
654
        return GDK_FILTER_CONTINUE;
 
655
}
 
656
 
 
657
static void
 
658
install_xkb_filter (GsdKeyboardManager *manager)
 
659
{
 
660
        gdk_window_add_filter (NULL,
 
661
                               xkb_events_filter,
 
662
                               manager);
 
663
}
 
664
 
 
665
static void
 
666
remove_xkb_filter (GsdKeyboardManager *manager)
 
667
{
 
668
        gdk_window_remove_filter (NULL,
 
669
                                  xkb_events_filter,
 
670
                                  manager);
 
671
}
 
672
 
 
673
static void
 
674
free_xkb_component_names (XkbComponentNamesRec *p)
 
675
{
 
676
        g_return_if_fail (p != NULL);
 
677
 
 
678
        free (p->keymap);
 
679
        free (p->keycodes);
 
680
        free (p->types);
 
681
        free (p->compat);
 
682
        free (p->symbols);
 
683
        free (p->geometry);
 
684
 
 
685
        g_free (p);
 
686
}
 
687
 
 
688
static void
 
689
upload_xkb_description (const gchar          *rules_file_path,
 
690
                        XkbRF_VarDefsRec     *var_defs,
 
691
                        XkbComponentNamesRec *comp_names)
 
692
{
 
693
        Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
694
        XkbDescRec *xkb_desc;
 
695
        gchar *rules_file;
 
696
 
 
697
        /* The layout we want is always in the first XKB group index
 
698
         * so we should enforce it to make sure we never end up with
 
699
         * the wrong one. */
 
700
        XkbLockGroup (display, XkbUseCoreKbd, 0);
 
701
 
 
702
        /* Upload it to the X server using the same method as setxkbmap */
 
703
        xkb_desc = XkbGetKeyboardByName (display,
 
704
                                         XkbUseCoreKbd,
 
705
                                         comp_names,
 
706
                                         XkbGBN_AllComponentsMask,
 
707
                                         XkbGBN_AllComponentsMask &
 
708
                                         (~XkbGBN_GeometryMask), True);
 
709
        if (!xkb_desc) {
 
710
                g_warning ("Couldn't upload new XKB keyboard description");
 
711
                return;
 
712
        }
 
713
 
 
714
        XkbFreeKeyboard (xkb_desc, 0, True);
 
715
 
 
716
        rules_file = g_path_get_basename (rules_file_path);
 
717
 
 
718
        if (!XkbRF_SetNamesProp (display, rules_file, var_defs))
 
719
                g_warning ("Couldn't update the XKB root window property");
 
720
 
 
721
        g_free (rules_file);
 
722
}
 
723
 
 
724
static gchar *
 
725
build_xkb_group_string (const gchar *user,
 
726
                        const gchar *locale,
 
727
                        const gchar *latin)
 
728
{
 
729
        gchar *string;
 
730
        gsize length = 0;
 
731
        guint commas = 2;
 
732
 
 
733
        if (latin)
 
734
                length += strlen (latin);
 
735
        else
 
736
                commas -= 1;
 
737
 
 
738
        if (locale)
 
739
                length += strlen (locale);
 
740
        else
 
741
                commas -= 1;
 
742
 
 
743
        length += strlen (user) + commas + 1;
 
744
 
 
745
        string = malloc (length);
 
746
 
 
747
        if (locale && latin)
 
748
                sprintf (string, "%s,%s,%s", user, locale, latin);
 
749
        else if (locale)
 
750
                sprintf (string, "%s,%s", user, locale);
 
751
        else if (latin)
 
752
                sprintf (string, "%s,%s", user, latin);
 
753
        else
 
754
                sprintf (string, "%s", user);
 
755
 
 
756
        return string;
 
757
}
 
758
 
 
759
static gboolean
 
760
layout_equal (const gchar *layout_a,
 
761
              const gchar *variant_a,
 
762
              const gchar *layout_b,
 
763
              const gchar *variant_b)
 
764
{
 
765
        return !g_strcmp0 (layout_a, layout_b) && !g_strcmp0 (variant_a, variant_b);
 
766
}
 
767
 
 
768
static void
 
769
get_locale_layout (GsdKeyboardManager  *manager,
 
770
                   const gchar        **layout,
 
771
                   const gchar        **variant)
 
772
{
 
773
        const gchar *locale;
 
774
        const gchar *type;
 
775
        const gchar *id;
 
776
        gboolean got_info;
 
777
 
 
778
        *layout = NULL;
 
779
        *variant = NULL;
 
780
 
 
781
        locale = setlocale (LC_MESSAGES, NULL);
 
782
        /* If LANG is empty, default to en_US */
 
783
        if (!locale)
 
784
                locale = DEFAULT_LANGUAGE;
 
785
 
 
786
        got_info = gnome_get_input_source_from_locale (locale, &type, &id);
 
787
        if (!got_info)
 
788
                if (!gnome_get_input_source_from_locale (DEFAULT_LANGUAGE, &type, &id))
 
789
                        return;
 
790
 
 
791
        if (!g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
 
792
                return;
 
793
 
 
794
        gnome_xkb_info_get_layout_info (manager->priv->xkb_info,
 
795
                                        id,
 
796
                                        NULL,
 
797
                                        NULL,
 
798
                                        layout,
 
799
                                        variant);
 
800
}
 
801
 
 
802
static void
 
803
replace_layout_and_variant (GsdKeyboardManager *manager,
 
804
                            XkbRF_VarDefsRec   *xkb_var_defs,
 
805
                            const gchar        *layout,
 
806
                            const gchar        *variant)
 
807
{
 
808
        /* Toolkits need to know about both a latin layout to handle
 
809
         * accelerators which are usually defined like Ctrl+C and a
 
810
         * layout with the symbols for the language used in UI strings
 
811
         * to handle mnemonics like Alt+Š¤, so we try to find and add
 
812
         * them in XKB group slots after the layout which the user
 
813
         * actually intends to type with. */
 
814
        const gchar *latin_layout = "us";
 
815
        const gchar *latin_variant = "";
 
816
        const gchar *locale_layout = NULL;
 
817
        const gchar *locale_variant = NULL;
 
818
 
 
819
        if (!layout)
 
820
                return;
 
821
 
 
822
        if (!variant)
 
823
                variant = "";
 
824
 
 
825
        get_locale_layout (manager, &locale_layout, &locale_variant);
 
826
 
 
827
        /* We want to minimize the number of XKB groups if we have
 
828
         * duplicated layout+variant pairs.
 
829
         *
 
830
         * Also, if a layout doesn't have a variant we still have to
 
831
         * include it in the variants string because the number of
 
832
         * variants must agree with the number of layouts. For
 
833
         * instance:
 
834
         *
 
835
         * layouts:  "us,ru,us"
 
836
         * variants: "dvorak,,"
 
837
         */
 
838
        if (layout_equal (latin_layout, latin_variant, locale_layout, locale_variant) ||
 
839
            layout_equal (latin_layout, latin_variant, layout, variant)) {
 
840
                latin_layout = NULL;
 
841
                latin_variant = NULL;
 
842
        }
 
843
 
 
844
        if (layout_equal (locale_layout, locale_variant, layout, variant)) {
 
845
                locale_layout = NULL;
 
846
                locale_variant = NULL;
 
847
        }
 
848
 
 
849
        free (xkb_var_defs->layout);
 
850
        xkb_var_defs->layout = build_xkb_group_string (layout, locale_layout, latin_layout);
 
851
 
 
852
        free (xkb_var_defs->variant);
 
853
        xkb_var_defs->variant = build_xkb_group_string (variant, locale_variant, latin_variant);
 
854
}
 
855
 
 
856
static gchar *
 
857
build_xkb_options_string (gchar **options)
 
858
{
 
859
        gchar *string;
 
860
 
 
861
        if (*options) {
 
862
                gint i;
 
863
                gsize len;
 
864
                gchar *ptr;
 
865
 
 
866
                /* First part, getting length */
 
867
                len = 1 + strlen (options[0]);
 
868
                for (i = 1; options[i] != NULL; i++)
 
869
                        len += strlen (options[i]);
 
870
                len += (i - 1); /* commas */
 
871
 
 
872
                /* Second part, building string */
 
873
                string = malloc (len);
 
874
                ptr = g_stpcpy (string, *options);
 
875
                for (i = 1; options[i] != NULL; i++) {
 
876
                        ptr = g_stpcpy (ptr, ",");
 
877
                        ptr = g_stpcpy (ptr, options[i]);
 
878
                }
 
879
        } else {
 
880
                string = malloc (1);
 
881
                *string = '\0';
 
882
        }
 
883
 
 
884
        return string;
 
885
}
 
886
 
 
887
static gchar **
 
888
append_options (gchar **a,
 
889
                gchar **b)
 
890
{
 
891
        gchar **c, **p;
 
892
 
 
893
        if (!a && !b)
 
894
                return NULL;
 
895
        else if (!a)
 
896
                return g_strdupv (b);
 
897
        else if (!b)
 
898
                return g_strdupv (a);
 
899
 
 
900
        c = g_new0 (gchar *, g_strv_length (a) + g_strv_length (b) + 1);
 
901
        p = c;
 
902
 
 
903
        while (*a) {
 
904
                *p = g_strdup (*a);
 
905
                p += 1;
 
906
                a += 1;
 
907
        }
 
908
        while (*b) {
 
909
                *p = g_strdup (*b);
 
910
                p += 1;
 
911
                b += 1;
 
912
        }
 
913
 
 
914
        return c;
 
915
}
 
916
 
 
917
static void
 
918
strip_xkb_option (gchar       **options,
 
919
                  const gchar  *prefix)
 
920
{
 
921
        guint last;
 
922
        gchar **p = options;
 
923
 
 
924
        if (!p)
 
925
                return;
 
926
 
 
927
        while (*p) {
 
928
                if (g_str_has_prefix (*p, prefix)) {
 
929
                        last = g_strv_length (options) - 1;
 
930
                        g_free (*p);
 
931
                        *p = options[last];
 
932
                        options[last] = NULL;
 
933
                }
 
934
                p += 1;
 
935
        }
 
936
}
 
937
 
 
938
static gchar *
 
939
prepare_xkb_options (GsdKeyboardManager *manager,
 
940
                     guint               n_sources,
 
941
                     gchar             **extra_options)
 
942
{
 
943
        gchar **options;
 
944
        gchar **settings_options;
 
945
        gchar  *options_str;
 
946
 
 
947
        settings_options = g_settings_get_strv (manager->priv->input_sources_settings,
 
948
                                                KEY_KEYBOARD_OPTIONS);
 
949
        options = append_options (settings_options, extra_options);
 
950
        g_strfreev (settings_options);
 
951
 
 
952
        /* We might set up different layouts in different groups - see
 
953
         * replace_layout_and_variant(). But we don't want the X
 
954
         * server group switching feature to actually switch
 
955
         * them. Regularly, if we have at least two input sources,
 
956
         * gnome-shell will tell us to switch input source at that
 
957
         * point so we fix that automatically. But when there's only
 
958
         * one source, gnome-shell short circuits as an optimization
 
959
         * and doesn't call us so we can't set the group switching XKB
 
960
         * option in the first place otherwise the X server's switch
 
961
         * will take effect and we get a broken configuration. */
 
962
        if (n_sources < 2 || g_strcmp0 (g_getenv ("XDG_CURRENT_DESKTOP"), "Unity") == 0)
 
963
                strip_xkb_option (options, "grp:");
 
964
 
 
965
        options_str = build_xkb_options_string (options);
 
966
        g_strfreev (options);
 
967
 
 
968
        return options_str;
 
969
}
 
970
 
 
971
static void
 
972
apply_xkb_settings (GsdKeyboardManager *manager,
 
973
                    const gchar        *layout,
 
974
                    const gchar        *variant,
 
975
                    gchar              *options)
 
976
{
 
977
        XkbRF_RulesRec *xkb_rules;
 
978
        XkbRF_VarDefsRec *xkb_var_defs;
 
979
        gchar *rules_file_path;
 
980
 
 
981
        gnome_xkb_info_get_var_defs (&rules_file_path, &xkb_var_defs);
 
982
 
 
983
        free (xkb_var_defs->options);
 
984
        xkb_var_defs->options = options;
 
985
 
 
986
        replace_layout_and_variant (manager, xkb_var_defs, layout, variant);
 
987
 
 
988
        gdk_error_trap_push ();
 
989
 
 
990
        xkb_rules = XkbRF_Load (rules_file_path, NULL, True, True);
 
991
        if (xkb_rules) {
 
992
                XkbComponentNamesRec *xkb_comp_names;
 
993
                xkb_comp_names = g_new0 (XkbComponentNamesRec, 1);
 
994
 
 
995
                XkbRF_GetComponents (xkb_rules, xkb_var_defs, xkb_comp_names);
 
996
                upload_xkb_description (rules_file_path, xkb_var_defs, xkb_comp_names);
 
997
 
 
998
                free_xkb_component_names (xkb_comp_names);
 
999
                XkbRF_Free (xkb_rules, True);
 
1000
        } else {
 
1001
                g_warning ("Couldn't load XKB rules");
 
1002
        }
 
1003
 
 
1004
        if (gdk_error_trap_pop ())
 
1005
                g_warning ("Error loading XKB rules");
 
1006
 
 
1007
        gnome_xkb_info_free_var_defs (xkb_var_defs);
 
1008
        g_free (rules_file_path);
 
1009
 
 
1010
        XkbLockModifiers (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XkbUseCoreKbd, LockMask, 0);
 
1011
}
 
1012
 
 
1013
static void
 
1014
user_notify_is_loaded_cb (GObject    *object,
 
1015
                          GParamSpec *pspec,
 
1016
                          gpointer    user_data)
 
1017
{
 
1018
        ActUser *user = ACT_USER (object);
 
1019
        GSettings *settings = user_data;
 
1020
 
 
1021
        if (act_user_is_loaded (user)) {
 
1022
                GVariant *sources;
 
1023
                GVariantIter iter;
 
1024
                const gchar *type;
 
1025
                const gchar *name;
 
1026
                GVariantBuilder builder;
 
1027
 
 
1028
                g_signal_handlers_disconnect_by_data (user, user_data);
 
1029
 
 
1030
                sources = g_settings_get_value (settings, KEY_INPUT_SOURCES);
 
1031
 
 
1032
                g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{ss}"));
 
1033
 
 
1034
                g_variant_iter_init (&iter, sources);
 
1035
                while (g_variant_iter_next (&iter, "(&s&s)", &type, &name)) {
 
1036
                        g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{ss}"));
 
1037
                        g_variant_builder_add (&builder, "{ss}", type, name);
 
1038
                        g_variant_builder_close (&builder);
 
1039
                }
 
1040
 
 
1041
                g_variant_unref (sources);
 
1042
 
 
1043
                sources = g_variant_ref_sink (g_variant_builder_end (&builder));
 
1044
                act_user_set_input_sources (user, sources);
 
1045
                g_variant_unref (sources);
 
1046
        }
 
1047
}
 
1048
 
 
1049
static void
 
1050
manager_notify_is_loaded_cb (GObject    *object,
 
1051
                             GParamSpec *pspec,
 
1052
                             gpointer    user_data)
 
1053
{
 
1054
        ActUserManager *manager = ACT_USER_MANAGER (object);
 
1055
 
 
1056
        gboolean loaded;
 
1057
        g_object_get (manager, "is-loaded", &loaded, NULL);
 
1058
 
 
1059
        if (loaded) {
 
1060
                ActUser *user;
 
1061
 
 
1062
                g_signal_handlers_disconnect_by_data (manager, user_data);
 
1063
 
 
1064
                user = act_user_manager_get_user (manager, g_get_user_name ());
 
1065
 
 
1066
                if (act_user_is_loaded (user))
 
1067
                        user_notify_is_loaded_cb (G_OBJECT (user), NULL, user_data);
 
1068
                else
 
1069
                        g_signal_connect (user, "notify::is-loaded",
 
1070
                                          user_notify_is_loaded_cb, user_data);
 
1071
        }
 
1072
}
 
1073
 
 
1074
static gboolean
 
1075
apply_input_sources_settings (GSettings          *settings,
 
1076
                              gpointer            keys,
 
1077
                              gint                n_keys,
 
1078
                              GsdKeyboardManager *manager)
 
1079
{
 
1080
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
1081
        GVariant *sources;
 
1082
        guint current;
 
1083
        guint n_sources;
 
1084
        const gchar *type = NULL;
 
1085
        const gchar *id = NULL;
 
1086
        gchar *layout = NULL;
 
1087
        gchar *variant = NULL;
 
1088
        gchar **options = NULL;
 
1089
        ActUserManager *user_manager;
 
1090
        gboolean user_manager_loaded;
 
1091
 
 
1092
        sources = g_settings_get_value (priv->input_sources_settings, KEY_INPUT_SOURCES);
 
1093
        current = g_settings_get_uint (priv->input_sources_settings, KEY_CURRENT_INPUT_SOURCE);
 
1094
        n_sources = g_variant_n_children (sources);
 
1095
 
 
1096
        user_manager = act_user_manager_get_default ();
 
1097
        g_object_get (user_manager, "is-loaded", &user_manager_loaded, NULL);
 
1098
        if (user_manager_loaded)
 
1099
                manager_notify_is_loaded_cb (G_OBJECT (user_manager), NULL, settings);
 
1100
        else
 
1101
                g_signal_connect (user_manager, "notify::is-loaded", G_CALLBACK (manager_notify_is_loaded_cb), settings);
 
1102
 
 
1103
        if (n_sources < 1)
 
1104
                goto exit;
 
1105
 
 
1106
        if (current >= n_sources) {
 
1107
                g_settings_set_uint (priv->input_sources_settings,
 
1108
                                     KEY_CURRENT_INPUT_SOURCE,
 
1109
                                     n_sources - 1);
 
1110
                goto exit;
 
1111
        }
 
1112
 
 
1113
#ifdef HAVE_IBUS
 
1114
        maybe_start_ibus (manager);
 
1115
#endif
 
1116
 
 
1117
        g_variant_get_child (sources, current, "(&s&s)", &type, &id);
 
1118
 
 
1119
        if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) {
 
1120
                const gchar *l, *v;
 
1121
                gnome_xkb_info_get_layout_info (priv->xkb_info, id, NULL, NULL, &l, &v);
 
1122
 
 
1123
                layout = g_strdup (l);
 
1124
                variant = g_strdup (v);
 
1125
 
 
1126
                if (!layout || !layout[0]) {
 
1127
                        g_warning ("Couldn't find XKB input source '%s'", id);
 
1128
                        goto exit;
 
1129
                }
 
1130
#ifdef HAVE_IBUS
 
1131
                set_gtk_im_module (manager, sources);
 
1132
                set_ibus_xkb_engine (manager);
 
1133
#endif
 
1134
        } else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) {
 
1135
#ifdef HAVE_IBUS
 
1136
                IBusEngineDesc *engine_desc = NULL;
 
1137
 
 
1138
                if (priv->ibus_engines)
 
1139
                        engine_desc = g_hash_table_lookup (priv->ibus_engines, id);
 
1140
                else
 
1141
                        goto exit; /* we'll be called again when ibus is up and running */
 
1142
 
 
1143
                if (engine_desc) {
 
1144
                        const gchar *ibus_layout;
 
1145
                        ibus_layout = ibus_engine_desc_get_layout (engine_desc);
 
1146
 
 
1147
                        if (ibus_layout) {
 
1148
                                layout = layout_from_ibus_layout (ibus_layout);
 
1149
                                variant = variant_from_ibus_layout (ibus_layout);
 
1150
                                options = options_from_ibus_layout (ibus_layout);
 
1151
                        }
 
1152
                } else {
 
1153
                        g_warning ("Couldn't find IBus input source '%s'", id);
 
1154
                        goto exit;
 
1155
                }
 
1156
 
 
1157
                /* NULL here is a shortcut for "I already know I
 
1158
                   need the IBus module". */
 
1159
                set_gtk_im_module (manager, NULL);
 
1160
                set_ibus_engine (manager, id);
 
1161
#else
 
1162
                g_warning ("IBus input source type specified but IBus support was not compiled");
 
1163
#endif
 
1164
        } else {
 
1165
                g_warning ("Unknown input source type '%s'", type);
 
1166
        }
 
1167
 
 
1168
 exit:
 
1169
        apply_xkb_settings (manager, layout, variant,
 
1170
                            prepare_xkb_options (manager, n_sources, options));
 
1171
        maybe_return_from_set_input_source (manager);
 
1172
        g_variant_unref (sources);
 
1173
        g_free (layout);
 
1174
        g_free (variant);
 
1175
        g_strfreev (options);
 
1176
        /* Prevent individual "changed" signal invocations since we
 
1177
           don't need them. */
 
1178
        return TRUE;
 
1179
}
 
1180
 
 
1181
static void
 
1182
apply_bell (GsdKeyboardManager *manager)
 
1183
{
 
1184
        GSettings       *settings;
 
1185
        XKeyboardControl kbdcontrol;
 
1186
        gboolean         click;
 
1187
        int              bell_volume;
 
1188
        int              bell_pitch;
 
1189
        int              bell_duration;
 
1190
        GsdBellMode      bell_mode;
 
1191
        int              click_volume;
 
1192
 
 
1193
        g_debug ("Applying the bell settings");
 
1194
        settings      = manager->priv->settings;
 
1195
        click         = g_settings_get_boolean  (settings, KEY_CLICK);
 
1196
        click_volume  = g_settings_get_int   (settings, KEY_CLICK_VOLUME);
 
1197
 
 
1198
        bell_pitch    = g_settings_get_int   (settings, KEY_BELL_PITCH);
 
1199
        bell_duration = g_settings_get_int   (settings, KEY_BELL_DURATION);
 
1200
 
 
1201
        bell_mode = g_settings_get_enum (settings, KEY_BELL_MODE);
 
1202
        bell_volume   = (bell_mode == GSD_BELL_MODE_ON) ? 50 : 0;
 
1203
 
 
1204
        /* as percentage from 0..100 inclusive */
 
1205
        if (click_volume < 0) {
 
1206
                click_volume = 0;
 
1207
        } else if (click_volume > 100) {
 
1208
                click_volume = 100;
 
1209
        }
 
1210
        kbdcontrol.key_click_percent = click ? click_volume : 0;
 
1211
        kbdcontrol.bell_percent = bell_volume;
 
1212
        kbdcontrol.bell_pitch = bell_pitch;
 
1213
        kbdcontrol.bell_duration = bell_duration;
 
1214
 
 
1215
        gdk_error_trap_push ();
 
1216
        XChangeKeyboardControl (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
 
1217
                                KBKeyClickPercent | KBBellPercent | KBBellPitch | KBBellDuration,
 
1218
                                &kbdcontrol);
 
1219
 
 
1220
        XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE);
 
1221
        gdk_error_trap_pop_ignored ();
 
1222
}
 
1223
 
 
1224
static void
 
1225
apply_numlock (GsdKeyboardManager *manager)
 
1226
{
 
1227
        GSettings *settings;
 
1228
        gboolean rnumlock;
 
1229
 
 
1230
        g_debug ("Applying the num-lock settings");
 
1231
        settings = manager->priv->settings;
 
1232
        rnumlock = g_settings_get_boolean  (settings, KEY_REMEMBER_NUMLOCK_STATE);
 
1233
        manager->priv->old_state = g_settings_get_enum (manager->priv->settings, KEY_NUMLOCK_STATE);
 
1234
 
 
1235
        gdk_error_trap_push ();
 
1236
        if (rnumlock) {
 
1237
                g_debug ("Remember num-lock is set, so applying setting '%s'",
 
1238
                         num_lock_state_to_string (manager->priv->old_state));
 
1239
                numlock_set_xkb_state (manager->priv->old_state);
 
1240
        }
 
1241
 
 
1242
        XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE);
 
1243
        gdk_error_trap_pop_ignored ();
 
1244
}
 
1245
 
 
1246
static void
 
1247
apply_repeat (GsdKeyboardManager *manager)
 
1248
{
 
1249
        GSettings       *settings;
 
1250
        gboolean         repeat;
 
1251
        guint            interval;
 
1252
        guint            delay;
 
1253
 
 
1254
        g_debug ("Applying the repeat settings");
 
1255
        settings      = manager->priv->settings;
 
1256
        repeat        = g_settings_get_boolean  (settings, KEY_REPEAT);
 
1257
        interval      = g_settings_get_uint  (settings, KEY_INTERVAL);
 
1258
        delay         = g_settings_get_uint  (settings, KEY_DELAY);
 
1259
 
 
1260
        gdk_error_trap_push ();
 
1261
        if (repeat) {
 
1262
                gboolean rate_set = FALSE;
 
1263
 
 
1264
                XAutoRepeatOn (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
 
1265
                /* Use XKB in preference */
 
1266
                rate_set = xkb_set_keyboard_autorepeat_rate (delay, interval);
 
1267
 
 
1268
                if (!rate_set)
 
1269
                        g_warning ("Neither XKeyboard not Xfree86's keyboard extensions are available,\n"
 
1270
                                   "no way to support keyboard autorepeat rate settings");
 
1271
        } else {
 
1272
                XAutoRepeatOff (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
 
1273
        }
 
1274
 
 
1275
        XSync (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), FALSE);
 
1276
        gdk_error_trap_pop_ignored ();
 
1277
}
 
1278
 
 
1279
static void
 
1280
apply_all_settings (GsdKeyboardManager *manager)
 
1281
{
 
1282
        apply_repeat (manager);
 
1283
        apply_bell (manager);
 
1284
        apply_numlock (manager);
 
1285
}
 
1286
 
 
1287
static void
 
1288
settings_changed (GSettings          *settings,
 
1289
                  const char         *key,
 
1290
                  GsdKeyboardManager *manager)
 
1291
{
 
1292
        if (g_strcmp0 (key, KEY_CLICK) == 0||
 
1293
            g_strcmp0 (key, KEY_CLICK_VOLUME) == 0 ||
 
1294
            g_strcmp0 (key, KEY_BELL_PITCH) == 0 ||
 
1295
            g_strcmp0 (key, KEY_BELL_DURATION) == 0 ||
 
1296
            g_strcmp0 (key, KEY_BELL_MODE) == 0) {
 
1297
                g_debug ("Bell setting '%s' changed, applying bell settings", key);
 
1298
                apply_bell (manager);
 
1299
        } else if (g_strcmp0 (key, KEY_REMEMBER_NUMLOCK_STATE) == 0) {
 
1300
                g_debug ("Remember Num-Lock state '%s' changed, applying num-lock settings", key);
 
1301
                apply_numlock (manager);
 
1302
        } else if (g_strcmp0 (key, KEY_NUMLOCK_STATE) == 0) {
 
1303
                g_debug ("Num-Lock state '%s' changed, will apply at next startup", key);
 
1304
        } else if (g_strcmp0 (key, KEY_REPEAT) == 0 ||
 
1305
                 g_strcmp0 (key, KEY_INTERVAL) == 0 ||
 
1306
                 g_strcmp0 (key, KEY_DELAY) == 0) {
 
1307
                g_debug ("Key repeat setting '%s' changed, applying key repeat settings", key);
 
1308
                apply_repeat (manager);
 
1309
        } else {
 
1310
                g_warning ("Unhandled settings change, key '%s'", key);
 
1311
        }
 
1312
 
 
1313
}
 
1314
 
 
1315
static void
 
1316
device_added_cb (GdkDeviceManager   *device_manager,
 
1317
                 GdkDevice          *device,
 
1318
                 GsdKeyboardManager *manager)
 
1319
{
 
1320
        GdkInputSource source;
 
1321
 
 
1322
        source = gdk_device_get_source (device);
 
1323
        if (source == GDK_SOURCE_KEYBOARD) {
 
1324
                g_debug ("New keyboard plugged in, applying all settings");
 
1325
                apply_input_sources_settings (manager->priv->input_sources_settings, NULL, 0, manager);
 
1326
                run_custom_command (device, COMMAND_DEVICE_ADDED);
 
1327
        }
 
1328
}
 
1329
 
 
1330
static void
 
1331
device_removed_cb (GdkDeviceManager   *device_manager,
 
1332
                   GdkDevice          *device,
 
1333
                   GsdKeyboardManager *manager)
 
1334
{
 
1335
        GdkInputSource source;
 
1336
 
 
1337
        source = gdk_device_get_source (device);
 
1338
        if (source == GDK_SOURCE_KEYBOARD) {
 
1339
                run_custom_command (device, COMMAND_DEVICE_REMOVED);
 
1340
        }
 
1341
}
 
1342
 
 
1343
static void
 
1344
set_devicepresence_handler (GsdKeyboardManager *manager)
 
1345
{
 
1346
        GdkDeviceManager *device_manager;
 
1347
 
 
1348
        device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
 
1349
 
 
1350
        manager->priv->device_added_id = g_signal_connect (G_OBJECT (device_manager), "device-added",
 
1351
                                                           G_CALLBACK (device_added_cb), manager);
 
1352
        manager->priv->device_removed_id = g_signal_connect (G_OBJECT (device_manager), "device-removed",
 
1353
                                                             G_CALLBACK (device_removed_cb), manager);
 
1354
        manager->priv->device_manager = device_manager;
 
1355
}
 
1356
 
 
1357
static void
 
1358
get_sources_from_xkb_config (GsdKeyboardManager *manager)
 
1359
{
 
1360
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
1361
        GVariantBuilder builder;
 
1362
        GVariant *v;
 
1363
        gint i, n;
 
1364
        gchar **layouts = NULL;
 
1365
        gchar **variants = NULL;
 
1366
        gboolean have_default_layout = FALSE;
 
1367
 
 
1368
        v = g_dbus_proxy_get_cached_property (priv->localed, "X11Layout");
 
1369
        if (v) {
 
1370
                const gchar *s = g_variant_get_string (v, NULL);
 
1371
                if (*s)
 
1372
                        layouts = g_strsplit (s, ",", -1);
 
1373
                g_variant_unref (v);
 
1374
        }
 
1375
 
 
1376
        if (!layouts)
 
1377
                return;
 
1378
 
 
1379
        v = g_dbus_proxy_get_cached_property (priv->localed, "X11Variant");
 
1380
        if (v) {
 
1381
                const gchar *s = g_variant_get_string (v, NULL);
 
1382
                if (*s)
 
1383
                        variants = g_strsplit (s, ",", -1);
 
1384
                g_variant_unref (v);
 
1385
        }
 
1386
 
 
1387
        if (variants && variants[0])
 
1388
                n = MIN (g_strv_length (layouts), g_strv_length (variants));
 
1389
        else
 
1390
                n = g_strv_length (layouts);
 
1391
 
 
1392
        init_builder_with_sources (&builder, priv->input_sources_settings);
 
1393
 
 
1394
        for (i = 0; i < n && layouts[i][0]; ++i) {
 
1395
                gchar *id;
 
1396
 
 
1397
                if (variants && variants[i] && variants[i][0])
 
1398
                        id = g_strdup_printf ("%s+%s", layouts[i], variants[i]);
 
1399
                else
 
1400
                        id = g_strdup (layouts[i]);
 
1401
 
 
1402
                if (g_str_equal (id, DEFAULT_LAYOUT))
 
1403
                        have_default_layout = TRUE;
 
1404
 
 
1405
                g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_XKB, id);
 
1406
                g_free (id);
 
1407
        }
 
1408
 
 
1409
        if (!have_default_layout)
 
1410
                g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_XKB, DEFAULT_LAYOUT);
 
1411
 
 
1412
        g_settings_set_value (priv->input_sources_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
 
1413
 
 
1414
        g_strfreev (layouts);
 
1415
        g_strfreev (variants);
 
1416
}
 
1417
 
 
1418
static void
 
1419
get_options_from_xkb_config (GsdKeyboardManager *manager)
 
1420
{
 
1421
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
1422
        GVariant *v;
 
1423
        gchar **options = NULL;
 
1424
 
 
1425
        v = g_dbus_proxy_get_cached_property (priv->localed, "X11Options");
 
1426
        if (v) {
 
1427
                const gchar *s = g_variant_get_string (v, NULL);
 
1428
                if (*s)
 
1429
                        options = g_strsplit (s, ",", -1);
 
1430
                g_variant_unref (v);
 
1431
        }
 
1432
 
 
1433
        if (!options)
 
1434
                return;
 
1435
 
 
1436
        g_settings_set_strv (priv->input_sources_settings, KEY_KEYBOARD_OPTIONS, (const gchar * const*) options);
 
1437
 
 
1438
        g_strfreev (options);
 
1439
}
 
1440
 
 
1441
static void
 
1442
convert_libgnomekbd_options (GSettings *settings)
 
1443
{
 
1444
        GPtrArray *opt_array;
 
1445
        GSettings *libgnomekbd_settings;
 
1446
        gchar **options, **o;
 
1447
 
 
1448
        if (!schema_is_installed ("org.gnome.libgnomekbd.keyboard"))
 
1449
                return;
 
1450
 
 
1451
        opt_array = g_ptr_array_new_with_free_func (g_free);
 
1452
 
 
1453
        libgnomekbd_settings = g_settings_new ("org.gnome.libgnomekbd.keyboard");
 
1454
        options = g_settings_get_strv (libgnomekbd_settings, "options");
 
1455
 
 
1456
        for (o = options; *o; ++o) {
 
1457
                gchar **strv;
 
1458
 
 
1459
                strv = g_strsplit (*o, "\t", 2);
 
1460
                if (strv[0] && strv[1])
 
1461
                        g_ptr_array_add (opt_array, g_strdup (strv[1]));
 
1462
                g_strfreev (strv);
 
1463
        }
 
1464
        g_ptr_array_add (opt_array, NULL);
 
1465
 
 
1466
        g_settings_set_strv (settings, KEY_KEYBOARD_OPTIONS, (const gchar * const*) opt_array->pdata);
 
1467
 
 
1468
        g_strfreev (options);
 
1469
        g_object_unref (libgnomekbd_settings);
 
1470
        g_ptr_array_free (opt_array, TRUE);
 
1471
}
 
1472
 
 
1473
static void
 
1474
convert_libgnomekbd_layouts (GSettings *settings)
 
1475
{
 
1476
        GVariantBuilder builder;
 
1477
        GSettings *libgnomekbd_settings;
 
1478
        gchar **layouts, **l;
 
1479
 
 
1480
        if (!schema_is_installed ("org.gnome.libgnomekbd.keyboard"))
 
1481
                return;
 
1482
 
 
1483
        init_builder_with_sources (&builder, settings);
 
1484
 
 
1485
        libgnomekbd_settings = g_settings_new ("org.gnome.libgnomekbd.keyboard");
 
1486
        layouts = g_settings_get_strv (libgnomekbd_settings, "layouts");
 
1487
 
 
1488
        for (l = layouts; *l; ++l) {
 
1489
                gchar *id;
 
1490
                gchar **strv;
 
1491
 
 
1492
                strv = g_strsplit (*l, "\t", 2);
 
1493
                if (strv[0] && !strv[1])
 
1494
                        id = g_strdup (strv[0]);
 
1495
                else if (strv[0] && strv[1])
 
1496
                        id = g_strdup_printf ("%s+%s", strv[0], strv[1]);
 
1497
                else
 
1498
                        id = NULL;
 
1499
 
 
1500
                if (id)
 
1501
                        g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_XKB, id);
 
1502
 
 
1503
                g_free (id);
 
1504
                g_strfreev (strv);
 
1505
        }
 
1506
 
 
1507
        g_settings_set_value (settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
 
1508
 
 
1509
        g_strfreev (layouts);
 
1510
        g_object_unref (libgnomekbd_settings);
 
1511
}
 
1512
 
 
1513
static void
 
1514
maybe_convert_old_settings (GSettings *settings)
 
1515
{
 
1516
        GVariant *sources;
 
1517
        gchar **options;
 
1518
        gchar *stamp_dir_path = NULL;
 
1519
        gchar *stamp_file_path = NULL;
 
1520
        GError *error = NULL;
 
1521
 
 
1522
        stamp_dir_path = g_build_filename (g_get_user_data_dir (), PACKAGE_NAME, NULL);
 
1523
        if (g_mkdir_with_parents (stamp_dir_path, 0755)) {
 
1524
                g_warning ("Failed to create directory %s: %s", stamp_dir_path, g_strerror (errno));
 
1525
                goto out;
 
1526
        }
 
1527
 
 
1528
        stamp_file_path = g_build_filename (stamp_dir_path, "input-sources-converted", NULL);
 
1529
        if (g_file_test (stamp_file_path, G_FILE_TEST_EXISTS))
 
1530
                goto out;
 
1531
 
 
1532
        sources = g_settings_get_value (settings, KEY_INPUT_SOURCES);
 
1533
        if (g_variant_n_children (sources) < 1) {
 
1534
                convert_libgnomekbd_layouts (settings);
 
1535
#ifdef HAVE_IBUS
 
1536
                convert_ibus (settings);
 
1537
#endif
 
1538
        }
 
1539
        g_variant_unref (sources);
 
1540
 
 
1541
        options = g_settings_get_strv (settings, KEY_KEYBOARD_OPTIONS);
 
1542
        if (g_strv_length (options) < 1)
 
1543
                convert_libgnomekbd_options (settings);
 
1544
        g_strfreev (options);
 
1545
 
 
1546
        if (!g_file_set_contents (stamp_file_path, "", 0, &error)) {
 
1547
                g_warning ("%s", error->message);
 
1548
                g_error_free (error);
 
1549
        }
 
1550
out:
 
1551
        g_free (stamp_file_path);
 
1552
        g_free (stamp_dir_path);
 
1553
}
 
1554
 
 
1555
static void
 
1556
maybe_create_initial_settings (GsdKeyboardManager *manager)
 
1557
{
 
1558
        GSettings *settings;
 
1559
        GVariant *sources;
 
1560
        gchar **options;
 
1561
 
 
1562
        settings = manager->priv->input_sources_settings;
 
1563
 
 
1564
        if (g_getenv ("RUNNING_UNDER_GDM")) {
 
1565
                GVariantBuilder builder;
 
1566
                /* clean the settings and get them from the "system" */
 
1567
                g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
 
1568
                g_settings_set_value (settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder));
 
1569
                get_sources_from_xkb_config (manager);
 
1570
 
 
1571
                g_settings_set_strv (settings, KEY_KEYBOARD_OPTIONS, NULL);
 
1572
                get_options_from_xkb_config (manager);
 
1573
                return;
 
1574
        }
 
1575
 
 
1576
        maybe_convert_old_settings (settings);
 
1577
 
 
1578
        /* if we still don't have anything do some educated guesses */
 
1579
        sources = g_settings_get_value (settings, KEY_INPUT_SOURCES);
 
1580
        if (g_variant_n_children (sources) < 1) {
 
1581
                get_sources_from_xkb_config (manager);
 
1582
#ifdef HAVE_IBUS
 
1583
                add_ibus_sources_from_locale (settings);
 
1584
#endif
 
1585
        }
 
1586
        g_variant_unref (sources);
 
1587
 
 
1588
        options = g_settings_get_strv (settings, KEY_KEYBOARD_OPTIONS);
 
1589
        if (g_strv_length (options) < 1)
 
1590
                get_options_from_xkb_config (manager);
 
1591
        g_strfreev (options);
 
1592
}
 
1593
 
 
1594
static void
 
1595
set_input_source_return (GDBusMethodInvocation *invocation)
 
1596
{
 
1597
        g_dbus_method_invocation_return_value (invocation, NULL);
 
1598
}
 
1599
 
 
1600
static void
 
1601
maybe_return_from_set_input_source (GsdKeyboardManager *manager)
 
1602
{
 
1603
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
1604
 
 
1605
        if (!priv->invocation)
 
1606
                return;
 
1607
 
 
1608
        if (priv->pending_ops > 0) {
 
1609
                priv->pending_ops -= 1;
 
1610
                return;
 
1611
        }
 
1612
 
 
1613
        g_clear_pointer (&priv->invocation, set_input_source_return);
 
1614
}
 
1615
 
 
1616
static void
 
1617
increment_set_input_source_ops (GsdKeyboardManager *manager)
 
1618
{
 
1619
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
1620
 
 
1621
        if (!priv->invocation)
 
1622
                return;
 
1623
 
 
1624
        priv->pending_ops += 1;
 
1625
}
 
1626
 
 
1627
static void
 
1628
set_input_source (GsdKeyboardManager *manager)
 
1629
{
 
1630
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
1631
        guint idx;
 
1632
 
 
1633
        g_variant_get (g_dbus_method_invocation_get_parameters (priv->invocation), "(u)", &idx);
 
1634
 
 
1635
        if (idx == g_settings_get_uint (priv->input_sources_settings, KEY_CURRENT_INPUT_SOURCE)) {
 
1636
                maybe_return_from_set_input_source (manager);
 
1637
                return;
 
1638
        }
 
1639
 
 
1640
        g_settings_set_uint (priv->input_sources_settings, KEY_CURRENT_INPUT_SOURCE, idx);
 
1641
}
 
1642
 
 
1643
static void
 
1644
handle_dbus_method_call (GDBusConnection       *connection,
 
1645
                         const gchar           *sender,
 
1646
                         const gchar           *object_path,
 
1647
                         const gchar           *interface_name,
 
1648
                         const gchar           *method_name,
 
1649
                         GVariant              *parameters,
 
1650
                         GDBusMethodInvocation *invocation,
 
1651
                         GsdKeyboardManager    *manager)
 
1652
{
 
1653
        GsdKeyboardManagerPrivate *priv = manager->priv;
 
1654
 
 
1655
        if (g_str_equal (method_name, "SetInputSource")) {
 
1656
                if (priv->invocation) {
 
1657
#ifdef HAVE_IBUS
 
1658
                        /* This can only happen if there's an
 
1659
                         * ibus_bus_set_global_engine_async() call
 
1660
                         * going on. */
 
1661
                        g_cancellable_cancel (priv->ibus_cancellable);
 
1662
#endif
 
1663
                        g_clear_pointer (&priv->invocation, set_input_source_return);
 
1664
                        priv->pending_ops = 0;
 
1665
                }
 
1666
                priv->invocation = invocation;
 
1667
                set_input_source (manager);
 
1668
        }
 
1669
}
 
1670
 
 
1671
static void
 
1672
on_bus_name_lost (GDBusConnection *connection,
 
1673
                  const gchar     *name,
 
1674
                  gpointer         data)
 
1675
{
 
1676
        g_warning ("DBus name %s lost", name);
 
1677
}
 
1678
 
 
1679
static void
 
1680
got_session_bus (GObject            *source,
 
1681
                 GAsyncResult       *res,
 
1682
                 GsdKeyboardManager *manager)
 
1683
{
 
1684
        GsdKeyboardManagerPrivate *priv;
 
1685
        GDBusConnection *connection;
 
1686
        GError *error = NULL;
 
1687
        GDBusInterfaceVTable vtable = {
 
1688
                (GDBusInterfaceMethodCallFunc) handle_dbus_method_call,
 
1689
                NULL,
 
1690
                NULL,
 
1691
        };
 
1692
 
 
1693
        connection = g_bus_get_finish (res, &error);
 
1694
        if (!connection) {
 
1695
                if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 
1696
                        g_warning ("Couldn't get session bus: %s", error->message);
 
1697
                g_error_free (error);
 
1698
                return;
 
1699
        }
 
1700
 
 
1701
        priv = manager->priv;
 
1702
        priv->dbus_connection = connection;
 
1703
 
 
1704
        priv->dbus_register_object_id = g_dbus_connection_register_object (priv->dbus_connection,
 
1705
                                                                           GSD_KEYBOARD_DBUS_PATH,
 
1706
                                                                           priv->dbus_introspection->interfaces[0],
 
1707
                                                                           &vtable,
 
1708
                                                                           manager,
 
1709
                                                                           NULL,
 
1710
                                                                           &error);
 
1711
        if (!priv->dbus_register_object_id) {
 
1712
                g_warning ("Error registering object: %s", error->message);
 
1713
                g_error_free (error);
 
1714
                return;
 
1715
        }
 
1716
 
 
1717
        priv->dbus_own_name_id = g_bus_own_name_on_connection (priv->dbus_connection,
 
1718
                                                               GSD_KEYBOARD_DBUS_NAME,
 
1719
                                                               G_BUS_NAME_OWNER_FLAGS_NONE,
 
1720
                                                               NULL,
 
1721
                                                               on_bus_name_lost,
 
1722
                                                               NULL,
 
1723
                                                               NULL);
 
1724
}
 
1725
 
 
1726
static void
 
1727
register_manager_dbus (GsdKeyboardManager *manager)
 
1728
{
 
1729
        GError *error = NULL;
 
1730
 
 
1731
        manager->priv->dbus_introspection = g_dbus_node_info_new_for_xml (introspection_xml, &error);
 
1732
        if (error) {
 
1733
                g_warning ("Error creating introspection data: %s", error->message);
 
1734
                g_error_free (error);
 
1735
                return;
 
1736
        }
 
1737
 
 
1738
        g_bus_get (G_BUS_TYPE_SESSION,
 
1739
                   manager->priv->cancellable,
 
1740
                   (GAsyncReadyCallback) got_session_bus,
 
1741
                   manager);
 
1742
}
 
1743
 
 
1744
static void
 
1745
localed_proxy_ready (GObject      *source,
 
1746
                     GAsyncResult *res,
 
1747
                     gpointer      data)
 
1748
{
 
1749
        GsdKeyboardManager *manager = data;
 
1750
        GDBusProxy *proxy;
 
1751
        GError *error = NULL;
 
1752
 
 
1753
        proxy = g_dbus_proxy_new_finish (res, &error);
 
1754
        if (!proxy) {
 
1755
                if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
 
1756
                        g_error_free (error);
 
1757
                        return;
 
1758
                }
 
1759
                g_warning ("Failed to contact localed: %s", error->message);
 
1760
                g_error_free (error);
 
1761
                goto out;
 
1762
        }
 
1763
 
 
1764
        manager->priv->localed = proxy;
 
1765
        maybe_create_initial_settings (manager);
 
1766
out:
 
1767
        apply_input_sources_settings (manager->priv->input_sources_settings, NULL, 0, manager);
 
1768
        register_manager_dbus (manager);
 
1769
}
 
1770
 
 
1771
static gboolean
 
1772
start_keyboard_idle_cb (GsdKeyboardManager *manager)
 
1773
{
 
1774
        gnome_settings_profile_start (NULL);
 
1775
 
 
1776
        g_debug ("Starting keyboard manager");
 
1777
 
 
1778
        manager->priv->settings = g_settings_new (GSD_KEYBOARD_DIR);
 
1779
 
 
1780
        xkb_init (manager);
 
1781
 
 
1782
        set_devicepresence_handler (manager);
 
1783
 
 
1784
        manager->priv->input_sources_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
 
1785
        manager->priv->interface_settings = g_settings_new (GNOME_DESKTOP_INTERFACE_DIR);
 
1786
        manager->priv->xkb_info = gnome_xkb_info_new ();
 
1787
 
 
1788
        manager->priv->cancellable = g_cancellable_new ();
 
1789
 
 
1790
        g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
 
1791
                                  G_DBUS_PROXY_FLAGS_NONE,
 
1792
                                  NULL,
 
1793
                                  "org.freedesktop.locale1",
 
1794
                                  "/org/freedesktop/locale1",
 
1795
                                  "org.freedesktop.locale1",
 
1796
                                  manager->priv->cancellable,
 
1797
                                  localed_proxy_ready,
 
1798
                                  manager);
 
1799
 
 
1800
        /* apply current settings before we install the callback */
 
1801
        g_debug ("Started the keyboard plugin, applying all settings");
 
1802
        apply_all_settings (manager);
 
1803
 
 
1804
        g_signal_connect (G_OBJECT (manager->priv->settings), "changed",
 
1805
                          G_CALLBACK (settings_changed), manager);
 
1806
        g_signal_connect (G_OBJECT (manager->priv->input_sources_settings), "change-event",
 
1807
                          G_CALLBACK (apply_input_sources_settings), manager);
 
1808
 
 
1809
        install_xkb_filter (manager);
 
1810
 
 
1811
        gnome_settings_profile_end (NULL);
 
1812
 
 
1813
        manager->priv->start_idle_id = 0;
 
1814
 
 
1815
        return FALSE;
 
1816
}
 
1817
 
 
1818
gboolean
 
1819
gsd_keyboard_manager_start (GsdKeyboardManager *manager,
 
1820
                            GError            **error)
 
1821
{
 
1822
        gnome_settings_profile_start (NULL);
 
1823
 
 
1824
        if (check_xkb_extension (manager) == FALSE) {
 
1825
                g_debug ("XKB is not supported, not applying any settings");
 
1826
                return TRUE;
 
1827
        }
 
1828
 
 
1829
        manager->priv->start_idle_id = g_idle_add ((GSourceFunc) start_keyboard_idle_cb, manager);
 
1830
 
 
1831
        gnome_settings_profile_end (NULL);
 
1832
 
 
1833
        return TRUE;
 
1834
}
 
1835
 
 
1836
void
 
1837
gsd_keyboard_manager_stop (GsdKeyboardManager *manager)
 
1838
{
 
1839
        GsdKeyboardManagerPrivate *p = manager->priv;
 
1840
 
 
1841
        g_debug ("Stopping keyboard manager");
 
1842
 
 
1843
        if (p->dbus_own_name_id) {
 
1844
                g_bus_unown_name (p->dbus_own_name_id);
 
1845
                p->dbus_own_name_id = 0;
 
1846
        }
 
1847
 
 
1848
        if (p->dbus_register_object_id) {
 
1849
                g_dbus_connection_unregister_object (p->dbus_connection,
 
1850
                                                     p->dbus_register_object_id);
 
1851
                p->dbus_register_object_id = 0;
 
1852
        }
 
1853
 
 
1854
        g_cancellable_cancel (p->cancellable);
 
1855
        g_clear_object (&p->cancellable);
 
1856
 
 
1857
        g_clear_object (&p->settings);
 
1858
        g_clear_object (&p->input_sources_settings);
 
1859
        g_clear_object (&p->interface_settings);
 
1860
        g_clear_object (&p->xkb_info);
 
1861
        g_clear_object (&p->localed);
 
1862
 
 
1863
#ifdef HAVE_IBUS
 
1864
        clear_ibus (manager);
 
1865
#endif
 
1866
 
 
1867
        if (p->device_manager != NULL) {
 
1868
                g_signal_handler_disconnect (p->device_manager, p->device_added_id);
 
1869
                g_signal_handler_disconnect (p->device_manager, p->device_removed_id);
 
1870
                p->device_manager = NULL;
 
1871
        }
 
1872
 
 
1873
        remove_xkb_filter (manager);
 
1874
 
 
1875
        g_clear_pointer (&p->invocation, set_input_source_return);
 
1876
        g_clear_pointer (&p->dbus_introspection, g_dbus_node_info_unref);
 
1877
        g_clear_object (&p->dbus_connection);
 
1878
}
 
1879
 
 
1880
static void
 
1881
gsd_keyboard_manager_class_init (GsdKeyboardManagerClass *klass)
 
1882
{
 
1883
        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
 
1884
 
 
1885
        object_class->finalize = gsd_keyboard_manager_finalize;
 
1886
 
 
1887
        g_type_class_add_private (klass, sizeof (GsdKeyboardManagerPrivate));
 
1888
}
 
1889
 
 
1890
static void
 
1891
gsd_keyboard_manager_init (GsdKeyboardManager *manager)
 
1892
{
 
1893
        manager->priv = GSD_KEYBOARD_MANAGER_GET_PRIVATE (manager);
 
1894
}
 
1895
 
 
1896
static void
 
1897
gsd_keyboard_manager_finalize (GObject *object)
 
1898
{
 
1899
        GsdKeyboardManager *keyboard_manager;
 
1900
 
 
1901
        g_return_if_fail (object != NULL);
 
1902
        g_return_if_fail (GSD_IS_KEYBOARD_MANAGER (object));
 
1903
 
 
1904
        keyboard_manager = GSD_KEYBOARD_MANAGER (object);
 
1905
 
 
1906
        g_return_if_fail (keyboard_manager->priv != NULL);
 
1907
 
 
1908
        if (keyboard_manager->priv->start_idle_id != 0)
 
1909
                g_source_remove (keyboard_manager->priv->start_idle_id);
 
1910
 
 
1911
        G_OBJECT_CLASS (gsd_keyboard_manager_parent_class)->finalize (object);
 
1912
}
 
1913
 
 
1914
GsdKeyboardManager *
 
1915
gsd_keyboard_manager_new (void)
 
1916
{
 
1917
        if (manager_object != NULL) {
 
1918
                g_object_ref (manager_object);
 
1919
        } else {
 
1920
                manager_object = g_object_new (GSD_TYPE_KEYBOARD_MANAGER, NULL);
 
1921
                g_object_add_weak_pointer (manager_object,
 
1922
                                           (gpointer *) &manager_object);
 
1923
        }
 
1924
 
 
1925
        return GSD_KEYBOARD_MANAGER (manager_object);
 
1926
}