~ubuntu-branches/ubuntu/precise/libgnomekbd/precise

« back to all changes in this revision

Viewing changes to libgnomekbd/gkbd-configuration.c

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Bigonville
  • Date: 2011-03-21 13:22:31 UTC
  • mfrom: (1.3.6 upstream) (3.2.13 experimental)
  • Revision ID: james.westby@ubuntu.com-20110321132231-zoay06noilk1thky
Tags: 2.91.91-2
* debian/libgnomekbd-common.install:
  - Install /usr/share/GConf/gsettings and /usr/share/libgnomekbd/icons
  - Add libatk1.0-dev (>= 1.32.0-2~) build-dep to be sure we have .gir file

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010 Canonical Ltd.
 
3
 * Copyright (C) 2010-2011 Sergey V. Udaltsov <svu@gnome.org>
 
4
 * 
 
5
 * Authors: Jan Arne Petersen <jpetersen@openismus.com>
 
6
 *          Sergey V. Udaltsov <svu@gnome.org>
 
7
 * 
 
8
 * This library is free software; you can redistribute it and/or
 
9
 * modify it under the terms of the GNU Lesser General Public
 
10
 * License as published by the Free Software Foundation; either
 
11
 * version 2 of the License, or (at your option) any later version.
 
12
 *
 
13
 * This library is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
 * Lesser General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU Lesser General Public
 
19
 * License along with this library; if not, write to the
 
20
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
21
 * Boston, MA 02111-1307, USA.
 
22
 */
 
23
#include <config.h>
 
24
 
 
25
#include <memory.h>
 
26
 
 
27
#include <gdk/gdkkeysyms.h>
 
28
#include <gdk/gdkx.h>
 
29
#include <glib/gi18n-lib.h>
 
30
 
 
31
#include <gkbd-configuration.h>
 
32
 
 
33
#include <gkbd-desktop-config.h>
 
34
 
 
35
struct _GkbdConfigurationPrivate {
 
36
        XklEngine *engine;
 
37
        XklConfigRegistry *registry;
 
38
 
 
39
        GkbdDesktopConfig cfg;
 
40
        GkbdIndicatorConfig ind_cfg;
 
41
        GkbdKeyboardConfig kbd_cfg;
 
42
 
 
43
        gchar **full_group_names;
 
44
        gchar **short_group_names;
 
45
 
 
46
        const gchar *tooltips_format;
 
47
 
 
48
        gulong state_changed_handler;
 
49
        gulong config_changed_handler;
 
50
 
 
51
        GSList *widget_instances;
 
52
 
 
53
        Atom caps_lock_atom;
 
54
        Atom num_lock_atom;
 
55
        Atom scroll_lock_atom;
 
56
};
 
57
 
 
58
enum {
 
59
        SIGNAL_CHANGED,
 
60
        SIGNAL_GROUP_CHANGED,
 
61
        SIGNAL_INDICATORS_CHANGED,
 
62
        LAST_SIGNAL
 
63
};
 
64
 
 
65
static guint signals[LAST_SIGNAL] = { 0, };
 
66
 
 
67
#define GKBD_CONFIGURATION_GET_PRIVATE(o) \
 
68
        (G_TYPE_INSTANCE_GET_PRIVATE ((o), GKBD_TYPE_CONFIGURATION, GkbdConfigurationPrivate))
 
69
 
 
70
G_DEFINE_TYPE (GkbdConfiguration, gkbd_configuration, G_TYPE_OBJECT)
 
71
 
 
72
/* Should be called once for all widgets */
 
73
static void
 
74
gkbd_configuration_cfg_changed (GSettings * settings, gchar * key,
 
75
                                GkbdConfiguration * configuration)
 
76
{
 
77
        GkbdConfigurationPrivate *priv = configuration->priv;
 
78
 
 
79
        xkl_debug (100,
 
80
                   "General configuration changed in GConf - reiniting...\n");
 
81
        gkbd_desktop_config_load (&priv->cfg);
 
82
        gkbd_desktop_config_activate (&priv->cfg);
 
83
 
 
84
        g_signal_emit (configuration, signals[SIGNAL_CHANGED], 0);
 
85
}
 
86
 
 
87
/* Should be called once for all widgets */
 
88
static void
 
89
gkbd_configuration_ind_cfg_changed (GSettings * settings, gchar * key,
 
90
                                    GkbdConfiguration * configuration)
 
91
{
 
92
        GkbdConfigurationPrivate *priv = configuration->priv;
 
93
        xkl_debug (100,
 
94
                   "Applet configuration changed in GConf - reiniting...\n");
 
95
        gkbd_indicator_config_load (&priv->ind_cfg);
 
96
 
 
97
        gkbd_indicator_config_free_image_filenames (&priv->ind_cfg);
 
98
        gkbd_indicator_config_load_image_filenames (&priv->ind_cfg,
 
99
                                                    &priv->kbd_cfg);
 
100
 
 
101
        gkbd_indicator_config_activate (&priv->ind_cfg);
 
102
 
 
103
        g_signal_emit (configuration, signals[SIGNAL_CHANGED], 0);
 
104
}
 
105
 
 
106
static void
 
107
gkbd_configuration_load_group_names (GkbdConfiguration * configuration,
 
108
                                     XklConfigRec * xklrec)
 
109
{
 
110
        GkbdConfigurationPrivate *priv = configuration->priv;
 
111
 
 
112
        if (!gkbd_desktop_config_load_group_descriptions (&priv->cfg,
 
113
                                                          priv->registry,
 
114
                                                          (const char **)
 
115
                                                          xklrec->layouts,
 
116
                                                          (const char **)
 
117
                                                          xklrec->variants,
 
118
                                                          &priv->short_group_names,
 
119
                                                          &priv->full_group_names))
 
120
        {
 
121
                /* We just populate no short names (remain NULL) - 
 
122
                 * full names are going to be used anyway */
 
123
                gint i, total_groups =
 
124
                    xkl_engine_get_num_groups (priv->engine);
 
125
                xkl_debug (150, "group descriptions loaded: %d!\n",
 
126
                           total_groups);
 
127
 
 
128
                if (xkl_engine_get_features (priv->engine) &
 
129
                    XKLF_MULTIPLE_LAYOUTS_SUPPORTED) {
 
130
                        priv->full_group_names =
 
131
                            g_strdupv (priv->kbd_cfg.layouts_variants);
 
132
                } else {
 
133
                        priv->full_group_names =
 
134
                            g_new0 (char *, total_groups + 1);
 
135
                        for (i = total_groups; --i >= 0;) {
 
136
                                priv->full_group_names[i] =
 
137
                                    g_strdup_printf ("Group %d", i);
 
138
                        }
 
139
                }
 
140
        }
 
141
}
 
142
 
 
143
/* Should be called once for all widgets */
 
144
static void
 
145
gkbd_configuration_kbd_cfg_callback (XklEngine * engine,
 
146
                                     GkbdConfiguration * configuration)
 
147
{
 
148
        GkbdConfigurationPrivate *priv = configuration->priv;
 
149
        XklConfigRec *xklrec = xkl_config_rec_new ();
 
150
        xkl_debug (100,
 
151
                   "XKB configuration changed on X Server - reiniting...\n");
 
152
 
 
153
        gkbd_keyboard_config_load_from_x_current (&priv->kbd_cfg, xklrec);
 
154
 
 
155
        gkbd_indicator_config_free_image_filenames (&priv->ind_cfg);
 
156
        gkbd_indicator_config_load_image_filenames (&priv->ind_cfg,
 
157
                                                    &priv->kbd_cfg);
 
158
 
 
159
        g_strfreev (priv->full_group_names);
 
160
        priv->full_group_names = NULL;
 
161
 
 
162
        g_strfreev (priv->short_group_names);
 
163
        priv->short_group_names = NULL;
 
164
 
 
165
        gkbd_configuration_load_group_names (configuration, xklrec);
 
166
 
 
167
        g_signal_emit (configuration, signals[SIGNAL_CHANGED], 0);
 
168
 
 
169
        g_object_unref (G_OBJECT (xklrec));
 
170
}
 
171
 
 
172
/* Should be called once for all applets */
 
173
static void
 
174
gkbd_configuration_state_callback (XklEngine * engine,
 
175
                                   XklEngineStateChange changeType,
 
176
                                   gint group, gboolean restore,
 
177
                                   GkbdConfiguration * configuration)
 
178
{
 
179
        xkl_debug (150, "change type: %d, group is now %d, restore: %d\n",
 
180
                   changeType, group, restore);
 
181
 
 
182
        switch (changeType) {
 
183
        case GROUP_CHANGED:
 
184
                g_signal_emit (configuration,
 
185
                               signals[SIGNAL_GROUP_CHANGED], 0, group);
 
186
                break;
 
187
        case INDICATORS_CHANGED:
 
188
                g_signal_emit (configuration,
 
189
                               signals[SIGNAL_INDICATORS_CHANGED], 0);
 
190
                break;
 
191
        }
 
192
}
 
193
 
 
194
static void
 
195
gkbd_configuration_init (GkbdConfiguration * configuration)
 
196
{
 
197
        Display *display;
 
198
        GkbdConfigurationPrivate *priv;
 
199
        XklConfigRec *xklrec = xkl_config_rec_new ();
 
200
 
 
201
        xkl_debug (100, "The config startup process for %p started\n",
 
202
                   configuration);
 
203
 
 
204
        priv = GKBD_CONFIGURATION_GET_PRIVATE (configuration);
 
205
        configuration->priv = priv;
 
206
 
 
207
        /* Initing some global vars */
 
208
        priv->tooltips_format = "%s";
 
209
 
 
210
        display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
211
        priv->engine = xkl_engine_get_instance (display);
 
212
        if (priv->engine == NULL) {
 
213
                xkl_debug (0, "Libxklavier initialization error");
 
214
                return;
 
215
        }
 
216
 
 
217
        priv->caps_lock_atom = XInternAtom (display, "Caps Lock", False);
 
218
        priv->num_lock_atom = XInternAtom (display, "Num Lock", False);
 
219
        priv->scroll_lock_atom =
 
220
            XInternAtom (display, "Scroll Lock", False);
 
221
 
 
222
        priv->state_changed_handler =
 
223
            g_signal_connect (priv->engine, "X-state-changed",
 
224
                              G_CALLBACK
 
225
                              (gkbd_configuration_state_callback),
 
226
                              configuration);
 
227
        priv->config_changed_handler =
 
228
            g_signal_connect (priv->engine, "X-config-changed",
 
229
                              G_CALLBACK
 
230
                              (gkbd_configuration_kbd_cfg_callback),
 
231
                              configuration);
 
232
 
 
233
        gkbd_desktop_config_init (&priv->cfg, priv->engine);
 
234
        gkbd_keyboard_config_init (&priv->kbd_cfg, priv->engine);
 
235
        gkbd_indicator_config_init (&priv->ind_cfg, priv->engine);
 
236
 
 
237
        gkbd_desktop_config_load (&priv->cfg);
 
238
        gkbd_desktop_config_activate (&priv->cfg);
 
239
 
 
240
        priv->registry = xkl_config_registry_get_instance (priv->engine);
 
241
        xkl_config_registry_load (priv->registry,
 
242
                                  priv->cfg.load_extra_items);
 
243
 
 
244
        gkbd_keyboard_config_load_from_x_current (&priv->kbd_cfg, xklrec);
 
245
 
 
246
        gkbd_indicator_config_load (&priv->ind_cfg);
 
247
 
 
248
        gkbd_indicator_config_load_image_filenames (&priv->ind_cfg,
 
249
                                                    &priv->kbd_cfg);
 
250
 
 
251
        gkbd_indicator_config_activate (&priv->ind_cfg);
 
252
 
 
253
        gkbd_configuration_load_group_names (configuration, xklrec);
 
254
        g_object_unref (G_OBJECT (xklrec));
 
255
 
 
256
        gkbd_desktop_config_start_listen (&priv->cfg,
 
257
                                          G_CALLBACK
 
258
                                          (gkbd_configuration_cfg_changed),
 
259
                                          configuration);
 
260
        gkbd_indicator_config_start_listen (&priv->ind_cfg,
 
261
                                            G_CALLBACK
 
262
                                            (gkbd_configuration_ind_cfg_changed),
 
263
                                            configuration);
 
264
        xkl_engine_start_listen (priv->engine, XKLL_TRACK_KEYBOARD_STATE);
 
265
 
 
266
        xkl_debug (100, "The config startup process for %p completed\n",
 
267
                   configuration);
 
268
}
 
269
 
 
270
static void
 
271
gkbd_configuration_finalize (GObject * obj)
 
272
{
 
273
        GkbdConfiguration *configuration = GKBD_CONFIGURATION (obj);
 
274
        GkbdConfigurationPrivate *priv = configuration->priv;
 
275
 
 
276
        xkl_debug (100,
 
277
                   "Starting the gnome-kbd-configuration widget shutdown process for %p\n",
 
278
                   configuration);
 
279
 
 
280
        xkl_engine_stop_listen (priv->engine, XKLL_TRACK_KEYBOARD_STATE);
 
281
 
 
282
        gkbd_desktop_config_stop_listen (&priv->cfg);
 
283
        gkbd_indicator_config_stop_listen (&priv->ind_cfg);
 
284
 
 
285
        gkbd_indicator_config_term (&priv->ind_cfg);
 
286
        gkbd_keyboard_config_term (&priv->kbd_cfg);
 
287
        gkbd_desktop_config_term (&priv->cfg);
 
288
 
 
289
        if (g_signal_handler_is_connected (priv->engine,
 
290
                                           priv->state_changed_handler)) {
 
291
                g_signal_handler_disconnect (priv->engine,
 
292
                                             priv->state_changed_handler);
 
293
                priv->state_changed_handler = 0;
 
294
        }
 
295
        if (g_signal_handler_is_connected (priv->engine,
 
296
                                           priv->config_changed_handler)) {
 
297
                g_signal_handler_disconnect (priv->engine,
 
298
                                             priv->config_changed_handler);
 
299
                priv->config_changed_handler = 0;
 
300
        }
 
301
 
 
302
        g_object_unref (priv->registry);
 
303
        priv->registry = NULL;
 
304
        g_object_unref (priv->engine);
 
305
        priv->engine = NULL;
 
306
 
 
307
        G_OBJECT_CLASS (gkbd_configuration_parent_class)->finalize (obj);
 
308
}
 
309
 
 
310
static void
 
311
gkbd_configuration_class_init (GkbdConfigurationClass * klass)
 
312
{
 
313
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
314
 
 
315
        /* Initing vtable */
 
316
        object_class->finalize = gkbd_configuration_finalize;
 
317
 
 
318
        /* Signals */
 
319
        signals[SIGNAL_CHANGED] = g_signal_new ("changed",
 
320
                                                GKBD_TYPE_CONFIGURATION,
 
321
                                                G_SIGNAL_RUN_LAST,
 
322
                                                0,
 
323
                                                NULL, NULL,
 
324
                                                g_cclosure_marshal_VOID__VOID,
 
325
                                                G_TYPE_NONE, 0);
 
326
        signals[SIGNAL_GROUP_CHANGED] = g_signal_new ("group-changed",
 
327
                                                      GKBD_TYPE_CONFIGURATION,
 
328
                                                      G_SIGNAL_RUN_LAST,
 
329
                                                      0,
 
330
                                                      NULL, NULL,
 
331
                                                      g_cclosure_marshal_VOID__INT,
 
332
                                                      G_TYPE_NONE,
 
333
                                                      1, G_TYPE_INT);
 
334
        signals[SIGNAL_INDICATORS_CHANGED] =
 
335
            g_signal_new ("indicators-changed", GKBD_TYPE_CONFIGURATION,
 
336
                          G_SIGNAL_RUN_LAST, 0, NULL, NULL,
 
337
                          g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
 
338
 
 
339
        g_type_class_add_private (klass,
 
340
                                  sizeof (GkbdConfigurationPrivate));
 
341
}
 
342
 
 
343
/**
 
344
 * gkbd_configuration_get: 
 
345
 * Returns: (transfer full): singleton of GkbdConfiguration
 
346
 */
 
347
GkbdConfiguration *
 
348
gkbd_configuration_get (void)
 
349
{
 
350
        static gpointer instance = NULL;
 
351
 
 
352
        if (!instance) {
 
353
                instance = g_object_new (GKBD_TYPE_CONFIGURATION, NULL);
 
354
                g_object_add_weak_pointer (instance, &instance);
 
355
        } else {
 
356
                g_object_ref (instance);
 
357
        }
 
358
 
 
359
        return instance;
 
360
}
 
361
 
 
362
XklEngine *
 
363
gkbd_configuration_get_xkl_engine (GkbdConfiguration * configuration)
 
364
{
 
365
        return configuration->priv->engine;
 
366
}
 
367
 
 
368
/**
 
369
 * gkbd_configuration_get_group_names:
 
370
 * Returns: (transfer none) (array zero-terminated=1): full group names
 
371
 */
 
372
gchar **
 
373
gkbd_configuration_get_group_names (GkbdConfiguration * configuration)
 
374
{
 
375
        return configuration->priv->full_group_names;
 
376
}
 
377
 
 
378
gchar *
 
379
gkbd_configuration_get_image_filename (GkbdConfiguration * configuration,
 
380
                                       guint group)
 
381
{
 
382
        if (!configuration->priv->ind_cfg.show_flags)
 
383
                return NULL;
 
384
        return (gchar *) g_slist_nth_data (configuration->priv->
 
385
                                           ind_cfg.image_filenames, group);
 
386
}
 
387
 
 
388
/**
 
389
 * gkbd_configuration_get_short_group_names:
 
390
 * Returns: (transfer none) (array zero-terminated=1): short group names
 
391
 */
 
392
gchar **
 
393
gkbd_configuration_get_short_group_names (GkbdConfiguration *
 
394
                                          configuration)
 
395
{
 
396
        return configuration->priv->short_group_names;
 
397
}
 
398
 
 
399
gchar *
 
400
gkbd_configuration_get_current_tooltip (GkbdConfiguration * configuration)
 
401
{
 
402
        XklState *state =
 
403
            xkl_engine_get_current_state (configuration->priv->engine);
 
404
        gchar *buf;
 
405
        if (state == NULL || state->group < 0
 
406
            || state->group >=
 
407
            g_strv_length (configuration->priv->full_group_names))
 
408
                return NULL;
 
409
 
 
410
        return g_strdup_printf (configuration->priv->tooltips_format,
 
411
                                configuration->
 
412
                                priv->full_group_names[state->group]);
 
413
}
 
414
 
 
415
gboolean
 
416
gkbd_configuration_if_flags_shown (GkbdConfiguration * configuration)
 
417
{
 
418
        return configuration->priv->ind_cfg.show_flags;
 
419
}
 
420
 
 
421
gchar *
 
422
gkbd_configuration_extract_layout_name (GkbdConfiguration * configuration,
 
423
                                        int group)
 
424
{
 
425
        char *layout_name = NULL;
 
426
        gchar **short_group_names = configuration->priv->short_group_names;
 
427
        gchar **full_group_names = configuration->priv->full_group_names;
 
428
        XklEngine *engine = configuration->priv->engine;
 
429
        if (group < g_strv_length (short_group_names)) {
 
430
                if (xkl_engine_get_features (engine) &
 
431
                    XKLF_MULTIPLE_LAYOUTS_SUPPORTED) {
 
432
                        char *full_layout_name =
 
433
                            configuration->priv->
 
434
                            kbd_cfg.layouts_variants[group];
 
435
                        char *variant_name;
 
436
                        if (!gkbd_keyboard_config_split_items
 
437
                            (full_layout_name, &layout_name,
 
438
                             &variant_name))
 
439
                                /* just in case */
 
440
                                layout_name = full_layout_name;
 
441
 
 
442
                        /* make it freeable */
 
443
                        layout_name = g_strdup (layout_name);
 
444
 
 
445
                        if (short_group_names != NULL) {
 
446
                                char *short_group_name =
 
447
                                    short_group_names[group];
 
448
                                if (short_group_name != NULL
 
449
                                    && *short_group_name != '\0') {
 
450
                                        /* drop the long name */
 
451
                                        g_free (layout_name);
 
452
                                        layout_name =
 
453
                                            g_strdup (short_group_name);
 
454
                                }
 
455
                        }
 
456
                } else {
 
457
                        layout_name = g_strdup (full_group_names[group]);
 
458
                }
 
459
        }
 
460
 
 
461
        if (layout_name == NULL)
 
462
                layout_name = g_strdup ("");
 
463
 
 
464
        return layout_name;
 
465
}
 
466
 
 
467
void
 
468
gkbd_configuration_lock_next_group (GkbdConfiguration * configuration)
 
469
{
 
470
        gkbd_desktop_config_lock_next_group (&configuration->priv->cfg);
 
471
}
 
472
 
 
473
void
 
474
gkbd_configuration_lock_group (GkbdConfiguration * configuration,
 
475
                               guint group)
 
476
{
 
477
        xkl_engine_lock_group (configuration->priv->engine, group);
 
478
}
 
479
 
 
480
guint
 
481
gkbd_configuration_get_current_group (GkbdConfiguration * configuration)
 
482
{
 
483
        XklState *state =
 
484
            xkl_engine_get_current_state (configuration->priv->engine);
 
485
        return state ? state->group : 0;
 
486
}
 
487
 
 
488
/**
 
489
 * gkbd_configuration_get_indicator_config: 
 
490
 * Returns: (transfer none): indicator config
 
491
 */
 
492
GkbdIndicatorConfig *
 
493
gkbd_configuration_get_indicator_config (GkbdConfiguration * configuration)
 
494
{
 
495
        return &configuration->priv->ind_cfg;
 
496
}
 
497
 
 
498
/**
 
499
 * gkbd_configuration_get_keyboard_config: 
 
500
 * Returns: (transfer none): keyboard config
 
501
 */
 
502
GkbdKeyboardConfig *
 
503
gkbd_configuration_get_keyboard_config (GkbdConfiguration * configuration)
 
504
{
 
505
        return &configuration->priv->kbd_cfg;
 
506
}
 
507
 
 
508
/**
 
509
 * gkbd_configuration_get_all_objects: 
 
510
 * Returns: (transfer none): list of widgets/status icons/...
 
511
 */
 
512
GSList *
 
513
gkbd_configuration_get_all_objects (GkbdConfiguration * configuration)
 
514
{
 
515
        return configuration->priv->widget_instances;
 
516
}
 
517
 
 
518
extern void
 
519
gkbd_configuration_append_object (GkbdConfiguration * configuration,
 
520
                                  GObject * obj)
 
521
{
 
522
        configuration->priv->widget_instances =
 
523
            g_slist_append (configuration->priv->widget_instances, obj);
 
524
}
 
525
 
 
526
extern void
 
527
gkbd_configuration_remove_object (GkbdConfiguration * configuration,
 
528
                                  GObject * obj)
 
529
{
 
530
        configuration->priv->widget_instances =
 
531
            g_slist_remove (configuration->priv->widget_instances, obj);
 
532
}
 
533
 
 
534
/**
 
535
 * gkbd_configuration_load_images: 
 
536
 * Returns: (transfer full) (element-type GdkPixbuf): list of images
 
537
 */
 
538
GSList *
 
539
gkbd_configuration_load_images (GkbdConfiguration * configuration)
 
540
{
 
541
        int i;
 
542
        GSList *image_filename, *images = NULL;
 
543
 
 
544
        if (!configuration->priv->ind_cfg.show_flags)
 
545
                return NULL;
 
546
 
 
547
        image_filename = configuration->priv->ind_cfg.image_filenames;
 
548
 
 
549
        for (i =
 
550
             xkl_engine_get_max_num_groups (configuration->priv->engine);
 
551
             --i >= 0; image_filename = image_filename->next) {
 
552
                GdkPixbuf *image = NULL;
 
553
                char *image_file = (char *) image_filename->data;
 
554
 
 
555
                if (image_file != NULL) {
 
556
                        GError *gerror = NULL;
 
557
                        image =
 
558
                            gdk_pixbuf_new_from_file (image_file, &gerror);
 
559
                        xkl_debug (150,
 
560
                                   "Image %d[%s] loaded -> %p[%dx%d]\n",
 
561
                                   i, image_file, image,
 
562
                                   gdk_pixbuf_get_width (image),
 
563
                                   gdk_pixbuf_get_height (image));
 
564
                }
 
565
                /* We append the image anyway - even if it is NULL! */
 
566
                images = g_slist_append (images, image);
 
567
        }
 
568
        return images;
 
569
}
 
570
 
 
571
void
 
572
gkbd_configuration_free_images (GkbdConfiguration * configuration,
 
573
                                GSList * images)
 
574
{
 
575
        GdkPixbuf *pi;
 
576
        GSList *img_node;
 
577
 
 
578
        while ((img_node = images) != NULL) {
 
579
                pi = GDK_PIXBUF (img_node->data);
 
580
                /* It can be NULL - some images may be missing */
 
581
                if (pi != NULL) {
 
582
                        g_object_unref (pi);
 
583
                }
 
584
                images = g_slist_remove_link (images, img_node);
 
585
                g_slist_free_1 (img_node);
 
586
        }
 
587
}
 
588
 
 
589
gchar *
 
590
gkbd_configuration_create_label_title (int group, GHashTable ** ln2cnt_map,
 
591
                                       gchar * layout_name)
 
592
{
 
593
        gpointer pcounter = NULL;
 
594
        char *prev_layout_name = NULL;
 
595
        char *lbl_title = NULL;
 
596
        int counter = 0;
 
597
 
 
598
        if (group == 0) {
 
599
                *ln2cnt_map =
 
600
                    g_hash_table_new_full (g_str_hash, g_str_equal,
 
601
                                           g_free, NULL);
 
602
        }
 
603
 
 
604
        /* Process layouts with repeating description */
 
605
        if (g_hash_table_lookup_extended
 
606
            (*ln2cnt_map, layout_name, (gpointer *) & prev_layout_name,
 
607
             &pcounter)) {
 
608
                /* "next" same description */
 
609
                gchar appendix[10] = "";
 
610
                gint utf8length;
 
611
                gunichar cidx;
 
612
                counter = GPOINTER_TO_INT (pcounter);
 
613
                /* Unicode subscript 2, 3, 4 */
 
614
                cidx = 0x2081 + counter;
 
615
                utf8length = g_unichar_to_utf8 (cidx, appendix);
 
616
                appendix[utf8length] = '\0';
 
617
                lbl_title = g_strconcat (layout_name, appendix, NULL);
 
618
        } else {
 
619
                /* "first" time this description */
 
620
                lbl_title = g_strdup (layout_name);
 
621
        }
 
622
        g_hash_table_insert (*ln2cnt_map, layout_name,
 
623
                             GINT_TO_POINTER (counter + 1));
 
624
        return lbl_title;
 
625
}
 
626
 
 
627
extern gboolean
 
628
gkbd_configuration_if_any_object_exists (GkbdConfiguration * configuration)
 
629
{
 
630
        return (configuration != NULL)
 
631
            && (g_slist_length (configuration->priv->widget_instances) !=
 
632
                0);
 
633
}
 
634
 
 
635
static GdkFilterReturn
 
636
gkbd_configuration_filter_x_evt (GdkXEvent * xev, GdkEvent * event,
 
637
                                 GkbdConfiguration * configuration)
 
638
{
 
639
        xkl_engine_filter_events (configuration->priv->engine,
 
640
                                  (XEvent *) xev);
 
641
        return GDK_FILTER_CONTINUE;
 
642
}
 
643
 
 
644
void
 
645
gkbd_configuration_start_listen (GkbdConfiguration * configuration)
 
646
{
 
647
        gdk_window_add_filter (NULL, (GdkFilterFunc)
 
648
                               gkbd_configuration_filter_x_evt,
 
649
                               configuration);
 
650
        gdk_window_add_filter (gdk_get_default_root_window (),
 
651
                               (GdkFilterFunc)
 
652
                               gkbd_configuration_filter_x_evt,
 
653
                               configuration);
 
654
}
 
655
 
 
656
void
 
657
gkbd_configuration_stop_listen (GkbdConfiguration * configuration)
 
658
{
 
659
        gdk_window_remove_filter (NULL, (GdkFilterFunc)
 
660
                                  gkbd_configuration_filter_x_evt,
 
661
                                  configuration);
 
662
        gdk_window_remove_filter (gdk_get_default_root_window (),
 
663
                                  (GdkFilterFunc)
 
664
                                  gkbd_configuration_filter_x_evt,
 
665
                                  configuration);
 
666
}
 
667
 
 
668
/**
 
669
 * gkbd_configuration_get_group_name:
 
670
 * Returns: (transfer full): group name
 
671
 */
 
672
gchar *
 
673
gkbd_configuration_get_group_name (GkbdConfiguration * configuration,
 
674
                                   guint group)
 
675
{
 
676
        gchar *layout, *variant;
 
677
        gchar **lv;
 
678
 
 
679
        if (configuration == NULL)
 
680
                return NULL;
 
681
 
 
682
        lv = configuration->priv->kbd_cfg.layouts_variants;
 
683
        if (group >= g_strv_length (lv))
 
684
                return NULL;
 
685
 
 
686
        if (gkbd_keyboard_config_split_items
 
687
            (lv[group], &layout, &variant)) {
 
688
                return g_strdup (layout);
 
689
        }
 
690
        return NULL;
 
691
}
 
692
 
 
693
gboolean
 
694
gkbd_configuration_get_caps_lock_state (GkbdConfiguration * configuration)
 
695
{
 
696
        Bool state;
 
697
        Display *display =
 
698
            GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
699
        XkbGetNamedIndicator (display, configuration->priv->caps_lock_atom,
 
700
                              NULL, &state, NULL, NULL);
 
701
        return state;
 
702
}
 
703
 
 
704
gboolean
 
705
gkbd_configuration_get_num_lock_state (GkbdConfiguration * configuration)
 
706
{
 
707
        Bool state;
 
708
        Display *display =
 
709
            GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
710
        XkbGetNamedIndicator (display, configuration->priv->num_lock_atom,
 
711
                              NULL, &state, NULL, NULL);
 
712
        return state;
 
713
}
 
714
 
 
715
gboolean
 
716
gkbd_configuration_get_scroll_lock_state (GkbdConfiguration *
 
717
                                          configuration)
 
718
{
 
719
        Bool state;
 
720
        Display *display =
 
721
            GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
722
        XkbGetNamedIndicator (display,
 
723
                              configuration->priv->scroll_lock_atom, NULL,
 
724
                              &state, NULL, NULL);
 
725
        return state;
 
726
}