24
24
#include <stdlib.h>
25
25
#include <X11/keysym.h>
27
#include <glib/gi18n.h>
27
#include <glib/gi18n-lib.h>
29
29
#include <gkbd-keyboard-config.h>
30
30
#include <gkbd-config-private.h>
31
#include <gkbd-util.h>
33
34
* GkbdKeyboardConfig
35
#define GKBD_KEYBOARD_CONFIG_KEY_PREFIX GKBD_CONFIG_KEY_PREFIX "/kbd"
37
37
#define GROUP_SWITCHERS_GROUP "grp"
38
38
#define DEFAULT_GROUP_SWITCH "grp:shift_caps_toggle"
40
const gchar GKBD_KEYBOARD_CONFIG_DIR[] = GKBD_KEYBOARD_CONFIG_KEY_PREFIX;
41
const gchar GKBD_KEYBOARD_CONFIG_KEY_MODEL[] =
42
GKBD_KEYBOARD_CONFIG_KEY_PREFIX "/model";
43
const gchar GKBD_KEYBOARD_CONFIG_KEY_LAYOUTS[] =
44
GKBD_KEYBOARD_CONFIG_KEY_PREFIX "/layouts";
45
const gchar GKBD_KEYBOARD_CONFIG_KEY_OPTIONS[] =
46
GKBD_KEYBOARD_CONFIG_KEY_PREFIX "/options";
40
#define XMODMAP_CMD "xmodmap"
42
const gchar GKBD_KEYBOARD_CONFIG_KEY_MODEL[] = "model";
43
const gchar GKBD_KEYBOARD_CONFIG_KEY_LAYOUTS[] = "layouts";
44
const gchar GKBD_KEYBOARD_CONFIG_KEY_OPTIONS[] = "options";
48
46
const gchar *GKBD_KEYBOARD_CONFIG_ACTIVE[] = {
49
47
GKBD_KEYBOARD_CONFIG_KEY_MODEL,
51
49
GKBD_KEYBOARD_CONFIG_KEY_OPTIONS
52
const gchar *XMODMAP_KNOWN_FILES[] = { ".xmodmap", ".Xmodmap" };
55
55
* static common functions
58
gkbd_keyboard_config_string_list_reset (GSList ** plist)
60
while (*plist != NULL) {
62
*plist = (*plist)->next;
69
gslist_str_equal (GSList * l1, GSList * l2)
59
g_strv_equal (gchar ** l1, gchar ** l2)
73
while (l1 != NULL && l2 != NULL) {
74
if ((l1->data != l2->data) &&
77
g_ascii_strcasecmp (l1->data, l2->data))
64
return g_strv_length (l2) == 0;
66
return g_strv_length (l1) == 0;
68
while ((*l1 != NULL) && (*l2 != NULL)) {
71
if (g_ascii_strcasecmp (*l1, *l2))
83
return (l1 == NULL && l2 == NULL);
80
return (*l1 == NULL) && (*l2 == NULL);
188
185
* static GkbdKeyboardConfig functions
191
gkbd_keyboard_config_options_add_full (GkbdKeyboardConfig * kbd_config,
192
const gchar * full_option_name)
194
kbd_config->options =
195
g_slist_append (kbd_config->options,
196
g_strdup (full_option_name));
200
gkbd_keyboard_config_layouts_add_full (GkbdKeyboardConfig * kbd_config,
201
const gchar * full_layout_name)
203
kbd_config->layouts_variants =
204
g_slist_append (kbd_config->layouts_variants,
205
g_strdup (full_layout_name));
209
189
gkbd_keyboard_config_copy_from_xkl_config (GkbdKeyboardConfig * kbd_config,
210
190
XklConfigRec * pdata)
213
194
gkbd_keyboard_config_model_set (kbd_config, pdata->model);
214
195
xkl_debug (150, "Loaded Kbd model: [%s]\n", pdata->model);
216
gkbd_keyboard_config_layouts_reset (kbd_config);
218
p1 = pdata->variants;
219
while (p != NULL && *p != NULL) {
220
const gchar *full_layout =
221
gkbd_keyboard_config_merge_items (*p, *p1);
223
"Loaded Kbd layout (with variant): [%s]\n",
225
gkbd_keyboard_config_layouts_add_full (kbd_config,
198
g_strfreev (kbd_config->layouts_variants);
199
kbd_config->layouts_variants = NULL;
200
if (pdata->layouts != NULL) {
202
p1 = pdata->variants;
203
kbd_config->layouts_variants =
204
g_new0 (gchar *, g_strv_length (pdata->layouts) + 1);
207
const gchar *full_layout =
208
gkbd_keyboard_config_merge_items (*p, *p1);
210
"Loaded Kbd layout (with variant): [%s]\n",
212
kbd_config->layouts_variants[i++] =
213
g_strdup (full_layout);
231
gkbd_keyboard_config_options_reset (kbd_config);
233
while (p != NULL && *p != NULL) {
234
char group[XKL_MAX_CI_NAME_LENGTH];
237
(option != NULL) ? strchr (option, ':') : NULL;
239
if ((delim != NULL) &&
240
((len = (delim - option)) < XKL_MAX_CI_NAME_LENGTH)) {
241
strncpy (group, option, len);
243
xkl_debug (150, "Loaded Kbd option: [%s][%s]\n",
245
gkbd_keyboard_config_options_add (kbd_config,
220
g_strfreev (kbd_config->options);
221
kbd_config->options = NULL;
223
if (pdata->options != NULL) {
225
kbd_config->options =
226
g_new0 (gchar *, g_strv_length (pdata->options) + 1);
229
char group[XKL_MAX_CI_NAME_LENGTH];
232
(option != NULL) ? strchr (option, ':') : NULL;
234
if ((delim != NULL) &&
237
XKL_MAX_CI_NAME_LENGTH)) {
238
strncpy (group, option, len);
241
"Loaded Kbd option: [%s][%s]\n",
243
gkbd_keyboard_config_options_set
244
(kbd_config, i++, group, option);
298
297
*p2 ? *p2 : "(nil)", *p2);
301
the_layout_variant = the_layout_variant->next;
300
the_layout_variant++;
305
304
if (num_options != 0) {
306
GSList *the_option = kbd_config->options;
305
gchar **the_option = kbd_config->options;
307
306
char **p = pdata->options =
308
307
g_new0 (char *, num_options + 1);
309
308
for (i = num_options; --i >= 0;) {
310
309
char *group, *option;
311
310
if (gkbd_keyboard_config_split_items
312
(the_option->data, &group, &option)
311
(*the_option, &group, &option)
313
312
&& option != NULL)
314
313
*(p++) = g_strdup (option);
316
315
*(p++) = g_strdup ("");
317
316
xkl_debug (150, "Could not split [%s]\n",
320
the_option = the_option->next;
326
325
gkbd_keyboard_config_load_params (GkbdKeyboardConfig * kbd_config,
327
326
const gchar * param_names[])
329
GError *gerror = NULL;
333
pc = gconf_client_get_string (kbd_config->conf_client,
334
param_names[0], &gerror);
335
if (pc == NULL || gerror != NULL) {
336
if (gerror != NULL) {
337
g_warning ("Error reading configuration:%s\n",
339
g_error_free (gerror);
330
pc = g_settings_get_string (kbd_config->settings, param_names[0]);
332
if (pc == NULL || pc[0] == '\0') {
343
333
gkbd_keyboard_config_model_set (kbd_config, NULL);
345
335
gkbd_keyboard_config_model_set (kbd_config, pc);
348
338
xkl_debug (150, "Loaded Kbd model: [%s]\n",
349
339
kbd_config->model ? kbd_config->model : "(null)");
351
gkbd_keyboard_config_layouts_reset (kbd_config);
353
l = pl = gconf_client_get_list (kbd_config->conf_client,
355
GCONF_VALUE_STRING, &gerror);
356
if (pl == NULL || gerror != NULL) {
357
if (gerror != NULL) {
358
g_warning ("Error reading configuration:%s\n",
360
g_error_free (gerror);
366
xkl_debug (150, "Loaded Kbd layout: [%s]\n", l->data);
367
gkbd_keyboard_config_layouts_add_full (kbd_config,
371
gkbd_keyboard_config_string_list_reset (&pl);
373
gkbd_keyboard_config_options_reset (kbd_config);
375
l = pl = gconf_client_get_list (kbd_config->conf_client,
377
GCONF_VALUE_STRING, &gerror);
378
if (pl == NULL || gerror != NULL) {
379
if (gerror != NULL) {
380
g_warning ("Error reading configuration:%s\n",
382
g_error_free (gerror);
388
xkl_debug (150, "Loaded Kbd option: [%s]\n", l->data);
389
gkbd_keyboard_config_options_add_full (kbd_config,
394
gkbd_keyboard_config_string_list_reset (&pl);
341
g_strfreev (kbd_config->layouts_variants);
343
kbd_config->layouts_variants =
344
g_settings_get_strv (kbd_config->settings, param_names[1]);
346
if (kbd_config->layouts_variants != NULL
347
&& kbd_config->layouts_variants[0] == NULL) {
348
g_strfreev (kbd_config->layouts_variants);
349
kbd_config->layouts_variants = NULL;
352
g_strfreev (kbd_config->options);
354
kbd_config->options =
355
g_settings_get_strv (kbd_config->settings, param_names[2]);
357
if (kbd_config->options != NULL && kbd_config->options[0] == NULL) {
358
g_strfreev (kbd_config->options);
359
kbd_config->options = NULL;
398
364
gkbd_keyboard_config_save_params (GkbdKeyboardConfig * kbd_config,
400
365
const gchar * param_names[])
404
369
if (kbd_config->model)
405
gconf_change_set_set_string (cs, param_names[0],
370
g_settings_set_string (kbd_config->settings,
371
param_names[0], kbd_config->model);
408
gconf_change_set_unset (cs, param_names[0]);
373
g_settings_set_string (kbd_config->settings,
374
param_names[0], NULL);
409
375
xkl_debug (150, "Saved Kbd model: [%s]\n",
410
376
kbd_config->model ? kbd_config->model : "(null)");
412
378
if (kbd_config->layouts_variants) {
413
379
pl = kbd_config->layouts_variants;
415
xkl_debug (150, "Saved Kbd layout: [%s]\n",
380
while (*pl != NULL) {
381
xkl_debug (150, "Saved Kbd layout: [%s]\n", *pl);
419
gconf_change_set_set_list (cs,
422
kbd_config->layouts_variants);
384
g_settings_set_strv (kbd_config->settings,
386
(const gchar * const *)
387
kbd_config->layouts_variants);
424
389
xkl_debug (150, "Saved Kbd layouts: []\n");
425
gconf_change_set_unset (cs, param_names[1]);
390
g_settings_set_strv (kbd_config->settings,
391
param_names[1], NULL);
428
394
if (kbd_config->options) {
429
395
pl = kbd_config->options;
431
xkl_debug (150, "Saved Kbd option: [%s]\n",
396
while (*pl != NULL) {
397
xkl_debug (150, "Saved Kbd option: [%s]\n", *pl);
435
gconf_change_set_set_list (cs,
438
kbd_config->options);
400
g_settings_set_strv (kbd_config->settings,
403
const *) kbd_config->options);
440
405
xkl_debug (150, "Saved Kbd options: []\n");
441
gconf_change_set_unset (cs, param_names[2]);
406
g_settings_set_strv (kbd_config->settings,
407
param_names[2], NULL);
472
426
gkbd_keyboard_config_model_set (kbd_config, NULL);
474
gkbd_keyboard_config_layouts_reset (kbd_config);
475
gkbd_keyboard_config_options_reset (kbd_config);
428
g_strfreev (kbd_config->layouts_variants);
429
kbd_config->layouts_variants = NULL;
430
g_strfreev (kbd_config->options);
431
kbd_config->options = NULL;
477
g_object_unref (kbd_config->conf_client);
478
kbd_config->conf_client = NULL;
433
g_object_unref (kbd_config->settings);
434
kbd_config->settings = NULL;
482
gkbd_keyboard_config_load_from_gconf (GkbdKeyboardConfig * kbd_config,
438
gkbd_keyboard_config_load (GkbdKeyboardConfig * kbd_config,
439
GkbdKeyboardConfig * kbd_config_default)
486
441
gkbd_keyboard_config_load_params (kbd_config,
487
442
GKBD_KEYBOARD_CONFIG_ACTIVE);
489
444
if (kbd_config_default != NULL) {
492
446
if (kbd_config->model == NULL)
493
447
kbd_config->model =
494
448
g_strdup (kbd_config_default->model);
496
450
if (kbd_config->layouts_variants == NULL) {
497
pl = kbd_config_default->layouts_variants;
499
kbd_config->layouts_variants =
501
(kbd_config->layouts_variants,
502
g_strdup (pl->data));
451
kbd_config->layouts_variants =
453
(kbd_config_default->layouts_variants);
507
456
if (kbd_config->options == NULL) {
508
pl = kbd_config_default->options;
510
kbd_config->options =
511
g_slist_append (kbd_config->options,
512
g_strdup (pl->data));
457
kbd_config->options =
458
g_strdupv (kbd_config_default->options);
565
509
(kbd_config2->model != NULL) &&
566
510
g_ascii_strcasecmp (kbd_config1->model, kbd_config2->model))
568
return gslist_str_equal (kbd_config1->layouts_variants,
569
kbd_config2->layouts_variants)
570
&& gslist_str_equal (kbd_config1->options,
571
kbd_config2->options);
512
return g_strv_equal (kbd_config1->layouts_variants,
513
kbd_config2->layouts_variants)
514
&& g_strv_equal (kbd_config1->options, kbd_config2->options);
575
gkbd_keyboard_config_save_to_gconf (GkbdKeyboardConfig * kbd_config)
518
gkbd_keyboard_config_save (GkbdKeyboardConfig * kbd_config)
578
GError *gerror = NULL;
580
cs = gconf_change_set_new ();
582
gkbd_keyboard_config_save_params (kbd_config, cs,
520
g_settings_delay (kbd_config->settings);
522
gkbd_keyboard_config_save_params (kbd_config,
583
523
GKBD_KEYBOARD_CONFIG_ACTIVE);
585
gconf_client_commit_change_set (kbd_config->conf_client, cs, TRUE,
587
if (gerror != NULL) {
588
g_warning ("Error saving active configuration: %s\n",
590
g_error_free (gerror);
593
gconf_change_set_unref (cs);
525
g_settings_apply (kbd_config->settings);
608
gkbd_keyboard_config_layouts_add (GkbdKeyboardConfig * kbd_config,
609
const gchar * layout_name,
610
const gchar * variant_name)
613
if (layout_name == NULL)
616
gkbd_keyboard_config_merge_items (layout_name, variant_name);
619
gkbd_keyboard_config_layouts_add_full (kbd_config, merged);
623
gkbd_keyboard_config_layouts_reset (GkbdKeyboardConfig * kbd_config)
625
gkbd_keyboard_config_string_list_reset
626
(&kbd_config->layouts_variants);
630
gkbd_keyboard_config_options_reset (GkbdKeyboardConfig * kbd_config)
632
gkbd_keyboard_config_string_list_reset (&kbd_config->options);
636
gkbd_keyboard_config_options_add (GkbdKeyboardConfig * kbd_config,
637
const gchar * group_name,
540
gkbd_keyboard_config_options_set (GkbdKeyboardConfig * kbd_config,
541
gint idx, const gchar * group_name,
638
542
const gchar * option_name)
640
544
const gchar *merged;
672
579
rv = xkl_config_rec_activate (data, kbd_config->engine);
673
580
g_object_unref (G_OBJECT (data));
582
/* Small bit of extensibility by using xmodmap */
585
sizeof (XMODMAP_KNOWN_FILES) /
586
sizeof (XMODMAP_KNOWN_FILES[0]);
588
gchar *xmodmap_file =
589
g_build_filename (g_get_home_dir (),
590
XMODMAP_KNOWN_FILES[i],
592
if (g_file_test (xmodmap_file, G_FILE_TEST_EXISTS)) {
593
GError *error = NULL;
595
"Loading custom xmodmap file %s\n",
598
g_strconcat (XMODMAP_CMD, " ",
601
/* Fire and forget - do not care about errors */
602
if (!g_spawn_command_line_async
605
"Error loading custom xmodmap file: [%s]\n",
607
g_error_free (error);
611
/* One file is enough */
615
g_free (xmodmap_file);
623
* gkbd_keyboard_config_start_listen:
624
* @func: (scope notified): a function to call when settings are changed
679
627
gkbd_keyboard_config_start_listen (GkbdKeyboardConfig * kbd_config,
680
GConfClientNotifyFunc func,
628
GCallback func, gpointer user_data)
683
gkbd_desktop_config_add_listener (kbd_config->conf_client,
684
GKBD_KEYBOARD_CONFIG_DIR, func,
686
&kbd_config->config_listener_id);
630
kbd_config->config_listener_id =
631
g_signal_connect (kbd_config->settings, "changed", func,
690
636
gkbd_keyboard_config_stop_listen (GkbdKeyboardConfig * kbd_config)
692
gkbd_desktop_config_remove_listener (kbd_config->conf_client,
638
g_signal_handler_disconnect (kbd_config->settings,
639
kbd_config->config_listener_id);
640
kbd_config->config_listener_id = 0;
795
gkbd_keyboard_config_add_default_switch_option_if_necessary (GSList *
735
* gkbd_keyboard_config_add_default_switch_option_if_necessary:
736
* Returns: (transfer full) (array zero-terminated=1): List of options
739
gkbd_keyboard_config_add_default_switch_option_if_necessary (gchar **
798
options_list, gboolean *was_appended)
800
746
*was_appended = FALSE;
801
if (g_slist_length (layouts_list) >= 2) {
747
if (g_strv_length (layouts_list) >= 2) {
802
748
gboolean any_switcher = False;
803
GSList *option = options_list;
804
while (option != NULL) {
806
if (gkbd_keyboard_config_split_items
807
(option->data, &g, &o)) {
808
if (!g_ascii_strcasecmp
809
(g, GROUP_SWITCHERS_GROUP)) {
749
if (*options_list != NULL) {
750
gchar **option = options_list;
751
while (*option != NULL) {
753
if (gkbd_keyboard_config_split_items
755
if (!g_ascii_strcasecmp
756
(g, GROUP_SWITCHERS_GROUP)) {
814
option = option->next;
816
764
if (!any_switcher) {
817
765
const gchar *id =