1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 2011 Red Hat, Inc.
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28
#include <glib/gi18n-lib.h>
30
#include "cc-keyboard-item.h"
32
#define CC_KEYBOARD_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_KEYBOARD_ITEM, CcKeyboardItemPrivate))
34
#define CUSTOM_KEYS_SCHEMA "org.gnome.settings-daemon.plugins.media-keys.custom-keybinding"
36
struct CcKeyboardItemPrivate
53
static void cc_keyboard_item_class_init (CcKeyboardItemClass *klass);
54
static void cc_keyboard_item_init (CcKeyboardItem *keyboard_item);
55
static void cc_keyboard_item_finalize (GObject *object);
57
G_DEFINE_TYPE (CcKeyboardItem, cc_keyboard_item, G_TYPE_OBJECT)
60
binding_from_string (const char *str,
61
guint *accelerator_key,
63
GdkModifierType *accelerator_mods)
65
g_return_val_if_fail (accelerator_key != NULL, FALSE);
68
if (str == NULL || strcmp (str, "disabled") == 0)
72
*accelerator_mods = 0;
76
gtk_accelerator_parse_with_keycode (str, accelerator_key, &keycodes, accelerator_mods);
79
*keycode = (keycodes ? keycodes[0] : 0);
82
if (*accelerator_key == 0)
89
_set_description (CcKeyboardItem *item,
92
g_free (item->description);
93
item->description = g_strdup (value);
97
cc_keyboard_item_get_description (CcKeyboardItem *item)
99
g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), NULL);
101
return item->description;
104
/* wrapper around g_settings_set_str[ing|v] */
106
settings_set_binding (GSettings *settings,
112
variant = g_settings_get_value (settings, key);
114
if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING))
115
g_settings_set_string (settings, key, value);
116
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING_ARRAY))
120
str_array = g_variant_dup_strv (variant, NULL);
122
/* create a space for the new binding if empty */
123
if (*str_array == NULL)
126
str_array = g_new0 (char *, 2);
129
/* replace the first binding */
131
*str_array = g_strdup (value);
133
g_settings_set_strv (settings, key, (const char * const *)str_array);
134
g_strfreev (str_array);
137
g_variant_unref (variant);
142
_set_binding (CcKeyboardItem *item,
144
gboolean set_backend)
146
/* don't reassign <Alt_L> or <Alt> key in the callback to the binding itself (as it's invalid for the cell renderer) */
147
if ((g_strcmp0 (value, "<Alt_L>") == 0) || (g_strcmp0 (value, "<Alt>") == 0))
150
g_free (item->binding);
151
item->binding = g_strdup (value);
152
binding_from_string (item->binding, &item->keyval, &item->keycode, &item->mask);
155
char *cheated_modifier = NULL;
156
if (g_strcmp0 (item->binding, "Alt_L") == 0)
157
cheated_modifier = g_strdup_printf ("<%s>", item->binding);
159
if (set_backend == FALSE)
162
settings_set_binding (item->settings, item->key, cheated_modifier ? cheated_modifier: item->binding);
164
g_free (cheated_modifier);
168
cc_keyboard_item_get_binding (CcKeyboardItem *item)
170
g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), NULL);
172
return item->binding;
176
_set_type (CcKeyboardItem *item,
183
_set_command (CcKeyboardItem *item,
186
g_free (item->command);
187
item->command = g_strdup (value);
191
cc_keyboard_item_get_command (CcKeyboardItem *item)
193
g_return_val_if_fail (CC_IS_KEYBOARD_ITEM (item), NULL);
195
return item->command;
199
cc_keyboard_item_set_property (GObject *object,
204
CcKeyboardItem *self;
206
self = CC_KEYBOARD_ITEM (object);
209
case PROP_DESCRIPTION:
210
_set_description (self, g_value_get_string (value));
213
_set_binding (self, g_value_get_string (value), TRUE);
216
_set_command (self, g_value_get_string (value));
219
_set_type (self, g_value_get_int (value));
222
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
228
cc_keyboard_item_get_property (GObject *object,
233
CcKeyboardItem *self;
235
self = CC_KEYBOARD_ITEM (object);
238
case PROP_DESCRIPTION:
239
g_value_set_string (value, self->description);
242
g_value_set_string (value, self->binding);
245
g_value_set_boolean (value, self->editable);
248
g_value_set_string (value, self->command);
251
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
257
cc_keyboard_item_constructor (GType type,
258
guint n_construct_properties,
259
GObjectConstructParam *construct_properties)
261
CcKeyboardItem *keyboard_item;
263
keyboard_item = CC_KEYBOARD_ITEM (G_OBJECT_CLASS (cc_keyboard_item_parent_class)->constructor (type,
264
n_construct_properties,
265
construct_properties));
267
return G_OBJECT (keyboard_item);
271
cc_keyboard_item_class_init (CcKeyboardItemClass *klass)
273
GObjectClass *object_class = G_OBJECT_CLASS (klass);
275
object_class->get_property = cc_keyboard_item_get_property;
276
object_class->set_property = cc_keyboard_item_set_property;
277
object_class->constructor = cc_keyboard_item_constructor;
278
object_class->finalize = cc_keyboard_item_finalize;
280
g_object_class_install_property (object_class,
282
g_param_spec_string ("description",
288
g_object_class_install_property (object_class,
290
g_param_spec_string ("binding",
296
g_object_class_install_property (object_class,
298
g_param_spec_boolean ("editable",
304
g_object_class_install_property (object_class,
306
g_param_spec_int ("type",
309
CC_KEYBOARD_ITEM_TYPE_NONE,
310
CC_KEYBOARD_ITEM_TYPE_GSETTINGS,
311
CC_KEYBOARD_ITEM_TYPE_NONE,
312
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
314
g_object_class_install_property (object_class,
316
g_param_spec_string ("command",
322
g_type_class_add_private (klass, sizeof (CcKeyboardItemPrivate));
326
cc_keyboard_item_init (CcKeyboardItem *item)
328
item->priv = CC_KEYBOARD_ITEM_GET_PRIVATE (item);
332
cc_keyboard_item_finalize (GObject *object)
334
CcKeyboardItem *item;
336
g_return_if_fail (object != NULL);
337
g_return_if_fail (CC_IS_KEYBOARD_ITEM (object));
339
item = CC_KEYBOARD_ITEM (object);
341
g_return_if_fail (item->priv != NULL);
343
if (item->settings != NULL)
344
g_object_unref (item->settings);
347
g_free (item->binding);
348
g_free (item->gettext_package);
349
g_free (item->gsettings_path);
350
g_free (item->description);
351
g_free (item->command);
352
g_free (item->schema);
355
G_OBJECT_CLASS (cc_keyboard_item_parent_class)->finalize (object);
359
cc_keyboard_item_new (CcKeyboardItemType type)
363
object = g_object_new (CC_TYPE_KEYBOARD_ITEM,
367
return CC_KEYBOARD_ITEM (object);
370
/* wrapper around g_settings_get_str[ing|v] */
372
settings_get_binding (GSettings *settings,
378
variant = g_settings_get_value (settings, key);
379
if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING))
380
value = g_variant_dup_string (variant, NULL);
381
else if (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING_ARRAY))
383
const char **str_array;
385
str_array = g_variant_get_strv (variant, NULL);
386
value = g_strdup (str_array[0]);
388
g_variant_unref (variant);
394
binding_changed (GSettings *settings,
396
CcKeyboardItem *item)
400
value = settings_get_binding (item->settings, item->key);
401
item->editable = g_settings_is_writable (item->settings, item->key);
402
_set_binding (item, value, FALSE);
404
g_object_notify (G_OBJECT (item), "binding");
408
cc_keyboard_item_load_from_gsettings_path (CcKeyboardItem *item,
412
item->schema = g_strdup (CUSTOM_KEYS_SCHEMA);
413
item->gsettings_path = g_strdup (path);
414
item->key = g_strdup ("binding");
415
item->settings = g_settings_new_with_path (item->schema, path);
416
item->editable = g_settings_is_writable (item->settings, item->key);
417
item->desc_editable = g_settings_is_writable (item->settings, "name");
418
item->cmd_editable = g_settings_is_writable (item->settings, "command");
422
g_settings_reset (item->settings, "name");
423
g_settings_reset (item->settings, "command");
424
g_settings_reset (item->settings, "binding");
427
g_settings_bind (item->settings, "name",
428
G_OBJECT (item), "description", G_SETTINGS_BIND_DEFAULT);
429
g_settings_bind (item->settings, "command",
430
G_OBJECT (item), "command", G_SETTINGS_BIND_DEFAULT);
432
item->binding = settings_get_binding (item->settings, item->key);
433
binding_from_string (item->binding, &item->keyval, &item->keycode, &item->mask);
434
g_signal_connect (G_OBJECT (item->settings), "changed::binding",
435
G_CALLBACK (binding_changed), item);
441
cc_keyboard_item_load_from_gsettings (CcKeyboardItem *item,
442
const char *description,
448
item->schema = g_strdup (schema);
449
item->key = g_strdup (key);
450
item->description = g_strdup (description);
452
item->settings = g_settings_new (item->schema);
453
item->binding = settings_get_binding (item->settings, item->key);
454
item->editable = g_settings_is_writable (item->settings, item->key);
456
if ((g_strcmp0 (item->binding, "<Alt>") == 0) || (g_strcmp0 (item->binding, "<Alt_L>") == 0))
458
g_free (item->binding);
459
item->binding = g_strdup ("Alt_L");
462
binding_from_string (item->binding, &item->keyval, &item->keycode, &item->mask);
464
signal_name = g_strdup_printf ("changed::%s", item->key);
465
g_signal_connect (G_OBJECT (item->settings), signal_name,
466
G_CALLBACK (binding_changed), item);
467
g_free (signal_name);
473
cc_keyboard_item_equal (CcKeyboardItem *a,
476
if (a->type != b->type)
480
case CC_KEYBOARD_ITEM_TYPE_GSETTINGS_PATH:
481
return g_str_equal (a->gsettings_path, b->gsettings_path);
482
case CC_KEYBOARD_ITEM_TYPE_GSETTINGS:
483
return (g_str_equal (a->schema, b->schema) &&
484
g_str_equal (a->key, b->key));
486
g_assert_not_reached ();
492
* vim: sw=2 ts=8 cindent noai bs=2